aboutsummaryrefslogtreecommitdiff
path: root/src/platform/wayland_platform.cc
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/wayland_platform.cc
parent105732dde10b317a81d5a10a3f66b315d6f85015 (diff)
downloadsrdwm-e4a0432383331e013808a97b7c24707e4ddc4726.tar.gz
srdwm-e4a0432383331e013808a97b7c24707e4ddc4726.zip
Initial Commit
Diffstat (limited to 'src/platform/wayland_platform.cc')
-rw-r--r--src/platform/wayland_platform.cc507
1 files changed, 507 insertions, 0 deletions
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
+}
+
+