aboutsummaryrefslogtreecommitdiff
path: root/src/core
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/core
parent105732dde10b317a81d5a10a3f66b315d6f85015 (diff)
downloadsrdwm-e4a0432383331e013808a97b7c24707e4ddc4726.tar.gz
srdwm-e4a0432383331e013808a97b7c24707e4ddc4726.zip
Initial Commit
Diffstat (limited to 'src/core')
-rw-r--r--src/core/event_system.cc94
-rw-r--r--src/core/event_system.h134
-rw-r--r--src/core/window.cc82
-rw-r--r--src/core/window.h49
-rw-r--r--src/core/window_manager.cc673
-rw-r--r--src/core/window_manager.h156
6 files changed, 1188 insertions, 0 deletions
diff --git a/src/core/event_system.cc b/src/core/event_system.cc
new file mode 100644
index 0000000..ed022cb
--- /dev/null
+++ b/src/core/event_system.cc
@@ -0,0 +1,94 @@
+#include "event_system.h"
+#include "window.h"
+#include <iostream>
+#include <algorithm>
+
+// Global event system instance
+EventSystem g_event_system;
+
+EventSystem::EventSystem() : processing_events(false) {
+}
+
+EventSystem::~EventSystem() {
+ clear_handlers();
+}
+
+void EventSystem::register_handler(EventType type, EventHandler handler) {
+ handlers[type].push_back(handler);
+}
+
+void EventSystem::unregister_handler(EventType type, EventHandler handler) {
+ auto& type_handlers = handlers[type];
+ type_handlers.erase(
+ std::remove_if(type_handlers.begin(), type_handlers.end(),
+ [&handler](const EventHandler& h) {
+ // Note: This is a simplified comparison
+ // In a real implementation, you'd want a more sophisticated way to identify handlers
+ return false; // For now, we don't remove handlers
+ }),
+ type_handlers.end()
+ );
+}
+
+void EventSystem::emit_event(const Event& event) {
+ if (processing_events) {
+ // Queue the event if we're currently processing events
+ event_queue.push_back(std::make_unique<Event>(event));
+ return;
+ }
+
+ auto it = handlers.find(event.type);
+ if (it != handlers.end()) {
+ for (const auto& handler : it->second) {
+ try {
+ handler(event);
+ } catch (const std::exception& e) {
+ std::cerr << "Error in event handler: " << e.what() << std::endl;
+ }
+ }
+ }
+}
+
+void EventSystem::emit_window_event(EventType type, SRDWindow* window) {
+ switch (type) {
+ case EventType::WINDOW_CREATED:
+ emit_event(SRDWindowCreatedEvent(window));
+ break;
+ case EventType::WINDOW_DESTROYED:
+ emit_event(SRDWindowDestroyedEvent(window));
+ break;
+ default:
+ // For other window events, we need more context
+ break;
+ }
+}
+
+void EventSystem::emit_key_event(EventType type, unsigned int keycode, unsigned int modifiers) {
+ emit_event(KeyEvent(type, keycode, modifiers));
+}
+
+void EventSystem::emit_mouse_event(EventType type, int x, int y, unsigned int button, unsigned int modifiers) {
+ emit_event(MouseEvent(type, x, y, button, modifiers));
+}
+
+void EventSystem::process_events() {
+ if (processing_events) {
+ return; // Prevent recursive processing
+ }
+
+ processing_events = true;
+
+ // Process queued events
+ while (!event_queue.empty()) {
+ auto event = std::move(event_queue.front());
+ event_queue.erase(event_queue.begin());
+
+ emit_event(*event);
+ }
+
+ processing_events = false;
+}
+
+void EventSystem::clear_handlers() {
+ handlers.clear();
+}
diff --git a/src/core/event_system.h b/src/core/event_system.h
new file mode 100644
index 0000000..2af717b
--- /dev/null
+++ b/src/core/event_system.h
@@ -0,0 +1,134 @@
+#ifndef SRDWM_EVENT_SYSTEM_H
+#define SRDWM_EVENT_SYSTEM_H
+
+#include <functional>
+#include <map>
+#include <vector>
+#include <string>
+#include <memory>
+
+// Forward declarations
+class SRDWindow;
+class Monitor;
+
+// Event types
+enum class EventType {
+ WINDOW_CREATED,
+ WINDOW_DESTROYED,
+ WINDOW_MOVED,
+ WINDOW_RESIZED,
+ WINDOW_FOCUSED,
+ WINDOW_UNFOCUSED,
+ WINDOW_MINIMIZED,
+ WINDOW_MAXIMIZED,
+ WINDOW_RESTORED,
+ MONITOR_ADDED,
+ MONITOR_REMOVED,
+ MONITOR_CHANGED,
+ KEY_PRESSED,
+ KEY_RELEASED,
+ MOUSE_MOVED,
+ MOUSE_PRESSED,
+ MOUSE_RELEASED,
+ MOUSE_WHEEL,
+ CUSTOM_EVENT
+};
+
+// Base event class
+class Event {
+public:
+ virtual ~Event() = default;
+ EventType type;
+
+ Event(EventType t) : type(t) {}
+};
+
+// SRDWindow events
+class SRDWindowEvent : public Event {
+public:
+ SRDWindow* window;
+
+ SRDWindowEvent(EventType t, SRDWindow* w) : Event(t), window(w) {}
+};
+
+class SRDWindowCreatedEvent : public SRDWindowEvent {
+public:
+ SRDWindowCreatedEvent(SRDWindow* w) : SRDWindowEvent(EventType::WINDOW_CREATED, w) {}
+};
+
+class SRDWindowDestroyedEvent : public SRDWindowEvent {
+public:
+ SRDWindowDestroyedEvent(SRDWindow* w) : SRDWindowEvent(EventType::WINDOW_DESTROYED, w) {}
+};
+
+class SRDWindowMovedEvent : public SRDWindowEvent {
+public:
+ int x, y;
+
+ SRDWindowMovedEvent(SRDWindow* w, int new_x, int new_y)
+ : SRDWindowEvent(EventType::WINDOW_MOVED, w), x(new_x), y(new_y) {}
+};
+
+class SRDWindowResizedEvent : public SRDWindowEvent {
+public:
+ int width, height;
+
+ SRDWindowResizedEvent(SRDWindow* w, int new_width, int new_height)
+ : SRDWindowEvent(EventType::WINDOW_RESIZED, w), width(new_width), height(new_height) {}
+};
+
+// Input events
+class KeyEvent : public Event {
+public:
+ unsigned int keycode;
+ unsigned int modifiers;
+
+ KeyEvent(EventType t, unsigned int kc, unsigned int mods)
+ : Event(t), keycode(kc), modifiers(mods) {}
+};
+
+class MouseEvent : public Event {
+public:
+ int x, y;
+ unsigned int button;
+ unsigned int modifiers;
+
+ MouseEvent(EventType t, int mouse_x, int mouse_y, unsigned int btn, unsigned int mods)
+ : Event(t), x(mouse_x), y(mouse_y), button(btn), modifiers(mods) {}
+};
+
+// Event handler function type
+using EventHandler = std::function<void(const Event&)>;
+
+// Event system class
+class EventSystem {
+public:
+ EventSystem();
+ ~EventSystem();
+
+ // Register event handlers
+ void register_handler(EventType type, EventHandler handler);
+ void unregister_handler(EventType type, EventHandler handler);
+
+ // Emit events
+ void emit_event(const Event& event);
+ void emit_window_event(EventType type, SRDWindow* window);
+ void emit_key_event(EventType type, unsigned int keycode, unsigned int modifiers);
+ void emit_mouse_event(EventType type, int x, int y, unsigned int button, unsigned int modifiers);
+
+ // Process event queue
+ void process_events();
+
+ // Clear all handlers
+ void clear_handlers();
+
+private:
+ std::map<EventType, std::vector<EventHandler>> handlers;
+ std::vector<std::unique_ptr<Event>> event_queue;
+ bool processing_events;
+};
+
+// Global event system instance
+extern EventSystem g_event_system;
+
+#endif // SRDWM_EVENT_SYSTEM_H
diff --git a/src/core/window.cc b/src/core/window.cc
new file mode 100644
index 0000000..cefc131
--- /dev/null
+++ b/src/core/window.cc
@@ -0,0 +1,82 @@
+#include "window.h"
+
+SRDWindow::SRDWindow(int id, const std::string& title)
+ : id_(id), title_(title), x_(0), y_(0), width_(0), height_(0), decorated_(true) {
+}
+
+int SRDWindow::getId() const {
+ return id_;
+}
+
+const std::string& SRDWindow::getTitle() const {
+ return title_;
+}
+
+int SRDWindow::getX() const {
+ return x_;
+}
+
+int SRDWindow::getY() const {
+ return y_;
+}
+
+int SRDWindow::getWidth() const {
+ return width_;
+}
+
+int SRDWindow::getHeight() const {
+ return height_;
+}
+
+bool SRDWindow::isDecorated() const {
+ return decorated_;
+}
+
+void SRDWindow::setPosition(int x, int y) {
+ x_ = x;
+ y_ = y;
+}
+
+void SRDWindow::setSize(int width, int height) {
+ width_ = width;
+ height_ = height;
+}
+
+void SRDWindow::setGeometry(int x, int y, int width, int height) {
+ x_ = x;
+ y_ = y;
+ width_ = width;
+ height_ = height;
+}
+
+void SRDWindow::setDimensions(int x, int y, int width, int height) {
+ x_ = x;
+ y_ = y;
+ width_ = width;
+ height_ = height;
+}
+
+void SRDWindow::setDecorated(bool decorated) {
+ decorated_ = decorated;
+}
+
+void SRDWindow::setId(int id) {
+ id_ = id;
+}
+
+// Basic methods for managing window state (will be platform-specific)
+void SRDWindow::map() {
+ // Platform-specific implementation to show the window
+}
+
+void SRDWindow::unmap() {
+ // Platform-specific implementation to hide the window
+}
+
+void SRDWindow::focus() {
+ // Platform-specific implementation to give focus to the window
+}
+
+void SRDWindow::close() {
+ // Platform-specific implementation to close the window
+}
diff --git a/src/core/window.h b/src/core/window.h
new file mode 100644
index 0000000..6d7405a
--- /dev/null
+++ b/src/core/window.h
@@ -0,0 +1,49 @@
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include <string>
+
+class SRDWindow {
+public:
+ // Constructor
+ SRDWindow(int id, const std::string& title);
+
+ // Getters
+ int getId() const;
+ const std::string& getTitle() const;
+ int getX() const;
+ int getY() const;
+ int getWidth() const;
+ int getHeight() const;
+ bool isDecorated() const;
+
+ // Setters
+ void setTitle(const std::string& title);
+ void setPosition(int x, int y);
+ void setSize(int width, int height);
+ void setGeometry(int x, int y, int width, int height);
+ void setDimensions(int x, int y, int width, int height);
+ void setDecorated(bool decorated);
+ void setId(int id);
+
+ // Window management methods
+ void map();
+ void unmap();
+ void focus();
+ void close();
+
+ // Comparison operators for use in containers
+ bool operator<(const SRDWindow& other) const { return id_ < other.id_; }
+ bool operator==(const SRDWindow& other) const { return id_ == other.id_; }
+
+private:
+ int id_;
+ std::string title_;
+ int x_;
+ int y_;
+ int width_;
+ int height_;
+ bool decorated_;
+};
+
+#endif // WINDOW_H
diff --git a/src/core/window_manager.cc b/src/core/window_manager.cc
new file mode 100644
index 0000000..08033fe
--- /dev/null
+++ b/src/core/window_manager.cc
@@ -0,0 +1,673 @@
+#include "window_manager.h"
+#include "window.h"
+#include "../input/input_handler.h"
+#include "../layouts/layout_engine.h"
+#include "../platform/platform.h"
+#include "../config/lua_manager.h"
+#include <iostream>
+#include <chrono>
+#include <thread>
+
+SRDWindowManager::SRDWindowManager() {
+ std::cout << "SRDWindowManager: Initializing..." << std::endl;
+}
+
+SRDWindowManager::~SRDWindowManager() {
+ std::cout << "SRDWindowManager: Shutting down..." << std::endl;
+}
+
+void SRDWindowManager::run() {
+ // Main event loop
+ std::cout << "SRDWindowManager: Starting main loop" << std::endl;
+
+ if (!platform_) {
+ std::cerr << "SRDWindowManager: No platform available, cannot run" << std::endl;
+ return;
+ }
+
+ std::cout << "SRDWindowManager: Entering main event loop..." << std::endl;
+
+ bool running = true;
+ while (running) {
+ // Poll for platform events
+ std::vector<Event> events;
+ if (platform_->poll_events(events)) {
+ // Process all events
+ for (const auto& event : events) {
+ handle_event(event);
+
+ // Check for exit condition
+ if (event.type == EventType::KeyPress) {
+ // TODO: Check for exit key combination
+ // For now, just continue
+ }
+ }
+ }
+
+ // Manage windows
+ manage_windows();
+
+ // Arrange windows if needed
+ if (layout_engine_) {
+ layout_engine_->arrange_all_monitors();
+ }
+
+ // Small delay to prevent busy waiting
+ // TODO: Use proper event-driven approach instead of polling
+ std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60 FPS
+ }
+
+ std::cout << "SRDWindowManager: Main loop ended" << std::endl;
+}
+
+// SRDWindow management
+void SRDWindowManager::add_window(std::unique_ptr<SRDWindow> window) {
+ if (window) {
+ windows_.push_back(window.get());
+ window.release(); // Transfer ownership
+
+ // Add to layout engine if available
+ if (layout_engine_) {
+ layout_engine_->add_window(window.get());
+ }
+
+ std::cout << "SRDWindowManager: Added window " << window->getId() << std::endl;
+ }
+}
+
+void SRDWindowManager::remove_window(SRDWindow* window) {
+ auto it = std::find(windows_.begin(), windows_.end(), window);
+ if (it != windows_.end()) {
+ windows_.erase(it);
+
+ // Remove from layout engine if available
+ if (layout_engine_) {
+ layout_engine_->remove_window(window);
+ }
+
+ std::cout << "SRDWindowManager: Removed window " << window->getId() << std::endl;
+ }
+}
+
+void SRDWindowManager::focus_window(SRDWindow* window) {
+ focused_window_ = window;
+ std::cout << "SRDWindowManager: Focused window " << (window ? window->getId() : -1) << std::endl;
+}
+
+SRDWindow* SRDWindowManager::get_focused_window() const {
+ return focused_window_;
+}
+
+std::vector<SRDWindow*> SRDWindowManager::get_windows() const {
+ return windows_;
+}
+
+void SRDWindowManager::focus_next_window() {
+ if (windows_.empty()) return;
+
+ if (!focused_window_) {
+ // No window focused, focus the first one
+ focus_window(windows_[0]);
+ return;
+ }
+
+ // Find current focused window index
+ auto it = std::find(windows_.begin(), windows_.end(), focused_window_);
+ if (it == windows_.end()) {
+ focus_window(windows_[0]);
+ return;
+ }
+
+ // Move to next window (wrap around)
+ ++it;
+ if (it == windows_.end()) {
+ it = windows_.begin();
+ }
+
+ focus_window(*it);
+ std::cout << "SRDWindowManager: Focused next window " << (*it)->getId() << std::endl;
+}
+
+void SRDWindowManager::focus_previous_window() {
+ if (windows_.empty()) return;
+
+ if (!focused_window_) {
+ // No window focused, focus the last one
+ focus_window(windows_.back());
+ return;
+ }
+
+ // Find current focused window index
+ auto it = std::find(windows_.begin(), windows_.end(), focused_window_);
+ if (it == windows_.end()) {
+ focus_window(windows_.back());
+ return;
+ }
+
+ // Move to previous window (wrap around)
+ if (it == windows_.begin()) {
+ it = windows_.end() - 1;
+ } else {
+ --it;
+ }
+
+ focus_window(*it);
+ std::cout << "SRDWindowManager: Focused previous window " << (*it)->getId() << std::endl;
+}
+
+void SRDWindowManager::manage_windows() {
+ // Manage window states
+ std::cout << "SRDWindowManager: Managing " << windows_.size() << " windows" << std::endl;
+}
+
+// SRDWindow operations
+void SRDWindowManager::close_window(SRDWindow* window) {
+ if (window) {
+ std::cout << "SRDWindowManager: Closing window " << window->getId() << std::endl;
+ // TODO: Implement actual window closing
+ }
+}
+
+void SRDWindowManager::minimize_window(SRDWindow* window) {
+ if (window) {
+ std::cout << "SRDWindowManager: Minimizing window " << window->getId() << std::endl;
+ // TODO: Implement actual window minimizing
+ }
+}
+
+void SRDWindowManager::maximize_window(SRDWindow* window) {
+ if (window) {
+ std::cout << "SRDWindowManager: Maximizing window " << window->getId() << std::endl;
+ // TODO: Implement actual window maximizing
+ }
+}
+
+void SRDWindowManager::move_window(SRDWindow* window, int x, int y) {
+ if (window) {
+ window->setPosition(x, y);
+ update_layout_for_window(window);
+ std::cout << "SRDWindowManager: Moved window " << window->getId() << " to (" << x << ", " << y << ")" << std::endl;
+ }
+}
+
+void SRDWindowManager::resize_window(SRDWindow* window, int width, int height) {
+ if (window) {
+ window->setSize(width, height);
+ update_layout_for_window(window);
+ std::cout << "SRDWindowManager: Resized window " << window->getId() << " to " << width << "x" << height << std::endl;
+ }
+}
+
+void SRDWindowManager::toggle_window_floating(SRDWindow* window) {
+ if (!window) return;
+
+ auto it = floating_windows_.find(window);
+ if (it != floating_windows_.end()) {
+ // Window is floating, make it tiled
+ floating_windows_.erase(it);
+ std::cout << "SRDWindowManager: Window " << window->getId() << " is now tiled" << std::endl;
+ } else {
+ // Window is tiled, make it floating
+ floating_windows_.insert(window);
+ std::cout << "SRDWindowManager: Window " << window->getId() << " is now floating" << std::endl;
+ }
+
+ // Re-arrange windows to reflect the change
+ arrange_windows();
+}
+
+bool SRDWindowManager::is_window_floating(SRDWindow* window) const {
+ if (!window) return false;
+ return floating_windows_.find(window) != floating_windows_.end();
+}
+
+// Window dragging and resizing implementation
+void SRDWindowManager::start_window_drag(SRDWindow* window, int start_x, int start_y) {
+ if (!window || dragging_window_) return;
+
+ dragging_window_ = window;
+ drag_start_x_ = start_x;
+ drag_start_y_ = start_y;
+ drag_start_window_x_ = window->getX();
+ drag_start_window_y_ = window->getY();
+
+ std::cout << "SRDWindowManager: Started dragging window " << window->getId() << std::endl;
+}
+
+void SRDWindowManager::start_window_resize(SRDWindow* window, int start_x, int start_y, int edge) {
+ if (!window || resizing_window_) return;
+
+ resizing_window_ = window;
+ resize_start_x_ = start_x;
+ resize_start_y_ = start_y;
+ resize_start_width_ = window->getWidth();
+ resize_start_height_ = window->getHeight();
+ resize_edge_ = edge;
+
+ std::cout << "SRDWindowManager: Started resizing window " << window->getId() << " edge: " << edge << std::endl;
+}
+
+void SRDWindowManager::update_window_drag(int x, int y) {
+ if (!dragging_window_) return;
+
+ int delta_x = x - drag_start_x_;
+ int delta_y = y - drag_start_y_;
+
+ int new_x = drag_start_window_x_ + delta_x;
+ int new_y = drag_start_window_y_ + delta_y;
+
+ // Ensure window stays within monitor bounds
+ // TODO: Get actual monitor bounds
+ new_x = std::max(0, std::min(new_x, 1920 - dragging_window_->getWidth()));
+ new_y = std::max(0, std::min(new_y, 1080 - dragging_window_->getHeight()));
+
+ dragging_window_->setPosition(new_x, new_y);
+ update_layout_for_window(dragging_window_);
+}
+
+void SRDWindowManager::update_window_resize(int x, int y) {
+ if (!resizing_window_) return;
+
+ int delta_x = x - resize_start_x_;
+ int delta_y = y - resize_start_y_;
+
+ int new_width = resize_start_width_;
+ int new_height = resize_start_height_;
+ int new_x = resizing_window_->getX();
+ int new_y = resizing_window_->getY();
+
+ // Handle different resize edges
+ switch (resize_edge_) {
+ case 1: // Left edge
+ new_width = std::max(100, resize_start_width_ - delta_x);
+ new_x = resize_start_x_ + resize_start_width_ - new_width;
+ break;
+ case 2: // Right edge
+ new_width = std::max(100, resize_start_width_ + delta_x);
+ break;
+ case 3: // Top edge
+ new_height = std::max(100, resize_start_height_ - delta_y);
+ new_y = resize_start_y_ + resize_start_height_ - new_height;
+ break;
+ case 4: // Bottom edge
+ new_height = std::max(100, resize_start_height_ + delta_y);
+ break;
+ case 5: // Corner (both width and height)
+ new_width = std::max(100, resize_start_width_ + delta_x);
+ new_height = std::max(100, resize_start_height_ + delta_y);
+ break;
+ }
+
+ // Ensure minimum size and bounds
+ new_width = std::max(100, std::min(new_width, 1920 - new_x));
+ new_height = std::max(100, std::min(new_height, 1080 - new_y));
+
+ resizing_window_->setPosition(new_x, new_y);
+ resizing_window_->setSize(new_width, new_height);
+ update_layout_for_window(resizing_window_);
+}
+
+void SRDWindowManager::end_window_drag() {
+ if (dragging_window_) {
+ std::cout << "SRDWindowManager: Ended dragging window " << dragging_window_->getId() << std::endl;
+ dragging_window_ = nullptr;
+ }
+}
+
+void SRDWindowManager::end_window_resize() {
+ if (resizing_window_) {
+ std::cout << "SRDWindowManager: Ended resizing window " << resizing_window_->getId() << std::endl;
+ resizing_window_ = nullptr;
+ }
+}
+
+// Layout management
+void SRDWindowManager::set_layout(int monitor_id, const std::string& layout_name) {
+ if (layout_engine_) {
+ layout_engine_->set_layout(monitor_id, layout_name);
+ std::cout << "SRDWindowManager: Set layout '" << layout_name << "' for monitor " << monitor_id << std::endl;
+ }
+}
+
+std::string SRDWindowManager::get_layout(int monitor_id) const {
+ if (layout_engine_) {
+ return layout_engine_->get_layout_name(monitor_id);
+ }
+ return "dynamic";
+}
+
+void SRDWindowManager::arrange_windows() {
+ if (layout_engine_) {
+ layout_engine_->arrange_all_monitors();
+ std::cout << "SRDWindowManager: Arranged all windows" << std::endl;
+ }
+}
+
+void SRDWindowManager::tile_windows() {
+ set_layout(0, "tiling");
+ arrange_windows();
+}
+
+void SRDWindowManager::arrange_windows_dynamic() {
+ set_layout(0, "dynamic");
+ arrange_windows();
+}
+
+// Key binding system
+void SRDWindowManager::bind_key(const std::string& key_combination, std::function<void()> action) {
+ key_bindings_[key_combination] = action;
+ std::cout << "SRDWindowManager: Bound key '" << key_combination << "'" << std::endl;
+}
+
+void SRDWindowManager::unbind_key(const std::string& key_combination) {
+ auto it = key_bindings_.find(key_combination);
+ if (it != key_bindings_.end()) {
+ key_bindings_.erase(it);
+ std::cout << "SRDWindowManager: Unbound key '" << key_combination << "'" << std::endl;
+ }
+}
+
+void SRDWindowManager::handle_key_press(int key_code, int modifiers) {
+ std::string key_string = key_code_to_string(key_code, modifiers);
+ pressed_keys_[key_code] = modifiers;
+
+ std::cout << "SRDWindowManager: Key press " << key_code << " (modifiers: " << modifiers << ") -> '" << key_string << "'" << std::endl;
+
+ // Check for key bindings
+ auto it = key_bindings_.find(key_string);
+ if (it != key_bindings_.end()) {
+ std::cout << "SRDWindowManager: Executing key binding for '" << key_string << "'" << std::endl;
+ it->second();
+ }
+}
+
+void SRDWindowManager::handle_key_release(int key_code, int modifiers) {
+ pressed_keys_.erase(key_code);
+ std::cout << "SRDWindowManager: Key release " << key_code << std::endl;
+}
+
+// Integration
+void SRDWindowManager::set_layout_engine(LayoutEngine* engine) {
+ layout_engine_ = engine;
+ std::cout << "SRDWindowManager: Layout engine connected" << std::endl;
+}
+
+void SRDWindowManager::set_lua_manager(LuaManager* manager) {
+ lua_manager_ = manager;
+ std::cout << "SRDWindowManager: Lua manager connected" << std::endl;
+}
+
+void SRDWindowManager::set_platform(Platform* platform) {
+ platform_ = platform;
+ std::cout << "SRDWindowManager: Platform connected" << std::endl;
+}
+
+// Legacy input handling (for compatibility)
+void SRDWindowManager::handle_key_press(int key_code) {
+ handle_key_press(key_code, 0);
+}
+
+void SRDWindowManager::handle_key_release(int key_code) {
+ handle_key_release(key_code, 0);
+}
+
+void SRDWindowManager::handle_mouse_button_press(int button, int x, int y) {
+ std::cout << "SRDWindowManager: Mouse button press " << button << " at (" << x << ", " << y << ")" << std::endl;
+
+ // Find window under cursor
+ SRDWindow* window_under_cursor = find_window_at_position(x, y);
+
+ if (window_under_cursor) {
+ // Focus the window
+ focus_window(window_under_cursor);
+
+ // Handle different mouse buttons
+ if (button == 1) { // Left button - start drag or resize
+ if (is_in_titlebar_area(window_under_cursor, x, y)) {
+ // Start dragging from titlebar
+ start_window_drag(window_under_cursor, x, y);
+ } else if (is_in_resize_area(window_under_cursor, x, y)) {
+ // Start resizing
+ int edge = get_resize_edge(window_under_cursor, x, y);
+ start_window_resize(window_under_cursor, x, y, edge);
+ }
+ }
+ }
+}
+
+void SRDWindowManager::handle_mouse_button_release(int button, int x, int y) {
+ std::cout << "SRDWindowManager: Mouse button release " << button << " at (" << x << ", " << y << ")" << std::endl;
+
+ if (button == 1) { // Left button
+ if (is_dragging()) {
+ end_window_drag();
+ } else if (is_resizing()) {
+ end_window_resize();
+ }
+ }
+}
+
+void SRDWindowManager::handle_mouse_motion(int x, int y) {
+ // Only log if we're not dragging or resizing to avoid spam
+ if (!is_dragging() && !is_resizing()) {
+ std::cout << "SRDWindowManager: Mouse motion to (" << x << ", " << y << ")" << std::endl;
+ }
+
+ // Update drag or resize if active
+ if (is_dragging()) {
+ update_window_drag(x, y);
+ } else if (is_resizing()) {
+ update_window_resize(x, y);
+ }
+}
+
+void SRDWindowManager::handle_event(const Event& event) {
+ std::cout << "SRDWindowManager: Handling event type " << static_cast<int>(event.type) << std::endl;
+}
+
+// Workspace management
+void SRDWindowManager::add_workspace(const std::string& name) {
+ Workspace workspace(next_workspace_id_++, name);
+ workspaces_.push_back(workspace);
+
+ // If this is the first workspace, make it current
+ if (workspaces_.size() == 1) {
+ current_workspace_ = workspace.id;
+ workspace.visible = true;
+ }
+
+ std::cout << "SRDWindowManager: Added workspace " << workspace.id << " (" << name << ")" << std::endl;
+}
+
+void SRDWindowManager::remove_workspace(int workspace_id) {
+ auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
+ [workspace_id](const Workspace& w) { return w.id == workspace_id; });
+
+ if (it != workspaces_.end()) {
+ // Move windows to current workspace if removing current
+ if (workspace_id == current_workspace_) {
+ for (auto* window : it->windows) {
+ move_window_to_workspace(window, current_workspace_);
+ }
+ }
+
+ workspaces_.erase(it);
+ std::cout << "SRDWindowManager: Removed workspace " << workspace_id << std::endl;
+ }
+}
+
+void SRDWindowManager::switch_to_workspace(int workspace_id) {
+ auto* workspace = get_workspace(workspace_id);
+ if (workspace) {
+ // Hide current workspace
+ auto* current = get_workspace(current_workspace_);
+ if (current) {
+ current->visible = false;
+ }
+
+ // Show new workspace
+ current_workspace_ = workspace_id;
+ workspace->visible = true;
+
+ // Arrange windows on the new workspace
+ arrange_workspace_windows(workspace_id);
+
+ std::cout << "SRDWindowManager: Switched to workspace " << workspace_id << std::endl;
+ }
+}
+
+void SRDWindowManager::move_window_to_workspace(SRDWindow* window, int workspace_id) {
+ if (!window) return;
+
+ auto* target_workspace = get_workspace(workspace_id);
+ if (!target_workspace) return;
+
+ // Remove from current workspace
+ for (auto& workspace : workspaces_) {
+ auto it = std::find(workspace.windows.begin(), workspace.windows.end(), window);
+ if (it != workspace.windows.end()) {
+ workspace.windows.erase(it);
+ break;
+ }
+ }
+
+ // Add to target workspace
+ target_workspace->windows.push_back(window);
+
+ std::cout << "SRDWindowManager: Moved window " << window->getId()
+ << " to workspace " << workspace_id << std::endl;
+}
+
+int SRDWindowManager::get_current_workspace() const {
+ return current_workspace_;
+}
+
+std::vector<Workspace> SRDWindowManager::get_workspaces() const {
+ return workspaces_;
+}
+
+Workspace* SRDWindowManager::get_workspace(int workspace_id) {
+ auto it = std::find_if(workspaces_.begin(), workspaces_.end(),
+ [workspace_id](const Workspace& w) { return w.id == workspace_id; });
+ return it != workspaces_.end() ? &(*it) : nullptr;
+}
+
+// Helper methods
+std::string SRDWindowManager::key_code_to_string(int key_code, int modifiers) const {
+ std::string result;
+
+ // Add modifiers
+ if (modifiers & 0x01) result += "Ctrl+"; // Control
+ if (modifiers & 0x02) result += "Shift+"; // Shift
+ if (modifiers & 0x04) result += "Alt+"; // Alt
+ if (modifiers & 0x08) result += "Mod4+"; // Super/SRDWindows
+
+ // Add key
+ if (key_code >= 'A' && key_code <= 'Z') {
+ result += static_cast<char>(key_code);
+ } else if (key_code >= '0' && key_code <= '9') {
+ result += static_cast<char>(key_code);
+ } else {
+ result += "Key" + std::to_string(key_code);
+ }
+
+ return result;
+}
+
+void SRDWindowManager::execute_key_binding(const std::string& key_combination) {
+ auto it = key_bindings_.find(key_combination);
+ if (it != key_bindings_.end()) {
+ it->second();
+ }
+}
+
+void SRDWindowManager::update_layout_for_window(SRDWindow* window) {
+ if (layout_engine_) {
+ layout_engine_->update_window(window);
+ }
+}
+
+void SRDWindowManager::arrange_workspace_windows(int workspace_id) {
+ auto* workspace = get_workspace(workspace_id);
+ if (!workspace || !layout_engine_) return;
+
+ // Get monitor for current workspace (simplified - assuming single monitor for now)
+ if (!workspace->windows.empty() && !monitors_.empty()) {
+ // Arrange windows using the layout engine
+ // TODO: Get the actual monitor for this workspace
+ layout_engine_->arrange_on_monitor(monitors_[0]);
+ }
+}
+
+void SRDWindowManager::update_workspace_visibility() {
+ for (auto& workspace : workspaces_) {
+ workspace.visible = (workspace.id == current_workspace_);
+ }
+}
+
+// Window interaction helper methods
+SRDWindow* SRDWindowManager::find_window_at_position(int x, int y) const {
+ // Find the topmost window at the given position
+ // For now, just check if point is within any window bounds
+ // TODO: Implement proper z-order checking
+ for (auto* window : windows_) {
+ if (x >= window->getX() && x < window->getX() + window->getWidth() &&
+ y >= window->getY() && y < window->getY() + window->getHeight()) {
+ return window;
+ }
+ }
+ return nullptr;
+}
+
+bool SRDWindowManager::is_in_titlebar_area(SRDWindow* window, int x, int y) const {
+ if (!window) return false;
+
+ // Check if point is in the top area of the window (titlebar region)
+ // Titlebar is typically the top 20-30 pixels of the window
+ int titlebar_height = 30;
+
+ return (x >= window->getX() && x < window->getX() + window->getWidth() &&
+ y >= window->getY() && y < window->getY() + titlebar_height);
+}
+
+bool SRDWindowManager::is_in_resize_area(SRDWindow* window, int x, int y) const {
+ if (!window) return false;
+
+ // Check if point is near the edges of the window (resize handles)
+ int resize_margin = 5;
+
+ int left = window->getX();
+ int right = left + window->getWidth();
+ int top = window->getY();
+ int bottom = top + window->getHeight();
+
+ return (x <= left + resize_margin || x >= right - resize_margin ||
+ y <= top + resize_margin || y >= bottom - resize_margin);
+}
+
+int SRDWindowManager::get_resize_edge(SRDWindow* window, int x, int y) const {
+ if (!window) return 0;
+
+ int resize_margin = 5;
+ int left = window->getX();
+ int right = left + window->getWidth();
+ int top = window->getY();
+ int bottom = top + window->getHeight();
+
+ bool near_left = (x <= left + resize_margin);
+ bool near_right = (x >= right - resize_margin);
+ bool near_top = (y <= top + resize_margin);
+ bool near_bottom = (y >= bottom - resize_margin);
+
+ // Determine which edge or corner
+ if (near_left && near_top) return 5; // Top-left corner
+ if (near_right && near_top) return 5; // Top-right corner
+ if (near_left && near_bottom) return 5; // Bottom-left corner
+ if (near_right && near_bottom) return 5; // Bottom-right corner
+ if (near_left) return 1; // Left edge
+ if (near_right) return 2; // Right edge
+ if (near_top) return 3; // Top edge
+ if (near_bottom) return 4; // Bottom edge
+
+ return 0; // No resize edge
+}
diff --git a/src/core/window_manager.h b/src/core/window_manager.h
new file mode 100644
index 0000000..2da999a
--- /dev/null
+++ b/src/core/window_manager.h
@@ -0,0 +1,156 @@
+#ifndef SRDWM_WINDOW_MANAGER_H
+#define SRDWM_WINDOW_MANAGER_H
+
+#include <vector>
+#include <algorithm> // Required for std::remove_if
+#include <memory> // Required for std::unique_ptr
+#include <map>
+#include <string>
+#include <functional>
+#include <set> // Required for std::set
+
+#include "../input/input_handler.h"
+#include "../layouts/layout_engine.h"
+#include "../platform/platform.h" // For Event type
+#include "../layouts/layout.h" // For Monitor type
+
+class SRDWindow; // Forward declaration
+class InputHandler; // Forward declaration
+class LuaManager; // Forward declaration
+
+// Workspace structure
+struct Workspace {
+ int id;
+ std::string name;
+ std::vector<SRDWindow*> windows;
+ std::string layout;
+ bool visible;
+
+ Workspace(int id, const std::string& name = "")
+ : id(id), name(name), layout("tiling"), visible(false) {}
+};
+
+class SRDWindowManager {
+public:
+ SRDWindowManager();
+ ~SRDWindowManager();
+
+ void run(); // Main loop
+
+ // SRDWindow management
+ void add_window(std::unique_ptr<SRDWindow> window);
+ void remove_window(SRDWindow* window);
+ void focus_window(SRDWindow* window);
+ SRDWindow* get_focused_window() const;
+ std::vector<SRDWindow*> get_windows() const;
+ void manage_windows(); // Added missing method
+ void focus_next_window();
+ void focus_previous_window();
+
+ // SRDWindow operations
+ void close_window(SRDWindow* window);
+ void minimize_window(SRDWindow* window);
+ void maximize_window(SRDWindow* window);
+ void move_window(SRDWindow* window, int x, int y);
+ void resize_window(SRDWindow* window, int width, int height);
+ void toggle_window_floating(SRDWindow* window);
+ bool is_window_floating(SRDWindow* window) const;
+
+ // Window dragging and resizing
+ void start_window_drag(SRDWindow* window, int start_x, int start_y);
+ void start_window_resize(SRDWindow* window, int start_x, int start_y, int edge);
+ void update_window_drag(int x, int y);
+ void update_window_resize(int x, int y);
+ void end_window_drag();
+ void end_window_resize();
+ bool is_dragging() const { return dragging_window_ != nullptr; }
+ bool is_resizing() const { return resizing_window_ != nullptr; }
+
+ // Workspace management
+ void add_workspace(const std::string& name = "");
+ void remove_workspace(int workspace_id);
+ void switch_to_workspace(int workspace_id);
+ void move_window_to_workspace(SRDWindow* window, int workspace_id);
+ int get_current_workspace() const;
+ std::vector<Workspace> get_workspaces() const;
+ Workspace* get_workspace(int workspace_id);
+
+ // Layout management
+ void set_layout(int monitor_id, const std::string& layout_name);
+ std::string get_layout(int monitor_id) const;
+ void arrange_windows();
+ void tile_windows();
+ void arrange_windows_dynamic();
+
+ // Key binding system
+ void bind_key(const std::string& key_combination, std::function<void()> action);
+ void unbind_key(const std::string& key_combination);
+ void handle_key_press(int key_code, int modifiers);
+ void handle_key_release(int key_code, int modifiers);
+
+ // Input event handling (called by InputHandler)
+ void handle_key_press(int key_code);
+ void handle_key_release(int key_code);
+ void handle_mouse_button_press(int button, int x, int y);
+ void handle_mouse_button_release(int button, int x, int y);
+ void handle_mouse_motion(int x, int y);
+ void handle_event(const Event& event); // Added missing method
+
+ // Integration
+ void set_layout_engine(LayoutEngine* engine);
+ void set_lua_manager(LuaManager* manager);
+ void set_platform(Platform* platform);
+
+private:
+ // Window tracking
+ std::vector<SRDWindow*> windows_; // Added missing member variable
+ SRDWindow* focused_window_ = nullptr;
+ std::set<SRDWindow*> floating_windows_; // Track floating windows
+ InputHandler* input_handler_ = nullptr;
+ LayoutEngine* layout_engine_ = nullptr;
+ LuaManager* lua_manager_ = nullptr;
+ Platform* platform_ = nullptr;
+
+ // Workspace management
+ std::vector<Workspace> workspaces_;
+ int current_workspace_ = 0;
+ int next_workspace_id_ = 1;
+
+ // Window dragging and resizing state
+ SRDWindow* dragging_window_ = nullptr;
+ SRDWindow* resizing_window_ = nullptr;
+ int drag_start_x_ = 0;
+ int drag_start_y_ = 0;
+ int drag_start_window_x_ = 0;
+ int drag_start_window_y_ = 0;
+ int resize_start_x_ = 0;
+ int resize_start_y_ = 0;
+ int resize_start_width_ = 0;
+ int resize_start_height_ = 0;
+ int resize_edge_ = 0; // 0=none, 1=left, 2=right, 3=top, 4=bottom, 5=corner
+
+ // Key binding system
+ std::map<std::string, std::function<void()>> key_bindings_;
+ std::map<int, int> pressed_keys_; // key_code -> modifiers
+
+ // Platform-specific data (placeholder)
+ void* platform_data_ = nullptr;
+
+ // Monitor information
+ std::vector<Monitor> monitors_;
+
+ // Helper methods
+ std::string key_code_to_string(int key_code, int modifiers) const;
+ void execute_key_binding(const std::string& key_combination);
+ void update_layout_for_window(SRDWindow* window);
+ void arrange_workspace_windows(int workspace_id);
+ void update_workspace_visibility();
+
+ // Window interaction helpers
+ SRDWindow* find_window_at_position(int x, int y) const;
+ bool is_in_titlebar_area(SRDWindow* window, int x, int y) const;
+ bool is_in_resize_area(SRDWindow* window, int x, int y) const;
+ int get_resize_edge(SRDWindow* window, int x, int y) const;
+};
+
+#endif // SRDWM_WINDOW_MANAGER_H