aboutsummaryrefslogtreecommitdiff
path: root/src/platform
diff options
context:
space:
mode:
authorsrdusr <trevorgray@srdusr.com>2025-09-26 12:23:19 +0200
committersrdusr <trevorgray@srdusr.com>2025-09-26 12:23:19 +0200
commite4a0432383331e013808a97b7c24707e4ddc4726 (patch)
tree3ef4465be03bc7b92a0b048f02f76475045404b6 /src/platform
parent105732dde10b317a81d5a10a3f66b315d6f85015 (diff)
downloadsrdwm-e4a0432383331e013808a97b7c24707e4ddc4726.tar.gz
srdwm-e4a0432383331e013808a97b7c24707e4ddc4726.zip
Initial Commit
Diffstat (limited to 'src/platform')
-rw-r--r--src/platform/linux_platform.h105
-rw-r--r--src/platform/macos_platform.cc480
-rw-r--r--src/platform/macos_platform.h118
-rw-r--r--src/platform/platform.h91
-rw-r--r--src/platform/platform_factory.cc214
-rw-r--r--src/platform/platform_factory.h37
-rw-r--r--src/platform/wayland_platform.cc507
-rw-r--r--src/platform/wayland_platform.h227
-rw-r--r--src/platform/wayland_platform_stub.cc114
-rw-r--r--src/platform/windows_platform.cc585
-rw-r--r--src/platform/windows_platform.h140
-rw-r--r--src/platform/x11_platform.cc1005
-rw-r--r--src/platform/x11_platform.h210
13 files changed, 3833 insertions, 0 deletions
diff --git a/src/platform/linux_platform.h b/src/platform/linux_platform.h
new file mode 100644
index 0000000..1237c85
--- /dev/null
+++ b/src/platform/linux_platform.h
@@ -0,0 +1,105 @@
+#ifndef SRDWM_LINUX_PLATFORM_H
+#define SRDWM_LINUX_PLATFORM_H
+
+#include "platform.h"
+#include <memory>
+#include <string>
+
+// Forward declarations for X11
+#ifdef __linux__
+struct _XDisplay;
+typedef struct _XDisplay Display;
+typedef unsigned long SRDWindow;
+typedef unsigned long Atom;
+
+// Forward declarations for Wayland
+struct wl_display;
+struct wl_registry;
+struct wl_compositor;
+struct wl_shell;
+struct wl_seat;
+struct wl_keyboard;
+struct wl_pointer;
+#endif
+
+class LinuxPlatform : public Platform {
+public:
+ enum class Backend {
+ Auto,
+ X11,
+ Wayland
+ };
+
+ explicit LinuxPlatform(Backend backend = Backend::Auto);
+ ~LinuxPlatform() override;
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ std::string get_platform_name() const override;
+ bool is_wayland() const override;
+ bool is_x11() const override;
+ bool is_windows() const override;
+ bool is_macos() const override;
+
+private:
+ Backend backend_;
+ bool initialized_;
+
+ // X11 specific members
+ Display* x11_display_;
+ SRDWindow x11_root_;
+ Atom x11_wm_delete_window_;
+ Atom x11_wm_protocols_;
+
+ // Wayland specific members
+ wl_display* wayland_display_;
+ wl_registry* wayland_registry_;
+ wl_compositor* wayland_compositor_;
+ wl_shell* wayland_shell_;
+ wl_seat* wayland_seat_;
+ wl_keyboard* wayland_keyboard_;
+ wl_pointer* wayland_pointer_;
+
+ // Common members
+ std::vector<Monitor> monitors_;
+
+ // Private methods
+ bool initialize_x11();
+ bool initialize_wayland();
+ void shutdown_x11();
+ void shutdown_wayland();
+
+ bool detect_backend();
+ void setup_x11_atoms();
+ void setup_wayland_registry();
+
+ // Event processing
+ void process_x11_event(XEvent& event, std::vector<Event>& events);
+ void process_wayland_event(wl_display* display, std::vector<Event>& events);
+};
+
+#endif // SRDWM_LINUX_PLATFORM_H
+
diff --git a/src/platform/macos_platform.cc b/src/platform/macos_platform.cc
new file mode 100644
index 0000000..d489cb7
--- /dev/null
+++ b/src/platform/macos_platform.cc
@@ -0,0 +1,480 @@
+#include "macos_platform.h"
+#include <iostream>
+#include <CoreGraphics/CoreGraphics.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <Carbon/Carbon.h>
+
+// Static member initialization
+MacOSPlatform* MacOSPlatform::instance_ = nullptr;
+
+MacOSPlatform::MacOSPlatform()
+ : event_tap_(nullptr) {
+
+ instance_ = this;
+}
+
+MacOSPlatform::~MacOSPlatform() {
+ shutdown();
+ if (instance_ == this) {
+ instance_ = nullptr;
+ }
+}
+
+bool MacOSPlatform::initialize() {
+ std::cout << "Initializing macOS platform..." << std::endl;
+
+ // Request accessibility permissions
+ if (!request_accessibility_permissions()) {
+ std::cerr << "Failed to get accessibility permissions" << std::endl;
+ return false;
+ }
+
+ // Setup event tap
+ setup_event_tap();
+
+ // Setup window monitoring
+ setup_window_monitoring();
+
+ std::cout << "macOS platform initialized successfully" << std::endl;
+ return true;
+}
+
+void MacOSPlatform::shutdown() {
+ std::cout << "Shutting down macOS platform..." << std::endl;
+
+ // Clean up event tap
+ if (event_tap_) {
+ CGEventTapEnable(event_tap_, false);
+ CFRelease(event_tap_);
+ event_tap_ = nullptr;
+ }
+
+ // Clean up windows
+ for (auto& pair : window_map_) {
+ if (pair.second) {
+ delete pair.second;
+ }
+ }
+ window_map_.clear();
+
+ std::cout << "macOS platform shutdown complete" << std::endl;
+}
+
+// SRDWindow decoration implementations (macOS limitations)
+void MacOSPlatform::set_window_decorations(SRDWindow* window, bool enabled) {
+ std::cout << "MacOSPlatform: Set window decorations " << (enabled ? "enabled" : "disabled") << std::endl;
+
+ if (!window) return;
+
+ decorations_enabled_ = enabled;
+
+ // macOS doesn't support custom window decorations like other platforms
+ // We can only work with native window properties
+ // For now, we'll just log the request
+
+ // TODO: Implement using accessibility APIs to modify window properties
+ // This would involve using AXUIElementRef to modify window attributes
+ std::cout << "Decoration state set to: " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+void MacOSPlatform::set_window_border_color(SRDWindow* window, int r, int g, int b) {
+ std::cout << "MacOSPlatform: Set border color RGB(" << r << "," << g << "," << b << ")" << std::endl;
+
+ if (!window) return;
+
+ // macOS doesn't support custom border colors through public APIs
+ // This would require private APIs or overlay windows
+ // For now, we'll just log the request
+
+ // TODO: Implement using private APIs or overlay windows
+ // This could involve:
+ // 1. Creating transparent overlay windows around the target window
+ // 2. Using private Core Graphics APIs (not recommended for production)
+ // 3. Using accessibility APIs to modify window properties
+
+ std::cout << "Border color set to RGB(" << r << "," << g << "," << b << ")" << std::endl;
+}
+
+void MacOSPlatform::set_window_border_width(SRDWindow* window, int width) {
+ std::cout << "MacOSPlatform: Set border width " << width << std::endl;
+
+ if (!window) return;
+
+ // macOS doesn't support custom border widths through public APIs
+ // This would require private APIs or overlay windows
+ // For now, we'll just log the request
+
+ // TODO: Implement using private APIs or overlay windows
+ // This could involve:
+ // 1. Creating transparent overlay windows around the target window
+ // 2. Using private Core Graphics APIs (not recommended for production)
+ // 3. Using accessibility APIs to modify window properties
+
+ std::cout << "Border width set to " << width << std::endl;
+}
+
+bool MacOSPlatform::get_window_decorations(SRDWindow* window) const {
+ if (!window) return false;
+
+ return decorations_enabled_;
+}
+
+void MacOSPlatform::create_overlay_window(SRDWindow* window) {
+ std::cout << "MacOSPlatform: Create overlay window for window " << window->getId() << std::endl;
+
+ if (!window) return;
+
+ // TODO: Implement overlay window creation for custom decorations
+ // This would involve:
+ // 1. Creating a transparent window using Core Graphics
+ // 2. Positioning it over the target window
+ // 3. Drawing custom borders/titlebar on it
+ // 4. Handling mouse events for window management
+
+ // For now, we'll just log the request
+ std::cout << "Overlay window creation requested" << std::endl;
+}
+
+void MacOSPlatform::destroy_overlay_window(SRDWindow* window) {
+ std::cout << "MacOSPlatform: Destroy overlay window for window " << window->getId() << std::endl;
+
+ if (!window) return;
+
+ // TODO: Implement overlay window destruction
+ // This would involve:
+ // 1. Finding the overlay window for this window
+ // 2. Destroying the overlay window
+ // 3. Cleaning up any associated resources
+
+ // For now, we'll just log the request
+ std::cout << "Overlay window destruction requested" << std::endl;
+}
+
+bool MacOSPlatform::request_accessibility_permissions() {
+ std::cout << "Requesting accessibility permissions..." << std::endl;
+
+ // 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);
+
+ if (trusted) {
+ std::cout << "Accessibility permissions granted" << std::endl;
+ } else {
+ std::cout << "Accessibility permissions denied" << std::endl;
+ }
+
+ return trusted;
+}
+
+void MacOSPlatform::setup_event_tap() {
+ std::cout << "Setting up event tap..." << std::endl;
+
+ // Create event tap for global events
+ event_tap_ = CGEventTapCreate(
+ kCGSessionEventTap,
+ kCGHeadInsertEventTap,
+ kCGEventTapOptionDefault,
+ CGEventMaskBit(kCGEventKeyDown) |
+ CGEventMaskBit(kCGEventKeyUp) |
+ CGEventMaskBit(kCGEventLeftMouseDown) |
+ CGEventMaskBit(kCGEventLeftMouseUp) |
+ CGEventMaskBit(kCGEventRightMouseDown) |
+ CGEventMaskBit(kCGEventRightMouseUp) |
+ 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);
+
+ std::cout << "Event tap setup complete" << std::endl;
+ } else {
+ std::cerr << "Failed to create event tap" << std::endl;
+ }
+}
+
+void MacOSPlatform::setup_window_monitoring() {
+ std::cout << "Setting up window monitoring..." << std::endl;
+
+ // Monitor window creation/destruction
+ CGSRDWindowListCopySRDWindowInfo(kCGSRDWindowListOptionOnScreenOnly |
+ kCGSRDWindowListExcludeDesktopElements,
+ kCGNullSRDWindowID);
+
+ std::cout << "SRDWindow monitoring setup complete" << std::endl;
+}
+
+bool MacOSPlatform::poll_events(std::vector<Event>& events) {
+ if (!initialized_ || !event_tap_) return false;
+
+ events.clear();
+
+ // macOS events are handled through the event tap callback
+ // The event tap callback handles event conversion
+ // For now, we'll just return any pending events
+
+ // TODO: Implement proper event queue processing
+ // This would involve processing events from the event tap callback
+
+ return false;
+}
+
+void MacOSPlatform::process_event(const Event& event) {
+ // TODO: Implement event processing
+}
+
+std::unique_ptr<SRDWindow> MacOSPlatform::create_window(const std::string& title, int x, int y, int width, int height) {
+ std::cout << "Creating macOS window: " << title << std::endl;
+
+ // TODO: Implement actual window creation using Core Graphics/AppKit
+ // For now, create a placeholder window object
+
+ auto window = std::make_unique<SRDWindow>();
+ // TODO: Set window properties
+
+ std::cout << "macOS window creation requested" << std::endl;
+ return window;
+}
+
+void MacOSPlatform::destroy_window(SRDWindow* window) {
+ std::cout << "Destroying macOS window" << std::endl;
+
+ // TODO: Implement window destruction
+}
+
+void MacOSPlatform::set_window_position(SRDWindow* window, int x, int y) {
+ // TODO: Implement window positioning using accessibility APIs
+}
+
+void MacOSPlatform::set_window_size(SRDWindow* window, int width, int height) {
+ // TODO: Implement window resizing using accessibility APIs
+}
+
+void MacOSPlatform::set_window_title(SRDWindow* window, const std::string& title) {
+ // TODO: Implement title setting
+}
+
+void MacOSPlatform::focus_window(SRDWindow* window) {
+ // TODO: Implement window focusing
+}
+
+void MacOSPlatform::minimize_window(SRDWindow* window) {
+ // TODO: Implement window minimization
+}
+
+void MacOSPlatform::maximize_window(SRDWindow* window) {
+ // TODO: Implement window maximization
+}
+
+void MacOSPlatform::close_window(SRDWindow* window) {
+ // TODO: Implement window closing
+}
+
+std::vector<Monitor> MacOSPlatform::get_monitors() {
+ std::vector<Monitor> monitors;
+
+ // Get display information using Core Graphics
+ uint32_t display_count = 0;
+ CGGetActiveDisplayList(0, nullptr, &display_count);
+
+ if (display_count > 0) {
+ std::vector<CGDirectDisplayID> display_ids(display_count);
+ CGGetActiveDisplayList(display_count, display_ids.data(), &display_count);
+
+ for (uint32_t i = 0; i < display_count; ++i) {
+ CGDirectDisplayID display_id = display_ids[i];
+
+ Monitor monitor;
+ monitor.id = static_cast<int>(display_id);
+ monitor.name = "Display " + std::to_string(i + 1);
+
+ // Get display bounds
+ CGRect bounds = CGDisplayBounds(display_id);
+ monitor.x = static_cast<int>(bounds.origin.x);
+ monitor.y = static_cast<int>(bounds.origin.y);
+ monitor.width = static_cast<int>(bounds.size.width);
+ monitor.height = static_cast<int>(bounds.size.height);
+
+ // Get refresh rate
+ CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display_id);
+ if (mode) {
+ monitor.refresh_rate = static_cast<int>(CGDisplayModeGetRefreshRate(mode));
+ CGDisplayModeRelease(mode);
+ } else {
+ monitor.refresh_rate = 60; // Default
+ }
+
+ monitors.push_back(monitor);
+
+ std::cout << "Monitor " << i << ": " << monitor.width << "x" << monitor.height
+ << " @ " << monitor.refresh_rate << "Hz" << std::endl;
+ }
+ }
+
+ return monitors;
+}
+
+Monitor MacOSPlatform::get_primary_monitor() {
+ auto monitors = get_monitors();
+ if (!monitors.empty()) {
+ return monitors[0];
+ }
+
+ // Fallback to main display
+ CGDirectDisplayID main_display = CGMainDisplayID();
+ CGRect bounds = CGDisplayBounds(main_display);
+
+ Monitor monitor;
+ monitor.id = static_cast<int>(main_display);
+ monitor.name = "Main Display";
+ monitor.x = static_cast<int>(bounds.origin.x);
+ monitor.y = static_cast<int>(bounds.origin.y);
+ monitor.width = static_cast<int>(bounds.size.width);
+ monitor.height = static_cast<int>(bounds.size.height);
+ monitor.refresh_rate = 60; // Default
+
+ return monitor;
+}
+
+void MacOSPlatform::grab_keyboard() {
+ // TODO: Implement keyboard grabbing
+ std::cout << "Keyboard grabbing setup" << std::endl;
+}
+
+void MacOSPlatform::ungrab_keyboard() {
+ // TODO: Implement keyboard ungrab
+ std::cout << "Keyboard ungrab" << std::endl;
+}
+
+void MacOSPlatform::grab_pointer() {
+ // TODO: Implement pointer grabbing
+ std::cout << "Pointer grabbing setup" << std::endl;
+}
+
+void MacOSPlatform::ungrab_pointer() {
+ // TODO: Implement pointer ungrab
+ std::cout << "Pointer ungrab" << std::endl;
+}
+
+// Static callback functions
+CGEventRef MacOSPlatform::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 MacOSPlatform::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, 1);
+ break;
+
+ case kCGEventLeftMouseUp:
+ handle_mouse_event(event, false, 1);
+ break;
+
+ case kCGEventRightMouseDown:
+ handle_mouse_event(event, true, 2);
+ break;
+
+ case kCGEventRightMouseUp:
+ handle_mouse_event(event, false, 2);
+ break;
+
+ case kCGEventMouseMoved:
+ handle_mouse_motion(event);
+ break;
+ }
+
+ return event;
+}
+
+void MacOSPlatform::handle_key_event(CGEventRef event, bool pressed) {
+ // Get key code
+ CGKeyCode key_code = static_cast<CGKeyCode>(CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode));
+
+ std::cout << "Key " << (pressed ? "press" : "release") << ": " << key_code << std::endl;
+
+ // TODO: Convert to SRDWM key event
+}
+
+void MacOSPlatform::handle_mouse_event(CGEventRef event, bool pressed, int button) {
+ // Get mouse position
+ CGPoint location = CGEventGetLocation(event);
+
+ std::cout << "Mouse button " << button << " " << (pressed ? "down" : "up")
+ << " at (" << location.x << ", " << location.y << ")" << std::endl;
+
+ // TODO: Convert to SRDWM button event
+}
+
+void MacOSPlatform::handle_mouse_motion(CGEventRef event) {
+ // Get mouse position
+ CGPoint location = CGEventGetLocation(event);
+
+ // TODO: Convert to SRDWM motion event
+}
+
+// Utility methods
+CGSRDWindowID MacOSPlatform::get_macos_window_id(SRDWindow* window) {
+ // TODO: Implement window ID retrieval
+ return 0;
+}
+
+pid_t MacOSPlatform::get_macos_pid(SRDWindow* window) {
+ // TODO: Implement PID retrieval
+ return 0;
+}
+
+void MacOSPlatform::update_window_monitoring() {
+ // TODO: Implement window monitoring update
+}
+
+void MacOSPlatform::handle_window_created(CGSRDWindowID window_id) {
+ std::cout << "SRDWindow created: " << window_id << std::endl;
+
+ // TODO: Create SRDWM window object and manage it
+}
+
+void MacOSPlatform::handle_window_destroyed(CGSRDWindowID window_id) {
+ std::cout << "SRDWindow destroyed: " << window_id << std::endl;
+
+ // TODO: Clean up SRDWM window object
+}
+
+void MacOSPlatform::handle_window_focused(CGSRDWindowID window_id) {
+ std::cout << "SRDWindow focused: " << window_id << std::endl;
+
+ // TODO: Handle window focus
+}
+
+void MacOSPlatform::handle_window_moved(CGSRDWindowID window_id, int x, int y) {
+ std::cout << "SRDWindow " << window_id << " moved to (" << x << ", " << y << ")" << std::endl;
+
+ // TODO: Handle window movement
+}
+
+void MacOSPlatform::handle_window_resized(CGSRDWindowID window_id, int width, int height) {
+ std::cout << "SRDWindow " << window_id << " resized to " << width << "x" << height << std::endl;
+
+ // TODO: Handle window resizing
+}
+
+
diff --git a/src/platform/macos_platform.h b/src/platform/macos_platform.h
new file mode 100644
index 0000000..39dc3db
--- /dev/null
+++ b/src/platform/macos_platform.h
@@ -0,0 +1,118 @@
+#ifndef SRDWM_MACOS_PLATFORM_H
+#define SRDWM_MACOS_PLATFORM_H
+
+#include "platform.h"
+#include <memory>
+#include <string>
+#include <map>
+
+// Forward declarations for macOS
+#ifdef __APPLE__
+typedef struct CGSRDWindow* CGSRDWindowRef;
+typedef struct CGEvent* CGEventRef;
+typedef struct CGDisplay* CGDirectDisplayID;
+typedef struct CGMenu* CGMenuRef;
+typedef struct CGMenuBar* CGMenuBarRef;
+#endif
+
+class MacOSPlatform : public Platform {
+public:
+ MacOSPlatform();
+ ~MacOSPlatform() override;
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ // SRDWindow decorations (macOS implementation)
+ void set_window_decorations(SRDWindow* window, bool enabled) override;
+ void set_window_border_color(SRDWindow* window, int r, int g, int b) override;
+ void set_window_border_width(SRDWindow* window, int width) override;
+ bool get_window_decorations(SRDWindow* window) const override;
+
+ // macOS-specific features
+ void setup_global_menu();
+ void update_global_menu(const std::string& app_name);
+ void set_menu_bar_visible(bool visible);
+ void set_dock_visible(bool visible);
+ void set_spaces_enabled(bool enabled);
+ void switch_to_space(int space_id);
+ int get_current_space() const;
+ std::vector<int> get_available_spaces() const;
+
+ // Mission Control and Spaces
+ void show_mission_control();
+ void show_app_expose();
+ void show_desktop();
+
+ // Window management enhancements
+ void set_window_level(SRDWindow* window, int level);
+ void set_window_shadow(SRDWindow* window, bool enabled);
+ void set_window_blur(SRDWindow* window, bool enabled);
+ void set_window_alpha(SRDWindow* window, float alpha);
+
+ std::string get_platform_name() const override;
+ bool is_wayland() const override;
+ bool is_x11() const override;
+ bool is_windows() const override;
+ bool is_macos() const override;
+
+private:
+ bool initialized_;
+ std::map<CGSRDWindowRef, SRDWindow*> window_map_;
+ std::vector<Monitor> monitors_;
+
+ // Decoration state (macOS limitations)
+ bool decorations_enabled_;
+ std::map<CGSRDWindowRef, CGSRDWindowRef> overlay_window_map_; // window -> overlay
+
+ // macOS-specific state
+ bool global_menu_enabled_;
+ bool dock_visible_;
+ bool spaces_enabled_;
+ CGMenuBarRef menu_bar_;
+ std::map<std::string, CGMenuRef> app_menus_;
+
+ // Event handling
+ void setup_event_tap();
+ void remove_event_tap();
+
+ // Monitor management
+ void update_monitors();
+
+ // Utility methods
+ SRDWindow* find_window_by_cgwindow(CGSRDWindowRef cgwindow);
+
+ // Decoration methods (macOS limitations)
+ void create_overlay_window(SRDWindow* window);
+ void destroy_overlay_window(SRDWindow* window);
+
+ // Global menu methods
+ void create_app_menu(const std::string& app_name);
+ void update_menu_bar();
+ void handle_menu_event(CGEventRef event);
+};
+
+#endif // SRDWM_MACOS_PLATFORM_H
+
diff --git a/src/platform/platform.h b/src/platform/platform.h
new file mode 100644
index 0000000..41cc6bf
--- /dev/null
+++ b/src/platform/platform.h
@@ -0,0 +1,91 @@
+#ifndef SRDWM_PLATFORM_H
+#define SRDWM_PLATFORM_H
+
+#include <memory>
+#include <vector>
+#include <string>
+#include <functional>
+
+// Forward declarations
+class SRDWindow;
+
+// Include Monitor struct definition from layouts
+#include "../layouts/layout.h"
+
+// Platform-independent event types
+enum class EventType {
+ WindowCreated,
+ WindowDestroyed,
+ WindowMoved,
+ WindowResized,
+ WindowFocused,
+ WindowUnfocused,
+ KeyPress,
+ KeyRelease,
+ MouseButtonPress,
+ MouseButtonRelease,
+ MouseMotion,
+ MonitorAdded,
+ MonitorRemoved
+};
+
+// Event structure
+struct Event {
+ EventType type;
+ void* data;
+ size_t data_size;
+};
+
+// Platform abstraction interface
+class Platform {
+public:
+ virtual ~Platform() = default;
+
+ // Initialization and cleanup
+ virtual bool initialize() = 0;
+ virtual void shutdown() = 0;
+
+ // Event handling
+ virtual bool poll_events(std::vector<Event>& events) = 0;
+ virtual void process_event(const Event& event) = 0;
+
+ // Window management
+ virtual std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) = 0;
+ virtual void destroy_window(SRDWindow* window) = 0;
+ virtual void set_window_position(SRDWindow* window, int x, int y) = 0;
+ virtual void set_window_size(SRDWindow* window, int width, int height) = 0;
+ virtual void set_window_title(SRDWindow* window, const std::string& title) = 0;
+ virtual void focus_window(SRDWindow* window) = 0;
+ virtual void minimize_window(SRDWindow* window) = 0;
+ virtual void maximize_window(SRDWindow* window) = 0;
+ virtual void close_window(SRDWindow* window) = 0;
+
+ // Window decorations (cross-platform)
+ virtual void set_window_decorations(SRDWindow* window, bool enabled) = 0;
+ virtual void set_window_border_color(SRDWindow* window, int r, int g, int b) = 0;
+ virtual void set_window_border_width(SRDWindow* window, int width) = 0;
+ virtual bool get_window_decorations(SRDWindow* window) const = 0;
+
+ // Monitor management
+ virtual std::vector<Monitor> get_monitors() = 0;
+ virtual Monitor get_primary_monitor() = 0;
+
+ // Input handling
+ virtual void grab_keyboard() = 0;
+ virtual void ungrab_keyboard() = 0;
+ virtual void grab_pointer() = 0;
+ virtual void ungrab_pointer() = 0;
+
+ // Utility
+ virtual std::string get_platform_name() const = 0;
+ virtual bool is_wayland() const = 0;
+ virtual bool is_x11() const = 0;
+ virtual bool is_windows() const = 0;
+ virtual bool is_macos() const = 0;
+};
+
+// Forward declaration
+class PlatformFactory;
+
+#endif // SRDWM_PLATFORM_H
+
diff --git a/src/platform/platform_factory.cc b/src/platform/platform_factory.cc
new file mode 100644
index 0000000..ef1981a
--- /dev/null
+++ b/src/platform/platform_factory.cc
@@ -0,0 +1,214 @@
+#include "platform_factory.h"
+#include <iostream>
+#include <cstring>
+#include <cstdlib>
+#include <algorithm>
+
+// Platform-specific includes
+#ifdef LINUX_PLATFORM
+ #include "x11_platform.h"
+ #ifdef WAYLAND_ENABLED
+ #include "wayland_platform.h"
+ #endif
+#elif defined(WIN32_PLATFORM)
+ #include "windows_platform.h"
+#elif defined(MACOS_PLATFORM)
+ #include "macos_platform.h"
+#endif
+
+std::unique_ptr<Platform> PlatformFactory::create_platform() {
+ #ifdef _WIN32
+ std::cout << "Creating SRDWindows platform..." << std::endl;
+ return std::make_unique<SRDWindowsPlatform>();
+
+ #elif defined(__APPLE__)
+ std::cout << "Creating macOS platform..." << std::endl;
+ return std::make_unique<MacOSPlatform>();
+
+ #else
+ // Linux: detect X11 vs Wayland
+ return detect_linux_platform();
+ #endif
+}
+
+std::unique_ptr<Platform> PlatformFactory::create_platform(const std::string& platform_name) {
+ std::cout << "Creating platform: " << platform_name << std::endl;
+
+ if (platform_name == "x11" || platform_name == "X11") {
+ #ifdef LINUX_PLATFORM
+ return std::make_unique<X11Platform>();
+ #else
+ std::cerr << "X11 platform not available on this system" << std::endl;
+ return nullptr;
+ #endif
+
+ } else if (platform_name == "wayland" || platform_name == "Wayland") {
+ #ifdef WAYLAND_ENABLED
+ return std::make_unique<WaylandPlatform>();
+ #else
+ std::cerr << "Wayland platform not available on this system" << std::endl;
+ return nullptr;
+ #endif
+
+ } else if (platform_name == "windows" || platform_name == "SRDWindows") {
+ #ifdef WIN32_PLATFORM
+ return std::make_unique<SRDWindowsPlatform>();
+ #else
+ std::cerr << "SRDWindows platform not available on this system" << std::endl;
+ return nullptr;
+ #endif
+
+ } else if (platform_name == "macos" || platform_name == "macOS") {
+ #ifdef MACOS_PLATFORM
+ return std::make_unique<MacOSPlatform>();
+ #else
+ std::cerr << "macOS platform not available on this system" << std::endl;
+ return nullptr;
+ #endif
+
+ } else {
+ std::cerr << "Unknown platform: " << platform_name << std::endl;
+ std::cerr << "Available platforms: x11, wayland, windows, macos" << std::endl;
+ return nullptr;
+ }
+}
+
+std::unique_ptr<Platform> PlatformFactory::detect_linux_platform() {
+ std::cout << "Detecting Linux platform..." << std::endl;
+
+ // Check environment variables for Wayland
+ const char* wayland_display = std::getenv("WAYLAND_DISPLAY");
+ const char* xdg_session_type = std::getenv("XDG_SESSION_TYPE");
+ const char* display = std::getenv("DISPLAY");
+
+ std::cout << "Environment variables:" << std::endl;
+ std::cout << " WAYLAND_DISPLAY: " << (wayland_display ? wayland_display : "not set") << std::endl;
+ std::cout << " XDG_SESSION_TYPE: " << (xdg_session_type ? xdg_session_type : "not set") << std::endl;
+ std::cout << " DISPLAY: " << (display ? display : "not set") << std::endl;
+
+ // Try Wayland first if environment suggests it
+ if (wayland_display || (xdg_session_type && strcmp(xdg_session_type, "wayland") == 0)) {
+ std::cout << "Wayland environment detected, attempting Wayland initialization..." << std::endl;
+
+ #ifdef WAYLAND_ENABLED
+ auto wayland_platform = std::make_unique<WaylandPlatform>();
+ if (wayland_platform->initialize()) {
+ std::cout << "✓ Wayland platform initialized successfully" << std::endl;
+ return wayland_platform;
+ } else {
+ std::cout << "✗ Wayland initialization failed, falling back to X11" << std::endl;
+ }
+ #else
+ std::cout << "Wayland support not compiled in, falling back to X11" << std::endl;
+ #endif
+ }
+
+ // Fall back to X11
+ std::cout << "Attempting X11 initialization..." << std::endl;
+
+ #ifdef LINUX_PLATFORM
+ auto x11_platform = std::make_unique<X11Platform>();
+ if (x11_platform->initialize()) {
+ std::cout << "✓ X11 platform initialized successfully" << std::endl;
+ return x11_platform;
+ } else {
+ std::cout << "✗ X11 initialization failed" << std::endl;
+ }
+ #else
+ std::cout << "X11 support not compiled in" << std::endl;
+ #endif
+
+ std::cerr << "Failed to initialize any platform backend" << std::endl;
+ return nullptr;
+}
+
+std::vector<std::string> PlatformFactory::get_available_platforms() {
+ std::vector<std::string> platforms;
+
+ #ifdef LINUX_PLATFORM
+ platforms.push_back("x11");
+ #ifdef WAYLAND_ENABLED
+ platforms.push_back("wayland");
+ #endif
+ #endif
+
+ #ifdef WIN32_PLATFORM
+ platforms.push_back("windows");
+ #endif
+
+ #ifdef MACOS_PLATFORM
+ platforms.push_back("macos");
+ #endif
+
+ return platforms;
+}
+
+std::string PlatformFactory::get_current_platform() {
+ #ifdef _WIN32
+ return "windows";
+ #elif defined(__APPLE__)
+ return "macos";
+ #else
+ // Check if we're running on Wayland
+ 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)) {
+ return "wayland";
+ } else {
+ return "x11";
+ }
+ #endif
+}
+
+bool PlatformFactory::is_platform_available(const std::string& platform_name) {
+ auto available = get_available_platforms();
+ return std::find(available.begin(), available.end(), platform_name) != available.end();
+}
+
+void PlatformFactory::print_platform_info() {
+ std::cout << "\n=== Platform Information ===" << std::endl;
+ std::cout << "Current platform: " << get_current_platform() << std::endl;
+
+ auto available = get_available_platforms();
+ std::cout << "Available platforms: ";
+ for (size_t i = 0; i < available.size(); ++i) {
+ if (i > 0) std::cout << ", ";
+ std::cout << available[i];
+ }
+ std::cout << std::endl;
+
+ std::cout << "Environment variables:" << std::endl;
+ const char* wayland_display = std::getenv("WAYLAND_DISPLAY");
+ const char* xdg_session_type = std::getenv("XDG_SESSION_TYPE");
+ const char* display = std::getenv("DISPLAY");
+
+ std::cout << " WAYLAND_DISPLAY: " << (wayland_display ? wayland_display : "not set") << std::endl;
+ std::cout << " XDG_SESSION_TYPE: " << (xdg_session_type ? xdg_session_type : "not set") << std::endl;
+ std::cout << " DISPLAY: " << (display ? display : "not set") << std::endl;
+
+ #ifdef LINUX_PLATFORM
+ std::cout << "Linux platform support: Enabled" << std::endl;
+ #ifdef WAYLAND_ENABLED
+ std::cout << "Wayland support: Enabled" << std::endl;
+ #else
+ std::cout << "Wayland support: Disabled" << std::endl;
+ #endif
+ #else
+ std::cout << "Linux platform support: Disabled" << std::endl;
+ #endif
+
+ #ifdef WIN32_PLATFORM
+ std::cout << "SRDWindows platform support: Enabled" << std::endl;
+ #else
+ std::cout << "SRDWindows platform support: Disabled" << std::endl;
+ #endif
+
+ #ifdef MACOS_PLATFORM
+ std::cout << "macOS platform support: Enabled" << std::endl;
+ #else
+ std::cout << "macOS platform support: Disabled" << std::endl;
+ #endif
+
+ std::cout << "=============================" << std::endl;
+}
diff --git a/src/platform/platform_factory.h b/src/platform/platform_factory.h
new file mode 100644
index 0000000..24f7586
--- /dev/null
+++ b/src/platform/platform_factory.h
@@ -0,0 +1,37 @@
+#ifndef SRDWM_PLATFORM_FACTORY_H
+#define SRDWM_PLATFORM_FACTORY_H
+
+#include "platform.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+// Platform factory for creating platform-specific implementations
+class PlatformFactory {
+public:
+ // Create platform with automatic detection
+ static std::unique_ptr<Platform> create_platform();
+
+ // Create specific platform by name
+ static std::unique_ptr<Platform> create_platform(const std::string& platform_name);
+
+ // Get list of available platforms
+ static std::vector<std::string> get_available_platforms();
+
+ // Get current platform name
+ static std::string get_current_platform();
+
+ // Check if platform is available
+ static bool is_platform_available(const std::string& platform_name);
+
+ // Print platform information
+ static void print_platform_info();
+
+private:
+ // Linux platform detection
+ static std::unique_ptr<Platform> detect_linux_platform();
+};
+
+#endif // SRDWM_PLATFORM_FACTORY_H
+
+
diff --git a/src/platform/wayland_platform.cc b/src/platform/wayland_platform.cc
new file mode 100644
index 0000000..2e4a591
--- /dev/null
+++ b/src/platform/wayland_platform.cc
@@ -0,0 +1,507 @@
+#include "wayland_platform.h"
+#include <iostream>
+#include <cstring>
+#include <cstdint>
+
+#ifndef USE_WAYLAND_STUB
+#include <wayland-server-core.h>
+extern "C" {
+ // Minimal wlroots declarations to avoid pulling C99-only headers into C++
+ struct wlr_backend;
+ struct wlr_renderer;
+ struct wlr_compositor;
+ struct wlr_seat;
+ struct wlr_xdg_shell;
+
+ // Logging
+ int wlr_log_init(int verbosity, void* callback);
+
+ // Backend
+ struct wlr_backend* wlr_backend_autocreate(struct wl_display* display, void* session);
+ bool wlr_backend_start(struct wlr_backend* backend);
+ void wlr_backend_destroy(struct wlr_backend* backend);
+ struct wlr_renderer* wlr_backend_get_renderer(struct wlr_backend* backend);
+
+ // Compositor and seat
+ struct wlr_compositor* wlr_compositor_create(struct wl_display* display, uint32_t version, struct wlr_renderer* renderer);
+ struct wlr_seat* wlr_seat_create(struct wl_display* display, const char* name);
+
+ // xdg-shell
+ struct wlr_xdg_shell* wlr_xdg_shell_create(struct wl_display* display, uint32_t version);
+ struct wlr_renderer* wlr_renderer_autocreate(struct wlr_backend* backend);
+ void wlr_renderer_init_wl_display(struct wlr_renderer* renderer, struct wl_display* display);
+
+ // Wayland display helpers (for C++ compilation)
+ struct wl_display* wl_display_create(void);
+ void wl_display_destroy(struct wl_display* display);
+ int wl_display_dispatch_pending(struct wl_display* display);
+ void wl_display_flush_clients(struct wl_display* display);
+}
+#endif
+
+// Static member initialization
+WaylandPlatform* WaylandPlatform::instance_ = nullptr;
+
+WaylandPlatform::WaylandPlatform()
+ : display_(nullptr)
+ , registry_(nullptr)
+ , compositor_(nullptr)
+ , shm_(nullptr)
+ , seat_(nullptr)
+ , output_(nullptr)
+ , shell_(nullptr)
+ , backend_(nullptr)
+ , renderer_(nullptr)
+ , wlr_compositor_(nullptr)
+ , output_layout_(nullptr)
+ , cursor_(nullptr)
+ , xcursor_manager_(nullptr)
+ , wlr_seat_(nullptr)
+ , xdg_shell_(nullptr)
+ // , layer_shell_(nullptr)
+ , event_loop_running_(false) {
+
+ instance_ = this;
+}
+
+WaylandPlatform::~WaylandPlatform() {
+ shutdown();
+ if (instance_ == this) {
+ instance_ = nullptr;
+ }
+}
+
+bool WaylandPlatform::initialize() {
+#ifndef USE_WAYLAND_STUB
+ std::cout << "Initializing Wayland platform (wlroots real backend)..." << std::endl;
+ // Create Wayland display
+ display_ = wl_display_create();
+ if (!display_) {
+ std::cerr << "Failed to create wl_display" << std::endl;
+ return false;
+ }
+
+ // Initialize wlroots logging (optional) - 2 corresponds to INFO
+ wlr_log_init(2, nullptr);
+
+ // Create backend (auto-detect e.g., DRM, Wayland, X11)
+ backend_ = wlr_backend_autocreate(display_, nullptr);
+ if (!backend_) {
+ std::cerr << "Failed to create wlr_backend" << std::endl;
+ return false;
+ }
+
+ // Create renderer and hook to display
+ renderer_ = wlr_renderer_autocreate(backend_);
+ if (!renderer_) {
+ std::cerr << "Failed to create wlr_renderer" << std::endl;
+ return false;
+ }
+ wlr_renderer_init_wl_display(renderer_, display_);
+
+ // Create compositor (wlroots 0.17 requires protocol version). Use version 6.
+ wlr_compositor_ = wlr_compositor_create(display_, 6, renderer_);
+ if (!wlr_compositor_) {
+ std::cerr << "Failed to create wlr_compositor" << std::endl;
+ return false;
+ }
+
+ // Create seat (input)
+ wlr_seat_ = wlr_seat_create(display_, "seat0");
+ if (!wlr_seat_) {
+ std::cerr << "Failed to create wlr_seat" << std::endl;
+ return false;
+ }
+
+ // Create xdg-shell (requires protocol version)
+ xdg_shell_ = wlr_xdg_shell_create(display_, 6);
+ if (!xdg_shell_) {
+ std::cerr << "Failed to create wlr_xdg_shell" << std::endl;
+ return false;
+ }
+
+ // Minimal bring-up: listeners will be wired in a follow-up
+
+ // Start backend
+ if (!wlr_backend_start(backend_)) {
+ std::cerr << "Failed to start wlr_backend" << std::endl;
+ return false;
+ }
+
+ decorations_enabled_ = true;
+ std::cout << "Wayland (wlroots) backend started." << std::endl;
+ return true;
+#else
+ // Minimal Wayland backend initialization (no wlroots API calls).
+ std::cout << "Initializing Wayland platform (minimal stub)..." << std::endl;
+ decorations_enabled_ = true;
+ std::cout << "Wayland platform initialized (stub)." << std::endl;
+ return true;
+#endif
+}
+
+void WaylandPlatform::shutdown() {
+#ifndef USE_WAYLAND_STUB
+ std::cout << "Shutting down Wayland platform (wlroots)..." << std::endl;
+ if (xdg_shell_) { xdg_shell_ = nullptr; }
+ // Seat is tied to display lifecycle; skip explicit destroy to avoid ABI issues
+ wlr_seat_ = nullptr;
+ if (wlr_compositor_) { /* wlr_compositor is owned by display, no explicit destroy */ wlr_compositor_ = nullptr; }
+ // Renderer is owned by backend in this path; no explicit destroy
+ renderer_ = nullptr;
+ if (backend_) { wlr_backend_destroy(backend_); backend_ = nullptr; }
+ if (display_) { wl_display_destroy(display_); display_ = nullptr; }
+#else
+ std::cout << "Shutting down Wayland platform (stub)..." << std::endl;
+#endif
+}
+
+bool WaylandPlatform::setup_wlroots_backend() { std::cout << "wlroots backend (stub)" << std::endl; return true; }
+
+bool WaylandPlatform::setup_compositor() { std::cout << "compositor (stub)" << std::endl; return true; }
+
+// (removed unused stub-only setup_output/setup_input in real backend path)
+
+bool WaylandPlatform::setup_shell_protocols() { std::cout << "shell protocols (stub)" << std::endl; return true; }
+
+// bool WaylandPlatform::setup_xwayland() { return true; }
+
+bool WaylandPlatform::poll_events(std::vector<Event>& events) {
+#ifndef USE_WAYLAND_STUB
+ if (!display_ || !backend_) return false;
+ events.clear();
+ // Dispatch Wayland events; non-blocking to integrate with app loop
+ wl_display_dispatch_pending(display_);
+ wl_display_flush_clients(display_);
+ return true;
+#else
+ events.clear();
+ return true;
+#endif
+}
+
+void WaylandPlatform::process_event(const Event& event) {
+ // TODO: Implement event processing
+}
+
+std::unique_ptr<SRDWindow> WaylandPlatform::create_window(const std::string& title, int x, int y, int width, int height) {
+ // TODO: Implement window creation
+ std::cout << "Creating Wayland window: " << title << std::endl;
+ return nullptr;
+}
+
+void WaylandPlatform::destroy_window(SRDWindow* window) {
+ // TODO: Implement window destruction
+ std::cout << "Destroying Wayland window" << std::endl;
+}
+
+void WaylandPlatform::set_window_position(SRDWindow* window, int x, int y) {
+ // TODO: Implement window positioning
+}
+
+void WaylandPlatform::set_window_size(SRDWindow* window, int width, int height) {
+ // TODO: Implement window resizing
+}
+
+void WaylandPlatform::set_window_title(SRDWindow* window, const std::string& title) {
+ // TODO: Implement title setting
+}
+
+void WaylandPlatform::focus_window(SRDWindow* window) {
+ // TODO: Implement window focusing
+}
+
+void WaylandPlatform::minimize_window(SRDWindow* window) {
+ // TODO: Implement window minimization
+}
+
+void WaylandPlatform::maximize_window(SRDWindow* window) {
+ // TODO: Implement window maximization
+}
+
+void WaylandPlatform::close_window(SRDWindow* window) {
+ // TODO: Implement window closing
+}
+
+std::vector<Monitor> WaylandPlatform::get_monitors() {
+ // TODO: Implement monitor detection
+ return {};
+}
+
+Monitor WaylandPlatform::get_primary_monitor() {
+ // TODO: Implement primary monitor detection
+ return Monitor{};
+}
+
+void WaylandPlatform::grab_keyboard() {
+ // TODO: Implement keyboard grabbing
+}
+
+void WaylandPlatform::ungrab_keyboard() {
+ // TODO: Implement keyboard ungrab
+}
+
+void WaylandPlatform::grab_pointer() {
+ // TODO: Implement pointer grabbing
+}
+
+void WaylandPlatform::ungrab_pointer() {
+ // TODO: Implement pointer ungrab
+}
+
+// Static callback functions
+void WaylandPlatform::registry_global_handler(void* data, struct wl_registry* registry,
+ uint32_t name, const char* interface, uint32_t version) {
+ (void)registry; (void)name; (void)interface; (void)version;
+ WaylandPlatform* platform = static_cast<WaylandPlatform*>(data);
+ platform->handle_registry_global(nullptr, 0, interface ? interface : "", 0);
+}
+
+void WaylandPlatform::registry_global_remove_handler(void* data, struct wl_registry* registry, uint32_t name) {
+ (void)registry; (void)name;
+ WaylandPlatform* platform = static_cast<WaylandPlatform*>(data);
+ platform->handle_registry_global_remove(nullptr, 0);
+}
+
+void WaylandPlatform::xdg_surface_new_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_xdg_surface_new(static_cast<struct wlr_xdg_surface*>(data));
+ }
+}
+
+void WaylandPlatform::xdg_surface_destroy_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_xdg_surface_destroy(static_cast<struct wlr_xdg_surface*>(data));
+ }
+}
+
+void WaylandPlatform::xdg_toplevel_new_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_xdg_toplevel_new(static_cast<struct wlr_xdg_toplevel*>(data));
+ }
+}
+
+void WaylandPlatform::xdg_toplevel_destroy_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_xdg_toplevel_destroy(static_cast<struct wlr_xdg_toplevel*>(data));
+ }
+}
+
+// (removed xwayland handlers; not declared while XWayland is disabled)
+
+void WaylandPlatform::output_new_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_output_new(static_cast<struct wlr_output*>(data));
+ }
+}
+
+void WaylandPlatform::output_destroy_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_output_destroy(static_cast<struct wlr_output*>(data));
+ }
+}
+
+void WaylandPlatform::output_frame_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_output_frame(static_cast<struct wlr_output*>(data));
+ }
+}
+
+void WaylandPlatform::pointer_motion_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_pointer_motion(static_cast<struct wlr_pointer_motion_event*>(data));
+ }
+}
+
+void WaylandPlatform::pointer_button_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_pointer_button(static_cast<struct wlr_pointer_button_event*>(data));
+ }
+}
+
+void WaylandPlatform::pointer_axis_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_pointer_axis(static_cast<struct wlr_pointer_axis_event*>(data));
+ }
+}
+
+void WaylandPlatform::keyboard_key_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_keyboard_key(static_cast<struct wlr_keyboard_key_event*>(data));
+ }
+}
+
+// Event handling methods
+void WaylandPlatform::handle_registry_global(struct wl_registry* registry, uint32_t name,
+ const char* interface, uint32_t version) {
+ (void)registry; (void)name; (void)version;
+ std::cout << "Registry global (stub): " << (interface ? interface : "?") << std::endl;
+}
+
+void WaylandPlatform::handle_registry_global_remove(struct wl_registry* registry, uint32_t name) {
+ (void)registry; (void)name;
+}
+
+void WaylandPlatform::handle_xdg_surface_new(struct wlr_xdg_surface* surface) {
+ std::cout << "New XDG surface" << std::endl;
+ manage_xdg_window(surface);
+}
+
+void WaylandPlatform::handle_xdg_surface_destroy(struct wlr_xdg_surface* surface) {
+ std::cout << "XDG surface destroyed" << std::endl;
+}
+
+void WaylandPlatform::handle_xdg_toplevel_new(struct wlr_xdg_toplevel* toplevel) {
+ std::cout << "New XDG toplevel" << std::endl;
+}
+
+void WaylandPlatform::handle_xdg_toplevel_destroy(struct wlr_xdg_toplevel* toplevel) {
+ std::cout << "XDG toplevel destroyed" << std::endl;
+}
+
+// void WaylandPlatform::handle_xwayland_surface_new(struct wlr_xwayland_surface* surface) {}
+
+// void WaylandPlatform::handle_xwayland_surface_destroy(struct wlr_xwayland_surface* surface) {}
+
+void WaylandPlatform::handle_output_new(struct wlr_output* output) {
+ std::cout << "New output" << std::endl;
+ handle_output_mode(output);
+}
+
+void WaylandPlatform::handle_output_destroy(struct wlr_output* output) {
+ std::cout << "Output destroyed" << std::endl;
+}
+
+void WaylandPlatform::handle_output_frame(struct wlr_output* output) {
+ // Handle output frame event
+}
+
+void WaylandPlatform::handle_pointer_motion(struct wlr_pointer_motion_event* event) {
+ // Handle pointer motion
+}
+
+void WaylandPlatform::handle_pointer_button(struct wlr_pointer_button_event* event) {
+ // Handle pointer button
+}
+
+void WaylandPlatform::handle_pointer_axis(struct wlr_pointer_axis_event* event) {
+ // Handle pointer axis
+}
+
+void WaylandPlatform::handle_keyboard_key(struct wlr_keyboard_key_event* event) {
+ // Handle keyboard key
+}
+
+void WaylandPlatform::manage_xdg_window(struct wlr_xdg_surface* surface) {
+ // TODO: Implement XDG window management
+}
+
+// void WaylandPlatform::manage_xwayland_window(struct wlr_xwayland_surface* surface) {}
+
+void WaylandPlatform::unmanage_window(SRDWindow* window) {
+ // TODO: Implement window unmanagement
+}
+
+void WaylandPlatform::handle_output_mode(struct wlr_output* output) {
+ // TODO: Implement output mode handling
+}
+
+void WaylandPlatform::handle_output_scale(struct wlr_output* output) {
+ // TODO: Implement output scale handling
+}
+
+void WaylandPlatform::handle_key_event(uint32_t key, bool pressed) {
+ // TODO: Implement key event handling
+}
+
+void WaylandPlatform::handle_button_event(uint32_t button, bool pressed) {
+ // TODO: Implement button event handling
+}
+
+void WaylandPlatform::create_surface_window(struct wlr_surface* surface) {
+ // TODO: Implement surface window creation
+}
+
+void WaylandPlatform::destroy_surface_window(struct wlr_surface* surface) {
+ // TODO: Implement surface window destruction
+}
+
+void WaylandPlatform::update_surface_window(struct wlr_surface* surface) {
+ // TODO: Implement surface window update
+}
+
+void WaylandPlatform::convert_wlroots_event_to_srdwm_event(void* event_data, EventType type) {
+ // TODO: Implement event conversion
+}
+
+void WaylandPlatform::handle_wlroots_error(const std::string& error) {
+ std::cerr << "wlroots error: " << error << std::endl;
+}
+
+// SRDWindow decoration implementations
+void WaylandPlatform::set_window_decorations(SRDWindow* window, bool enabled) {
+ // Temporary stub: wlroots xdg-decoration v1 helpers differ across versions.
+ // Keep internal state and log, skip calling decoration APIs.
+ std::cout << "WaylandPlatform: Set window decorations " << (enabled ? "enabled" : "disabled") << std::endl;
+ (void)window; // unused for now
+ decorations_enabled_ = enabled;
+}
+
+void WaylandPlatform::set_window_border_color(SRDWindow* window, int r, int g, int b) {
+ std::cout << "WaylandPlatform: Set border color RGB(" << r << "," << g << "," << b << ")" << std::endl;
+
+ if (!window || !renderer_) return;
+
+ // Store border color for this window
+ // In a full implementation, this would be stored in a window-specific data structure
+ // and applied during rendering
+
+ // For now, we'll just log the request
+ // TODO: Implement custom border rendering via wlroots rendering pipeline
+ std::cout << "Border color set for window " << window->getId()
+ << ": RGB(" << r << "," << g << "," << b << ")" << std::endl;
+}
+
+void WaylandPlatform::set_window_border_width(SRDWindow* window, int width) {
+ std::cout << "WaylandPlatform: Set border width " << width << std::endl;
+
+ if (!window) return;
+
+ // TODO: Implement when wlroots rendering is set up
+ // This would involve drawing custom borders on surfaces
+}
+
+bool WaylandPlatform::get_window_decorations(SRDWindow* window) const {
+ if (!window) return false;
+
+ return decorations_enabled_;
+}
+
+void WaylandPlatform::setup_decoration_manager() {
+ // Temporary stub: skip creating xdg-decoration manager to avoid
+ // wlroots API/ABI differences across distro versions.
+ std::cout << "Decoration manager (stub) initialized" << std::endl;
+}
+
+void WaylandPlatform::handle_decoration_request(struct wlr_xdg_surface* surface, uint32_t mode) {
+ std::cout << "Handling decoration request, mode: " << mode << std::endl;
+
+ // TODO: Implement when zxdg-decoration protocol is available
+ // This would involve:
+ // 1. Checking if server-side decorations are enabled
+ // 2. Setting the decoration mode for the surface
+ // 3. Drawing decorations if needed
+}
+
+
diff --git a/src/platform/wayland_platform.h b/src/platform/wayland_platform.h
new file mode 100644
index 0000000..3df5867
--- /dev/null
+++ b/src/platform/wayland_platform.h
@@ -0,0 +1,227 @@
+#ifndef SRDWM_WAYLAND_PLATFORM_H
+#define SRDWM_WAYLAND_PLATFORM_H
+
+#include "platform.h"
+#ifndef USE_WAYLAND_STUB
+#include <wayland-server-core.h>
+#endif
+// Forward-declare Wayland and wlroots types to avoid version-specific headers.
+struct wl_display; struct wl_registry; struct wl_compositor; struct wl_shm; struct wl_seat; struct wl_output; struct wl_shell; struct wl_listener; struct wl_surface;
+struct wlr_backend; struct wlr_renderer; struct wlr_compositor; struct wlr_output_layout; struct wlr_cursor; struct wlr_xcursor_manager; struct wlr_seat;
+struct wlr_xdg_shell; struct wlr_xdg_surface; struct wlr_xdg_toplevel;
+struct wlr_output; struct wlr_pointer_motion_event; struct wlr_pointer_button_event; struct wlr_pointer_axis_event; struct wlr_keyboard_key_event;
+struct wlr_xdg_decoration_manager_v1;
+#include <map>
+#include <memory>
+#include <vector>
+
+// Forward declarations
+class SRDWindow;
+class Monitor;
+
+// Wayland-specific platform implementation
+class WaylandPlatform : public Platform {
+public:
+ WaylandPlatform();
+ ~WaylandPlatform();
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+
+ // Event handling
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ // SRDWindow management
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ // Monitor management
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ // Input handling
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ // Utility
+ // SRDWindow decorations (Wayland implementation)
+ void set_window_decorations(SRDWindow* window, bool enabled) override;
+ void set_window_border_color(SRDWindow* window, int r, int g, int b) override;
+ void set_window_border_width(SRDWindow* window, int width) override;
+ bool get_window_decorations(SRDWindow* window) const override;
+
+ std::string get_platform_name() const override { return "Wayland"; }
+ bool is_wayland() const override { return true; }
+ bool is_x11() const override { return false; }
+ bool is_windows() const override { return false; }
+ bool is_macos() const override { return false; }
+
+private:
+ static WaylandPlatform* instance_;
+ // Wayland-specific members
+ struct wl_display* display_;
+ struct wl_registry* registry_;
+ struct wl_compositor* compositor_;
+ struct wl_shm* shm_;
+ struct wl_seat* seat_;
+ struct wl_output* output_;
+ struct wl_shell* shell_;
+
+ // wlroots backend
+ struct wlr_backend* backend_;
+ struct wlr_renderer* renderer_;
+ struct wlr_compositor* wlr_compositor_;
+ struct wlr_output_layout* output_layout_;
+ struct wlr_cursor* cursor_;
+ struct wlr_xcursor_manager* xcursor_manager_;
+ struct wlr_seat* wlr_seat_;
+
+ // Shell protocols
+ struct wlr_xdg_shell* xdg_shell_;
+ // struct wlr_layer_shell_v1* layer_shell_;
+
+ // XWayland support (temporarily disabled)
+ // struct wlr_xwayland* xwayland_;
+ // struct wlr_xwayland_server* xwayland_server_;
+
+ // SRDWindow tracking
+ std::map<struct wlr_surface*, SRDWindow*> surface_window_map_;
+ std::map<struct wlr_xdg_surface*, SRDWindow*> xdg_window_map_;
+ // std::map<struct wlr_xwayland_surface*, SRDWindow*> xwayland_window_map_;
+
+ // Monitor information
+ std::vector<Monitor> monitors_;
+ Monitor primary_monitor_;
+
+ // Event handling
+ bool event_loop_running_;
+ std::vector<Event> pending_events_;
+
+ // Private methods
+ bool setup_wlroots_backend();
+ bool setup_compositor();
+ bool setup_shell_protocols();
+ // bool setup_xwayland();
+
+ // Event handling
+ void handle_registry_global(struct wl_registry* registry, uint32_t name,
+ const char* interface, uint32_t version);
+ void handle_registry_global_remove(struct wl_registry* registry, uint32_t name);
+
+ // Shell protocol handlers
+ void handle_xdg_surface_new(struct wlr_xdg_surface* surface);
+ void handle_xdg_surface_destroy(struct wlr_xdg_surface* surface);
+ void handle_xdg_toplevel_new(struct wlr_xdg_toplevel* toplevel);
+ void handle_xdg_toplevel_destroy(struct wlr_xdg_toplevel* toplevel);
+
+ // XWayland handlers (temporarily disabled)
+ // void handle_xwayland_surface_new(struct wlr_xwayland_surface* surface);
+ // void handle_xwayland_surface_destroy(struct wlr_xwayland_surface* surface);
+
+ // Output handlers
+ void handle_output_new(struct wlr_output* output);
+ void handle_output_destroy(struct wlr_output* output);
+ void handle_output_frame(struct wlr_output* output);
+
+ // Input handlers
+ void handle_pointer_motion(struct wlr_pointer_motion_event* event);
+ void handle_pointer_button(struct wlr_pointer_button_event* event);
+ void handle_pointer_axis(struct wlr_pointer_axis_event* event);
+ void handle_keyboard_key(struct wlr_keyboard_key_event* event);
+
+ // SRDWindow management helpers
+ SRDWindow* find_window_by_surface(struct wlr_surface* surface);
+ SRDWindow* find_window_by_xdg_surface(struct wlr_xdg_surface* surface);
+ // SRDWindow* find_window_by_xwayland_surface(struct wlr_xwayland_surface* surface);
+ void manage_xdg_window(struct wlr_xdg_surface* surface);
+ // void manage_xwayland_window(struct wlr_xwayland_surface* surface);
+ void unmanage_window(SRDWindow* window);
+
+ // Monitor helpers
+ void update_monitor_info();
+ void handle_output_mode(struct wlr_output* output);
+ void handle_output_scale(struct wlr_output* output);
+
+ // Input helpers
+ void setup_keyboard_grab();
+ void setup_pointer_grab();
+ void handle_key_event(uint32_t key, bool pressed);
+ void handle_button_event(uint32_t button, bool pressed);
+
+ // Utility helpers
+ void create_surface_window(struct wlr_surface* surface);
+ void destroy_surface_window(struct wlr_surface* surface);
+ void update_surface_window(struct wlr_surface* surface);
+
+ // Event conversion
+ void convert_wlroots_event_to_srdwm_event(void* event_data, EventType type);
+
+ // Error handling
+ void handle_wlroots_error(const std::string& error);
+
+ // Decoration methods
+ void setup_decoration_manager();
+ void handle_decoration_request(struct wlr_xdg_surface* surface, uint32_t mode);
+
+ // Static callback functions
+ static void registry_global_handler(void* data, struct wl_registry* registry,
+ uint32_t name, const char* interface, uint32_t version);
+ static void registry_global_remove_handler(void* data, struct wl_registry* registry, uint32_t name);
+
+ static void xdg_surface_new_handler(struct wl_listener* listener, void* data);
+ static void xdg_surface_destroy_handler(struct wl_listener* listener, void* data);
+ static void xdg_toplevel_new_handler(struct wl_listener* listener, void* data);
+ static void xdg_toplevel_destroy_handler(struct wl_listener* listener, void* data);
+
+ // static void xwayland_surface_new_handler(struct wl_listener* listener, void* data);
+ // static void xwayland_surface_destroy_handler(struct wl_listener* listener, void* data);
+
+ static void output_new_handler(struct wl_listener* listener, void* data);
+ static void output_destroy_handler(struct wl_listener* listener, void* data);
+ static void output_frame_handler(struct wl_listener* listener, void* data);
+
+ static void pointer_motion_handler(struct wl_listener* listener, void* data);
+ static void pointer_button_handler(struct wl_listener* listener, void* data);
+ static void pointer_axis_handler(struct wl_listener* listener, void* data);
+ static void keyboard_key_handler(struct wl_listener* listener, void* data);
+
+ // Event listeners removed in stubbed build to avoid wl_listener dependency
+ // wlroots event listeners (instantiated only in real Wayland path)
+ #ifndef USE_WAYLAND_STUB
+ struct wl_listener xdg_surface_new_listener_;
+ struct wl_listener xdg_surface_destroy_listener_;
+ struct wl_listener xdg_toplevel_new_listener_;
+ struct wl_listener xdg_toplevel_destroy_listener_;
+ struct wl_listener output_new_listener_;
+ struct wl_listener output_destroy_listener_;
+ struct wl_listener output_frame_listener_;
+ struct wl_listener pointer_motion_listener_;
+ struct wl_listener pointer_button_listener_;
+ struct wl_listener pointer_axis_listener_;
+ struct wl_listener keyboard_key_listener_;
+ #endif
+
+ // Decoration state
+ bool decorations_enabled_;
+ struct wlr_xdg_decoration_manager_v1* decoration_manager_;
+
+ // struct wl_listener xwayland_new_surface;
+ // struct wl_listener xwayland_destroy;
+
+ // Additional listeners removed in stubbed build
+};
+
+#endif // SRDWM_WAYLAND_PLATFORM_H
+
+
diff --git a/src/platform/wayland_platform_stub.cc b/src/platform/wayland_platform_stub.cc
new file mode 100644
index 0000000..bdf6ee9
--- /dev/null
+++ b/src/platform/wayland_platform_stub.cc
@@ -0,0 +1,114 @@
+#include "wayland_platform.h"
+#include <iostream>
+#include <cstdint>
+
+WaylandPlatform* WaylandPlatform::instance_ = nullptr;
+
+WaylandPlatform::WaylandPlatform()
+ : display_(nullptr)
+ , registry_(nullptr)
+ , compositor_(nullptr)
+ , shm_(nullptr)
+ , seat_(nullptr)
+ , output_(nullptr)
+ , shell_(nullptr)
+ , backend_(nullptr)
+ , renderer_(nullptr)
+ , wlr_compositor_(nullptr)
+ , output_layout_(nullptr)
+ , cursor_(nullptr)
+ , xcursor_manager_(nullptr)
+ , wlr_seat_(nullptr)
+ , xdg_shell_(nullptr)
+ , event_loop_running_(false)
+ , decorations_enabled_(true)
+ , decoration_manager_(nullptr) {
+ instance_ = this;
+}
+
+WaylandPlatform::~WaylandPlatform() {
+ shutdown();
+ if (instance_ == this) instance_ = nullptr;
+}
+
+bool WaylandPlatform::initialize() {
+ std::cout << "Wayland (stub): initialize" << std::endl;
+ decorations_enabled_ = true;
+ return true;
+}
+
+void WaylandPlatform::shutdown() {
+ std::cout << "Wayland (stub): shutdown" << std::endl;
+}
+
+bool WaylandPlatform::poll_events(std::vector<Event>& events) {
+ events.clear();
+ return true;
+}
+
+void WaylandPlatform::process_event(const Event& /*event*/) {}
+
+std::unique_ptr<SRDWindow> WaylandPlatform::create_window(const std::string& title, int, int, int, int) {
+ std::cout << "Wayland (stub): create_window '" << title << "'" << std::endl;
+ return nullptr;
+}
+
+void WaylandPlatform::destroy_window(SRDWindow*) {}
+void WaylandPlatform::set_window_position(SRDWindow*, int, int) {}
+void WaylandPlatform::set_window_size(SRDWindow*, int, int) {}
+void WaylandPlatform::set_window_title(SRDWindow*, const std::string&) {}
+void WaylandPlatform::focus_window(SRDWindow*) {}
+void WaylandPlatform::minimize_window(SRDWindow*) {}
+void WaylandPlatform::maximize_window(SRDWindow*) {}
+void WaylandPlatform::close_window(SRDWindow*) {}
+std::vector<Monitor> WaylandPlatform::get_monitors() { return {}; }
+Monitor WaylandPlatform::get_primary_monitor() { return Monitor{}; }
+void WaylandPlatform::grab_keyboard() {}
+void WaylandPlatform::ungrab_keyboard() {}
+void WaylandPlatform::grab_pointer() {}
+void WaylandPlatform::ungrab_pointer() {}
+void WaylandPlatform::set_window_decorations(SRDWindow*, bool enabled) { decorations_enabled_ = enabled; }
+void WaylandPlatform::set_window_border_color(SRDWindow*, int, int, int) {}
+void WaylandPlatform::set_window_border_width(SRDWindow*, int) {}
+bool WaylandPlatform::get_window_decorations(SRDWindow*) const { return decorations_enabled_; }
+
+// Private helpers (stubs)
+bool WaylandPlatform::setup_wlroots_backend() { return true; }
+bool WaylandPlatform::setup_compositor() { return true; }
+bool WaylandPlatform::setup_shell_protocols() { return true; }
+void WaylandPlatform::handle_registry_global(struct wl_registry*, uint32_t, const char*, uint32_t) {}
+void WaylandPlatform::handle_registry_global_remove(struct wl_registry*, uint32_t) {}
+void WaylandPlatform::handle_xdg_surface_new(struct wlr_xdg_surface*) {}
+void WaylandPlatform::handle_xdg_surface_destroy(struct wlr_xdg_surface*) {}
+void WaylandPlatform::handle_xdg_toplevel_new(struct wlr_xdg_toplevel*) {}
+void WaylandPlatform::handle_xdg_toplevel_destroy(struct wlr_xdg_toplevel*) {}
+void WaylandPlatform::handle_output_new(struct wlr_output*) {}
+void WaylandPlatform::handle_output_destroy(struct wlr_output*) {}
+void WaylandPlatform::handle_output_frame(struct wlr_output*) {}
+void WaylandPlatform::handle_pointer_motion(struct wlr_pointer_motion_event*) {}
+void WaylandPlatform::handle_pointer_button(struct wlr_pointer_button_event*) {}
+void WaylandPlatform::handle_pointer_axis(struct wlr_pointer_axis_event*) {}
+void WaylandPlatform::keyboard_key_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::pointer_motion_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::pointer_button_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::pointer_axis_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::output_new_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::output_destroy_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::output_frame_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::xdg_surface_new_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::xdg_surface_destroy_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::xdg_toplevel_new_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::xdg_toplevel_destroy_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::manage_xdg_window(struct wlr_xdg_surface*) {}
+void WaylandPlatform::unmanage_window(SRDWindow*) {}
+void WaylandPlatform::handle_output_mode(struct wlr_output*) {}
+void WaylandPlatform::handle_output_scale(struct wlr_output*) {}
+void WaylandPlatform::handle_key_event(uint32_t, bool) {}
+void WaylandPlatform::handle_button_event(uint32_t, bool) {}
+void WaylandPlatform::create_surface_window(struct wlr_surface*) {}
+void WaylandPlatform::destroy_surface_window(struct wlr_surface*) {}
+void WaylandPlatform::update_surface_window(struct wlr_surface*) {}
+void WaylandPlatform::convert_wlroots_event_to_srdwm_event(void*, EventType) {}
+void WaylandPlatform::handle_wlroots_error(const std::string&) {}
+void WaylandPlatform::setup_decoration_manager() {}
+void WaylandPlatform::handle_decoration_request(struct wlr_xdg_surface*, uint32_t) {}
diff --git a/src/platform/windows_platform.cc b/src/platform/windows_platform.cc
new file mode 100644
index 0000000..11cadca
--- /dev/null
+++ b/src/platform/windows_platform.cc
@@ -0,0 +1,585 @@
+#include "windows_platform.h"
+#include <iostream>
+#include <windows.h>
+#include <dwmapi.h>
+
+// Static member initialization
+SRDWindowsPlatform* SRDWindowsPlatform::instance_ = nullptr;
+
+SRDWindowsPlatform::SRDWindowsPlatform()
+ : h_instance_(nullptr)
+ , keyboard_hook_(nullptr)
+ , mouse_hook_(nullptr) {
+
+ instance_ = this;
+}
+
+SRDWindowsPlatform::~SRDWindowsPlatform() {
+ shutdown();
+ if (instance_ == this) {
+ instance_ = nullptr;
+ }
+}
+
+bool SRDWindowsPlatform::initialize() {
+ std::cout << "Initializing SRDWindows platform..." << std::endl;
+
+ // Get module handle
+ h_instance_ = GetModuleHandle(nullptr);
+ if (!h_instance_) {
+ std::cerr << "Failed to get module handle" << std::endl;
+ return false;
+ }
+
+ // Register window class
+ if (!register_window_class()) {
+ std::cerr << "Failed to register window class" << std::endl;
+ return false;
+ }
+
+ // Setup global hooks
+ setup_global_hooks();
+
+ std::cout << "SRDWindows platform initialized successfully" << std::endl;
+ return true;
+}
+
+void SRDWindowsPlatform::shutdown() {
+ std::cout << "Shutting down SRDWindows platform..." << std::endl;
+
+ // Unhook global hooks
+ if (keyboard_hook_) {
+ UnhookSRDWindowsHookEx(keyboard_hook_);
+ keyboard_hook_ = nullptr;
+ }
+
+ if (mouse_hook_) {
+ UnhookSRDWindowsHookEx(mouse_hook_);
+ mouse_hook_ = nullptr;
+ }
+
+ // Clean up windows
+ for (auto& pair : window_map_) {
+ if (pair.second) {
+ delete pair.second;
+ }
+ }
+ window_map_.clear();
+
+ std::cout << "SRDWindows platform shutdown complete" << std::endl;
+}
+
+// SRDWindow decoration implementations
+void SRDWindowsPlatform::set_window_decorations(SRDWindow* window, bool enabled) {
+ std::cout << "SRDWindowsPlatform: Set window decorations " << (enabled ? "enabled" : "disabled") << std::endl;
+
+ if (!window) return;
+
+ // Find the HWND for this window
+ HWND hwnd = nullptr;
+ for (const auto& pair : window_map_) {
+ if (pair.second == window) {
+ hwnd = pair.first;
+ break;
+ }
+ }
+
+ if (!hwnd) return;
+
+ decorations_enabled_ = enabled;
+
+ if (enabled) {
+ // Enable native window decorations
+ LONG style = GetSRDWindowLong(hwnd, GWL_STYLE);
+ style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+ SetSRDWindowLong(hwnd, GWL_STYLE, style);
+ } else {
+ // Disable native window decorations
+ LONG style = GetSRDWindowLong(hwnd, GWL_STYLE);
+ style &= ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
+ SetSRDWindowLong(hwnd, GWL_STYLE, style);
+ }
+
+ // Force window redraw
+ SetSRDWindowPos(hwnd, nullptr, 0, 0, 0, 0,
+ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
+}
+
+void SRDWindowsPlatform::set_window_border_color(SRDWindow* window, int r, int g, int b) {
+ std::cout << "SRDWindowsPlatform: Set border color RGB(" << r << "," << g << "," << b << ")" << std::endl;
+
+ if (!window) return;
+
+ // Find the HWND for this window
+ HWND hwnd = nullptr;
+ for (const auto& pair : window_map_) {
+ if (pair.second == window) {
+ hwnd = pair.first;
+ break;
+ }
+ }
+
+ if (!hwnd) return;
+
+ COLORREF color = RGB(r, g, b);
+ apply_dwm_border_color(hwnd, r, g, b);
+}
+
+void SRDWindowsPlatform::set_window_border_width(SRDWindow* window, int width) {
+ std::cout << "SRDWindowsPlatform: Set border width " << width << std::endl;
+
+ if (!window) return;
+
+ border_width_ = width;
+
+ // SRDWindows doesn't support custom border widths via DWM
+ // This would need to be implemented with custom window frames
+}
+
+bool SRDWindowsPlatform::get_window_decorations(SRDWindow* window) const {
+ if (!window) return false;
+
+ return decorations_enabled_;
+}
+
+void SRDWindowsPlatform::apply_dwm_border_color(HWND hwnd, int r, int g, int b) {
+ // Use DWM API to set border color (SRDWindows 11 feature)
+ COLORREF color = RGB(r, g, b);
+
+ HRESULT result = DwmSetSRDWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));
+ if (FAILED(result)) {
+ std::cerr << "Failed to set DWM border color" << std::endl;
+ }
+}
+
+void SRDWindowsPlatform::remove_dwm_border_color(HWND hwnd) {
+ // Remove custom border color
+ COLORREF color = DWMWA_COLOR_DEFAULT;
+
+ HRESULT result = DwmSetSRDWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));
+ if (FAILED(result)) {
+ std::cerr << "Failed to remove DWM border color" << std::endl;
+ }
+}
+
+bool SRDWindowsPlatform::register_window_class() {
+ WNDCLASSEX wc = {};
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.lpfnWndProc = window_proc;
+ wc.hInstance = h_instance_;
+ wc.lpszClassName = L"SRDWM_SRDWindow";
+ wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+
+ return RegisterClassEx(&wc) != 0;
+}
+
+void SRDWindowsPlatform::setup_global_hooks() {
+ std::cout << "Setting up global hooks..." << std::endl;
+
+ // Global keyboard hook
+ keyboard_hook_ = SetSRDWindowsHookEx(WH_KEYBOARD_LL,
+ keyboard_proc, h_instance_, 0);
+ if (!keyboard_hook_) {
+ std::cerr << "Failed to set keyboard hook" << std::endl;
+ }
+
+ // Global mouse hook
+ mouse_hook_ = SetSRDWindowsHookEx(WH_MOUSE_LL,
+ mouse_proc, h_instance_, 0);
+ if (!mouse_hook_) {
+ std::cerr << "Failed to set mouse hook" << std::endl;
+ }
+
+ std::cout << "Global hooks setup complete" << std::endl;
+}
+
+LRESULT CALLBACK SRDWindowsPlatform::window_proc(HWND hwnd, UINT msg,
+ WPARAM wparam, LPARAM lparam) {
+ switch (msg) {
+ case WM_CREATE:
+ std::cout << "SRDWindow created: " << hwnd << std::endl;
+ break;
+
+ case WM_DESTROY:
+ std::cout << "SRDWindow destroyed: " << hwnd << std::endl;
+ break;
+
+ case WM_SIZE:
+ // Handle window resizing
+ break;
+
+ case WM_MOVE:
+ // Handle window moving
+ break;
+
+ case WM_SETFOCUS:
+ // Handle window focus
+ break;
+
+ case WM_KILLFOCUS:
+ // Handle window unfocus
+ break;
+
+ case WM_CLOSE:
+ // Handle window close request
+ break;
+
+ default:
+ return DefSRDWindowProc(hwnd, msg, wparam, lparam);
+ }
+ return 0;
+}
+
+LRESULT CALLBACK SRDWindowsPlatform::keyboard_proc(int nCode, WPARAM wparam, LPARAM lparam) {
+ if (nCode >= 0) {
+ KBDLLHOOKSTRUCT* kbhs = (KBDLLHOOKSTRUCT*)lparam;
+
+ if (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN) {
+ std::cout << "Key pressed: " << kbhs->vkCode << std::endl;
+ } else if (wparam == WM_KEYUP || wparam == WM_SYSKEYUP) {
+ std::cout << "Key released: " << kbhs->vkCode << std::endl;
+ }
+ }
+ return CallNextHookEx(nullptr, nCode, wparam, lparam);
+}
+
+LRESULT CALLBACK SRDWindowsPlatform::mouse_proc(int nCode, WPARAM wparam, LPARAM lparam) {
+ if (nCode >= 0) {
+ MSLLHOOKSTRUCT* mhs = (MSLLHOOKSTRUCT*)lparam;
+
+ switch (wparam) {
+ case WM_LBUTTONDOWN:
+ std::cout << "Left mouse button down at (" << mhs->pt.x << ", " << mhs->pt.y << ")" << std::endl;
+ break;
+
+ case WM_LBUTTONUP:
+ std::cout << "Left mouse button up at (" << mhs->pt.x << ", " << mhs->pt.y << ")" << std::endl;
+ break;
+
+ case WM_RBUTTONDOWN:
+ std::cout << "Right mouse button down at (" << mhs->pt.x << ", " << mhs->pt.y << ")" << std::endl;
+ break;
+
+ case WM_RBUTTONUP:
+ std::cout << "Right mouse button up at (" << mhs->pt.x << ", " << mhs->pt.y << ")" << std::endl;
+ break;
+
+ case WM_MOUSEMOVE:
+ // Handle mouse movement
+ break;
+ }
+ }
+ return CallNextHookEx(nullptr, nCode, wparam, lparam);
+}
+
+void SRDWindowsPlatform::convert_win32_message(UINT msg, WPARAM wparam, LPARAM lparam, std::vector<Event>& events) {
+ Event event;
+
+ switch (msg) {
+ case WM_CREATE:
+ event.type = EventType::SRDWindowCreated;
+ break;
+ case WM_DESTROY:
+ event.type = EventType::SRDWindowDestroyed;
+ break;
+ case WM_MOVE:
+ event.type = EventType::SRDWindowMoved;
+ break;
+ case WM_SIZE:
+ event.type = EventType::SRDWindowResized;
+ break;
+ case WM_SETFOCUS:
+ event.type = EventType::SRDWindowFocused;
+ break;
+ case WM_KILLFOCUS:
+ event.type = EventType::SRDWindowUnfocused;
+ break;
+ case WM_KEYDOWN:
+ event.type = EventType::KeyPress;
+ break;
+ case WM_KEYUP:
+ event.type = EventType::KeyRelease;
+ break;
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ event.type = EventType::MouseButtonPress;
+ break;
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ event.type = EventType::MouseButtonRelease;
+ break;
+ case WM_MOUSEMOVE:
+ event.type = EventType::MouseMotion;
+ break;
+ default:
+ return; // Skip unknown messages
+ }
+
+ event.data = nullptr;
+ event.data_size = 0;
+ events.push_back(event);
+}
+
+bool SRDWindowsPlatform::poll_events(std::vector<Event>& events) {
+ if (!initialized_) return false;
+
+ events.clear();
+
+ // Process SRDWindows messages
+ MSG msg;
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+
+ // Convert SRDWindows message to SRDWM event
+ convert_win32_message(msg.message, msg.wParam, msg.lParam, events);
+ }
+
+ return !events.empty();
+}
+
+void SRDWindowsPlatform::process_event(const Event& event) {
+ // TODO: Implement event processing
+}
+
+std::unique_ptr<SRDWindow> SRDWindowsPlatform::create_window(const std::string& title, int x, int y, int width, int height) {
+ // Convert title to wide string
+ int title_len = MultiByteToWideChar(CP_UTF8, 0, title.c_str(), -1, nullptr, 0);
+ std::wstring wtitle(title_len, 0);
+ MultiByteToWideChar(CP_UTF8, 0, title.c_str(), -1, &wtitle[0], title_len);
+
+ // Create window
+ HWND hwnd = CreateSRDWindowEx(
+ WS_EX_OVERLAPPEDWINDOW,
+ L"SRDWM_SRDWindow",
+ wtitle.c_str(),
+ WS_OVERLAPPEDWINDOW,
+ x, y, width, height,
+ nullptr, nullptr, h_instance_, nullptr
+ );
+
+ if (!hwnd) {
+ std::cerr << "Failed to create SRDWindows window" << std::endl;
+ return nullptr;
+ }
+
+ // Create SRDWM window object
+ auto window = std::make_unique<SRDWindow>();
+ // TODO: Set window properties
+
+ // Store window mapping
+ window_map_[hwnd] = window.get();
+
+ std::cout << "Created SRDWindows window: " << hwnd << " (" << title << ")" << std::endl;
+ return window;
+}
+
+void SRDWindowsPlatform::destroy_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ DestroySRDWindow(pair.first);
+ window_map_.erase(pair.first);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::set_window_position(SRDWindow* window, int x, int y) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ SetSRDWindowPos(pair.first, nullptr, x, y, 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::set_window_size(SRDWindow* window, int width, int height) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ SetSRDWindowPos(pair.first, nullptr, 0, 0, width, height,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::set_window_title(SRDWindow* window, const std::string& title) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ // Convert title to wide string
+ int title_len = MultiByteToWideChar(CP_UTF8, 0, title.c_str(), -1, nullptr, 0);
+ std::wstring wtitle(title_len, 0);
+ MultiByteToWideChar(CP_UTF8, 0, title.c_str(), -1, &wtitle[0], title_len);
+
+ SetSRDWindowText(pair.first, wtitle.c_str());
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::focus_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ SetForegroundSRDWindow(pair.first);
+ SetFocus(pair.first);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::minimize_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ ShowSRDWindow(pair.first, SW_MINIMIZE);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::maximize_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ ShowSRDWindow(pair.first, SW_MAXIMIZE);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::close_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ PostMessage(pair.first, WM_CLOSE, 0, 0);
+ break;
+ }
+ }
+}
+
+std::vector<Monitor> SRDWindowsPlatform::get_monitors() {
+ std::vector<Monitor> monitors;
+
+ // Enumerate monitors using EnumDisplayMonitors
+ EnumDisplayMonitors(nullptr, nullptr,
+ [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL {
+ auto* monitors = reinterpret_cast<std::vector<Monitor>*>(dwData);
+
+ MONITORINFOEX monitorInfo;
+ monitorInfo.cbSize = sizeof(MONITORINFOEX);
+ GetMonitorInfo(hMonitor, &monitorInfo);
+
+ Monitor monitor;
+ monitor.id = reinterpret_cast<int>(hMonitor);
+ monitor.name = std::string(monitorInfo.szDevice);
+ monitor.x = monitorInfo.rcMonitor.left;
+ monitor.y = monitorInfo.rcMonitor.top;
+ monitor.width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
+ monitor.height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
+ monitor.refresh_rate = 60; // TODO: Get actual refresh rate
+
+ monitors->push_back(monitor);
+
+ return TRUE;
+ }, reinterpret_cast<LPARAM>(&monitors));
+
+ return monitors;
+}
+
+Monitor SRDWindowsPlatform::get_primary_monitor() {
+ auto monitors = get_monitors();
+ if (!monitors.empty()) {
+ return monitors[0];
+ }
+
+ // Fallback to primary display
+ Monitor monitor;
+ monitor.id = 0;
+ monitor.name = "Primary Display";
+ monitor.x = 0;
+ monitor.y = 0;
+ monitor.width = GetSystemMetrics(SM_CXSCREEN);
+ monitor.height = GetSystemMetrics(SM_CYSCREEN);
+ monitor.refresh_rate = 60;
+
+ return monitor;
+}
+
+void SRDWindowsPlatform::grab_keyboard() {
+ // TODO: Implement keyboard grabbing
+ std::cout << "Keyboard grabbing setup" << std::endl;
+}
+
+void SRDWindowsPlatform::ungrab_keyboard() {
+ // TODO: Implement keyboard ungrab
+ std::cout << "Keyboard ungrab" << std::endl;
+}
+
+void SRDWindowsPlatform::grab_pointer() {
+ // TODO: Implement pointer grabbing
+ std::cout << "Pointer grabbing setup" << std::endl;
+}
+
+void SRDWindowsPlatform::ungrab_pointer() {
+ // TODO: Implement pointer ungrab
+ std::cout << "Pointer ungrab" << std::endl;
+}
+
+void SRDWindowsPlatform::convert_windows_message_to_event(const MSG& msg, std::vector<Event>& events) {
+ // TODO: Convert SRDWindows messages to SRDWM events
+ switch (msg.message) {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ // Convert to key press event
+ break;
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ // Convert to key release event
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ // Convert to button press event
+ break;
+
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ // Convert to button release event
+ break;
+
+ case WM_MOUSEMOVE:
+ // Convert to mouse motion event
+ break;
+
+ case WM_SIZE:
+ // Convert to window resize event
+ break;
+
+ case WM_MOVE:
+ // Convert to window move event
+ break;
+ }
+}
+
+void SRDWindowsPlatform::handle_global_keyboard(WPARAM wparam, KBDLLHOOKSTRUCT* kbhs) {
+ // TODO: Implement global keyboard handling
+}
+
+void SRDWindowsPlatform::handle_global_mouse(WPARAM wparam, MSLLHOOKSTRUCT* mhs) {
+ // TODO: Implement global mouse handling
+}
+
+
diff --git a/src/platform/windows_platform.h b/src/platform/windows_platform.h
new file mode 100644
index 0000000..70b7d54
--- /dev/null
+++ b/src/platform/windows_platform.h
@@ -0,0 +1,140 @@
+#ifndef SRDWM_WINDOWS_PLATFORM_H
+#define SRDWM_WINDOWS_PLATFORM_H
+
+#include "platform.h"
+#include <windows.h>
+#include <memory>
+#include <string>
+#include <map>
+
+class SRDWindowsPlatform : public Platform {
+public:
+ SRDWindowsPlatform();
+ ~SRDWindowsPlatform() override;
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ // SRDWindow decorations (SRDWindows implementation)
+ void set_window_decorations(SRDWindow* window, bool enabled) override;
+ void set_window_border_color(SRDWindow* window, int r, int g, int b) override;
+ void set_window_border_width(SRDWindow* window, int width) override;
+ bool get_window_decorations(SRDWindow* window) const override;
+
+ // Windows-specific features
+ void enable_dwm_composition(bool enabled);
+ void set_dwm_window_attribute(HWND hwnd, DWORD attribute, DWORD value);
+ void set_dwm_window_thumbnail(HWND hwnd, HWND thumbnail_hwnd);
+ void set_dwm_window_peek(HWND hwnd, bool enabled);
+
+ // Virtual Desktop support (Windows 10+)
+ void create_virtual_desktop();
+ void remove_virtual_desktop(int desktop_id);
+ void switch_to_virtual_desktop(int desktop_id);
+ int get_current_virtual_desktop() const;
+ std::vector<int> get_virtual_desktops() const;
+ void move_window_to_desktop(SRDWindow* window, int desktop_id);
+
+ // Taskbar integration
+ void set_taskbar_visible(bool visible);
+ void set_taskbar_position(int position); // 0=bottom, 1=top, 2=left, 3=right
+ void set_taskbar_auto_hide(bool enabled);
+ void update_taskbar_preview(HWND hwnd, const std::string& title);
+
+ // Aero effects
+ void enable_aero_effects(bool enabled);
+ void set_window_transparency(HWND hwnd, BYTE alpha);
+ void set_window_blur(HWND hwnd, bool enabled);
+ void set_window_shadow(HWND hwnd, bool enabled);
+
+ // System tray integration
+ void add_system_tray_icon(const std::string& tooltip, HICON icon);
+ void remove_system_tray_icon();
+ void show_system_tray_menu(HMENU menu);
+
+ std::string get_platform_name() const override;
+ bool is_wayland() const override;
+ bool is_x11() const override;
+ bool is_windows() const override;
+ bool is_macos() const override;
+
+private:
+ bool initialized_;
+ HINSTANCE h_instance_;
+ std::map<HWND, SRDWindow*> window_map_;
+ std::vector<Monitor> monitors_;
+
+ // Decoration state
+ bool decorations_enabled_;
+ int border_width_;
+ COLORREF border_color_;
+ COLORREF focused_border_color_;
+
+ // Windows-specific state
+ bool dwm_enabled_;
+ bool aero_enabled_;
+ bool taskbar_visible_;
+ bool taskbar_auto_hide_;
+ int taskbar_position_;
+ int current_virtual_desktop_;
+ std::vector<int> virtual_desktops_;
+ NOTIFYICONDATA system_tray_icon_;
+
+ // SRDWindow class registration
+ bool register_window_class();
+ void unregister_window_class();
+
+ // SRDWindow procedure
+ static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
+
+ // Event conversion
+ void convert_win32_message(UINT msg, WPARAM wparam, LPARAM lparam, std::vector<Event>& events);
+
+ // Monitor enumeration
+ static BOOL CALLBACK enum_monitor_proc(HMONITOR hmonitor, HDC hdc_monitor, LPRECT lprc_monitor, LPARAM dw_data);
+
+ // Utility methods
+ void update_monitors();
+ SRDWindow* find_window_by_hwnd(HWND hwnd);
+
+ // Decoration methods
+ void apply_dwm_border_color(HWND hwnd, int r, int g, int b);
+ void remove_dwm_border_color(HWND hwnd);
+
+ // Virtual Desktop methods
+ void initialize_virtual_desktops();
+ void cleanup_virtual_desktops();
+
+ // DWM methods
+ bool initialize_dwm();
+ void cleanup_dwm();
+
+ // Taskbar methods
+ void initialize_taskbar();
+ void update_taskbar();
+};
+
+#endif // SRDWM_WINDOWS_PLATFORM_H
+
diff --git a/src/platform/x11_platform.cc b/src/platform/x11_platform.cc
new file mode 100644
index 0000000..0d25369
--- /dev/null
+++ b/src/platform/x11_platform.cc
@@ -0,0 +1,1005 @@
+#include "x11_platform.h"
+#include <iostream>
+#include <cstring>
+
+X11Platform::X11Platform() {
+ std::cout << "X11Platform: Constructor called" << std::endl;
+}
+
+X11Platform::~X11Platform() {
+ std::cout << "X11Platform: Destructor called" << std::endl;
+}
+
+bool X11Platform::initialize() {
+ std::cout << "X11Platform: Initializing X11 backend..." << std::endl;
+
+ // Open X11 display
+ display_ = XOpenDisplay(nullptr);
+ if (!display_) {
+ std::cerr << "Failed to open X11 display" << std::endl;
+ return false;
+ }
+
+ // Get root window
+ root_ = DefaultRootWindow(display_);
+
+ // Check for other window manager
+ if (!check_for_other_wm()) {
+ std::cerr << "Another window manager is already running" << std::endl;
+ return false;
+ }
+
+ // Setup X11 environment
+ if (!setup_x11_environment()) {
+ std::cerr << "Failed to setup X11 environment" << std::endl;
+ return false;
+ }
+
+ // Setup event masks
+ if (!setup_event_masks()) {
+ std::cerr << "Failed to setup event masks" << std::endl;
+ return false;
+ }
+
+ // Setup atoms
+ setup_atoms();
+
+ // Setup extensions
+ setup_extensions();
+
+ // Initialize decoration state
+ decorations_enabled_ = true;
+ border_width_ = 2;
+ border_color_ = 0x2e3440; // Default border color
+ focused_border_color_ = 0x88c0d0; // Default focused border color
+
+ std::cout << "X11Platform: Initialized successfully" << std::endl;
+ return true;
+}
+
+void X11Platform::shutdown() {
+ std::cout << "X11Platform: Shutting down..." << std::endl;
+
+ // Clean up windows
+ for (auto& pair : window_map_) {
+ if (pair.second) {
+ destroy_window(pair.second);
+ }
+ }
+ window_map_.clear();
+ frame_window_map_.clear();
+
+ // Close X11 display
+ if (display_) {
+ XCloseDisplay(display_);
+ display_ = nullptr;
+ }
+
+ std::cout << "X11Platform: Shutdown complete" << std::endl;
+}
+
+bool X11Platform::poll_events(std::vector<Event>& events) {
+ if (!display_) return false;
+
+ events.clear();
+
+ // Check for pending events
+ if (XPending(display_) > 0) {
+ XEvent xevent;
+ XNextEvent(display_, &xevent);
+
+ // Handle the X11 event
+ handle_x11_event(xevent);
+
+ // Convert to SRDWM events (simplified for now)
+ Event event;
+ event.type = EventType::WindowCreated; // Placeholder
+ event.data = nullptr;
+ event.data_size = 0;
+ events.push_back(event);
+
+ return true;
+ }
+
+ return false;
+}
+
+void X11Platform::process_event(const Event& event) {
+ std::cout << "X11Platform: Process event called" << std::endl;
+}
+
+std::unique_ptr<SRDWindow> X11Platform::create_window(const std::string& title, int x, int y, int width, int height) {
+ std::cout << "X11Platform: Create window called" << std::endl;
+ // TODO: Implement actual window creation when headers are available
+ return nullptr;
+}
+
+void X11Platform::destroy_window(SRDWindow* window) {
+ std::cout << "X11Platform: Destroy window called" << std::endl;
+}
+
+void X11Platform::set_window_position(SRDWindow* window, int x, int y) {
+ std::cout << "X11Platform: Set window position to (" << x << "," << y << ")" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XMoveWindow(display_, to_x11_window(x11_window), x, y);
+ XFlush(display_);
+}
+
+void X11Platform::set_window_size(SRDWindow* window, int width, int height) {
+ std::cout << "X11Platform: Set window size to (" << width << "x" << height << ")" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XResizeWindow(display_, to_x11_window(x11_window), static_cast<unsigned int>(width), static_cast<unsigned int>(height));
+ XFlush(display_);
+}
+
+void X11Platform::set_window_title(SRDWindow* window, const std::string& title) {
+ std::cout << "X11Platform: Set window title to '" << title << "'" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XStoreName(display_, to_x11_window(x11_window), title.c_str());
+ XFlush(display_);
+}
+
+void X11Platform::focus_window(SRDWindow* window) {
+ std::cout << "X11Platform: Focus window" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XSetInputFocus(display_, to_x11_window(x11_window), RevertToParent, CurrentTime);
+ XFlush(display_);
+}
+
+void X11Platform::minimize_window(SRDWindow* window) {
+ std::cout << "X11Platform: Minimize window called" << std::endl;
+}
+
+void X11Platform::maximize_window(SRDWindow* window) {
+ std::cout << "X11Platform: Maximize window called" << std::endl;
+}
+
+void X11Platform::close_window(SRDWindow* window) {
+ std::cout << "X11Platform: Close window" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ Atom wm_delete = XInternAtom(display_, "WM_DELETE_WINDOW", False);
+ if (wm_delete != None) {
+ XEvent ev{};
+ ev.xclient.type = ClientMessage;
+ ev.xclient.message_type = XInternAtom(display_, "WM_PROTOCOLS", False);
+ ev.xclient.display = display_;
+ ev.xclient.window = to_x11_window(x11_window);
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = wm_delete;
+ ev.xclient.data.l[1] = CurrentTime;
+ XSendEvent(display_, to_x11_window(x11_window), False, NoEventMask, &ev);
+ XFlush(display_);
+ } else {
+ XDestroyWindow(display_, to_x11_window(x11_window));
+ XFlush(display_);
+ }
+}
+
+// EWMH (Extended Window Manager Hints) support implementation
+void X11Platform::set_ewmh_supported(bool supported) {
+ ewmh_supported_ = supported;
+ if (supported) {
+ setup_ewmh();
+ }
+ std::cout << "X11Platform: EWMH support " << (supported ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::set_window_type(SRDWindow* window, const std::string& type) {
+ if (!ewmh_supported_ || !window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ Atom window_type_atom = None;
+
+ if (type == "desktop") window_type_atom = _NET_WM_WINDOW_TYPE_DESKTOP_;
+ else if (type == "dock") window_type_atom = _NET_WM_WINDOW_TYPE_DOCK_;
+ else if (type == "toolbar") window_type_atom = _NET_WM_WINDOW_TYPE_TOOLBAR_;
+ else if (type == "menu") window_type_atom = _NET_WM_WINDOW_TYPE_MENU_;
+ else if (type == "utility") window_type_atom = _NET_WM_WINDOW_TYPE_UTILITY_;
+ else if (type == "splash") window_type_atom = _NET_WM_WINDOW_TYPE_SPLASH_;
+ else if (type == "dialog") window_type_atom = _NET_WM_WINDOW_TYPE_DIALOG_;
+ else if (type == "dropdown_menu") window_type_atom = _NET_WM_WINDOW_TYPE_DROPDOWN_MENU_;
+ else if (type == "popup_menu") window_type_atom = _NET_WM_WINDOW_TYPE_POPUP_MENU_;
+ else if (type == "tooltip") window_type_atom = _NET_WM_WINDOW_TYPE_TOOLTIP_;
+ else if (type == "notification") window_type_atom = _NET_WM_WINDOW_TYPE_NOTIFICATION_;
+ else if (type == "combo") window_type_atom = _NET_WM_WINDOW_TYPE_COMBO_;
+ else if (type == "dnd") window_type_atom = _NET_WM_WINDOW_TYPE_DND_;
+ else window_type_atom = _NET_WM_WINDOW_TYPE_NORMAL_;
+
+ if (window_type_atom != None) {
+ XChangeProperty(display_, x11_window, _NET_WM_WINDOW_TYPE_, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)&window_type_atom, 1);
+ }
+}
+
+void X11Platform::set_window_state(SRDWindow* window, const std::vector<std::string>& states) {
+ if (!ewmh_supported_ || !window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ std::vector<Atom> state_atoms;
+
+ for (const auto& state : states) {
+ Atom state_atom = None;
+ if (state == "maximized_vert") state_atom = _NET_WM_STATE_MAXIMIZED_VERT_;
+ else if (state == "maximized_horz") state_atom = _NET_WM_STATE_MAXIMIZED_HORZ_;
+ else if (state == "fullscreen") state_atom = _NET_WM_STATE_FULLSCREEN_;
+ else if (state == "above") state_atom = _NET_WM_STATE_ABOVE_;
+ else if (state == "below") state_atom = _NET_WM_STATE_BELOW_;
+
+ if (state_atom != None) {
+ state_atoms.push_back(state_atom);
+ }
+ }
+
+ if (!state_atoms.empty()) {
+ XChangeProperty(display_, x11_window, _NET_WM_STATE_, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)state_atoms.data(), state_atoms.size());
+ }
+}
+
+void X11Platform::set_window_strut(SRDWindow* window, int left, int right, int top, int bottom) {
+ if (!ewmh_supported_ || !window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ long strut[12] = {left, right, top, bottom, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ XChangeProperty(display_, x11_window, XInternAtom(display_, "_NET_WM_STRUT_PARTIAL", False),
+ XA_CARDINAL, 32, PropModeReplace, (unsigned char*)strut, 12);
+}
+
+// Virtual Desktop support implementation
+void X11Platform::create_virtual_desktop(const std::string& name) {
+ if (!ewmh_supported_) return;
+
+ int desktop_id = virtual_desktops_.size();
+ virtual_desktops_.push_back(desktop_id);
+
+ // Update EWMH desktop info
+ update_ewmh_desktop_info();
+
+ std::cout << "X11Platform: Created virtual desktop " << desktop_id << " (" << name << ")" << std::endl;
+}
+
+void X11Platform::remove_virtual_desktop(int desktop_id) {
+ if (!ewmh_supported_) return;
+
+ auto it = std::find(virtual_desktops_.begin(), virtual_desktops_.end(), desktop_id);
+ if (it != virtual_desktops_.end()) {
+ virtual_desktops_.erase(it);
+
+ // If removing current desktop, switch to first available
+ if (desktop_id == current_virtual_desktop_ && !virtual_desktops_.empty()) {
+ switch_to_virtual_desktop(virtual_desktops_[0]);
+ }
+
+ update_ewmh_desktop_info();
+ std::cout << "X11Platform: Removed virtual desktop " << desktop_id << std::endl;
+ }
+}
+
+void X11Platform::switch_to_virtual_desktop(int desktop_id) {
+ if (!ewmh_supported_) return;
+
+ auto it = std::find(virtual_desktops_.begin(), virtual_desktops_.end(), desktop_id);
+ if (it != virtual_desktops_.end()) {
+ current_virtual_desktop_ = desktop_id;
+
+ // Update EWMH current desktop
+ XChangeProperty(display_, root_, _NET_CURRENT_DESKTOP_, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&current_virtual_desktop_, 1);
+
+ std::cout << "X11Platform: Switched to virtual desktop " << desktop_id << std::endl;
+ }
+}
+
+int X11Platform::get_current_virtual_desktop() const {
+ return current_virtual_desktop_;
+}
+
+std::vector<int> X11Platform::get_virtual_desktops() const {
+ return virtual_desktops_;
+}
+
+void X11Platform::move_window_to_desktop(SRDWindow* window, int desktop_id) {
+ if (!ewmh_supported_ || !window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XChangeProperty(display_, x11_window, _NET_WM_DESKTOP_, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&desktop_id, 1);
+
+ std::cout << "X11Platform: Moved window " << window->getId() << " to desktop " << desktop_id << std::endl;
+}
+
+std::vector<Monitor> X11Platform::get_monitors() {
+ std::cout << "X11Platform: Get monitors called" << std::endl;
+ // Return a default monitor for now
+ return {Monitor{0, 0, 0, 1920, 1080}};
+}
+
+Monitor X11Platform::get_primary_monitor() {
+ std::cout << "X11Platform: Get primary monitor called" << std::endl;
+ return Monitor{0, 0, 0, 1920, 1080};
+}
+
+void X11Platform::grab_keyboard() {
+ std::cout << "X11Platform: Grab keyboard called" << std::endl;
+}
+
+void X11Platform::ungrab_keyboard() {
+ std::cout << "X11Platform: Ungrab keyboard called" << std::endl;
+}
+
+void X11Platform::grab_pointer() {
+ std::cout << "X11Platform: Grab pointer called" << std::endl;
+}
+
+void X11Platform::ungrab_pointer() {
+ std::cout << "X11Platform: Ungrab pointer called" << std::endl;
+}
+
+// Private method stubs removed - actual implementations exist below
+
+void X11Platform::setup_extensions() {
+ std::cout << "X11Platform: Setup extensions called" << std::endl;
+}
+
+bool X11Platform::check_for_other_wm() {
+ // Try to select SubstructureRedirectMask on root window
+ // If another WM is running, this will fail
+ XSelectInput(display_, root_, SubstructureRedirectMask);
+ XSync(display_, False);
+
+ // Check if the selection was successful
+ XErrorHandler old_handler = XSetErrorHandler([](Display*, XErrorEvent*) -> int {
+ return 0; // Ignore errors
+ });
+
+ XSync(display_, False);
+ XSetErrorHandler(old_handler);
+
+ return true; // Simplified check
+}
+
+bool X11Platform::setup_x11_environment() {
+ std::cout << "X11Platform: Setting up X11 environment..." << std::endl;
+
+ // Set up error handling
+ XSetErrorHandler([](Display*, XErrorEvent* e) -> int {
+ if (e->error_code == BadWindow ||
+ e->error_code == BadMatch ||
+ e->error_code == BadAccess) {
+ return 0; // Ignore common errors
+ }
+ std::cerr << "X11 error: " << e->error_code << std::endl;
+ return 0;
+ });
+
+ return true;
+}
+
+bool X11Platform::setup_event_masks() {
+ std::cout << "X11Platform: Setting up event masks..." << std::endl;
+
+ // Set up root window event mask
+ long event_mask = SubstructureRedirectMask | SubstructureNotifyMask |
+ StructureNotifyMask | PropertyChangeMask |
+ ButtonPressMask | ButtonReleaseMask |
+ KeyPressMask | KeyReleaseMask |
+ PointerMotionMask | EnterWindowMask | LeaveWindowMask;
+
+ XSelectInput(display_, root_, event_mask);
+
+ return true;
+}
+
+void X11Platform::setup_atoms() {
+ std::cout << "X11Platform: Setting up atoms..." << std::endl;
+
+ // TODO: Implement atom setup for EWMH/ICCCM
+ // This would involve creating atoms for window manager protocols
+}
+
+void X11Platform::handle_x11_event(XEvent& event) {
+ std::cout << "X11Platform: Handle X11 event called" << std::endl;
+
+ switch (event.type) {
+ case MapRequest:
+ handle_map_request(event.xmaprequest);
+ break;
+ case ConfigureRequest:
+ handle_configure_request(event.xconfigurerequest);
+ break;
+ case DestroyNotify:
+ handle_destroy_notify(event.xdestroywindow);
+ break;
+ case UnmapNotify:
+ handle_unmap_notify(event.xunmap);
+ break;
+ case KeyPress:
+ handle_key_press(event.xkey);
+ break;
+ case ButtonPress:
+ handle_button_press(event.xbutton);
+ break;
+ case MotionNotify:
+ handle_motion_notify(event.xmotion);
+ break;
+ default:
+ break;
+ }
+}
+
+void X11Platform::handle_map_request(XMapRequestEvent& event) {
+ std::cout << "X11Platform: Map request for window " << static_cast<unsigned long>(event.window) << std::endl;
+
+ // Create a SRDWindow object for this X11 window
+ auto window = std::make_unique<SRDWindow>(static_cast<int>(static_cast<unsigned long>(event.window)), "X11 Window");
+
+ // Add to window map
+ window_map_[from_x11_window(event.window)] = window.get();
+ window.release();
+
+ // Map the window
+ XMapWindow(display_, event.window);
+
+ // Apply decorations if enabled
+ if (decorations_enabled_) {
+ create_frame_window(window_map_[from_x11_window(event.window)]);
+ }
+}
+
+void X11Platform::handle_configure_request(XConfigureRequestEvent& event) {
+ std::cout << "X11Platform: Configure request for window " << static_cast<unsigned long>(event.window) << std::endl;
+
+ XWindowChanges changes;
+ changes.x = event.x;
+ changes.y = event.y;
+ changes.width = event.width;
+ changes.height = event.height;
+ changes.border_width = event.border_width;
+ changes.sibling = static_cast<::Window>(event.above);
+ changes.stack_mode = event.detail;
+
+ XConfigureWindow(display_, event.window, event.value_mask, &changes);
+}
+
+void X11Platform::handle_destroy_notify(XDestroyWindowEvent& event) {
+ std::cout << "X11Platform: Destroy notify for window " << static_cast<unsigned long>(event.window) << std::endl;
+
+ auto it = window_map_.find(from_x11_window(event.window));
+ if (it != window_map_.end()) {
+ destroy_window(it->second);
+ window_map_.erase(it);
+ }
+}
+
+void X11Platform::handle_unmap_notify(XUnmapEvent& event) {
+ std::cout << "X11Platform: Unmap notify for window " << static_cast<unsigned long>(event.window) << std::endl;
+
+ // Handle window unmapping
+}
+
+void X11Platform::handle_key_press(XKeyEvent& event) {
+ std::cout << "X11Platform: Key press event" << std::endl;
+
+ // Convert X11 key event to SRDWM event
+ // TODO: Implement key event conversion
+}
+
+void X11Platform::handle_button_press(XButtonEvent& event) {
+ std::cout << "X11Platform: Button press event" << std::endl;
+
+ // Convert X11 button event to SRDWM event
+ // TODO: Implement button event conversion
+}
+
+void X11Platform::handle_motion_notify(XMotionEvent& event) {
+ std::cout << "X11Platform: Motion notify event" << std::endl;
+
+ // Convert X11 motion event to SRDWM event
+ // TODO: Implement motion event conversion
+}
+
+// Window decoration implementations
+void X11Platform::set_window_decorations(SRDWindow* window, bool enabled) {
+ std::cout << "X11Platform: Set window decorations " << (enabled ? "enabled" : "disabled") << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+
+ if (enabled) {
+ create_frame_window(window);
+ } else {
+ destroy_frame_window(window);
+ }
+
+ decorations_enabled_ = enabled;
+}
+
+void X11Platform::set_window_border_color(SRDWindow* window, int r, int g, int b) {
+ std::cout << "X11Platform: Set border color RGB(" << r << "," << g << "," << b << ")" << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ unsigned long color = (r << 16) | (g << 8) | b;
+
+ XSetWindowBorder(display_, to_x11_window(x11_window), color);
+
+ // Update decoration state
+ if (window == get_focused_window()) {
+ focused_border_color_ = color;
+ } else {
+ border_color_ = color;
+ }
+}
+
+void X11Platform::set_window_border_width(SRDWindow* window, int width) {
+ std::cout << "X11Platform: Set border width " << width << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XSetWindowBorderWidth(display_, to_x11_window(x11_window), width);
+
+ border_width_ = width;
+}
+
+bool X11Platform::get_window_decorations(SRDWindow* window) const {
+ if (!window) return false;
+
+ // Check if window has a frame window
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ auto it = frame_window_map_.find(x11_window);
+
+ return it != frame_window_map_.end();
+}
+
+void X11Platform::create_frame_window(SRDWindow* window) {
+ std::cout << "X11Platform: Create frame window for window " << window->getId() << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window client_window = static_cast<X11Window>(window->getId());
+
+ // Check if frame already exists
+ if (frame_window_map_.find(client_window) != frame_window_map_.end()) {
+ return;
+ }
+
+ // Get client window attributes
+ XWindowAttributes attr;
+ attr.x = 0;
+ attr.y = 0;
+ attr.width = 0;
+ attr.height = 0;
+ attr.border_width = 0;
+ attr.depth = 0;
+ attr.visual = nullptr;
+ attr.root = 0;
+ attr.c_class = 0;
+ attr.bit_gravity = 0;
+ attr.win_gravity = 0;
+ attr.backing_store = 0;
+ attr.backing_planes = 0;
+ attr.backing_pixel = 0;
+ attr.save_under = 0;
+ attr.colormap = 0;
+ attr.map_installed = 0;
+ attr.map_state = 0;
+ attr.all_event_masks = 0;
+ attr.your_event_mask = 0;
+ attr.do_not_propagate_mask = 0;
+ attr.override_redirect = 0;
+ if (XGetWindowAttributes(display_, to_x11_window(client_window), &attr) == 0) {
+ std::cerr << "Failed to get window attributes" << std::endl;
+ return;
+ }
+
+ // Create frame window
+ X11Window frame_window = from_x11_window(XCreateSimpleWindow(
+ display_, to_x11_window(root_),
+ attr.x, attr.y,
+ attr.width + border_width_ * 2,
+ attr.height + border_width_ + 30, // Add titlebar height
+ border_width_,
+ border_color_,
+ 0x000000 // Background color
+ ));
+
+ // Set frame window properties
+ XSetWindowAttributes frame_attr;
+ frame_attr.event_mask = ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | ExposureMask;
+ XChangeWindowAttributes(display_, to_x11_window(frame_window), CWEventMask, &frame_attr);
+
+ // Reparent client window into frame
+ XReparentWindow(display_, to_x11_window(client_window), to_x11_window(frame_window), border_width_, 30);
+
+ // Map frame window
+ XMapWindow(display_, to_x11_window(frame_window));
+
+ // Store frame window mapping
+ frame_window_map_[client_window] = frame_window;
+
+ // Draw titlebar
+ draw_titlebar(window);
+
+ std::cout << "X11Platform: Frame window created successfully" << std::endl;
+}
+
+void X11Platform::destroy_frame_window(SRDWindow* window) {
+ std::cout << "X11Platform: Destroy frame window for window " << window->getId() << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window client_window = static_cast<X11Window>(window->getId());
+
+ // Find frame window
+ auto it = frame_window_map_.find(client_window);
+ if (it == frame_window_map_.end()) {
+ return;
+ }
+
+ X11Window frame_window = it->second;
+
+ // Reparent client window back to root
+ XReparentWindow(display_, to_x11_window(client_window), to_x11_window(root_), 0, 0);
+
+ // Destroy frame window
+ XDestroyWindow(display_, to_x11_window(frame_window));
+
+ // Remove from mapping
+ frame_window_map_.erase(it);
+
+ std::cout << "X11Platform: Frame window destroyed successfully" << std::endl;
+}
+
+void X11Platform::draw_titlebar(SRDWindow* window) {
+ std::cout << "X11Platform: Draw titlebar for window " << window->getId() << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window client_window = static_cast<X11Window>(window->getId());
+
+ // Find frame window
+ auto it = frame_window_map_.find(client_window);
+ if (it == frame_window_map_.end()) {
+ return;
+ }
+
+ X11Window frame_window = it->second;
+
+ // Get window title
+ char* window_name = nullptr;
+ if (XFetchName(display_, to_x11_window(client_window), &window_name) && window_name) {
+ // Create GC for drawing
+ XGCValues gc_values;
+ gc_values.foreground = 0xFFFFFF; // White text
+ gc_values.background = 0x2E3440; // Dark background
+ gc_values.font = XLoadFont(display_, "fixed");
+
+ GC gc = XCreateGC(display_, to_x11_window(frame_window),
+ GCForeground | GCBackground | GCFont, &gc_values);
+
+ // Draw titlebar background
+ XSetForeground(display_, gc, 0x2E3440);
+ XFillRectangle(display_, to_x11_window(frame_window), gc, 0, 0, 800, 30); // Placeholder size
+
+ // Draw title text
+ XSetForeground(display_, gc, 0xFFFFFF);
+ XDrawString(display_, to_x11_window(frame_window), gc, 10, 20, window_name, strlen(window_name));
+
+ // Clean up
+ XFreeGC(display_, gc);
+ XFree(window_name);
+ }
+}
+
+void X11Platform::update_frame_geometry(SRDWindow* window) {
+ std::cout << "X11Platform: Update frame geometry" << std::endl;
+
+ // TODO: Implement when X11 headers are available
+ // Update frame window geometry when client window changes
+}
+
+SRDWindow* X11Platform::get_focused_window() const {
+ if (!display_) return nullptr;
+
+ typedef ::Window X11WindowType;
+ X11WindowType focused_window;
+ int revert_to;
+ XGetInputFocus(display_, &focused_window, &revert_to);
+
+ auto it = window_map_.find(from_x11_window(focused_window));
+ if (it != window_map_.end()) {
+ return it->second;
+ }
+
+ return nullptr;
+}
+
+// EWMH helper methods
+void X11Platform::setup_ewmh() {
+ if (!display_ || !ewmh_supported_) return;
+
+ // Set EWMH supported atoms
+ Atom supported[] = {
+ _NET_WM_STATE_,
+ _NET_WM_STATE_MAXIMIZED_VERT_,
+ _NET_WM_STATE_MAXIMIZED_HORZ_,
+ _NET_WM_STATE_FULLSCREEN_,
+ _NET_WM_STATE_ABOVE_,
+ _NET_WM_STATE_BELOW_,
+ _NET_WM_WINDOW_TYPE_,
+ _NET_WM_WINDOW_TYPE_DESKTOP_,
+ _NET_WM_WINDOW_TYPE_DOCK_,
+ _NET_WM_WINDOW_TYPE_TOOLBAR_,
+ _NET_WM_WINDOW_TYPE_MENU_,
+ _NET_WM_WINDOW_TYPE_UTILITY_,
+ _NET_WM_WINDOW_TYPE_SPLASH_,
+ _NET_WM_WINDOW_TYPE_DIALOG_,
+ _NET_WM_WINDOW_TYPE_DROPDOWN_MENU_,
+ _NET_WM_WINDOW_TYPE_POPUP_MENU_,
+ _NET_WM_WINDOW_TYPE_TOOLTIP_,
+ _NET_WM_WINDOW_TYPE_NOTIFICATION_,
+ _NET_WM_WINDOW_TYPE_COMBO_,
+ _NET_WM_WINDOW_TYPE_DND_,
+ _NET_WM_WINDOW_TYPE_NORMAL_,
+ _NET_WM_DESKTOP_,
+ _NET_NUMBER_OF_DESKTOPS_,
+ _NET_CURRENT_DESKTOP_,
+ _NET_DESKTOP_NAMES_
+ };
+
+ XChangeProperty(display_, root_, XInternAtom(display_, "_NET_SUPPORTED", False),
+ XA_ATOM, 32, PropModeReplace, (unsigned char*)supported,
+ sizeof(supported) / sizeof(supported[0]));
+
+ // Set initial desktop info
+ update_ewmh_desktop_info();
+
+ std::cout << "X11Platform: EWMH setup completed" << std::endl;
+}
+
+void X11Platform::update_ewmh_desktop_info() {
+ if (!display_ || !ewmh_supported_) return;
+
+ // Set number of desktops
+ int num_desktops = virtual_desktops_.size();
+ XChangeProperty(display_, root_, _NET_NUMBER_OF_DESKTOPS_, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&num_desktops, 1);
+
+ // Set current desktop
+ XChangeProperty(display_, root_, _NET_CURRENT_DESKTOP_, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&current_virtual_desktop_, 1);
+
+ // Set desktop names (simplified - just use numbers for now)
+ std::vector<std::string> desktop_names;
+ for (int i = 0; i < num_desktops; ++i) {
+ desktop_names.push_back("Desktop " + std::to_string(i + 1));
+ }
+
+ // Convert to X11 string format
+ std::string names_str;
+ for (const auto& name : desktop_names) {
+ names_str += name + '\0';
+ }
+
+ XChangeProperty(display_, root_, _NET_DESKTOP_NAMES_, XA_STRING, 8,
+ PropModeReplace, (unsigned char*)names_str.c_str(), names_str.length());
+}
+
+// Linux/X11-specific features implementation
+void X11Platform::enable_compositor(bool enabled) {
+ compositor_enabled_ = enabled;
+
+ if (enabled) {
+ // Try to enable compositor effects
+ // This is a simplified implementation - real compositors have more complex setup
+ std::cout << "X11Platform: Compositor effects enabled" << std::endl;
+ } else {
+ std::cout << "X11Platform: Compositor effects disabled" << std::endl;
+ }
+}
+
+void X11Platform::set_window_opacity(SRDWindow* window, unsigned char opacity) {
+ if (!window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+
+ // Set window opacity using _NET_WM_WINDOW_OPACITY atom
+ Atom opacity_atom = XInternAtom(display_, "_NET_WM_WINDOW_OPACITY", False);
+ if (opacity_atom != None) {
+ unsigned long opacity_value = (opacity << 24) | (opacity << 16) | (opacity << 8) | opacity;
+ XChangeProperty(display_, x11_window, opacity_atom, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&opacity_value, 1);
+ }
+
+ std::cout << "X11Platform: Set window " << window->getId() << " opacity to " << (int)opacity << std::endl;
+}
+
+void X11Platform::set_window_blur(SRDWindow* window, bool enabled) {
+ if (!window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+
+ // Set window blur using _NET_WM_WINDOW_BLUR atom (if supported)
+ Atom blur_atom = XInternAtom(display_, "_NET_WM_WINDOW_BLUR", False);
+ if (blur_atom != None) {
+ unsigned long blur_value = enabled ? 1 : 0;
+ XChangeProperty(display_, x11_window, blur_atom, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&blur_value, 1);
+ }
+
+ std::cout << "X11Platform: Set window " << window->getId() << " blur " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::set_window_shadow(SRDWindow* window, bool enabled) {
+ if (!window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+
+ // Set window shadow using _NET_WM_WINDOW_SHADOW atom (if supported)
+ Atom shadow_atom = XInternAtom(display_, "_NET_WM_WINDOW_SHADOW", False);
+ if (shadow_atom != None) {
+ unsigned long shadow_value = enabled ? 1 : 0;
+ XChangeProperty(display_, x11_window, shadow_atom, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&shadow_value, 1);
+ }
+
+ std::cout << "X11Platform: Set window " << window->getId() << " shadow " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+// RandR (Resize and Rotate) support implementation
+void X11Platform::enable_randr(bool enabled) {
+ randr_enabled_ = enabled;
+
+ if (enabled) {
+ initialize_randr();
+ } else {
+ cleanup_randr();
+ }
+
+ std::cout << "X11Platform: RandR support " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::set_monitor_rotation(int monitor_id, int rotation) {
+ if (!randr_enabled_) return;
+
+ // Rotation values: 0=0°, 1=90°, 2=180°, 3=270°
+ if (rotation < 0 || rotation > 3) return;
+
+ // TODO: Implement actual RandR rotation
+ std::cout << "X11Platform: Set monitor " << monitor_id << " rotation to " << (rotation * 90) << "°" << std::endl;
+}
+
+void X11Platform::set_monitor_refresh_rate(int monitor_id, int refresh_rate) {
+ if (!randr_enabled_) return;
+
+ if (refresh_rate < 30 || refresh_rate > 240) return;
+
+ // TODO: Implement actual RandR refresh rate setting
+ std::cout << "X11Platform: Set monitor " << monitor_id << " refresh rate to " << refresh_rate << " Hz" << std::endl;
+}
+
+void X11Platform::set_monitor_scale(int monitor_id, float scale) {
+ if (!randr_enabled_) return;
+
+ if (scale < 0.5f || scale > 3.0f) return;
+
+ // TODO: Implement actual RandR scaling
+ std::cout << "X11Platform: Set monitor " << monitor_id << " scale to " << scale << "x" << std::endl;
+}
+
+void X11Platform::initialize_randr() {
+ if (!display_) return;
+
+ // Check if RandR extension is available
+ int event_base, error_base;
+ if (XRRQueryExtension(display_, &event_base, &error_base)) {
+ std::cout << "X11Platform: RandR extension available" << std::endl;
+
+ // Get screen resources
+ Window root = DefaultRootWindow(display_);
+ int screen = DefaultScreen(display_);
+ XRRScreenResources* resources = XRRGetScreenResources(display_, root);
+
+ if (resources) {
+ // Process monitor information
+ for (int i = 0; i < resources->noutput; ++i) {
+ XRROutputInfo* output_info = XRRGetOutputInfo(display_, resources, resources->outputs[i]);
+ if (output_info && output_info->connection == RR_Connected) {
+ // Add monitor to our list
+ Monitor monitor;
+ monitor.id = i;
+ monitor.x = 0; // TODO: Get actual position
+ monitor.y = 0;
+ monitor.width = output_info->mm_width; // Convert mm to pixels
+ monitor.height = output_info->mm_height;
+ monitor.name = output_info->name;
+ monitor.refresh_rate = 60; // Default
+
+ monitors_.push_back(monitor);
+ }
+ if (output_info) XRRFreeOutputInfo(output_info);
+ }
+ XRRFreeScreenResources(resources);
+ }
+ } else {
+ std::cout << "X11Platform: RandR extension not available" << std::endl;
+ }
+}
+
+void X11Platform::cleanup_randr() {
+ // Clean up RandR resources if needed
+ std::cout << "X11Platform: RandR cleanup completed" << std::endl;
+}
+
+// Panel/Dock integration implementation
+void X11Platform::set_panel_visible(bool visible) {
+ panel_visible_ = visible;
+
+ // TODO: Implement actual panel visibility control
+ std::cout << "X11Platform: Panel visibility " << (visible ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::set_panel_position(int position) {
+ if (position < 0 || position > 3) return;
+
+ panel_position_ = position;
+
+ // Position values: 0=bottom, 1=top, 2=left, 3=right
+ std::string position_str;
+ switch (position) {
+ case 0: position_str = "bottom"; break;
+ case 1: position_str = "top"; break;
+ case 2: position_str = "left"; break;
+ case 3: position_str = "right"; break;
+ default: position_str = "unknown"; break;
+ }
+
+ std::cout << "X11Platform: Panel position set to " << position_str << std::endl;
+}
+
+void X11Platform::set_panel_auto_hide(bool enabled) {
+ panel_auto_hide_ = enabled;
+
+ // TODO: Implement actual panel auto-hide behavior
+ std::cout << "X11Platform: Panel auto-hide " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::update_panel_workspace_list() {
+ if (!ewmh_supported_) return;
+
+ // Update panel with current workspace information
+ // This would typically involve communicating with the panel application
+ std::cout << "X11Platform: Updated panel workspace list" << std::endl;
+}
+
+// System tray integration implementation
+void X11Platform::add_system_tray_icon(const std::string& tooltip, Pixmap icon) {
+ // TODO: Implement actual system tray icon addition
+ // This would involve using the _NET_SYSTEM_TRAY_S0 atom and related protocols
+
+ system_tray_icon_ = 1; // Placeholder
+ std::cout << "X11Platform: Added system tray icon with tooltip: " << tooltip << std::endl;
+}
+
+void X11Platform::remove_system_tray_icon() {
+ if (system_tray_icon_) {
+ // TODO: Implement actual system tray icon removal
+ system_tray_icon_ = 0;
+ std::cout << "X11Platform: Removed system tray icon" << std::endl;
+ }
+}
+
+void X11Platform::show_system_tray_menu(Window menu) {
+ // TODO: Implement system tray menu display
+ std::cout << "X11Platform: Show system tray menu" << std::endl;
+}
diff --git a/src/platform/x11_platform.h b/src/platform/x11_platform.h
new file mode 100644
index 0000000..095081e
--- /dev/null
+++ b/src/platform/x11_platform.h
@@ -0,0 +1,210 @@
+#ifndef SRDWM_X11_PLATFORM_H
+#define SRDWM_X11_PLATFORM_H
+
+#include "platform.h"
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/Xinerama.h>
+
+// X11 types are now properly included
+// Use X11Window typedef to avoid collision with our SRDWindow class
+typedef unsigned long X11Window;
+
+// Helper functions to convert between X11Window and X11's Window type
+inline ::Window to_x11_window(X11Window w) { return static_cast<::Window>(w); }
+inline X11Window from_x11_window(::Window w) { return static_cast<X11Window>(w); }
+
+class X11Platform : public Platform {
+public:
+ X11Platform();
+ ~X11Platform() override;
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ // Window management
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ // Monitor management
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ // Input handling
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ // Window decorations (X11 implementation)
+ void set_window_decorations(SRDWindow* window, bool enabled) override;
+ void set_window_border_color(SRDWindow* window, int r, int g, int b) override;
+ void set_window_border_width(SRDWindow* window, int width) override;
+ bool get_window_decorations(SRDWindow* window) const override;
+
+ // Linux/X11-specific features
+ void enable_compositor(bool enabled);
+ void set_window_opacity(SRDWindow* window, unsigned char opacity);
+ void set_window_blur(SRDWindow* window, bool enabled);
+ void set_window_shadow(SRDWindow* window, bool enabled);
+
+ // EWMH (Extended Window Manager Hints) support
+ void set_ewmh_supported(bool supported);
+ void set_window_type(SRDWindow* window, const std::string& type);
+ void set_window_state(SRDWindow* window, const std::vector<std::string>& states);
+ void set_window_strut(SRDWindow* window, int left, int right, int top, int bottom);
+
+ // Virtual Desktop support (X11 workspaces)
+ void create_virtual_desktop(const std::string& name);
+ void remove_virtual_desktop(int desktop_id);
+ void switch_to_virtual_desktop(int desktop_id);
+ int get_current_virtual_desktop() const;
+ std::vector<int> get_virtual_desktops() const;
+ void move_window_to_desktop(SRDWindow* window, int desktop_id);
+
+ // Panel/Dock integration
+ void set_panel_visible(bool visible);
+ void set_panel_position(int position); // 0=bottom, 1=top, 2=left, 3=right
+ void set_panel_auto_hide(bool enabled);
+ void update_panel_workspace_list();
+
+ // System tray integration
+ void add_system_tray_icon(const std::string& tooltip, Pixmap icon);
+ void remove_system_tray_icon();
+ void show_system_tray_menu(Window menu);
+
+ // RandR (Resize and Rotate) support
+ void enable_randr(bool enabled);
+ void set_monitor_rotation(int monitor_id, int rotation);
+ void set_monitor_refresh_rate(int monitor_id, int refresh_rate);
+ void set_monitor_scale(int monitor_id, float scale);
+
+ // Utility
+ std::string get_platform_name() const override { return "X11"; }
+ bool is_wayland() const override { return false; }
+ bool is_x11() const override { return true; }
+ bool is_windows() const override { return false; }
+ bool is_macos() const override { return false; }
+
+private:
+ // X11-specific members
+ Display* display_ = nullptr;
+ X11Window root_ = 0;
+
+ // Window tracking
+ std::map<X11Window, ::SRDWindow*> window_map_;
+ std::map<X11Window, X11Window> frame_window_map_; // client -> frame
+
+ // Monitor information
+ std::vector<Monitor> monitors_;
+
+ // Decoration state
+ bool decorations_enabled_;
+ int border_width_;
+ unsigned long border_color_;
+ unsigned long focused_border_color_;
+
+ // Linux/X11-specific state
+ bool compositor_enabled_;
+ bool ewmh_supported_;
+ bool randr_enabled_;
+ int current_virtual_desktop_;
+ std::vector<int> virtual_desktops_;
+ bool panel_visible_;
+ bool panel_auto_hide_;
+ int panel_position_;
+ Window system_tray_icon_;
+
+ // EWMH atoms
+ Atom _NET_WM_STATE_;
+ Atom _NET_WM_STATE_MAXIMIZED_VERT_;
+ Atom _NET_WM_STATE_MAXIMIZED_HORZ_;
+ Atom _NET_WM_STATE_FULLSCREEN_;
+ Atom _NET_WM_STATE_ABOVE_;
+ Atom _NET_WM_STATE_BELOW_;
+ Atom _NET_WM_WINDOW_TYPE_;
+ Atom _NET_WM_WINDOW_TYPE_DESKTOP_;
+ Atom _NET_WM_WINDOW_TYPE_DOCK_;
+ Atom _NET_WM_WINDOW_TYPE_TOOLBAR_;
+ Atom _NET_WM_WINDOW_TYPE_MENU_;
+ Atom _NET_WM_WINDOW_TYPE_UTILITY_;
+ Atom _NET_WM_WINDOW_TYPE_SPLASH_;
+ Atom _NET_WM_WINDOW_TYPE_DIALOG_;
+ Atom _NET_WM_WINDOW_TYPE_DROPDOWN_MENU_;
+ Atom _NET_WM_WINDOW_TYPE_POPUP_MENU_;
+ Atom _NET_WM_WINDOW_TYPE_TOOLTIP_;
+ Atom _NET_WM_WINDOW_TYPE_NOTIFICATION_;
+ Atom _NET_WM_WINDOW_TYPE_COMBO_;
+ Atom _NET_WM_WINDOW_TYPE_DND_;
+ Atom _NET_WM_WINDOW_TYPE_NORMAL_;
+ Atom _NET_WM_DESKTOP_;
+ Atom _NET_NUMBER_OF_DESKTOPS_;
+ Atom _NET_CURRENT_DESKTOP_;
+ Atom _NET_DESKTOP_NAMES_;
+ Atom _NET_WM_STRUT_;
+ Atom _NET_WM_STRUT_PARTIAL_;
+ Atom _NET_WM_OPACITY_;
+
+ // Helper methods
+ SRDWindow* get_focused_window() const;
+
+ // Private methods
+ bool setup_x11_environment();
+ bool setup_event_masks();
+ void handle_x11_event(XEvent& event);
+ void setup_atoms();
+ void setup_extensions();
+ bool check_for_other_wm();
+
+ // Event handlers
+ void handle_map_request(XMapRequestEvent& event);
+ void handle_configure_request(XConfigureRequestEvent& event);
+ void handle_destroy_notify(XDestroyWindowEvent& event);
+ void handle_unmap_notify(XUnmapEvent& event);
+ void handle_key_press(XKeyEvent& event);
+ void handle_button_press(XButtonEvent& event);
+ void handle_motion_notify(XMotionEvent& event);
+
+ // Decoration methods
+ void create_frame_window(SRDWindow* window);
+ void destroy_frame_window(SRDWindow* window);
+ void draw_titlebar(SRDWindow* window);
+ void update_frame_geometry(SRDWindow* window);
+
+ // EWMH methods
+ void setup_ewmh();
+ void update_ewmh_desktop_info();
+ void handle_ewmh_message(XClientMessageEvent& event);
+
+ // Virtual Desktop methods
+ void initialize_virtual_desktops();
+ void cleanup_virtual_desktops();
+
+ // RandR methods
+ void initialize_randr();
+ void cleanup_randr();
+
+ // Panel methods
+ void initialize_panel();
+ void update_panel();
+};
+
+#endif // SRDWM_X11_PLATFORM_H
+