Skip to content

Latest commit

 

History

History
590 lines (463 loc) · 14.2 KB

File metadata and controls

590 lines (463 loc) · 14.2 KB

PromptOS GUI Protocol v1

Version: 1.0
Status: Draft
Codename: Aurora Display Protocol


1. Overview

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)               │
└──────────────────────────────────────────────────────────────┘

2. Connection

2.1 Display Handle

// Connect to Compositor
handle_t display = sys_display_connect(NULL);  // Default Display
if (display < 0) {
    // Error
}

// Disconnect
sys_close(display);

2.2 Display Info

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);

3. Surfaces

3.1 Concept

A Surface is a drawing area (window):

  • Has a Shared Memory Buffer
  • Can be rendered by the Compositor
  • Receives Input Events

3.2 Creation

// 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);

3.3 Surface Types

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;

3.4 Pixel Formats

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;

4. Buffer Management

4.1 Get Buffer

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]

4.2 Double Buffering

// 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);

4.3 Damage Tracking

// 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 Surface

5. Message Protocol

5.1 Message Format

typedef 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;

5.2 Client → Compositor

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

5.3 Compositor → Client

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

6. Input Events

6.1 Event Structure

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;

6.2 Keyboard Events

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    0x0020

6.3 Mouse Events

typedef 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       0x0010

6.4 Text Input

typedef struct {
    char        text[32];   // UTF-8 encoded text
    uint32_t    length;     // Byte length
} TextEvent;

6.5 Reading Events

// 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);
}

7. Window Management

7.1 Configure Events

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      0x0010

7.2 Configure Acknowledge

After MSG_CONFIGURE the app must:

  1. Adjust buffer (if size changed)
  2. Redraw
  3. 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);
    }
}

7.3 Window Decorations

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);
}

7.4 Hit Testing

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;
}

8. Cursor

8.1 Set Cursor

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);

8.2 Custom Cursor

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);

9. Clipboard

9.1 Text Clipboard

// 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);

9.2 Image Clipboard

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);

10. Drag & Drop

10.1 Start Drag

// 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);

10.2 Receive Drop

// 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);
    }
}

11. Rendering Tips

11.1 Dirty Rectangles

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;
}

11.2 VSync

// Enable VSync
sys_ioctl(surface, SURFACE_SET_VSYNC, (void*)1);

// Frame Callback
// After commit() Compositor sends MSG_FRAME when ready for next frame

11.3 Animation Loop

void 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