From e4a0432383331e013808a97b7c24707e4ddc4726 Mon Sep 17 00:00:00 2001 From: srdusr Date: Fri, 26 Sep 2025 12:23:19 +0200 Subject: Initial Commit --- src/core/window_manager.cc | 673 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 673 insertions(+) create mode 100644 src/core/window_manager.cc (limited to 'src/core/window_manager.cc') 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 +#include +#include + +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 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 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 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 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(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 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(key_code); + } else if (key_code >= '0' && key_code <= '9') { + result += static_cast(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 +} -- cgit v1.2.3