[feat] Layers mangaing
This commit is contained in:
@@ -20,7 +20,8 @@ KERNEL_CPP = kernel/entry.cpp kernel/main.cpp kernel/serial.cpp kernel/fs.cpp \
|
||||
kernel/scheduler/scheduler.cpp \
|
||||
kernel/interrupt/gdt.cpp kernel/interrupt/idt.cpp \
|
||||
kernel/interrupt/pic.cpp kernel/interrupt/pit.cpp \
|
||||
graphics/context.cpp graphics/draw.cpp \
|
||||
kernel/graphics/layer.cpp \
|
||||
graphics/context.cpp graphics/draw.cpp graphics/rect.cpp \
|
||||
fonts/pixel_font.cpp
|
||||
KERNEL_ASM = kernel/scheduler/context_switch.S kernel/interrupt/isr.S kernel/interrupt/idt_helpers.S
|
||||
KERNEL_OBJ = $(KERNEL_CPP:%.cpp=build/%.o) $(KERNEL_ASM:%.S=build/%.o)
|
||||
@@ -48,7 +49,7 @@ all: _bd $(EFI_OBJ) $(BOOT_OBJ) $(KERNEL_OBJ)
|
||||
|
||||
_bd:
|
||||
@mkdir -p build/graphics build/kernel build/fonts build/kernel/memory \
|
||||
build/kernel/scheduler build/kernel/interrupt \
|
||||
build/kernel/scheduler build/kernel/interrupt build/kernel/graphics \
|
||||
build/efi/lib build/efi/lib/x86_64 build/efi/lib/runtime build/efi/gnuefi
|
||||
|
||||
$(EFI_CRT0_OBJ): efi/gnuefi/crt0-efi-x86_64.S | _bd
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include <graphics/rect.h>
|
||||
|
||||
void gfx_fill_rect(EFI_GRAPHICS_OUTPUT_BLT_PIXEL* buf,
|
||||
UINT32 buf_w, UINT32 buf_h,
|
||||
UINT32 x, UINT32 y, UINT32 w, UINT32 h,
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color) {
|
||||
if (x >= buf_w || y >= buf_h) return;
|
||||
|
||||
UINT32 x2 = x + w;
|
||||
UINT32 y2 = y + h;
|
||||
if (x2 > buf_w) x2 = buf_w;
|
||||
if (y2 > buf_h) y2 = buf_h;
|
||||
|
||||
for (UINT32 row = y; row < y2; row++) {
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* p = buf + (buf_w * row) + x;
|
||||
for (UINT32 col = x; col < x2; col++) {
|
||||
p->Blue = color.Blue;
|
||||
p->Green = color.Green;
|
||||
p->Red = color.Red;
|
||||
p->Reserved = color.Reserved;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gfx_draw_rect(EFI_GRAPHICS_OUTPUT_BLT_PIXEL* buf,
|
||||
UINT32 buf_w, UINT32 buf_h,
|
||||
UINT32 x, UINT32 y, UINT32 w, UINT32 h,
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color) {
|
||||
if (x >= buf_w || y >= buf_h) return;
|
||||
|
||||
UINT32 x2 = x + w;
|
||||
UINT32 y2 = y + h;
|
||||
if (x2 > buf_w) x2 = buf_w;
|
||||
if (y2 > buf_h) y2 = buf_h;
|
||||
|
||||
// Top edge
|
||||
for (UINT32 col = x; col < x2; col++) {
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* p = buf + (buf_w * y) + col;
|
||||
p->Blue = color.Blue; p->Green = color.Green; p->Red = color.Red; p->Reserved = color.Reserved;
|
||||
}
|
||||
// Bottom edge
|
||||
if (y2 - 1 < buf_h) {
|
||||
for (UINT32 col = x; col < x2; col++) {
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* p = buf + (buf_w * (y2 - 1)) + col;
|
||||
p->Blue = color.Blue; p->Green = color.Green; p->Red = color.Red; p->Reserved = color.Reserved;
|
||||
}
|
||||
}
|
||||
// Left edge
|
||||
for (UINT32 row = y; row < y2; row++) {
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* p = buf + (buf_w * row) + x;
|
||||
p->Blue = color.Blue; p->Green = color.Green; p->Red = color.Red; p->Reserved = color.Reserved;
|
||||
}
|
||||
// Right edge
|
||||
if (x2 - 1 < buf_w) {
|
||||
for (UINT32 row = y; row < y2; row++) {
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* p = buf + (buf_w * row) + (x2 - 1);
|
||||
p->Blue = color.Blue; p->Green = color.Green; p->Red = color.Red; p->Reserved = color.Reserved;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#include <efi.h>
|
||||
|
||||
#define LAYER_MAX 32
|
||||
#define LAYER_NAME_LEN 32
|
||||
|
||||
typedef enum {
|
||||
LAYER_TYPE_DESKTOP,
|
||||
LAYER_TYPE_WINDOW,
|
||||
LAYER_TYPE_MOUSE,
|
||||
LAYER_TYPE_OVERLAY,
|
||||
} layer_type_t;
|
||||
|
||||
typedef struct layer {
|
||||
UINT32 id;
|
||||
char name[LAYER_NAME_LEN];
|
||||
layer_type_t type;
|
||||
int x, y;
|
||||
UINT32 w, h;
|
||||
int z;
|
||||
bool visible;
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* buffer;
|
||||
struct layer* next;
|
||||
} layer_t;
|
||||
|
||||
// Initialization — allocates back buffer, registers keyboard handler
|
||||
void layer_init(void);
|
||||
|
||||
// Layer management
|
||||
layer_t* layer_create(const char* name, layer_type_t type, UINT32 w, UINT32 h);
|
||||
void layer_destroy(layer_t* layer);
|
||||
void layer_set_z(layer_t* layer, int z);
|
||||
void layer_set_pos(layer_t* layer, int x, int y);
|
||||
void layer_set_visible(layer_t* layer, bool visible);
|
||||
layer_t* layer_get_by_id(UINT32 id);
|
||||
layer_t* layer_get_focused(void);
|
||||
|
||||
// Compositor task entry
|
||||
void layer_compositor_task(void);
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <efi.h>
|
||||
|
||||
void gfx_fill_rect(EFI_GRAPHICS_OUTPUT_BLT_PIXEL* buf,
|
||||
UINT32 buf_w, UINT32 buf_h,
|
||||
UINT32 x, UINT32 y, UINT32 w, UINT32 h,
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color);
|
||||
|
||||
void gfx_draw_rect(EFI_GRAPHICS_OUTPUT_BLT_PIXEL* buf,
|
||||
UINT32 buf_w, UINT32 buf_h,
|
||||
UINT32 x, UINT32 y, UINT32 w, UINT32 h,
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color);
|
||||
@@ -0,0 +1,319 @@
|
||||
#include <graphics/layer.h>
|
||||
#include <graphics/rect.h>
|
||||
#include <graphics/context.h>
|
||||
#include <memory/heap.h>
|
||||
#include <memory/pmm.h>
|
||||
#include <scheduler.h>
|
||||
#include <serial.h>
|
||||
#include <idt.h>
|
||||
#include <pic.h>
|
||||
#include <common.h>
|
||||
|
||||
// --- Layer list (sorted by z, lowest first) ---
|
||||
|
||||
static layer_t g_layers[LAYER_MAX];
|
||||
static UINT32 g_layer_count = 0;
|
||||
static layer_t* g_layer_list = NULL;
|
||||
|
||||
// Compositor back buffer
|
||||
static EFI_GRAPHICS_OUTPUT_BLT_PIXEL* g_back_buffer = NULL;
|
||||
|
||||
// Focus tracking
|
||||
static layer_t* g_focused = NULL;
|
||||
|
||||
// Shift+F10 state (set by IRQ handler, consumed by compositor)
|
||||
static volatile bool g_shift_held = false;
|
||||
static volatile bool g_switch_pending = false;
|
||||
static volatile layer_t* g_switch_target = NULL;
|
||||
|
||||
// PS/2 scan code set 1
|
||||
#define PS2_F10 0x44
|
||||
#define PS2_LSHIFT 0x2A
|
||||
#define PS2_RSHIFT 0x36
|
||||
#define PS2_BREAK_BIT 0x80
|
||||
|
||||
// Forward declare
|
||||
static void layer_insert_sorted(layer_t* layer);
|
||||
static void layer_remove(layer_t* layer);
|
||||
static layer_t* find_next_window(layer_t* from);
|
||||
|
||||
// --- PS/2 keyboard IRQ handler ---
|
||||
|
||||
static void ps2_irq_handler(trap_frame* frame) {
|
||||
(void)frame;
|
||||
pic_send_eoi(1);
|
||||
|
||||
UINT8 sc;
|
||||
ASM("inb %1, %0" : "=a"(sc) : "Nd"((UINT16)0x60));
|
||||
|
||||
bool is_break = (sc & PS2_BREAK_BIT) != 0;
|
||||
UINT8 code = sc & 0x7F;
|
||||
|
||||
if (code == PS2_LSHIFT || code == PS2_RSHIFT) {
|
||||
g_shift_held = !is_break;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_break && g_shift_held && code == PS2_F10) {
|
||||
layer_t* next = find_next_window((layer_t*)g_focused);
|
||||
if (next) {
|
||||
g_switch_target = next;
|
||||
g_switch_pending = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Layer management ---
|
||||
|
||||
layer_t* layer_create(const char* name, layer_type_t type, UINT32 w, UINT32 h) {
|
||||
if (g_layer_count >= LAYER_MAX) {
|
||||
serial_write("LAYER: limit reached\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UINT32 id = g_layer_count++;
|
||||
layer_t* layer = &g_layers[id];
|
||||
|
||||
layer->id = id;
|
||||
layer->type = type;
|
||||
layer->x = 0;
|
||||
layer->y = 0;
|
||||
layer->w = w;
|
||||
layer->h = h;
|
||||
layer->z = 0;
|
||||
layer->visible = true;
|
||||
layer->next = NULL;
|
||||
|
||||
const char* s = name;
|
||||
char* d = layer->name;
|
||||
for (int i = 0; i < LAYER_NAME_LEN - 1 && *s; i++) {
|
||||
*d++ = *s++;
|
||||
}
|
||||
*d = '\0';
|
||||
|
||||
UINTN buf_size = (UINTN)w * h * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
||||
layer->buffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL*)kmalloc(buf_size);
|
||||
if (!layer->buffer) {
|
||||
serial_write("LAYER: buffer alloc failed for ");
|
||||
serial_write(name);
|
||||
serial_write("\n");
|
||||
g_layer_count--;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* p = layer->buffer;
|
||||
for (UINTN i = 0; i < (UINTN)w * h; i++) {
|
||||
p->Blue = 0; p->Green = 0; p->Red = 0; p->Reserved = 0;
|
||||
p++;
|
||||
}
|
||||
|
||||
layer_insert_sorted(layer);
|
||||
|
||||
serial_write("LAYER: created '");
|
||||
serial_write(name);
|
||||
serial_write("' id=");
|
||||
serial_write_hex(id);
|
||||
serial_write("\n");
|
||||
|
||||
return layer;
|
||||
}
|
||||
|
||||
void layer_destroy(layer_t* layer) {
|
||||
if (!layer) return;
|
||||
|
||||
layer_remove(layer);
|
||||
|
||||
if (layer->buffer) {
|
||||
kfree(layer->buffer);
|
||||
layer->buffer = NULL;
|
||||
}
|
||||
|
||||
if (g_focused == layer) g_focused = NULL;
|
||||
if (g_switch_target == layer) {
|
||||
g_switch_target = NULL;
|
||||
g_switch_pending = false;
|
||||
}
|
||||
|
||||
serial_write("LAYER: destroyed '");
|
||||
serial_write(layer->name);
|
||||
serial_write("'\n");
|
||||
}
|
||||
|
||||
layer_t* layer_get_by_id(UINT32 id) {
|
||||
if (id >= LAYER_MAX) return NULL;
|
||||
layer_t* l = &g_layers[id];
|
||||
return l->buffer ? l : NULL;
|
||||
}
|
||||
|
||||
layer_t* layer_get_focused(void) {
|
||||
return g_focused;
|
||||
}
|
||||
|
||||
void layer_set_z(layer_t* layer, int z) {
|
||||
if (!layer) return;
|
||||
layer_remove(layer);
|
||||
layer->z = z;
|
||||
layer_insert_sorted(layer);
|
||||
}
|
||||
|
||||
void layer_set_pos(layer_t* layer, int x, int y) {
|
||||
if (!layer) return;
|
||||
layer->x = x;
|
||||
layer->y = y;
|
||||
}
|
||||
|
||||
void layer_set_visible(layer_t* layer, bool visible) {
|
||||
if (!layer) return;
|
||||
layer->visible = visible;
|
||||
}
|
||||
|
||||
// --- Sorted insert/remove ---
|
||||
|
||||
static void layer_insert_sorted(layer_t* layer) {
|
||||
layer->next = NULL;
|
||||
|
||||
if (!g_layer_list || layer->z < g_layer_list->z) {
|
||||
layer->next = g_layer_list;
|
||||
g_layer_list = layer;
|
||||
return;
|
||||
}
|
||||
|
||||
layer_t* cur = g_layer_list;
|
||||
while (cur->next && cur->next->z <= layer->z) {
|
||||
cur = cur->next;
|
||||
}
|
||||
layer->next = cur->next;
|
||||
cur->next = layer;
|
||||
}
|
||||
|
||||
static void layer_remove(layer_t* layer) {
|
||||
if (!g_layer_list) return;
|
||||
|
||||
if (g_layer_list == layer) {
|
||||
g_layer_list = layer->next;
|
||||
layer->next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
layer_t* cur = g_layer_list;
|
||||
while (cur->next && cur->next != layer) {
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur->next == layer) {
|
||||
cur->next = layer->next;
|
||||
layer->next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static layer_t* find_next_window(layer_t* from) {
|
||||
layer_t* start = from ? from->next : g_layer_list;
|
||||
if (!start) start = g_layer_list;
|
||||
|
||||
layer_t* cur = start;
|
||||
do {
|
||||
if (cur->type == LAYER_TYPE_WINDOW && cur->visible) {
|
||||
return cur;
|
||||
}
|
||||
cur = cur->next;
|
||||
if (!cur) cur = g_layer_list;
|
||||
} while (cur != start);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// --- Initialization ---
|
||||
|
||||
void layer_init(void) {
|
||||
UINT32 hr = g_gfx.hr;
|
||||
UINT32 vr = g_gfx.vr;
|
||||
|
||||
UINTN buf_size = (UINTN)hr * vr * sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
|
||||
g_back_buffer = (EFI_GRAPHICS_OUTPUT_BLT_PIXEL*)kmalloc(buf_size);
|
||||
if (!g_back_buffer) {
|
||||
serial_write("LAYER: back buffer alloc FAILED\n");
|
||||
return;
|
||||
}
|
||||
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* p = g_back_buffer;
|
||||
for (UINTN i = 0; i < (UINTN)hr * vr; i++) {
|
||||
p->Blue = 0; p->Green = 0; p->Red = 0; p->Reserved = 0;
|
||||
p++;
|
||||
}
|
||||
|
||||
// Register keyboard IRQ and unmask
|
||||
idt_set_handler(PIC_IRQ_BASE + 1, ps2_irq_handler);
|
||||
pic_unmask_irq(1);
|
||||
|
||||
serial_write("LAYER: compositor init OK (back buffer = ");
|
||||
serial_write_hex(buf_size);
|
||||
serial_write(" bytes)\n");
|
||||
}
|
||||
|
||||
// --- Compositor task ---
|
||||
|
||||
void layer_compositor_task(void) {
|
||||
serial_write("LAYER: compositor task running\n");
|
||||
|
||||
UINT32 hr = g_gfx.hr;
|
||||
UINT32 vr = g_gfx.vr;
|
||||
|
||||
while (1) {
|
||||
// Process deferred Shift+F10 switch (safe: not inside IRQ)
|
||||
if (g_switch_pending) {
|
||||
g_switch_pending = false;
|
||||
layer_t* target = (layer_t*)g_switch_target;
|
||||
if (target && target->visible && target->type == LAYER_TYPE_WINDOW) {
|
||||
g_focused = target;
|
||||
layer_set_z(target, 99);
|
||||
serial_write("LAYER: Shift+F10 -> '");
|
||||
serial_write(target->name);
|
||||
serial_write("'\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Clear back buffer
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
|
||||
gfx_fill_rect(g_back_buffer, hr, vr, 0, 0, hr, vr, black);
|
||||
|
||||
// Composite layers from lowest z to highest
|
||||
layer_t* cur = g_layer_list;
|
||||
while (cur) {
|
||||
if (cur->visible && cur->buffer) {
|
||||
int sx = 0, sy = 0;
|
||||
int dx = cur->x, dy = cur->y;
|
||||
UINT32 sw = cur->w, sh = cur->h;
|
||||
|
||||
if (dx < 0) { sx = -dx; sw -= sx; dx = 0; }
|
||||
if (dy < 0) { sy = -dy; sh -= sy; dy = 0; }
|
||||
if (dx + (int)sw > (int)hr) sw = hr - dx;
|
||||
if (dy + (int)sh > (int)vr) sh = vr - dy;
|
||||
if (sw == 0 || sh == 0) { cur = cur->next; continue; }
|
||||
|
||||
for (UINT32 row = 0; row < sh; row++) {
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* src = cur->buffer + ((UINTN)cur->w * (sy + row)) + sx;
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* dst = g_back_buffer + ((UINTN)hr * (dy + row)) + dx;
|
||||
for (UINT32 col = 0; col < sw; col++) {
|
||||
dst->Blue = src->Blue;
|
||||
dst->Green = src->Green;
|
||||
dst->Red = src->Red;
|
||||
dst->Reserved = src->Reserved;
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
// Blit to screen
|
||||
g_gfx.GOP->Blt(
|
||||
g_gfx.GOP,
|
||||
g_back_buffer,
|
||||
EfiBltBufferToVideo,
|
||||
0, 0, 0, 0,
|
||||
hr, vr, 0
|
||||
);
|
||||
|
||||
yield();
|
||||
}
|
||||
}
|
||||
+47
-26
@@ -1,6 +1,8 @@
|
||||
#include <efi.h>
|
||||
#include <graphics/context.h>
|
||||
#include <graphics/draw.h>
|
||||
#include <graphics/rect.h>
|
||||
#include <graphics/layer.h>
|
||||
#include <fonts/pixel_font.h>
|
||||
#include <serial.h>
|
||||
#include <common.h>
|
||||
@@ -155,34 +157,53 @@ extern "C" void kernel_main() {
|
||||
// --- Multitasking demo ---
|
||||
serial_write("Sylva: creating tasks...\n");
|
||||
|
||||
// Task A: prints messages — preemption handles time slicing
|
||||
task_create("taskA", []() {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
serial_write("[taskA] running iteration ");
|
||||
serial_write_hex(i);
|
||||
serial_write("\n");
|
||||
for (volatile int j = 0; j < 50000000; j++) {}
|
||||
}
|
||||
serial_write("[taskA] done\n");
|
||||
});
|
||||
// Init compositor (allocates back buffer, registers keyboard handler)
|
||||
layer_init();
|
||||
|
||||
// Task B: prints messages
|
||||
task_create("taskB", []() {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
serial_write("[taskB] hello from taskB #");
|
||||
serial_write_hex(i);
|
||||
serial_write("\n");
|
||||
for (volatile int j = 0; j < 50000000; j++) {}
|
||||
}
|
||||
serial_write("[taskB] done\n");
|
||||
});
|
||||
// Create desktop layer (full screen, z=0)
|
||||
layer_t* desktop = layer_create("desktop", LAYER_TYPE_DESKTOP, g_gfx.hr, g_gfx.vr);
|
||||
if (desktop) {
|
||||
layer_set_z(desktop, 0);
|
||||
// Fill with dark blue
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL bg = {180, 80, 40, 0}; // BGRA: dark blue
|
||||
gfx_fill_rect(desktop->buffer, g_gfx.hr, g_gfx.vr, 0, 0, g_gfx.hr, g_gfx.vr, bg);
|
||||
layer_set_pos(desktop, 0, 0);
|
||||
}
|
||||
|
||||
// Task C: short task
|
||||
task_create("taskC", []() {
|
||||
serial_write("[taskC] quick task\n");
|
||||
for (volatile int j = 0; j < 50000000; j++) {}
|
||||
serial_write("[taskC] finished\n");
|
||||
});
|
||||
// Create window 1 (centered)
|
||||
layer_t* win1 = layer_create("window_1", LAYER_TYPE_WINDOW, 300, 200);
|
||||
if (win1) {
|
||||
layer_set_pos(win1, (int)(g_gfx.hr / 2) - 150, (int)(g_gfx.vr / 2) - 100);
|
||||
layer_set_z(win1, 1);
|
||||
// Fill with gray
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL win_color = {200, 200, 200, 0};
|
||||
gfx_fill_rect(win1->buffer, 300, 200, 0, 0, 300, 200, win_color);
|
||||
// White border
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL border = {255, 255, 255, 0};
|
||||
gfx_draw_rect(win1->buffer, 300, 200, 0, 0, 300, 200, border);
|
||||
// Title bar (blue strip at top)
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL title_bar = {180, 100, 30, 0};
|
||||
gfx_fill_rect(win1->buffer, 300, 200, 0, 0, 300, 30, title_bar);
|
||||
}
|
||||
|
||||
// Create window 2 (offset from center)
|
||||
layer_t* win2 = layer_create("window_2", LAYER_TYPE_WINDOW, 250, 180);
|
||||
if (win2) {
|
||||
layer_set_pos(win2, (int)(g_gfx.hr / 2) - 50, (int)(g_gfx.vr / 2) - 40);
|
||||
layer_set_z(win2, 2);
|
||||
// Fill with light green
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL win2_color = {180, 220, 140, 0};
|
||||
gfx_fill_rect(win2->buffer, 250, 180, 0, 0, 250, 180, win2_color);
|
||||
// Dark border
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL border2 = {50, 50, 50, 0};
|
||||
gfx_draw_rect(win2->buffer, 250, 180, 0, 0, 250, 180, border2);
|
||||
// Title bar
|
||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL title2 = {160, 180, 100, 0};
|
||||
gfx_fill_rect(win2->buffer, 250, 180, 0, 0, 250, 28, title2);
|
||||
}
|
||||
|
||||
// Compositor task (replaces the old demo tasks)
|
||||
task_create("compositor", layer_compositor_task);
|
||||
|
||||
serial_write("Sylva: starting preemptive scheduler\n");
|
||||
scheduler_run(); // never returns
|
||||
|
||||
Reference in New Issue
Block a user