Version: 1.0
Status: Draft
Codename: Aurora Display Protocol
The Aurora Display Protocol is a Wayland-like protocol for the GUI:
┌──────────────────────────────────────────────────────────────┐
│ Applications │
│ (Notepad, Paint, File Manager, Settings, ...) │
├──────────────────────────────────────────────────────────────┤
│ libgui / Toolkit │
│ (Buttons, Labels, TextBox, ListView, ...) │
├──────────────────────────────────────────────────────────────┤
│ Aurora Display Protocol │
│ (Surfaces, Buffers, Events, Regions) │
├──────────────────────────────────────────────────────────────┤
│ Compositor │
│ (Composition, Window Management, Input Routing) │
├──────────────────────────────────────────────────────────────┤
│ Kernel │
│ (Framebuffer, Input Devices, Shared Memory) │
└──────────────────────────────────────────────────────────────┘
// Connect to Compositor
handle_t display = sys_display_connect(NULL); // Default Display
if (display < 0) {
// Error
}
// Disconnect
sys_close(display);struct DisplayInfo {
uint32_t width; // Screen width
uint32_t height; // Screen height
uint32_t refresh_rate; // Refresh Rate in mHz
uint32_t scale; // DPI scaling (100 = 1.0x)
char name[64]; // Display name
};
DisplayInfo info;
sys_ioctl(display, DISPLAY_GET_INFO, &info);A Surface is a drawing area (window):
- Has a Shared Memory Buffer
- Can be rendered by the Compositor
- Receives Input Events
// Create Surface (window)
handle_t surface = sys_surface_create(display, 800, 600, PIXEL_FORMAT_BGRA);
// Set Surface attributes
SurfaceAttribs attribs = {
.title = "My Application",
.type = SURFACE_TYPE_NORMAL,
.min_width = 200,
.min_height = 150,
.max_width = 4096,
.max_height = 4096,
};
sys_ioctl(surface, SURFACE_SET_ATTRIBS, &attribs);typedef enum {
SURFACE_TYPE_NORMAL = 0, // Normal window
SURFACE_TYPE_DIALOG = 1, // Dialog (modal)
SURFACE_TYPE_POPUP = 2, // Popup menu
SURFACE_TYPE_TOOLTIP = 3, // Tooltip
SURFACE_TYPE_DOCK = 4, // Taskbar/Dock
SURFACE_TYPE_DESKTOP = 5, // Desktop background
SURFACE_TYPE_SPLASH = 6, // Splash Screen
} SurfaceType;typedef enum {
PIXEL_FORMAT_BGRA = 0, // 32-bit BGRA (Default)
PIXEL_FORMAT_RGBA = 1, // 32-bit RGBA
PIXEL_FORMAT_RGB = 2, // 24-bit RGB
PIXEL_FORMAT_GRAY = 3, // 8-bit Grayscale
} PixelFormat;void *buffer;
int stride; // Bytes per row
sys_surface_buffer(surface, &buffer, &stride);
// Buffer is now directly writable
// Format: BGRA, Pixel[y * stride/4 + x]// Create Surface with Double Buffering
handle_t surface = sys_surface_create(display, 800, 600,
PIXEL_FORMAT_BGRA | SURFACE_FLAG_DOUBLE_BUFFER);
// Swap Front/Back Buffer
sys_ioctl(surface, SURFACE_SWAP_BUFFERS, NULL);// Report changed region
Rect damage = { .x = 10, .y = 20, .width = 100, .height = 50 };
sys_ioctl(surface, SURFACE_DAMAGE, &damage);
// Multiple Regions
Rect damages[3] = { ... };
sys_ioctl(surface, SURFACE_DAMAGE_MULTI, &(struct { int count; Rect *rects; }){ 3, damages });
// Commit and display frame
sys_surface_commit(surface, 0, 0, 800, 600); // Entire Surfacetypedef struct {
uint32_t type; // Message type
uint32_t size; // Total size
uint32_t surface; // Surface ID (or 0)
uint32_t seq; // Sequence number
uint8_t data[]; // Type-specific data
} Message;| Type | Name | Description |
|---|---|---|
| 0x0001 | MSG_SURFACE_CREATE |
Create Surface |
| 0x0002 | MSG_SURFACE_DESTROY |
Destroy Surface |
| 0x0003 | MSG_SURFACE_ATTACH |
Attach Buffer |
| 0x0004 | MSG_SURFACE_DAMAGE |
Changed Region |
| 0x0005 | MSG_SURFACE_COMMIT |
Frame ready |
| 0x0006 | MSG_SURFACE_SET_TITLE |
Set title |
| 0x0007 | MSG_SURFACE_SET_TYPE |
Set window type |
| 0x0008 | MSG_SURFACE_RESIZE |
Request resize |
| 0x0009 | MSG_SURFACE_MOVE |
Request move |
| 0x000A | MSG_SURFACE_MINIMIZE |
Minimize |
| 0x000B | MSG_SURFACE_MAXIMIZE |
Maximize |
| 0x000C | MSG_SURFACE_CLOSE |
Request close |
| Type | Name | Description |
|---|---|---|
| 0x1001 | MSG_CONFIGURE |
Size/Position changed |
| 0x1002 | MSG_CLOSE |
Window should close |
| 0x1003 | MSG_FOCUS |
Focus gained/lost |
| 0x1004 | MSG_FRAME |
VSync/Frame Callback |
| 0x2001 | MSG_KEY_DOWN |
Key pressed |
| 0x2002 | MSG_KEY_UP |
Key released |
| 0x2003 | MSG_KEY_REPEAT |
Key repeated |
| 0x2004 | MSG_TEXT_INPUT |
Text input (UTF-8) |
| 0x3001 | MSG_MOUSE_MOVE |
Mouse movement |
| 0x3002 | MSG_MOUSE_BUTTON |
Mouse button |
| 0x3003 | MSG_MOUSE_SCROLL |
Mouse wheel |
| 0x3004 | MSG_MOUSE_ENTER |
Mouse enters Surface |
| 0x3005 | MSG_MOUSE_LEAVE |
Mouse leaves Surface |
typedef struct {
uint32_t type; // Event type
uint32_t time; // Timestamp (ms)
uint32_t surface; // Target Surface
union {
KeyEvent key;
MouseEvent mouse;
TextEvent text;
ConfigureEvent configure;
FocusEvent focus;
};
} InputEvent;typedef struct {
uint32_t keycode; // Physical Keycode
uint32_t keysym; // Logical Key Symbol
uint32_t modifiers; // Modifier flags
uint32_t state; // KEY_PRESSED / KEY_RELEASED
} KeyEvent;
// Modifier Flags
#define MOD_SHIFT 0x0001
#define MOD_CTRL 0x0002
#define MOD_ALT 0x0004
#define MOD_SUPER 0x0008 // Windows/Meta
#define MOD_CAPS_LOCK 0x0010
#define MOD_NUM_LOCK 0x0020typedef struct {
int32_t x, y; // Position relative to Surface
int32_t dx, dy; // Delta since last event
uint32_t buttons; // Button status
int32_t scroll_x; // Horizontal scroll
int32_t scroll_y; // Vertical scroll
} MouseEvent;
// Button Flags
#define BUTTON_LEFT 0x0001
#define BUTTON_RIGHT 0x0002
#define BUTTON_MIDDLE 0x0004
#define BUTTON_X1 0x0008
#define BUTTON_X2 0x0010typedef struct {
char text[32]; // UTF-8 encoded text
uint32_t length; // Byte length
} TextEvent;// Blocking wait
InputEvent events[16];
int count = sys_input_poll(display, events, 16);
// Non-blocking
sys_ioctl(display, DISPLAY_SET_NONBLOCK, (void*)1);
count = sys_input_poll(display, events, 16);
// count == 0 if no events
// With poll()
struct pollfd pfd = { .fd = display, .events = POLLIN };
sys_poll(&pfd, 1, timeout_ms);
if (pfd.revents & POLLIN) {
count = sys_input_poll(display, events, 16);
}The Compositor sends MSG_CONFIGURE on:
- Window size changed
- Window moved
- Window maximized/minimized
- State changes
typedef struct {
int32_t x, y; // New position (or -1)
uint32_t width, height; // New size
uint32_t states; // State Flags
} ConfigureEvent;
// State Flags
#define STATE_MAXIMIZED 0x0001
#define STATE_MINIMIZED 0x0002
#define STATE_FULLSCREEN 0x0004
#define STATE_FOCUSED 0x0008
#define STATE_RESIZING 0x0010After MSG_CONFIGURE the app must:
- Adjust buffer (if size changed)
- Redraw
- Commit with new size
void handle_configure(ConfigureEvent *cfg) {
if (cfg->width != current_width || cfg->height != current_height) {
// Reallocate buffer
resize_buffer(cfg->width, cfg->height);
// Redraw
redraw();
// Commit
sys_surface_commit(surface, 0, 0, cfg->width, cfg->height);
}
}ASSUMPTION: Client-Side Decorations (CSD)
Applications draw their own title bar:
void draw_decorations(Surface *s) {
// Title bar (30px high)
draw_rect(s, 0, 0, s->width, 30, COLOR_TITLEBAR);
// Title
draw_text(s, 10, 5, s->title, COLOR_WHITE);
// Buttons
draw_close_button(s, s->width - 30, 0);
draw_maximize_button(s, s->width - 60, 0);
draw_minimize_button(s, s->width - 90, 0);
}typedef enum {
HIT_NONE = 0,
HIT_CLIENT = 1,
HIT_TITLEBAR = 2,
HIT_CLOSE = 3,
HIT_MAXIMIZE = 4,
HIT_MINIMIZE = 5,
HIT_RESIZE_N = 6,
HIT_RESIZE_E = 7,
HIT_RESIZE_S = 8,
HIT_RESIZE_W = 9,
HIT_RESIZE_NE = 10,
HIT_RESIZE_SE = 11,
HIT_RESIZE_SW = 12,
HIT_RESIZE_NW = 13,
} HitArea;
HitArea hit_test(int x, int y, int width, int height) {
const int BORDER = 5;
const int TITLE_HEIGHT = 30;
// Resize areas
if (y < BORDER) {
if (x < BORDER) return HIT_RESIZE_NW;
if (x > width - BORDER) return HIT_RESIZE_NE;
return HIT_RESIZE_N;
}
// ... other areas
// Title bar
if (y < TITLE_HEIGHT) {
if (x > width - 30) return HIT_CLOSE;
if (x > width - 60) return HIT_MAXIMIZE;
if (x > width - 90) return HIT_MINIMIZE;
return HIT_TITLEBAR;
}
return HIT_CLIENT;
}typedef enum {
CURSOR_ARROW = 0,
CURSOR_TEXT = 1,
CURSOR_WAIT = 2,
CURSOR_CROSS = 3,
CURSOR_HAND = 4,
CURSOR_RESIZE_H = 5,
CURSOR_RESIZE_V = 6,
CURSOR_RESIZE_DIAG1 = 7,
CURSOR_RESIZE_DIAG2 = 8,
CURSOR_MOVE = 9,
CURSOR_NOT_ALLOWED = 10,
CURSOR_HIDDEN = 11,
} CursorType;
sys_ioctl(surface, SURFACE_SET_CURSOR, (void*)CURSOR_TEXT);typedef struct {
void *pixels; // 32x32 BGRA
int32_t hotspot_x; // Hotspot X
int32_t hotspot_y; // Hotspot Y
} CustomCursor;
CustomCursor cursor = { ... };
sys_ioctl(surface, SURFACE_SET_CUSTOM_CURSOR, &cursor);// Copy text
const char *text = "Hello, World!";
sys_ioctl(display, CLIPBOARD_SET_TEXT, text);
// Paste text
char buffer[4096];
ssize_t len = sys_ioctl(display, CLIPBOARD_GET_TEXT, buffer);typedef struct {
uint32_t width, height;
uint32_t format; // PIXEL_FORMAT_*
void *data;
} ClipboardImage;
// Copy image
ClipboardImage img = { 100, 100, PIXEL_FORMAT_BGRA, pixels };
sys_ioctl(display, CLIPBOARD_SET_IMAGE, &img);
// Paste image
ClipboardImage img;
sys_ioctl(display, CLIPBOARD_GET_IMAGE, &img);// On Mouse-Down + Movement
typedef struct {
char mime_type[64]; // e.g. "text/uri-list"
void *data;
size_t length;
} DragData;
DragData drag = {
.mime_type = "text/uri-list",
.data = "file:///path/to/file\n",
.length = 22
};
sys_ioctl(surface, DRAG_START, &drag);// Event: MSG_DRAG_ENTER, MSG_DRAG_MOTION, MSG_DRAG_LEAVE, MSG_DRAG_DROP
void handle_drag_drop(DragDropEvent *evt) {
if (evt->type == MSG_DRAG_DROP) {
// Request data
char buffer[4096];
ssize_t len = sys_ioctl(display, DRAG_GET_DATA, buffer);
// Parse URI list
parse_uri_list(buffer, len);
}
}Only redraw changed areas:
typedef struct {
Rect dirty_rects[32];
int count;
} DirtyRegion;
void mark_dirty(DirtyRegion *r, int x, int y, int w, int h) {
if (r->count < 32) {
r->dirty_rects[r->count++] = (Rect){ x, y, w, h };
}
}
void commit_dirty(handle_t surface, DirtyRegion *r) {
for (int i = 0; i < r->count; i++) {
Rect *d = &r->dirty_rects[i];
sys_surface_commit(surface, d->x, d->y, d->width, d->height);
}
r->count = 0;
}// Enable VSync
sys_ioctl(surface, SURFACE_SET_VSYNC, (void*)1);
// Frame Callback
// After commit() Compositor sends MSG_FRAME when ready for next framevoid animation_loop(void) {
while (running) {
// Process events
InputEvent events[16];
int count = sys_input_poll(display, events, 16);
for (int i = 0; i < count; i++) {
handle_event(&events[i]);
}
// Update animation
update_animation();
// Draw
render();
// Commit and wait for VSync
sys_surface_commit(surface, 0, 0, width, height);
wait_for_frame_callback();
}
}GUI Protocol v1 - PromptOS