Overview

DWN v2.0 introduces a comprehensive abstraction layer that separates the window manager logic from backend-specific implementations. This architecture enables:

  • Backend Portability - Clean migration path from X11 to Wayland
  • Type Safety - Strongly typed handles eliminate void* casting
  • Memory Safety - Abstract strings and containers prevent buffer overflows
  • Plugin Extensibility - Dynamic loading of layouts and widgets
  • 100% Compatibility - Existing code continues to work unchanged

Core Types

The abstraction layer provides type-safe replacements for backend-specific types:

Abstract Type X11 Equivalent Description
WmWindowHandle Window Opaque window reference
WmClientId - Unique client identifier
WmWorkspaceId int Workspace identifier
WmRect - Rectangle geometry (x, y, w, h)
WmColor unsigned long RGBA color value

Geometry Operations

Inline functions for rectangle operations:

WmRect rect = wm_rect_make(0, 0, 1920, 1080);
bool contains = wm_rect_contains_point(&rect, 100, 100);
bool intersects = wm_rect_intersects(&rect1, &rect2);
WmRect intersection = wm_rect_intersection(&rect1, &rect2);

Color Operations

WmColor color = wm_color_rgb(255, 0, 128);        // RGB
WmColor color = wm_color_rgba(255, 0, 128, 200);  // RGBA
uint8_t r = wm_color_get_red(color);
uint8_t a = wm_color_get_alpha(color);

Backend Interface

The backend interface defines a vtable of operations that any backend must implement:

typedef struct BackendInterface {
    /* Identification */
    const char *name;
    WmBackendInfo (*get_info)(void);
    
    /* Lifecycle */
    bool (*init)(void *config);
    void (*shutdown)(void);
    
    /* Window Management */
    void (*window_move)(WmWindowHandle window, int x, int y);
    void (*window_resize)(WmWindowHandle window, int width, int height);
    void (*window_focus)(WmWindowHandle window);
    
    /* Events */
    bool (*poll_event)(WmBackendEvent *event_out);
    
    /* ... 80+ operations */
} BackendInterface;

X11 Backend

The X11 backend is the reference implementation, translating abstract operations to X11 calls:

  • Event translation (X11 → abstract events)
  • Protocol support (ICCCM, EWMH)
  • Property management with atom caching
  • Error handling with custom handlers

Future Backends

The architecture supports multiple backends:

  • X11 - Current, fully implemented
  • Wayland - Planned for future
  • Headless - For testing and CI

Client Abstraction

The AbstractClient type provides a backend-agnostic representation of a managed window:

/* Create from native window */
AbstractClient* client = wm_client_create(window, WM_CLIENT_TYPE_NORMAL);

/* State management */
wm_client_set_state(client, WM_CLIENT_STATE_FULLSCREEN);
wm_client_add_state(client, WM_CLIENT_STATE_FLOATING);
bool is_floating = wm_client_is_floating(client);

/* Geometry */
WmRect geom = wm_client_get_geometry(client);
wm_client_set_geometry(client, &new_geom);
wm_client_move_resize(client, x, y, width, height);

/* Properties */
wm_client_set_title(client, "New Title");
const char* title = wm_client_get_title(client);

Legacy Compatibility

Abstract clients maintain bidirectional synchronization with legacy Client structures:

/* Wrap existing legacy client */
AbstractClient* abs_client = wm_client_from_legacy(legacy_client);

/* Access legacy client when needed */
Client* legacy = wm_client_get_legacy(abs_client);

Container Types

Safe, dynamic container implementations:

WmString (Dynamic Strings)

WmString* str = wm_string_new("Hello");
wm_string_append(str, " World");
wm_string_append_printf(str, " %d", 42);

const char* cstr = wm_string_cstr(str);
bool empty = wm_string_is_empty(str);

wm_string_destroy(str);

WmList (Dynamic Arrays)

WmList* list = wm_list_new();
wm_list_append(list, item1);
wm_list_prepend(list, item2);

void* item = wm_list_get(list, 0);
wm_list_foreach(list, my_callback, user_data);

wm_list_destroy(list);

WmHashMap

WmHashMap* map = wm_hashmap_new_string_key();
wm_hashmap_insert_string(map, "key", value);

void* value = wm_hashmap_get_string(map, "key");
bool exists = wm_hashmap_contains_string(map, "key");

wm_hashmap_destroy(map);

Migration Strategy

The abstraction layer uses an incremental migration approach:

  1. Phase 1: Infrastructure (Complete)
    • Core types defined
    • Backend interface specified
    • X11 backend implemented
  2. Phase 2: Client Migration (Complete)
    • AbstractClient type created
    • Bidirectional sync with legacy Client
    • Client manager with MRU tracking
  3. Phase 3: Plugin System (Complete)
    • Layout plugin API
    • Widget plugin API
    • 4 built-in layout plugins
  4. Phase 4: Future
    • Gradual migration of existing code
    • Wayland backend implementation
    • Legacy code deprecation (long-term)
Note: The abstraction layer is fully backward compatible. Existing code using X11 types continues to work unchanged.