diff options
| author | srdusr <trevorgray@srdusr.com> | 2025-09-26 12:23:19 +0200 |
|---|---|---|
| committer | srdusr <trevorgray@srdusr.com> | 2025-09-26 12:23:19 +0200 |
| commit | e4a0432383331e013808a97b7c24707e4ddc4726 (patch) | |
| tree | 3ef4465be03bc7b92a0b048f02f76475045404b6 /src/core | |
| parent | 105732dde10b317a81d5a10a3f66b315d6f85015 (diff) | |
| download | srdwm-e4a0432383331e013808a97b7c24707e4ddc4726.tar.gz srdwm-e4a0432383331e013808a97b7c24707e4ddc4726.zip | |
Initial Commit
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/event_system.cc | 94 | ||||
| -rw-r--r-- | src/core/event_system.h | 134 | ||||
| -rw-r--r-- | src/core/window.cc | 82 | ||||
| -rw-r--r-- | src/core/window.h | 49 | ||||
| -rw-r--r-- | src/core/window_manager.cc | 673 | ||||
| -rw-r--r-- | src/core/window_manager.h | 156 |
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 |
