diff options
Diffstat (limited to 'legacy-cpp/docs/PLATFORM_IMPLEMENTATION.md')
| -rw-r--r-- | legacy-cpp/docs/PLATFORM_IMPLEMENTATION.md | 636 |
1 files changed, 0 insertions, 636 deletions
diff --git a/legacy-cpp/docs/PLATFORM_IMPLEMENTATION.md b/legacy-cpp/docs/PLATFORM_IMPLEMENTATION.md deleted file mode 100644 index 4e70767..0000000 --- a/legacy-cpp/docs/PLATFORM_IMPLEMENTATION.md +++ /dev/null @@ -1,636 +0,0 @@ -# SRDWM Platform Implementation Guide - -## Overview -This document outlines the proper implementation approach for each platform, recognizing that **Wayland/XWayland is fundamentally different from X11** and requires completely different technologies and approaches. - -## Platform Architecture Differences - -### Linux: X11 vs Wayland -- **X11**: Traditional X11 window management with Xlib/XCB -- **Wayland**: Modern display protocol requiring wlroots or similar compositor framework -- **XWayland**: X11 applications running on Wayland (requires special handling) - -### Windows vs macOS vs Linux -- **Windows**: Win32 API with global hooks and window subclassing -- **macOS**: Core Graphics/AppKit with accessibility APIs and event taps -- **Linux**: X11 or Wayland with different event systems - -## Linux Implementation - -### X11 Backend -```cpp -// X11-specific implementation using Xlib/XCB -class X11Platform : public Platform { -private: - Display* display_; - Window root_; - std::map<Window, Window*> window_map_; - -public: - bool initialize() override { - display_ = XOpenDisplay(nullptr); - if (!display_) return false; - - root_ = DefaultRootWindow(display_); - setup_event_handling(); - return true; - } - - void setup_event_handling() { - // X11 event masks and handlers - XSelectInput(display_, root_, - SubstructureRedirectMask | SubstructureNotifyMask | - KeyPressMask | KeyReleaseMask | - ButtonPressMask | ButtonReleaseMask | - PointerMotionMask); - } - - bool poll_events(std::vector<Event>& events) override { - XEvent xevent; - while (XPending(display_)) { - XNextEvent(display_, &xevent); - convert_x11_event(xevent, events); - } - return true; - } - - void convert_x11_event(const XEvent& xevent, std::vector<Event>& events) { - switch (xevent.type) { - case MapRequest: - handle_map_request(xevent.xmaprequest); - break; - case ConfigureRequest: - handle_configure_request(xevent.xconfigurerequest); - break; - case KeyPress: - handle_key_press(xevent.xkey); - break; - // ... other event types - } - } -}; -``` - -### Wayland Backend (using wlroots) -```cpp -// Wayland implementation using wlroots -class WaylandPlatform : public Platform { -private: - struct wl_display* display_; - struct wlroots_backend* backend_; - struct wlroots_compositor* compositor_; - struct wlroots_output* output_; - struct wlroots_input_device* input_device_; - -public: - bool initialize() override { - // Initialize wlroots backend - backend_ = wlroots_backend_create(); - if (!backend_) return false; - - // Create compositor - compositor_ = wlroots_compositor_create(backend_); - if (!compositor_) return false; - - // Setup output and input - setup_output(); - setup_input(); - - return true; - } - - void setup_output() { - // Create and configure output - output_ = wlroots_output_create(compositor_); - wlroots_output_set_mode(output_, 1920, 1080, 60); - wlroots_output_commit(output_); - } - - void setup_input() { - // Setup input devices - input_device_ = wlroots_input_device_create(compositor_); - wlroots_input_device_set_capabilities(input_device_, - WLROOTS_INPUT_DEVICE_CAP_KEYBOARD | - WLROOTS_INPUT_DEVICE_CAP_POINTER); - } - - bool poll_events(std::vector<Event>& events) override { - // wlroots event loop - wlroots_backend_dispatch(backend_); - - // Process wlroots events - struct wlroots_event* event; - while ((event = wlroots_backend_get_event(backend_))) { - convert_wlroots_event(event, events); - wlroots_event_destroy(event); - } - - return true; - } - - void convert_wlroots_event(struct wlroots_event* event, std::vector<Event>& events) { - switch (wlroots_event_get_type(event)) { - case WLROOTS_EVENT_NEW_SURFACE: - handle_new_surface(event); - break; - case WLROOTS_EVENT_SURFACE_COMMIT: - handle_surface_commit(event); - break; - case WLROOTS_EVENT_KEYBOARD_KEY: - handle_keyboard_key(event); - break; - // ... other event types - } - } -}; -``` - -### XWayland Support -```cpp -// XWayland support for running X11 apps on Wayland -class XWaylandManager { -private: - struct wlroots_xwayland* xwayland_; - struct wlroots_xwayland_server* xwayland_server_; - -public: - bool initialize(struct wlroots_compositor* compositor) { - // Create XWayland server - xwayland_server_ = wlroots_xwayland_server_create(compositor); - if (!xwayland_server_) return false; - - // Setup XWayland - xwayland_ = wlroots_xwayland_create(xwayland_server_); - if (!xwayland_) return false; - - return true; - } - - void handle_xwayland_surface(struct wlroots_surface* surface) { - // Handle X11 windows running on Wayland - // These need special treatment for proper integration - } -}; -``` - -## Windows Implementation - -### Win32 API Integration -```cpp -// Windows implementation using Win32 API -class WindowsPlatform : public Platform { -private: - HINSTANCE h_instance_; - std::map<HWND, Window*> window_map_; - HHOOK keyboard_hook_; - HHOOK mouse_hook_; - -public: - bool initialize() override { - h_instance_ = GetModuleHandle(nullptr); - - // Register window class - if (!register_window_class()) return false; - - // Setup global hooks - setup_global_hooks(); - - return true; - } - - bool register_window_class() { - WNDCLASSEX wc = {}; - wc.cbSize = sizeof(WNDCLASSEX); - wc.lpfnWndProc = window_proc; - wc.hInstance = h_instance_; - wc.lpszClassName = L"SRDWM_Window"; - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - - return RegisterClassEx(&wc) != 0; - } - - void setup_global_hooks() { - // Global keyboard hook - keyboard_hook_ = SetWindowsHookEx(WH_KEYBOARD_LL, - keyboard_proc, h_instance_, 0); - - // Global mouse hook - mouse_hook_ = SetWindowsHookEx(WH_MOUSE_LL, - mouse_proc, h_instance_, 0); - } - - static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, - WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_CREATE: - // Handle window creation - break; - case WM_DESTROY: - // Handle window destruction - break; - case WM_SIZE: - // Handle window resizing - break; - // ... other messages - } - return DefWindowProc(hwnd, msg, wparam, lparam); - } - - static LRESULT CALLBACK keyboard_proc(int nCode, WPARAM wparam, LPARAM lparam) { - if (nCode >= 0) { - KBDLLHOOKSTRUCT* kbhs = (KBDLLHOOKSTRUCT*)lparam; - // Handle global keyboard events - handle_global_keyboard(wparam, kbhs); - } - return CallNextHookEx(nullptr, nCode, wparam, lparam); - } - - static LRESULT CALLBACK mouse_proc(int nCode, WPARAM wparam, LPARAM lparam) { - if (nCode >= 0) { - MSLLHOOKSTRUCT* mhs = (MSLLHOOKSTRUCT*)lparam; - // Handle global mouse events - handle_global_mouse(wparam, mhs); - } - return CallNextHookEx(nullptr, nCode, wparam, lparam); - } -}; -``` - -## macOS Implementation - -### Core Graphics/AppKit Integration -```cpp -// macOS implementation using Core Graphics and AppKit -class MacOSPlatform : public Platform { -private: - CGEventTap event_tap_; - std::map<CGWindowID, Window*> window_map_; - -public: - bool initialize() override { - // Request accessibility permissions - if (!request_accessibility_permissions()) return false; - - // Setup event tap - setup_event_tap(); - - // Setup window monitoring - setup_window_monitoring(); - - return true; - } - - bool request_accessibility_permissions() { - // Check if accessibility is enabled - const void* keys[] = { kAXTrustedCheckOptionPrompt }; - const void* values[] = { kCFBooleanTrue }; - - CFDictionaryRef options = CFDictionaryCreate( - kCFAllocatorDefault, keys, values, 1, nullptr, nullptr); - - bool trusted = AXIsProcessTrustedWithOptions(options); - CFRelease(options); - - return trusted; - } - - void setup_event_tap() { - // Create event tap for global events - event_tap_ = CGEventTapCreate( - kCGSessionEventTap, - kCGHeadInsertEventTap, - kCGEventTapOptionDefault, - CGEventMaskBit(kCGEventKeyDown) | - CGEventMaskBit(kCGEventKeyUp) | - CGEventMaskBit(kCGEventLeftMouseDown) | - CGEventMaskBit(kCGEventLeftMouseUp) | - CGEventMaskBit(kCGEventMouseMoved), - event_tap_callback, - this); - - if (event_tap_) { - CFRunLoopSourceRef run_loop_source = - CFMachPortCreateRunLoopSource(kCFAllocatorDefault, event_tap_, 0); - CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source, kCFRunLoopCommonModes); - CGEventTapEnable(event_tap_, true); - } - } - - static CGEventRef event_tap_callback(CGEventTapProxy proxy, CGEventType type, - CGEventRef event, void* user_info) { - MacOSPlatform* platform = static_cast<MacOSPlatform*>(user_info); - return platform->handle_event_tap(proxy, type, event); - } - - CGEventRef handle_event_tap(CGEventTapProxy proxy, CGEventType type, CGEventRef event) { - switch (type) { - case kCGEventKeyDown: - handle_key_event(event, true); - break; - case kCGEventKeyUp: - handle_key_event(event, false); - break; - case kCGEventLeftMouseDown: - handle_mouse_event(event, true); - break; - case kCGEventLeftMouseUp: - handle_mouse_event(event, false); - break; - case kCGEventMouseMoved: - handle_mouse_motion(event); - break; - } - return event; - } - - void setup_window_monitoring() { - // Monitor window creation/destruction - CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | - kCGWindowListExcludeDesktopElements, - kCGNullWindowID); - } -}; -``` - -## Platform Detection and Selection - -### Automatic Platform Detection -```cpp -// Platform factory with automatic detection -class PlatformFactory { -public: - static std::unique_ptr<Platform> create_platform() { - #ifdef _WIN32 - return std::make_unique<WindowsPlatform>(); - #elif defined(__APPLE__) - return std::make_unique<MacOSPlatform>(); - #else - // Linux: detect X11 vs Wayland - return detect_linux_platform(); - #endif - } - -private: - static std::unique_ptr<Platform> detect_linux_platform() { - // Check environment variables - const char* wayland_display = std::getenv("WAYLAND_DISPLAY"); - const char* xdg_session_type = std::getenv("XDG_SESSION_TYPE"); - - if (wayland_display || (xdg_session_type && strcmp(xdg_session_type, "wayland") == 0)) { - // Try Wayland first - auto wayland_platform = std::make_unique<WaylandPlatform>(); - if (wayland_platform->initialize()) { - std::cout << "Using Wayland backend" << std::endl; - return wayland_platform; - } - std::cout << "Wayland initialization failed, falling back to X11" << std::endl; - } - - // Fall back to X11 - auto x11_platform = std::make_unique<X11Platform>(); - if (x11_platform->initialize()) { - std::cout << "Using X11 backend" << std::endl; - return x11_platform; - } - - std::cerr << "Failed to initialize any platform backend" << std::endl; - return nullptr; - } -}; -``` - -## Dependencies and Build System - -### CMake Configuration -```cmake -# Platform-specific dependencies -if(WIN32) - # Windows dependencies - find_package(PkgConfig REQUIRED) - set(PLATFORM_LIBS user32 gdi32) - -elseif(APPLE) - # macOS dependencies - find_library(COCOA_LIBRARY Cocoa) - find_library(CARBON_LIBRARY Carbon) - find_library(IOKIT_LIBRARY IOKit) - set(PLATFORM_LIBS ${COCOA_LIBRARY} ${CARBON_LIBRARY} ${IOKIT_LIBRARY}) - -else() - # Linux dependencies - find_package(PkgConfig REQUIRED) - - # X11 dependencies - pkg_check_modules(X11 REQUIRED x11 xcb xcb-keysyms) - - # Wayland dependencies (optional) - pkg_check_modules(WAYLAND wayland-client wayland-cursor) - pkg_check_modules(WLROOTS wlroots) - - if(WAYLAND_FOUND AND WLROOTS_FOUND) - add_definitions(-DWAYLAND_ENABLED) - set(PLATFORM_LIBS ${PLATFORM_LIBS} ${WAYLAND_LIBRARIES} ${WLROOTS_LIBRARIES}) - endif() - - set(PLATFORM_LIBS ${PLATFORM_LIBS} ${X11_LIBRARIES}) -endif() -``` - -### Package Dependencies -```bash -# Ubuntu/Debian -sudo apt install libx11-dev libxcb1-dev libxcb-keysyms1-dev -sudo apt install libwayland-dev libwlroots-dev - -# Arch Linux -sudo pacman -S xorg-server-devel wayland wlroots - -# Fedora -sudo dnf install libX11-devel libxcb-devel wayland-devel wlroots-devel -``` - -## Event Handling Differences - -### X11 Event System -```cpp -// X11 events are synchronous and direct -void X11Platform::handle_map_request(const XMapRequestEvent& event) { - Window* window = create_window(event.window); - if (window) { - window_map_[event.window] = window; - // X11 window is now managed - } -} -``` - -### Wayland Event System -```cpp -// Wayland events are asynchronous and callback-based -void WaylandPlatform::handle_new_surface(struct wlroots_event* event) { - struct wlroots_surface* surface = wlroots_event_get_surface(event); - - // Create window for new surface - Window* window = create_window_from_surface(surface); - if (window) { - surface_window_map_[surface] = window; - } -} -``` - -### Windows Event System -```cpp -// Windows uses message-based event system -LRESULT WindowsPlatform::window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { - switch (msg) { - case WM_CREATE: - // Window creation - break; - case WM_DESTROY: - // Window destruction - break; - } - return DefWindowProc(hwnd, msg, wparam, lparam); -} -``` - -### macOS Event System -```cpp -// macOS uses event taps and accessibility APIs -CGEventRef MacOSPlatform::handle_event_tap(CGEventTapProxy proxy, CGEventType type, CGEventRef event) { - switch (type) { - case kCGEventKeyDown: - // Handle key press - break; - case kCGEventMouseMoved: - // Handle mouse movement - break; - } - return event; -} -``` - -## Window Management Differences - -### X11 Window Management -```cpp -// X11: Direct window manipulation -void X11Platform::set_window_position(Window* window, int x, int y) { - XMoveWindow(display_, window->get_x11_handle(), x, y); -} - -void X11Platform::set_window_size(Window* window, int width, int height) { - XResizeWindow(display_, window->get_x11_handle(), width, height); -} -``` - -### Wayland Window Management -```cpp -// Wayland: Surface-based management -void WaylandPlatform::set_window_position(Window* window, int x, int y) { - struct wlroots_surface* surface = window->get_wayland_surface(); - wlroots_surface_set_position(surface, x, y); -} - -void WaylandPlatform::set_window_size(Window* window, int width, int height) { - struct wlroots_surface* surface = window->get_wayland_surface(); - wlroots_surface_set_size(surface, width, height); -} -``` - -### Windows Window Management -```cpp -// Windows: Win32 API calls -void WindowsPlatform::set_window_position(Window* window, int x, int y) { - HWND hwnd = window->get_win32_handle(); - SetWindowPos(hwnd, nullptr, x, y, 0, 0, - SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); -} - -void WindowsPlatform::set_window_size(Window* window, int width, int height) { - HWND hwnd = window->get_win32_handle(); - SetWindowPos(hwnd, nullptr, 0, 0, width, height, - SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); -} -``` - -### macOS Window Management -```cpp -// macOS: Core Graphics API calls -void MacOSPlatform::set_window_position(Window* window, int x, int y) { - CGWindowID window_id = window->get_macos_window_id(); - CGPoint position = CGPointMake(x, y); - - // Use accessibility APIs to move window - AXUIElementRef element = AXUIElementCreateApplication( - window->get_macos_pid()); - - if (element) { - AXUIElementSetAttributeValue(element, kAXPositionAttribute, &position); - CFRelease(element); - } -} -``` - -## Testing and Validation - -### Platform-Specific Testing -```cpp -// Test each platform independently -class PlatformTest { -public: - static void test_x11_platform() { - auto platform = std::make_unique<X11Platform>(); - assert(platform->initialize()); - // Test X11-specific functionality - } - - static void test_wayland_platform() { - auto platform = std::make_unique<WaylandPlatform>(); - assert(platform->initialize()); - // Test Wayland-specific functionality - } - - static void test_windows_platform() { - auto platform = std::make_unique<WindowsPlatform>(); - assert(platform->initialize()); - // Test Windows-specific functionality - } - - static void test_macos_platform() { - auto platform = std::make_unique<MacOSPlatform>(); - assert(platform->initialize()); - // Test macOS-specific functionality - } -}; -``` - -## Best Practices - -### 1. **Platform Abstraction** -- Keep platform-specific code isolated -- Use common interfaces for cross-platform functionality -- Implement platform detection automatically - -### 2. **Wayland vs X11** -- **Never mix X11 and Wayland APIs** -- Use wlroots for Wayland (don't implement from scratch) -- Handle XWayland as a special case within Wayland - -### 3. **Event Handling** -- Respect each platform's event model -- Don't force synchronous behavior on asynchronous platforms -- Handle platform-specific quirks gracefully - -### 4. **Window Management** -- Use platform-native APIs for best performance -- Don't try to emulate one platform's behavior on another -- Handle platform-specific window states properly - -### 5. **Testing** -- Test each platform independently -- Use CI/CD with multiple platform targets -- Validate platform-specific features thoroughly - -This implementation approach ensures that SRDWM works correctly on each platform while respecting the fundamental differences between X11, Wayland, Windows, and macOS. - - |