aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/config/config_manager.h101
-rw-r--r--src/config/lua_manager.cc1024
-rw-r--r--src/config/lua_manager.h166
-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
-rw-r--r--src/input/input_handler.h36
-rw-r--r--src/layouts/dynamic_layout.cc31
-rw-r--r--src/layouts/dynamic_layout.h17
-rw-r--r--src/layouts/layout.h33
-rw-r--r--src/layouts/layout_engine.cc188
-rw-r--r--src/layouts/layout_engine.h70
-rw-r--r--src/layouts/smart_placement.cc278
-rw-r--r--src/layouts/smart_placement.h62
-rw-r--r--src/layouts/tiling_layout.cc38
-rw-r--r--src/layouts/tiling_layout.h17
-rw-r--r--src/main.cc321
-rw-r--r--src/platform/linux_platform.h105
-rw-r--r--src/platform/macos_platform.cc480
-rw-r--r--src/platform/macos_platform.h118
-rw-r--r--src/platform/platform.h91
-rw-r--r--src/platform/platform_factory.cc214
-rw-r--r--src/platform/platform_factory.h37
-rw-r--r--src/platform/wayland_platform.cc507
-rw-r--r--src/platform/wayland_platform.h227
-rw-r--r--src/platform/wayland_platform_stub.cc114
-rw-r--r--src/platform/windows_platform.cc585
-rw-r--r--src/platform/windows_platform.h140
-rw-r--r--src/platform/x11_platform.cc1005
-rw-r--r--src/platform/x11_platform.h210
-rw-r--r--src/utils/logger.cc126
-rw-r--r--src/utils/logger.h92
35 files changed, 7621 insertions, 0 deletions
diff --git a/src/config/config_manager.h b/src/config/config_manager.h
new file mode 100644
index 0000000..97f751e
--- /dev/null
+++ b/src/config/config_manager.h
@@ -0,0 +1,101 @@
+#ifndef SRDWM_CONFIG_MANAGER_H
+#define SRDWM_CONFIG_MANAGER_H
+
+#include <string>
+#include <memory>
+#include <map>
+#include <functional>
+#include <vector> // Added missing include
+
+// Forward declarations
+class WindowManager;
+
+// Configuration manager for srdwm
+class ConfigManager {
+public:
+ struct KeyBinding {
+ std::string key;
+ std::string command;
+ std::string description;
+ };
+
+ struct LayoutConfig {
+ std::string name;
+ std::string type; // "tiling", "dynamic", "floating"
+ std::map<std::string, std::string> properties;
+ };
+
+ struct ThemeConfig {
+ std::string name;
+ std::map<std::string, std::string> colors;
+ std::map<std::string, std::string> fonts;
+ std::map<std::string, int> dimensions;
+ };
+
+ ConfigManager();
+ ~ConfigManager();
+
+ // Configuration loading
+ bool load_config(const std::string& config_path);
+ bool reload_config();
+
+ // Configuration access
+ std::string get_string(const std::string& key, const std::string& default_value = "") const;
+ int get_int(const std::string& key, int default_value = 0) const;
+ bool get_bool(const std::string& key, bool default_value = false) const;
+ double get_float(const std::string& key, double default_value = 0.0) const;
+
+ // Key bindings
+ std::vector<KeyBinding> get_key_bindings() const;
+ bool add_key_binding(const std::string& key, const std::string& command, const std::string& description = "");
+ bool remove_key_binding(const std::string& key);
+
+ // Layout configuration
+ std::vector<LayoutConfig> get_layout_configs() const;
+ LayoutConfig get_layout_config(const std::string& name) const;
+
+ // Theme configuration
+ ThemeConfig get_theme_config() const;
+ bool set_theme(const std::string& theme_name);
+
+ // Window rules
+ struct WindowRule {
+ std::string match_type; // "class", "title", "role"
+ std::string match_value;
+ std::map<std::string, std::string> properties;
+ };
+
+ std::vector<WindowRule> get_window_rules() const;
+ bool add_window_rule(const WindowRule& rule);
+
+ // Configuration validation
+ bool validate_config() const;
+ std::vector<std::string> get_validation_errors() const;
+
+private:
+ std::string config_path_;
+ std::map<std::string, std::string> string_values_;
+ std::map<std::string, int> int_values_;
+ std::map<std::string, bool> bool_values_;
+ std::map<std::string, double> float_values_;
+
+ std::vector<KeyBinding> key_bindings_;
+ std::vector<LayoutConfig> layout_configs_;
+ std::vector<WindowRule> window_rules_;
+ ThemeConfig current_theme_;
+
+ std::vector<std::string> validation_errors_;
+
+ // Private methods
+ void parse_config_file(const std::string& content);
+ void setup_default_config();
+ bool validate_key_binding(const KeyBinding& binding) const;
+ bool validate_layout_config(const LayoutConfig& config) const;
+ bool validate_window_rule(const WindowRule& rule) const;
+
+ // Lua integration (placeholder for future implementation)
+ bool execute_lua_config(const std::string& lua_code);
+};
+
+#endif // SRDWM_CONFIG_MANAGER_H
+
diff --git a/src/config/lua_manager.cc b/src/config/lua_manager.cc
new file mode 100644
index 0000000..1956578
--- /dev/null
+++ b/src/config/lua_manager.cc
@@ -0,0 +1,1024 @@
+#include "lua_manager.h"
+#include <iostream>
+#include <fstream>
+#include <filesystem>
+#include <algorithm>
+#include <cstring>
+
+// Global Lua manager instance
+std::unique_ptr<LuaManager> g_lua_manager;
+
+// Default configuration values
+namespace Defaults {
+ std::map<std::string, LuaConfigValue> create_default_config() {
+ std::map<std::string, LuaConfigValue> config;
+
+ config["general.default_layout"] = {LuaConfigValue::Type::String, "dynamic", 0.0, false, {}, ""};
+ config["general.smart_placement"] = {LuaConfigValue::Type::Boolean, "", 0.0, true, {}, ""};
+ config["general.window_gap"] = {LuaConfigValue::Type::Number, "", 8.0, false, {}, ""};
+ config["general.border_width"] = {LuaConfigValue::Type::Number, "", 2.0, false, {}, ""};
+ config["general.animations"] = {LuaConfigValue::Type::Boolean, "", 0.0, true, {}, ""};
+ config["general.animation_duration"] = {LuaConfigValue::Type::Number, "", 200.0, false, {}, ""};
+ config["general.focus_follows_mouse"] = {LuaConfigValue::Type::Boolean, "", 0.0, false, {}, ""};
+ config["general.mouse_follows_focus"] = {LuaConfigValue::Type::Boolean, "", 0.0, true, {}, ""};
+ config["general.auto_raise"] = {LuaConfigValue::Type::Boolean, "", 0.0, false, {}, ""};
+ config["general.auto_focus"] = {LuaConfigValue::Type::Boolean, "", 0.0, true, {}, ""};
+
+ config["monitor.primary_layout"] = {LuaConfigValue::Type::String, "dynamic", 0.0, false, {}, ""};
+ config["monitor.secondary_layout"] = {LuaConfigValue::Type::String, "tiling", 0.0, false, {}, ""};
+ config["monitor.auto_detect"] = {LuaConfigValue::Type::Boolean, "", 0.0, true, {}, ""};
+ config["monitor.primary_workspace"] = {LuaConfigValue::Type::Number, "", 1.0, false, {}, ""};
+ config["monitor.workspace_count"] = {LuaConfigValue::Type::Number, "", 10.0, false, {}, ""};
+
+ config["performance.vsync"] = {LuaConfigValue::Type::Boolean, "", 0.0, true, {}, ""};
+ config["performance.max_fps"] = {LuaConfigValue::Type::Number, "", 60.0, false, {}, ""};
+ config["performance.window_cache_size"] = {LuaConfigValue::Type::Number, "", 100.0, false, {}, ""};
+ config["performance.event_queue_size"] = {LuaConfigValue::Type::Number, "", 1000.0, false, {}, ""};
+
+ config["debug.logging"] = {LuaConfigValue::Type::Boolean, "", 0.0, true, {}, ""};
+ config["debug.log_level"] = {LuaConfigValue::Type::String, "info", 0.0, false, {}, ""};
+ config["debug.profile"] = {LuaConfigValue::Type::Boolean, "", 0.0, false, {}, ""};
+ config["debug.trace_events"] = {LuaConfigValue::Type::Boolean, "", 0.0, false, {}, ""};
+
+ return config;
+ }
+}
+
+LuaManager::LuaManager()
+ : L_(nullptr)
+ , window_manager_(nullptr)
+ , layout_engine_(nullptr)
+ , platform_(nullptr) {
+
+ // Initialize with default values
+ config_values_ = Defaults::create_default_config();
+}
+
+LuaManager::~LuaManager() {
+ shutdown();
+}
+
+bool LuaManager::initialize() {
+ std::cout << "Initializing Lua manager..." << std::endl;
+
+ // Create Lua state
+ L_ = luaL_newstate();
+ if (!L_) {
+ std::cerr << "Failed to create Lua state" << std::endl;
+ return false;
+ }
+
+ std::cout << "Lua state created successfully" << std::endl;
+
+ // Open Lua libraries
+ luaL_openlibs(L_);
+ std::cout << "Lua libraries opened" << std::endl;
+
+ // Setup Lua environment
+ setup_lua_environment();
+ std::cout << "Lua environment setup complete" << std::endl;
+
+ // Register SRD module
+ register_srd_module();
+ std::cout << "SRD module registration complete" << std::endl;
+
+ // Load default configuration
+ load_default_config();
+ std::cout << "Default configuration loaded" << std::endl;
+
+ std::cout << "Lua manager initialized successfully" << std::endl;
+ return true;
+}
+
+void LuaManager::shutdown() {
+ if (L_) {
+ lua_close(L_);
+ L_ = nullptr;
+ }
+
+ config_values_.clear();
+ key_bindings_.clear();
+ lua_errors_.clear();
+ validation_errors_.clear();
+}
+
+void LuaManager::setup_lua_environment() {
+ // Set Lua path to include SRDWM modules
+ std::string lua_path = "package.path = package.path .. ';";
+ lua_path += get_config_file_path() + "/?.lua;";
+ lua_path += get_config_file_path() + "/?/init.lua'";
+
+ if (luaL_dostring(L_, lua_path.c_str()) != LUA_OK) {
+ std::cerr << "Failed to set Lua path: " << lua_tostring(L_, -1) << std::endl;
+ lua_pop(L_, 1);
+ }
+
+ // Set global error handler
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ std::string error_msg = lua_tostring(L, 1);
+ std::cerr << "Lua error: " << error_msg << std::endl;
+ return 0;
+ });
+ lua_setglobal(L_, "error_handler");
+}
+
+void LuaManager::register_srd_module() {
+ std::cout << "Creating srd table..." << std::endl;
+
+ // Create srd table
+ lua_newtable(L_);
+
+ std::cout << "Registering window functions..." << std::endl;
+ // Register window functions
+ register_window_functions();
+
+ std::cout << "Registering layout functions..." << std::endl;
+ // Register layout functions
+ register_layout_functions();
+
+ std::cout << "Registering theme functions..." << std::endl;
+ // Register theme functions
+ register_theme_functions();
+
+ std::cout << "Registering utility functions..." << std::endl;
+ // Register utility functions
+ register_utility_functions();
+
+ std::cout << "Setting global srd variable..." << std::endl;
+ // Set global srd variable
+ lua_setglobal(L_, "srd");
+
+ // Store reference to this LuaManager instance for callbacks
+ lua_pushlightuserdata(L_, this);
+ lua_setglobal(L_, "_lua_manager_instance");
+
+ std::cout << "SRD module registered successfully" << std::endl;
+}
+
+void LuaManager::register_window_functions() {
+ // Create window subtable
+ lua_newtable(L_);
+
+ // Register window functions
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.window.focused()
+ // Get the global Lua manager instance
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager) {
+ // Return focused window info
+ lua_newtable(L);
+ lua_pushstring(L, "id");
+ lua_pushinteger(L, 0); // Placeholder
+ lua_settable(L, -3);
+ lua_pushstring(L, "title");
+ lua_pushstring(L, "Focused SRDWindow");
+ lua_settable(L, -3);
+ return 1;
+ }
+ }
+ lua_pop(L, 1);
+ lua_pushnil(L);
+ return 1;
+ });
+ lua_setfield(L_, -2, "focused");
+
+ // SRDWindow decoration controls
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.window.set_decorations(window_id, enabled)
+ const char* window_id = lua_tostring(L, 1);
+ bool enabled = lua_toboolean(L, 2);
+
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager && window_id) {
+ manager->set_window_decorations(window_id, enabled);
+ }
+ }
+ lua_pop(L, 1);
+ return 0;
+ });
+ lua_setfield(L_, -2, "set_decorations");
+
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.window.set_border_color(window_id, r, g, b)
+ const char* window_id = lua_tostring(L, 1);
+ int r = lua_tointeger(L, 2);
+ int g = lua_tointeger(L, 3);
+ int b = lua_tointeger(L, 4);
+
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager && window_id) {
+ manager->set_window_border_color(window_id, r, g, b);
+ }
+ }
+ lua_pop(L, 1);
+ return 0;
+ });
+ lua_setfield(L_, -2, "set_border_color");
+
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.window.set_border_width(window_id, width)
+ const char* window_id = lua_tostring(L, 1);
+ int width = lua_tointeger(L, 2);
+
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager && window_id) {
+ manager->set_window_border_width(window_id, width);
+ }
+ }
+ lua_pop(L, 1);
+ return 0;
+ });
+ lua_setfield(L_, -2, "set_border_width");
+
+ // SRDWindow state controls
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.window.set_floating(window_id, floating)
+ const char* window_id = lua_tostring(L, 1);
+ bool floating = lua_toboolean(L, 2);
+
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager && window_id) {
+ manager->set_window_floating(window_id, floating);
+ }
+ }
+ lua_pop(L, 1);
+ return 0;
+ });
+ lua_setfield(L_, -2, "set_floating");
+
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.window.toggle_floating(window_id)
+ const char* window_id = lua_tostring(L, 1);
+
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager && window_id) {
+ manager->toggle_window_floating(window_id);
+ }
+ }
+ lua_pop(L, 1);
+ return 0;
+ });
+ lua_setfield(L_, -2, "toggle_floating");
+
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.window.is_floating(window_id)
+ const char* window_id = lua_tostring(L, 1);
+
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager && window_id) {
+ bool floating = manager->is_window_floating(window_id);
+ lua_pushboolean(L, floating);
+ lua_pop(L, 1); // Pop userdata
+ return 1;
+ }
+ }
+ lua_pop(L, 1);
+ lua_pushboolean(L, false);
+ return 1;
+ });
+ lua_setfield(L_, -2, "is_floating");
+
+ // Set window subtable in the srd table (which is at index -2)
+ lua_setfield(L_, -2, "window");
+}
+
+void LuaManager::register_layout_functions() {
+ // Create layout subtable
+ lua_newtable(L_);
+
+ // Register layout functions
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.layout.set(layout_name)
+ const char* layout_name = lua_tostring(L, 1);
+ if (layout_name) {
+ // Get the global Lua manager instance
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager) {
+ // For now, set layout on monitor 0 (primary monitor)
+ manager->set_layout(0, layout_name);
+ }
+ }
+ lua_pop(L, 1); // Pop the userdata
+ std::cout << "Switching to layout: " << layout_name << std::endl;
+ }
+ return 0;
+ });
+ lua_setfield(L_, -2, "set");
+
+ // Register configure function
+ lua_pushcclosure(L_, [](lua_State* L) -> int {
+ // srd.layout.configure(layout_name, config_table)
+ const char* layout_name = lua_tostring(L, 1);
+ if (layout_name && lua_istable(L, 2)) {
+ // Get the global Lua manager instance
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager) {
+ // Convert Lua table to C++ map
+ std::map<std::string, std::string> config;
+ lua_pushnil(L); // First key
+ while (lua_next(L, 2) != 0) {
+ if (lua_isstring(L, -2) && lua_isstring(L, -1)) {
+ const char* key = lua_tostring(L, -2);
+ const char* value = lua_tostring(L, -1);
+ config[key] = value;
+ }
+ lua_pop(L, 1); // Remove value, keep key for next iteration
+ }
+ lua_pop(L, 1); // Remove the userdata
+
+ // Configure the layout
+ manager->configure_layout(layout_name, config);
+ }
+ } else {
+ lua_pop(L, 1);
+ }
+ std::cout << "Configuring layout: " << layout_name << std::endl;
+ }
+ return 0;
+ }, 0);
+ lua_setfield(L_, -2, "configure");
+
+ // Set layout subtable in the srd table (which is at index -2)
+ lua_setfield(L_, -2, "layout");
+}
+
+void LuaManager::register_theme_functions() {
+ // Create theme subtable
+ lua_newtable(L_);
+
+ // Register theme functions
+ lua_pushcclosure(L_, [](lua_State* L) -> int {
+ // srd.theme.set_colors(colors_table)
+ if (lua_istable(L, 1)) {
+ // Get the global Lua manager instance
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager) {
+ // Convert Lua table to C++ map
+ std::map<std::string, std::string> colors;
+ lua_pushnil(L); // First key
+ while (lua_next(L, 1) != 0) {
+ if (lua_isstring(L, -2) && lua_isstring(L, -1)) {
+ const char* key = lua_tostring(L, -2);
+ const char* value = lua_tostring(L, -1);
+ colors[key] = value;
+ }
+ lua_pop(L, 1); // Remove value, keep key for next iteration
+ }
+ lua_pop(L, 1); // Remove the userdata
+
+ // Set theme colors
+ for (const auto& [key, value] : colors) {
+ manager->set_string("theme." + key, value);
+ }
+ }
+ } else {
+ lua_pop(L, 1);
+ }
+ std::cout << "Setting theme colors" << std::endl;
+ }
+ return 0;
+ }, 0);
+ lua_setfield(L_, -2, "set_colors");
+
+ // Set theme subtable in the srd table (which is at index -2)
+ lua_setfield(L_, -2, "theme");
+}
+
+void LuaManager::register_utility_functions() {
+ // Register utility functions directly in the srd table (which is at index -1)
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.set(key, value)
+ const char* key = lua_tostring(L, 1);
+ if (key) {
+ // Get the global Lua manager instance
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager) {
+ // Handle different value types
+ if (lua_isstring(L, 2)) {
+ const char* value = lua_tostring(L, 2);
+ manager->set_string(key, value);
+ } else if (lua_isnumber(L, 2)) {
+ double value = lua_tonumber(L, 2);
+ manager->set_float(key, value);
+ } else if (lua_isboolean(L, 2)) {
+ bool value = lua_toboolean(L, 2);
+ manager->set_bool(key, value);
+ }
+ }
+ }
+ lua_pop(L, 1); // Remove the userdata
+ std::cout << "Setting config: " << key << std::endl;
+ }
+ return 0;
+ });
+ lua_setfield(L_, -2, "set");
+
+ // Register bind function
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.bind(key, function)
+ const char* key = lua_tostring(L, 1);
+ if (key && lua_isfunction(L, 2)) {
+ // Get the global Lua manager instance
+ lua_getglobal(L, "_lua_manager_instance");
+ if (lua_islightuserdata(L, -1)) {
+ LuaManager* manager = static_cast<LuaManager*>(lua_touserdata(L, -1));
+ if (manager) {
+ // Store the function reference
+ // For now, just store the key binding
+ manager->bind_key(key, "lua_function");
+ }
+ }
+ lua_pop(L, 1); // Remove the userdata
+ std::cout << "Binding key: " << key << std::endl;
+ }
+ return 0;
+ });
+ lua_setfield(L_, -2, "bind");
+
+ // Register load function
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.load(module_name)
+ const char* module_name = lua_tostring(L, 1);
+ if (module_name) {
+ // TODO: Implement module loading
+ std::cout << "Loading module: " << module_name << std::endl;
+ }
+ return 0;
+ });
+ lua_setfield(L_, -2, "load");
+
+ // Register spawn function
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.spawn(command)
+ const char* command = lua_tostring(L, 1);
+ if (command) {
+ // TODO: Implement command spawning
+ std::cout << "Spawning command: " << command << std::endl;
+ }
+ return 0;
+ });
+ lua_setfield(L_, -2, "spawn");
+
+ // Register notify function
+ lua_pushcfunction(L_, [](lua_State* L) -> int {
+ // srd.notify(message, level)
+ const char* message = lua_tostring(L, 1);
+ const char* level = lua_tostring(L, 2);
+ if (message) {
+ std::cout << "Notification [" << (level ? level : "info") << "]: " << message << std::endl;
+ }
+ return 0;
+ });
+ lua_setfield(L_, -2, "notify");
+}
+
+bool LuaManager::load_config_file(const std::string& path) {
+ if (!L_) {
+ std::cerr << "Lua manager not initialized" << std::endl;
+ return false;
+ }
+
+ std::cout << "Loading config file: " << path << std::endl;
+
+ // Test if srd module exists before loading
+ lua_getglobal(L_, "srd");
+ if (lua_isnil(L_, -1)) {
+ std::cerr << "ERROR: srd module is nil before loading config!" << std::endl;
+ lua_pop(L_, 1);
+ return false;
+ } else {
+ std::cout << "srd module exists before loading config" << std::endl;
+ lua_pop(L_, 1);
+ }
+
+ // Load and execute Lua file
+ if (luaL_dofile(L_, path.c_str()) != LUA_OK) {
+ std::string error = lua_tostring(L_, -1);
+ add_lua_error("Failed to load config file: " + error);
+ lua_pop(L_, 1);
+ return false;
+ }
+
+ std::cout << "Config file loaded successfully: " << path << std::endl;
+ return true;
+}
+
+bool LuaManager::load_config_directory(const std::string& dir_path) {
+ std::cout << "Loading config directory: " << dir_path << std::endl;
+
+ try {
+ std::filesystem::path config_dir(dir_path);
+ if (!std::filesystem::exists(config_dir)) {
+ std::cerr << "Config directory does not exist: " << dir_path << std::endl;
+ return false;
+ }
+
+ // Load init.lua first if it exists
+ std::filesystem::path init_file = config_dir / "init.lua";
+ if (std::filesystem::exists(init_file)) {
+ if (!load_config_file(init_file.string())) {
+ return false;
+ }
+ }
+
+ // Load other .lua files
+ for (const auto& entry : std::filesystem::directory_iterator(config_dir)) {
+ if (entry.is_regular_file() && entry.path().extension() == ".lua") {
+ if (entry.path().filename() != "init.lua") {
+ if (!load_config_file(entry.path().string())) {
+ std::cerr << "Failed to load config file: " << entry.path() << std::endl;
+ // Continue loading other files
+ }
+ }
+ }
+ }
+
+ std::cout << "Config directory loaded successfully: " << dir_path << std::endl;
+ return true;
+
+ } catch (const std::exception& e) {
+ std::cerr << "Error loading config directory: " << e.what() << std::endl;
+ return false;
+ }
+}
+
+bool LuaManager::reload_config() {
+ std::cout << "Reloading configuration..." << std::endl;
+
+ // Clear current configuration
+ config_values_.clear();
+ key_bindings_.clear();
+ clear_errors();
+
+ // Reload default configuration
+ load_default_config();
+
+ // Reload user configuration
+ std::string config_path = get_config_file_path();
+ if (!load_config_directory(config_path)) {
+ std::cerr << "Failed to reload configuration" << std::endl;
+ return false;
+ }
+
+ std::cout << "Configuration reloaded successfully" << std::endl;
+ return true;
+}
+
+// SRDWindow decoration controls implementation
+bool LuaManager::set_window_decorations(const std::string& window_id, bool enabled) {
+ std::cout << "LuaManager: Set window decorations for " << window_id << " to " << (enabled ? "enabled" : "disabled") << std::endl;
+
+ if (!platform_) {
+ std::cerr << "Platform not available for decoration control" << std::endl;
+ return false;
+ }
+
+ // Find window by ID (placeholder implementation)
+ // In a real implementation, you'd look up the window in the window manager
+ SRDWindow* window = nullptr; // TODO: Get window from window manager
+
+ if (window) {
+ platform_->set_window_decorations(window, enabled);
+ return true;
+ }
+
+ return false;
+}
+
+bool LuaManager::set_window_border_color(const std::string& window_id, int r, int g, int b) {
+ std::cout << "LuaManager: Set border color for " << window_id << " to RGB(" << r << "," << g << "," << b << ")" << std::endl;
+
+ if (!platform_) {
+ std::cerr << "Platform not available for border color control" << std::endl;
+ return false;
+ }
+
+ // Find window by ID (placeholder implementation)
+ SRDWindow* window = nullptr; // TODO: Get window from window manager
+
+ if (window) {
+ platform_->set_window_border_color(window, r, g, b);
+ return true;
+ }
+
+ return false;
+}
+
+bool LuaManager::set_window_border_width(const std::string& window_id, int width) {
+ std::cout << "LuaManager: Set border width for " << window_id << " to " << width << std::endl;
+
+ if (!platform_) {
+ std::cerr << "Platform not available for border width control" << std::endl;
+ return false;
+ }
+
+ // Find window by ID (placeholder implementation)
+ SRDWindow* window = nullptr; // TODO: Get window from window manager
+
+ if (window) {
+ platform_->set_window_border_width(window, width);
+ return true;
+ }
+
+ return false;
+}
+
+bool LuaManager::get_window_decorations(const std::string& window_id) const {
+ if (!platform_) {
+ return false;
+ }
+
+ // Find window by ID (placeholder implementation)
+ SRDWindow* window = nullptr; // TODO: Get window from window manager
+
+ if (window) {
+ return platform_->get_window_decorations(window);
+ }
+
+ return false;
+}
+
+// SRDWindow state controls implementation
+bool LuaManager::set_window_floating(const std::string& window_id, bool floating) {
+ std::cout << "LuaManager: Set window " << window_id << " floating to " << (floating ? "true" : "false") << std::endl;
+
+ if (!window_manager_) {
+ std::cerr << "SRDWindow manager not available for floating control" << std::endl;
+ return false;
+ }
+
+ // Find window by ID (placeholder implementation)
+ SRDWindow* window = nullptr; // TODO: Get window from window manager
+
+ if (window) {
+ // TODO: Implement window floating state change
+ // This would involve changing the window's layout state
+ return true;
+ }
+
+ return false;
+}
+
+bool LuaManager::toggle_window_floating(const std::string& window_id) {
+ std::cout << "LuaManager: Toggle window " << window_id << " floating state" << std::endl;
+
+ bool current_state = is_window_floating(window_id);
+ return set_window_floating(window_id, !current_state);
+}
+
+bool LuaManager::is_window_floating(const std::string& window_id) const {
+ if (!window_manager_) {
+ return false;
+ }
+
+ // Find window by ID (placeholder implementation)
+ SRDWindow* window = nullptr; // TODO: Get window from window manager
+
+ if (window) {
+ // TODO: Check window's current layout state
+ return false; // Placeholder
+ }
+
+ return false;
+}
+
+void LuaManager::load_default_config() {
+ config_values_ = Defaults::create_default_config();
+}
+
+std::string LuaManager::get_string(const std::string& key, const std::string& default_value) const {
+ auto it = config_values_.find(key);
+ if (it != config_values_.end() && it->second.type == LuaConfigValue::Type::String) {
+ return it->second.string_value;
+ }
+ return default_value;
+}
+
+int LuaManager::get_int(const std::string& key, int default_value) const {
+ auto it = config_values_.find(key);
+ if (it != config_values_.end() && it->second.type == LuaConfigValue::Type::Number) {
+ return static_cast<int>(it->second.number_value);
+ }
+ return default_value;
+}
+
+bool LuaManager::get_bool(const std::string& key, bool default_value) const {
+ auto it = config_values_.find(key);
+ if (it != config_values_.end() && it->second.type == LuaConfigValue::Type::Boolean) {
+ return it->second.bool_value;
+ }
+ return default_value;
+}
+
+double LuaManager::get_float(const std::string& key, double default_value) const {
+ auto it = config_values_.find(key);
+ if (it != config_values_.end() && it->second.type == LuaConfigValue::Type::Number) {
+ return it->second.number_value;
+ }
+ return default_value;
+}
+
+void LuaManager::set_string(const std::string& key, const std::string& value) {
+ LuaConfigValue config_value;
+ config_value.type = LuaConfigValue::Type::String;
+ config_value.string_value = value;
+ config_values_[key] = config_value;
+}
+
+void LuaManager::set_int(const std::string& key, int value) {
+ LuaConfigValue config_value;
+ config_value.type = LuaConfigValue::Type::Number;
+ config_value.number_value = static_cast<double>(value);
+ config_values_[key] = config_value;
+}
+
+void LuaManager::set_bool(const std::string& key, bool value) {
+ LuaConfigValue config_value;
+ config_value.type = LuaConfigValue::Type::Boolean;
+ config_value.bool_value = value;
+ config_values_[key] = config_value;
+}
+
+void LuaManager::set_float(const std::string& key, double value) {
+ LuaConfigValue config_value;
+ config_value.type = LuaConfigValue::Type::Number;
+ config_value.number_value = value;
+ config_values_[key] = config_value;
+}
+
+bool LuaManager::bind_key(const std::string& key_combination, const std::string& lua_function) {
+ key_bindings_[key_combination] = lua_function;
+ std::cout << "Bound key: " << key_combination << " -> " << lua_function << std::endl;
+ return true;
+}
+
+bool LuaManager::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 << "Unbound key: " << key_combination << std::endl;
+ return true;
+ }
+ return false;
+}
+
+std::vector<std::string> LuaManager::get_bound_keys() const {
+ std::vector<std::string> keys;
+ for (const auto& binding : key_bindings_) {
+ keys.push_back(binding.first);
+ }
+ return keys;
+}
+
+bool LuaManager::execute_lua_code(const std::string& code) {
+ if (!L_) {
+ return false;
+ }
+
+ if (luaL_dostring(L_, code.c_str()) != LUA_OK) {
+ std::string error = lua_tostring(L_, -1);
+ add_lua_error("Failed to execute Lua code: " + error);
+ lua_pop(L_, 1);
+ return false;
+ }
+
+ return true;
+}
+
+bool LuaManager::validate_lua_syntax(const std::string& code) {
+ if (!L_) {
+ return false;
+ }
+
+ // Try to load the code as a function (syntax check)
+ if (luaL_loadstring(L_, code.c_str()) != LUA_OK) {
+ std::string error = lua_tostring(L_, -1);
+ add_lua_error("Lua syntax error: " + error);
+ lua_pop(L_, 1);
+ return false;
+ }
+
+ // Pop the loaded function
+ lua_pop(L_, 1);
+ return true;
+}
+
+std::vector<std::string> LuaManager::get_lua_errors() const {
+ return lua_errors_;
+}
+
+bool LuaManager::validate_config() const {
+ std::cout << "LuaManager: Validating configuration..." << std::endl;
+
+ // Check for required configuration values
+ std::vector<std::string> required_keys = {
+ "general.default_layout",
+ "general.window_gap",
+ "general.border_width"
+ };
+
+ for (const auto& key : required_keys) {
+ auto it = config_values_.find(key);
+ if (it == config_values_.end()) {
+ add_validation_error("Missing required configuration: " + key);
+ return false;
+ }
+ }
+
+ // Validate layout configuration
+ auto layout_it = config_values_.find("general.default_layout");
+ if (layout_it != config_values_.end()) {
+ std::string layout = layout_it->second.string_value;
+ if (layout != "tiling" && layout != "dynamic" && layout != "floating") {
+ add_validation_error("Invalid default layout: " + layout);
+ return false;
+ }
+ }
+
+ // Validate numeric values
+ auto gap_it = config_values_.find("general.window_gap");
+ if (gap_it != config_values_.end()) {
+ double gap = gap_it->second.number_value;
+ if (gap < 0 || gap > 100) {
+ add_validation_error("SRDWindow gap must be between 0 and 100");
+ return false;
+ }
+ }
+
+ auto border_it = config_values_.find("general.border_width");
+ if (border_it != config_values_.end()) {
+ double border = border_it->second.number_value;
+ if (border < 0 || border > 50) {
+ add_validation_error("Border width must be between 0 and 50");
+ return false;
+ }
+ }
+
+ std::cout << "LuaManager: Configuration validation passed" << std::endl;
+ return true;
+}
+
+std::vector<std::string> LuaManager::get_validation_errors() const {
+ return validation_errors_;
+}
+
+void LuaManager::reset_config(const std::string& key) {
+ auto default_config = Defaults::create_default_config();
+ auto it = default_config.find(key);
+ if (it != default_config.end()) {
+ config_values_[key] = it->second;
+ }
+}
+
+void LuaManager::reset_all_configs() {
+ config_values_ = Defaults::create_default_config();
+}
+
+void LuaManager::reset_category(const std::string& category) {
+ std::string prefix = category + ".";
+ auto default_config = Defaults::create_default_config();
+ for (const auto& default_item : default_config) {
+ if (default_item.first.substr(0, prefix.length()) == prefix) {
+ config_values_[default_item.first] = default_item.second;
+ }
+ }
+}
+
+void LuaManager::add_lua_error(const std::string& error) {
+ lua_errors_.push_back(error);
+}
+
+void LuaManager::add_validation_error(const std::string& error) const {
+ const_cast<LuaManager*>(this)->validation_errors_.push_back(error);
+}
+
+void LuaManager::clear_errors() {
+ lua_errors_.clear();
+ validation_errors_.clear();
+}
+
+std::string LuaManager::get_config_file_path() const {
+ // Platform-specific config path detection
+ const char* home = std::getenv("HOME");
+ if (home) {
+ std::string config_dir = std::string(home) + "/.config/srdwm";
+ return config_dir + "/config.lua";
+ }
+ return "./config.lua";
+}
+
+std::string LuaManager::get_default_config_path() const {
+ // Platform-specific default config path
+ const char* home = std::getenv("HOME");
+ if (home) {
+ std::string config_dir = std::string(home) + "/.config/srdwm";
+ return config_dir + "/default.lua";
+ }
+ return "./default.lua";
+}
+
+bool LuaManager::create_default_config() const {
+ std::cout << "LuaManager: Creating default configuration..." << std::endl;
+
+ // Create default configuration directory
+ const char* home = std::getenv("HOME");
+ if (home) {
+ std::string config_dir = std::string(home) + "/.config/srdwm";
+ std::string config_file = config_dir + "/config.lua";
+
+ // Create directory if it doesn't exist
+ std::filesystem::create_directories(config_dir);
+
+ // Create default config file
+ std::ofstream file(config_file);
+ if (file.is_open()) {
+ file << "-- SRDWM Default Configuration\n";
+ file << "-- Generated automatically\n\n";
+ file << "-- Basic settings\n";
+ file << "srd.set('general.default_layout', 'dynamic')\n";
+ file << "srd.set('general.window_gap', 8)\n";
+ file << "srd.set('general.border_width', 2)\n";
+ file << "srd.set('general.animations', true)\n\n";
+ file << "-- Key bindings\n";
+ file << "srd.bind('Mod4+Return', function()\n";
+ file << " srd.spawn('alacritty')\n";
+ file << "end)\n\n";
+ file << "srd.bind('Mod4+Q', function()\n";
+ file << " local focused = srd.window.focused()\n";
+ file << " if focused then\n";
+ file << " srd.window.close(focused)\n";
+ file << " end\n";
+ file << "end)\n\n";
+ file << "srd.bind('Mod4+Space', function()\n";
+ file << " srd.layout.set('tiling')\n";
+ file << "end)\n";
+ file.close();
+
+ std::cout << "LuaManager: Default configuration created at " << config_file << std::endl;
+ return true;
+ }
+ }
+
+ std::cout << "LuaManager: Failed to create default configuration" << std::endl;
+ return false;
+}
+
+// Layout system methods
+std::vector<std::string> LuaManager::get_available_layouts() const {
+ if (layout_engine_) {
+ return layout_engine_->get_available_layouts();
+ }
+ return {"tiling", "dynamic", "floating"};
+}
+
+bool LuaManager::set_layout(int monitor_id, const std::string& layout_name) {
+ if (layout_engine_) {
+ return layout_engine_->set_layout(monitor_id, layout_name);
+ }
+ std::cout << "LuaManager: Setting layout '" << layout_name << "' for monitor " << monitor_id << std::endl;
+ return true;
+}
+
+std::string LuaManager::get_layout_name(int monitor_id) const {
+ if (layout_engine_) {
+ return layout_engine_->get_layout_name(monitor_id);
+ }
+ return "dynamic";
+}
+
+void LuaManager::set_layout_engine(LayoutEngine* engine) {
+ layout_engine_ = engine;
+ std::cout << "LuaManager: Layout engine connected" << std::endl;
+}
+
+bool LuaManager::configure_layout(const std::string& layout_name, const std::map<std::string, std::string>& config) {
+ if (layout_engine_) {
+ return layout_engine_->configure_layout(layout_name, config);
+ }
+ std::cout << "LuaManager: Configured layout '" << layout_name << "' with " << config.size() << " parameters" << std::endl;
+ return true;
+}
+
+
diff --git a/src/config/lua_manager.h b/src/config/lua_manager.h
new file mode 100644
index 0000000..c1c22c5
--- /dev/null
+++ b/src/config/lua_manager.h
@@ -0,0 +1,166 @@
+#ifndef SRDWM_LUA_MANAGER_H
+#define SRDWM_LUA_MANAGER_H
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <map>
+#include <functional>
+#include <lua.hpp>
+
+// Forward declarations
+class SRDWindow;
+class SRDWindowManager;
+class LayoutEngine;
+
+// Include platform header for full definition
+#include "../platform/platform.h"
+
+// Include layout engine header
+#include "../layouts/layout_engine.h"
+
+// Lua callback function type
+using LuaCallback = std::function<void()>;
+
+// Lua configuration value
+struct LuaConfigValue {
+ enum class Type {
+ String,
+ Number,
+ Boolean,
+ Table,
+ Function
+ };
+
+ Type type;
+ std::string string_value;
+ double number_value;
+ bool bool_value;
+ std::map<std::string, LuaConfigValue> table_value;
+ std::string function_name;
+};
+
+// Lua manager for SRDWM
+class LuaManager {
+public:
+ LuaManager();
+ ~LuaManager();
+
+ // Initialization and cleanup
+ bool initialize();
+ void shutdown();
+
+ // Configuration loading
+ bool load_config_file(const std::string& path);
+ bool load_config_directory(const std::string& dir_path);
+ bool reload_config();
+
+ // Configuration access
+ LuaConfigValue get_config(const std::string& key) const;
+ std::string get_string(const std::string& key, const std::string& default_value = "") const;
+ int get_int(const std::string& key, int default_value = 0) const;
+ bool get_bool(const std::string& key, bool default_value = false) const;
+ double get_float(const std::string& key, double default_value = 0.0) const;
+
+ // Configuration modification
+ void set_config(const std::string& key, const LuaConfigValue& value);
+ void set_string(const std::string& key, const std::string& value);
+ void set_int(const std::string& key, int value);
+ void set_bool(const std::string& key, bool value);
+ void set_float(const std::string& key, double value);
+
+ // Key binding system
+ bool bind_key(const std::string& key_combination, const std::string& lua_function);
+ bool unbind_key(const std::string& key_combination);
+ std::vector<std::string> get_bound_keys() const;
+
+ // Layout system
+ bool configure_layout(const std::string& layout_name, const std::map<std::string, LuaConfigValue>& config);
+ bool configure_layout(const std::string& layout_name, const std::map<std::string, std::string>& config);
+ bool register_custom_layout(const std::string& name, const std::string& lua_function);
+ std::vector<std::string> get_available_layouts() const;
+ bool set_layout(int monitor_id, const std::string& layout_name);
+ std::string get_layout_name(int monitor_id) const;
+ void set_layout_engine(LayoutEngine* engine);
+
+ // Theme system
+ bool set_theme_colors(const std::map<std::string, std::string>& colors);
+ bool set_theme_decorations(const std::map<std::string, LuaConfigValue>& decorations);
+
+ // SRDWindow decoration controls
+ bool set_window_decorations(const std::string& window_id, bool enabled);
+ bool set_window_border_color(const std::string& window_id, int r, int g, int b);
+ bool set_window_border_width(const std::string& window_id, int width);
+ bool get_window_decorations(const std::string& window_id) const;
+
+ // SRDWindow state controls
+ bool set_window_floating(const std::string& window_id, bool floating);
+ bool toggle_window_floating(const std::string& window_id);
+ bool is_window_floating(const std::string& window_id) const;
+ std::map<std::string, std::string> get_theme_colors() const;
+
+ // SRDWindow rules
+ bool add_window_rule(const std::map<std::string, LuaConfigValue>& rule);
+ bool remove_window_rule(const std::string& rule_name);
+ std::vector<std::map<std::string, LuaConfigValue>> get_window_rules() const;
+
+ // Utility functions
+ bool execute_lua_code(const std::string& code);
+ bool validate_lua_syntax(const std::string& code);
+ std::vector<std::string> get_lua_errors() const;
+
+ // Configuration validation
+ bool validate_config() const;
+ std::vector<std::string> get_validation_errors() const;
+
+ // Reset functionality
+ void reset_config(const std::string& key);
+ void reset_all_configs();
+ void reset_category(const std::string& category);
+
+private:
+ lua_State* L_;
+ std::map<std::string, LuaConfigValue> config_values_;
+ std::map<std::string, std::string> key_bindings_;
+ std::vector<std::string> lua_errors_;
+ std::vector<std::string> validation_errors_;
+
+ // SRDWindow manager reference
+ SRDWindowManager* window_manager_;
+ LayoutEngine* layout_engine_;
+ Platform* platform_;
+
+ // Private methods
+ void setup_lua_environment();
+ void register_srd_module();
+ void register_window_functions();
+ void register_layout_functions();
+ void register_theme_functions();
+ void register_utility_functions();
+
+ // Configuration helpers
+ void parse_config_value(lua_State* L, int index, const std::string& key);
+ void save_config_to_lua();
+ void load_default_config();
+
+ // Error handling
+ void add_lua_error(const std::string& error);
+ void add_validation_error(const std::string& error) const;
+ void clear_errors();
+
+ // File watching
+ void setup_file_watcher();
+ void on_config_file_changed(const std::string& path);
+
+ // Helper functions
+ std::string get_config_file_path() const;
+ std::string get_default_config_path() const;
+ bool create_default_config() const;
+};
+
+// Global Lua manager instance
+extern std::unique_ptr<LuaManager> g_lua_manager;
+
+#endif // SRDWM_LUA_MANAGER_H
+
+
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
diff --git a/src/input/input_handler.h b/src/input/input_handler.h
new file mode 100644
index 0000000..2f35608
--- /dev/null
+++ b/src/input/input_handler.h
@@ -0,0 +1,36 @@
+#ifndef SRDWM_INPUT_HANDLER_H
+#define SRDWM_INPUT_HANDLER_H
+
+#include <memory>
+
+// Define basic event structures (these will need more detail later)
+struct KeyboardEvent {
+ int key_code;
+ // Add modifiers, state (press/release)
+};
+
+struct MouseEvent {
+ enum class Type { Press, Release, Motion };
+ Type type;
+ int button; // Valid for Press/Release
+ int x, y;
+ // Add modifiers
+};
+
+class InputHandler {
+public:
+ virtual ~InputHandler() = default;
+
+ // Pure virtual methods for handling events
+ virtual void handle_key_press(const KeyboardEvent& event) = 0;
+ virtual void handle_key_release(const KeyboardEvent& event) = 0;
+ virtual void handle_mouse_button_press(const MouseEvent& event) = 0;
+ virtual void handle_mouse_button_release(const MouseEvent& event) = 0;
+ virtual void handle_mouse_motion(const MouseEvent& event) = 0;
+
+ // Other potential input-related methods
+ // virtual void initialize() = 0;
+ // virtual void shutdown() = 0;
+};
+
+#endif // SRDWM_INPUT_HANDLER_H
diff --git a/src/layouts/dynamic_layout.cc b/src/layouts/dynamic_layout.cc
new file mode 100644
index 0000000..7f10ac8
--- /dev/null
+++ b/src/layouts/dynamic_layout.cc
@@ -0,0 +1,31 @@
+#include "dynamic_layout.h"
+#include "../core/window.h"
+#include <iostream>
+
+DynamicLayout::DynamicLayout() {
+ // Constructor implementation if needed
+}
+
+DynamicLayout::~DynamicLayout() {
+ // Destructor implementation if needed
+}
+
+void DynamicLayout::arrange_windows(const std::vector<SRDWindow*>& windows, const Monitor& monitor) {
+ std::cout << "DynamicLayout::arrange_windows called for monitor (" << monitor.x << ", " << monitor.y << ", " << monitor.width << ", " << monitor.height << ")" << std::endl;
+ std::cout << "Arranging " << windows.size() << " windows dynamically." << std::endl;
+
+ // Basic placeholder: In a real dynamic layout, you might not resize/reposition
+ // windows automatically here unless triggered by user interaction or specific rules.
+ // For now, just iterate through the windows and acknowledge them.
+ for (const auto& window : windows) {
+ std::cout << " - SRDWindow ID: " << window->getId() << ", Title: " << window->getTitle() << std::endl;
+ // In a real implementation, you might update window properties based on
+ // the dynamic layout logic, or simply leave their positions/sizes as they are
+ // unless a move/resize operation is in progress.
+ }
+
+ // Future implementation would involve logic for:
+ // - Remembering window positions and sizes.
+ // - Handling user-initiated moves and resizes.
+ // - Potentially snapping windows to grid or other windows.
+}
diff --git a/src/layouts/dynamic_layout.h b/src/layouts/dynamic_layout.h
new file mode 100644
index 0000000..3692c36
--- /dev/null
+++ b/src/layouts/dynamic_layout.h
@@ -0,0 +1,17 @@
+#ifndef SRDWM_DYNAMIC_LAYOUT_H
+#define SRDWM_DYNAMIC_LAYOUT_H
+
+#include "layout.h"
+#include "../core/window.h"
+#include <vector>
+
+class DynamicLayout : public Layout {
+public:
+ DynamicLayout();
+ ~DynamicLayout();
+
+ // Implement the pure virtual method from the base class
+ void arrange_windows(const std::vector<SRDWindow*>& windows, const Monitor& monitor) override;
+};
+
+#endif // SRDWM_DYNAMIC_LAYOUT_H
diff --git a/src/layouts/layout.h b/src/layouts/layout.h
new file mode 100644
index 0000000..00c002f
--- /dev/null
+++ b/src/layouts/layout.h
@@ -0,0 +1,33 @@
+#ifndef SRDWM_LAYOUT_H
+#define SRDWM_LAYOUT_H
+
+#include <vector>
+#include "../core/window.h"
+
+struct Monitor {
+ int id;
+ int x;
+ int y;
+ int width;
+ int height;
+ std::string name;
+ int refresh_rate;
+
+ Monitor() : id(0), x(0), y(0), width(0), height(0), refresh_rate(60) {}
+ Monitor(int id, int x, int y, int width, int height, const std::string& name = "", int refresh = 60)
+ : id(id), x(x), y(y), width(width), height(height), name(name), refresh_rate(refresh) {}
+};
+
+class Layout {
+public:
+ virtual ~Layout() = default;
+
+ // Pure virtual method to arrange windows on a given monitor
+ virtual void arrange_windows(const std::vector<SRDWindow*>& windows, const Monitor& monitor) = 0;
+
+ // You might add other common layout methods here later, e.g.:
+ // virtual void add_window(SRDWindow* window) = 0;
+ // virtual void remove_window(SRDWindow* window) = 0;
+};
+
+#endif // SRDWM_LAYOUT_H
diff --git a/src/layouts/layout_engine.cc b/src/layouts/layout_engine.cc
new file mode 100644
index 0000000..f6bc20f
--- /dev/null
+++ b/src/layouts/layout_engine.cc
@@ -0,0 +1,188 @@
+#include "layout_engine.h"
+#include <iostream>
+#include <algorithm>
+
+LayoutEngine::LayoutEngine() {
+ std::cout << "LayoutEngine: Initializing..." << std::endl;
+}
+
+LayoutEngine::~LayoutEngine() {
+ std::cout << "LayoutEngine: Shutting down..." << std::endl;
+}
+
+// Layout management
+bool LayoutEngine::set_layout(int monitor_id, LayoutType layout_type) {
+ active_layouts_[monitor_id] = layout_type;
+ std::cout << "LayoutEngine: Set layout " << layout_type_to_string(layout_type)
+ << " for monitor " << monitor_id << std::endl;
+ return true;
+}
+
+bool LayoutEngine::set_layout(int monitor_id, const std::string& layout_name) {
+ LayoutType layout_type = string_to_layout_type(layout_name);
+ if (layout_type != LayoutType::TILING && layout_type != LayoutType::DYNAMIC && layout_type != LayoutType::FLOATING) {
+ std::cerr << "LayoutEngine: Unknown layout type: " << layout_name << std::endl;
+ return false;
+ }
+ return set_layout(monitor_id, layout_type);
+}
+
+LayoutType LayoutEngine::get_layout(int monitor_id) const {
+ auto it = active_layouts_.find(monitor_id);
+ if (it != active_layouts_.end()) {
+ return it->second;
+ }
+ return LayoutType::DYNAMIC; // Default layout
+}
+
+std::string LayoutEngine::get_layout_name(int monitor_id) const {
+ return layout_type_to_string(get_layout(monitor_id));
+}
+
+// Layout configuration
+bool LayoutEngine::configure_layout(const std::string& layout_name, const std::map<std::string, std::string>& config) {
+ layout_configs_[layout_name] = config;
+ std::cout << "LayoutEngine: Configured layout '" << layout_name << "' with "
+ << config.size() << " parameters" << std::endl;
+ return true;
+}
+
+bool LayoutEngine::register_custom_layout(const std::string& name, std::function<void(const std::vector<SRDWindow*>&, const Monitor&)> layout_func) {
+ custom_layouts_[name] = layout_func;
+ std::cout << "LayoutEngine: Registered custom layout '" << name << "'" << std::endl;
+ return true;
+}
+
+// SRDWindow management
+void LayoutEngine::add_window(SRDWindow* window) {
+ if (window && std::find(windows_.begin(), windows_.end(), window) == windows_.end()) {
+ windows_.push_back(window);
+ std::cout << "LayoutEngine: Added window " << window->getId() << std::endl;
+ }
+}
+
+void LayoutEngine::remove_window(SRDWindow* window) {
+ auto it = std::find(windows_.begin(), windows_.end(), window);
+ if (it != windows_.end()) {
+ windows_.erase(it);
+ std::cout << "LayoutEngine: Removed window " << window->getId() << std::endl;
+ }
+}
+
+void LayoutEngine::update_window(SRDWindow* window) {
+ // Trigger rearrangement for the monitor this window is on
+ // For now, just log the update
+ std::cout << "LayoutEngine: Updated window " << window->getId() << std::endl;
+}
+
+// Monitor management
+void LayoutEngine::add_monitor(const Monitor& monitor) {
+ // Check if monitor already exists
+ auto it = std::find_if(monitors_.begin(), monitors_.end(),
+ [&](const Monitor& m) { return m.id == monitor.id; });
+ if (it == monitors_.end()) {
+ monitors_.push_back(monitor);
+ // Set default layout for new monitor
+ active_layouts_[monitor.id] = LayoutType::DYNAMIC;
+ std::cout << "LayoutEngine: Added monitor " << monitor.id << std::endl;
+ }
+}
+
+void LayoutEngine::remove_monitor(int monitor_id) {
+ auto it = std::find_if(monitors_.begin(), monitors_.end(),
+ [monitor_id](const Monitor& m) { return m.id == monitor_id; });
+ if (it != monitors_.end()) {
+ monitors_.erase(it);
+ active_layouts_.erase(monitor_id);
+ std::cout << "LayoutEngine: Removed monitor " << monitor_id << std::endl;
+ }
+}
+
+void LayoutEngine::update_monitor(const Monitor& monitor) {
+ auto it = std::find_if(monitors_.begin(), monitors_.end(),
+ [&](const Monitor& m) { return m.id == monitor.id; });
+ if (it != monitors_.end()) {
+ *it = monitor;
+ std::cout << "LayoutEngine: Updated monitor " << monitor.id << std::endl;
+ }
+}
+
+// Arrangement
+void LayoutEngine::arrange_on_monitor(const Monitor& monitor) {
+ if (active_layouts_.count(monitor.id)) {
+ LayoutType current_layout_type = active_layouts_[monitor.id];
+ std::vector<SRDWindow*> windows_on_monitor = get_windows_on_monitor(monitor.id);
+
+ std::cout << "LayoutEngine: Arranging " << windows_on_monitor.size()
+ << " windows on monitor " << monitor.id
+ << " with layout " << layout_type_to_string(current_layout_type) << std::endl;
+
+ if (current_layout_type == LayoutType::TILING) {
+ tiling_layout_.arrange_windows(windows_on_monitor, monitor);
+ } else if (current_layout_type == LayoutType::DYNAMIC) {
+ dynamic_layout_.arrange_windows(windows_on_monitor, monitor);
+ } else if (current_layout_type == LayoutType::FLOATING) {
+ // Floating layout - windows keep their current positions
+ std::cout << "LayoutEngine: Floating layout - no arrangement needed" << std::endl;
+ }
+ }
+}
+
+void LayoutEngine::arrange_all_monitors() {
+ for (const auto& monitor : monitors_) {
+ arrange_on_monitor(monitor);
+ }
+}
+
+// Utility
+std::vector<std::string> LayoutEngine::get_available_layouts() const {
+ return {"tiling", "dynamic", "floating"};
+}
+
+std::vector<SRDWindow*> LayoutEngine::get_windows_on_monitor(int monitor_id) const {
+ std::vector<SRDWindow*> windows_on_monitor;
+
+ // Find the monitor
+ auto monitor_it = std::find_if(monitors_.begin(), monitors_.end(),
+ [monitor_id](const Monitor& m) { return m.id == monitor_id; });
+ if (monitor_it == monitors_.end()) {
+ return windows_on_monitor;
+ }
+
+ // Get windows that are on this monitor
+ for (SRDWindow* window : windows_) {
+ if (is_window_on_monitor(window, *monitor_it)) {
+ windows_on_monitor.push_back(window);
+ }
+ }
+
+ return windows_on_monitor;
+}
+
+// Helper methods
+LayoutType LayoutEngine::string_to_layout_type(const std::string& name) const {
+ if (name == "tiling") return LayoutType::TILING;
+ if (name == "dynamic") return LayoutType::DYNAMIC;
+ if (name == "floating") return LayoutType::FLOATING;
+ return LayoutType::DYNAMIC; // Default
+}
+
+std::string LayoutEngine::layout_type_to_string(LayoutType type) const {
+ switch (type) {
+ case LayoutType::TILING: return "tiling";
+ case LayoutType::DYNAMIC: return "dynamic";
+ case LayoutType::FLOATING: return "floating";
+ default: return "dynamic";
+ }
+}
+
+bool LayoutEngine::is_window_on_monitor(const SRDWindow* window, const Monitor& monitor) const {
+ if (!window) return false;
+
+ // Simple check: window center is within monitor bounds
+ int window_center_x = window->getX() + window->getWidth() / 2;
+ int window_center_y = window->getY() + window->getHeight() / 2;
+
+ return window_center_x >= monitor.x && window_center_x < monitor.x + monitor.width &&
+ window_center_y >= monitor.y && window_center_y < monitor.y + monitor.height;
+}
diff --git a/src/layouts/layout_engine.h b/src/layouts/layout_engine.h
new file mode 100644
index 0000000..d23033c
--- /dev/null
+++ b/src/layouts/layout_engine.h
@@ -0,0 +1,70 @@
+#ifndef SRDWM_LAYOUT_ENGINE_H
+#define SRDWM_LAYOUT_ENGINE_H
+
+#include "layout.h"
+#include "tiling_layout.h"
+#include "dynamic_layout.h"
+#include <vector>
+#include <map>
+#include <string>
+#include <functional>
+
+class SRDWindow; // Forward declaration to avoid circular dependency
+
+enum class LayoutType {
+ TILING,
+ DYNAMIC,
+ FLOATING
+ // Add other layout types here later
+};
+
+class LayoutEngine {
+public:
+ LayoutEngine();
+ ~LayoutEngine();
+
+ // Layout management
+ bool set_layout(int monitor_id, LayoutType layout_type);
+ bool set_layout(int monitor_id, const std::string& layout_name);
+ LayoutType get_layout(int monitor_id) const;
+ std::string get_layout_name(int monitor_id) const;
+
+ // Layout configuration
+ bool configure_layout(const std::string& layout_name, const std::map<std::string, std::string>& config);
+ bool register_custom_layout(const std::string& name, std::function<void(const std::vector<SRDWindow*>&, const Monitor&)> layout_func);
+
+ // SRDWindow management
+ void add_window(SRDWindow* window);
+ void remove_window(SRDWindow* window);
+ void update_window(SRDWindow* window);
+
+ // Monitor management
+ void add_monitor(const Monitor& monitor);
+ void remove_monitor(int monitor_id);
+ void update_monitor(const Monitor& monitor);
+
+ // Arrangement
+ void arrange_on_monitor(const Monitor& monitor);
+ void arrange_all_monitors();
+
+ // Utility
+ std::vector<std::string> get_available_layouts() const;
+ std::vector<SRDWindow*> get_windows_on_monitor(int monitor_id) const;
+
+private:
+ // Member variables for layout state
+ std::vector<Monitor> monitors_;
+ std::vector<SRDWindow*> windows_;
+ TilingLayout tiling_layout_;
+ DynamicLayout dynamic_layout_;
+ std::map<int, LayoutType> active_layouts_; // Map monitor ID to active layout type
+ std::map<std::string, std::function<void(const std::vector<SRDWindow*>&, const Monitor&)>> custom_layouts_;
+ std::map<std::string, std::map<std::string, std::string>> layout_configs_;
+
+ // Helper methods
+ LayoutType string_to_layout_type(const std::string& name) const;
+ std::string layout_type_to_string(LayoutType type) const;
+ bool is_window_on_monitor(const SRDWindow* window, const Monitor& monitor) const;
+};
+
+#endif // SRDWM_LAYOUT_ENGINE_H
diff --git a/src/layouts/smart_placement.cc b/src/layouts/smart_placement.cc
new file mode 100644
index 0000000..b23844c
--- /dev/null
+++ b/src/layouts/smart_placement.cc
@@ -0,0 +1,278 @@
+#include "smart_placement.h"
+#include <algorithm>
+#include <cmath>
+#include <iostream>
+
+// Constants
+constexpr int SmartPlacement::MIN_WINDOW_WIDTH;
+constexpr int SmartPlacement::MIN_WINDOW_HEIGHT;
+constexpr int SmartPlacement::GRID_MARGIN;
+constexpr int SmartPlacement::CASCADE_OFFSET;
+
+SmartPlacement::PlacementResult SmartPlacement::place_window(
+ const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows) {
+
+ // Try grid placement first (SRDWindows 11 style)
+ auto grid_result = place_in_grid(window, monitor, existing_windows);
+ if (grid_result.success) {
+ return grid_result;
+ }
+
+ // Fall back to cascade placement
+ return cascade_place(window, monitor, existing_windows);
+}
+
+SmartPlacement::PlacementResult SmartPlacement::place_in_grid(
+ const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows) {
+
+ PlacementResult result = {0, 0, 0, 0, false, "Grid placement failed"};
+
+ // Calculate optimal grid size based on monitor and window count
+ int window_count = existing_windows.size() + 1;
+ int grid_size = calculate_optimal_grid_size(monitor, window_count);
+
+ if (grid_size <= 0) {
+ result.reason = "Invalid grid size";
+ return result;
+ }
+
+ // Calculate grid position for this window
+ auto [grid_x, grid_y] = calculate_grid_position(window, monitor);
+
+ // Calculate cell dimensions
+ int cell_width = (monitor.width - (grid_size + 1) * GRID_MARGIN) / grid_size;
+ int cell_height = (monitor.height - (grid_size + 1) * GRID_MARGIN) / grid_size;
+
+ // Ensure minimum cell size
+ cell_width = std::max(cell_width, MIN_WINDOW_WIDTH);
+ cell_height = std::max(cell_height, MIN_WINDOW_HEIGHT);
+
+ // Calculate window position
+ int x = monitor.x + GRID_MARGIN + grid_x * (cell_width + GRID_MARGIN);
+ int y = monitor.y + GRID_MARGIN + grid_y * (cell_height + GRID_MARGIN);
+
+ // Check if position is valid
+ if (is_position_valid(x, y, cell_width, cell_height, monitor)) {
+ result.x = x;
+ result.y = y;
+ result.width = cell_width;
+ result.height = cell_height;
+ result.success = true;
+ result.reason = "Grid placement successful";
+ }
+
+ return result;
+}
+
+SmartPlacement::PlacementResult SmartPlacement::snap_to_edge(
+ const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows) {
+
+ PlacementResult result = {0, 0, 0, 0, false, "Snap placement failed"};
+
+ // For now, implement simple edge snapping
+ // In a full implementation, this would detect when windows are dragged near edges
+
+ int x = monitor.x + monitor.width / 4;
+ int y = monitor.y + monitor.height / 4;
+ int width = monitor.width / 2;
+ int height = monitor.height / 2;
+
+ if (is_position_valid(x, y, width, height, monitor)) {
+ result.x = x;
+ result.y = y;
+ result.width = width;
+ result.height = height;
+ result.success = true;
+ result.reason = "Snap placement successful";
+ }
+
+ return result;
+}
+
+SmartPlacement::PlacementResult SmartPlacement::cascade_place(
+ const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows) {
+
+ PlacementResult result = {0, 0, 0, 0, false, "Cascade placement failed"};
+
+ // Find a free space for cascading
+ auto free_spaces = find_free_spaces(monitor, existing_windows);
+
+ if (free_spaces.empty()) {
+ // No free spaces, use default position
+ int x = monitor.x + CASCADE_OFFSET;
+ int y = monitor.y + CASCADE_OFFSET;
+ int width = std::min(800, monitor.width - 2 * CASCADE_OFFSET);
+ int height = std::min(600, monitor.height - 2 * CASCADE_OFFSET);
+
+ if (is_position_valid(x, y, width, height, monitor)) {
+ result.x = x;
+ result.y = y;
+ result.width = width;
+ result.height = height;
+ result.success = true;
+ result.reason = "Default cascade placement";
+ }
+ } else {
+ // Use the first free space
+ auto [x, y] = free_spaces[0];
+ int width = std::min(800, monitor.width - x - CASCADE_OFFSET);
+ int height = std::min(600, monitor.height - y - CASCADE_OFFSET);
+
+ if (is_position_valid(x, y, width, height, monitor)) {
+ result.x = x;
+ result.y = y;
+ result.width = width;
+ result.height = height;
+ result.success = true;
+ result.reason = "Cascade placement in free space";
+ }
+ }
+
+ return result;
+}
+
+SmartPlacement::PlacementResult SmartPlacement::smart_tile(
+ const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows) {
+
+ PlacementResult result = {0, 0, 0, 0, false, "Smart tile placement failed"};
+
+ // Calculate overlap score to find best position
+ int best_score = -1;
+ int best_x = monitor.x;
+ int best_y = monitor.y;
+ int best_width = monitor.width / 2;
+ int best_height = monitor.height / 2;
+
+ // Try different positions and find the one with least overlap
+ for (int x = monitor.x; x < monitor.x + monitor.width - MIN_WINDOW_WIDTH; x += 50) {
+ for (int y = monitor.y; y < monitor.y + monitor.height - MIN_WINDOW_HEIGHT; y += 50) {
+ int width = std::min(800, monitor.width - x);
+ int height = std::min(600, monitor.height - y);
+
+ if (is_position_valid(x, y, width, height, monitor)) {
+ int score = calculate_overlap_score(window, monitor, existing_windows);
+ if (score > best_score) {
+ best_score = score;
+ best_x = x;
+ best_y = y;
+ best_width = width;
+ best_height = height;
+ }
+ }
+ }
+ }
+
+ if (best_score >= 0) {
+ result.x = best_x;
+ result.y = best_y;
+ result.width = best_width;
+ result.height = best_height;
+ result.success = true;
+ result.reason = "Smart tile placement successful";
+ }
+
+ return result;
+}
+
+bool SmartPlacement::windows_overlap(const SRDWindow* w1, const SRDWindow* w2) {
+ // Simple AABB overlap detection
+ int x1 = w1->getX();
+ int y1 = w1->getY();
+ int w1_width = w1->getWidth();
+ int w1_height = w1->getHeight();
+
+ int x2 = w2->getX();
+ int y2 = w2->getY();
+ int w2_width = w2->getWidth();
+ int w2_height = w2->getHeight();
+
+ return !(x1 + w1_width <= x2 || x2 + w2_width <= x1 ||
+ y1 + w1_height <= y2 || y2 + w2_height <= y1);
+}
+
+int SmartPlacement::calculate_overlap_score(const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows) {
+ int score = 0;
+
+ // Calculate how much this position overlaps with existing windows
+ for (const auto* existing : existing_windows) {
+ if (windows_overlap(window, existing)) {
+ score -= 10; // Penalty for overlap
+ } else {
+ score += 1; // Bonus for no overlap
+ }
+ }
+
+ return score;
+}
+
+std::vector<std::pair<int, int>> SmartPlacement::find_free_spaces(
+ const Monitor& monitor, const std::vector<SRDWindow*>& existing_windows) {
+
+ std::vector<std::pair<int, int>> free_spaces;
+
+ // Simple algorithm: try positions in a grid pattern
+ for (int x = monitor.x; x < monitor.x + monitor.width - MIN_WINDOW_WIDTH; x += 100) {
+ for (int y = monitor.y; y < monitor.y + monitor.height - MIN_WINDOW_HEIGHT; y += 100) {
+ bool is_free = true;
+
+ // Check if this position overlaps with any existing window
+ for (const auto* existing : existing_windows) {
+ int ex = existing->getX();
+ int ey = existing->getY();
+ int ew = existing->getWidth();
+ int eh = existing->getHeight();
+
+ if (x < ex + ew && x + MIN_WINDOW_WIDTH > ex &&
+ y < ey + eh && y + MIN_WINDOW_HEIGHT > ey) {
+ is_free = false;
+ break;
+ }
+ }
+
+ if (is_free) {
+ free_spaces.emplace_back(x, y);
+ }
+ }
+ }
+
+ return free_spaces;
+}
+
+bool SmartPlacement::is_position_valid(int x, int y, int width, int height, const Monitor& monitor) {
+ return x >= monitor.x && y >= monitor.y &&
+ x + width <= monitor.x + monitor.width &&
+ y + height <= monitor.y + monitor.height &&
+ width >= MIN_WINDOW_WIDTH && height >= MIN_WINDOW_HEIGHT;
+}
+
+std::pair<int, int> SmartPlacement::calculate_grid_position(const SRDWindow* window, const Monitor& monitor) {
+ // Simple grid position calculation
+ // In a real implementation, this might consider window properties or user preferences
+
+ // For now, use a simple pattern: first window top-left, second top-right, etc.
+ static int window_counter = 0;
+ int grid_x = window_counter % 2;
+ int grid_y = window_counter / 2;
+ window_counter++;
+
+ return {grid_x, grid_y};
+}
+
+int SmartPlacement::calculate_optimal_grid_size(const Monitor& monitor, int window_count) {
+ // Calculate optimal grid size based on monitor dimensions and window count
+ if (window_count <= 0) return 1;
+
+ // Simple heuristic: try to create a roughly square grid
+ int grid_size = static_cast<int>(std::ceil(std::sqrt(window_count)));
+
+ // Ensure grid size is reasonable
+ grid_size = std::max(1, std::min(grid_size, 4));
+
+ return grid_size;
+}
diff --git a/src/layouts/smart_placement.h b/src/layouts/smart_placement.h
new file mode 100644
index 0000000..69f4b94
--- /dev/null
+++ b/src/layouts/smart_placement.h
@@ -0,0 +1,62 @@
+#ifndef SRDWM_SMART_PLACEMENT_H
+#define SRDWM_SMART_PLACEMENT_H
+
+#include "layout.h"
+#include <vector>
+#include <memory>
+
+// Forward declarations
+class SRDWindow;
+class Monitor;
+
+// Smart placement algorithm that mimics SRDWindows 11 behavior
+class SmartPlacement {
+public:
+ struct PlacementResult {
+ int x, y, width, height;
+ bool success;
+ std::string reason;
+ };
+
+ // Main placement function
+ static PlacementResult place_window(const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows);
+
+ // Grid-based placement (SRDWindows 11 style)
+ static PlacementResult place_in_grid(const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows);
+
+ // Snap-to-edge placement
+ static PlacementResult snap_to_edge(const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows);
+
+ // Cascade placement for overlapping windows
+ static PlacementResult cascade_place(const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows);
+
+ // Smart tiling placement
+ static PlacementResult smart_tile(const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows);
+
+private:
+ // Helper functions
+ static bool windows_overlap(const SRDWindow* w1, const SRDWindow* w2);
+ static int calculate_overlap_score(const SRDWindow* window, const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows);
+ static std::vector<std::pair<int, int>> find_free_spaces(const Monitor& monitor,
+ const std::vector<SRDWindow*>& existing_windows);
+ static bool is_position_valid(int x, int y, int width, int height, const Monitor& monitor);
+
+ // Grid calculations
+ static std::pair<int, int> calculate_grid_position(const SRDWindow* window, const Monitor& monitor);
+ static int calculate_optimal_grid_size(const Monitor& monitor, int window_count);
+
+ // Constants
+ static constexpr int MIN_WINDOW_WIDTH = 200;
+ static constexpr int MIN_WINDOW_HEIGHT = 150;
+ static constexpr int GRID_MARGIN = 10;
+ static constexpr int CASCADE_OFFSET = 30;
+};
+
+#endif // SRDWM_SMART_PLACEMENT_H
+
diff --git a/src/layouts/tiling_layout.cc b/src/layouts/tiling_layout.cc
new file mode 100644
index 0000000..440c95a
--- /dev/null
+++ b/src/layouts/tiling_layout.cc
@@ -0,0 +1,38 @@
+#include "tiling_layout.h"
+#include <iostream>
+
+TilingLayout::TilingLayout() {
+ // Constructor implementation
+}
+
+TilingLayout::~TilingLayout() {
+ // Destructor implementation
+}
+
+void TilingLayout::arrange_windows(const std::vector<SRDWindow*>& windows, const Monitor& monitor) {
+ std::cout << "TilingLayout::arrange_windows called for monitor:" << std::endl;
+ std::cout << " Position: (" << monitor.x << ", " << monitor.y << "), Dimensions: (" << monitor.width << ", " << monitor.height << ")" << std::endl;
+ std::cout << " Number of windows: " << windows.size() << std::endl;
+
+ // Basic placeholder tiling logic (e.g., splitting the screen vertically)
+ if (!windows.empty()) {
+ int window_width = monitor.width / windows.size();
+ int current_x = monitor.x;
+
+ for (size_t i = 0; i < windows.size(); ++i) {
+ SRDWindow* window = windows[i];
+ // In a real implementation, you would calculate the desired
+ // position and size for the window based on the tiling algorithm
+ // and then call a method on the window object (which would
+ // internally use the platform backend) to apply these changes.
+ std::cout << " SRDWindow " << window->getId() << ": Placeholder position (" << current_x << ", " << monitor.y << "), size (" << window_width << ", " << monitor.height << ")" << std::endl;
+
+ // Update the window's properties in the SRDWindow object
+ window->setPosition(current_x, monitor.y);
+ window->setDimensions(current_x, monitor.y, window_width, monitor.height);
+
+
+ current_x += window_width;
+ }
+ }
+}
diff --git a/src/layouts/tiling_layout.h b/src/layouts/tiling_layout.h
new file mode 100644
index 0000000..333950a
--- /dev/null
+++ b/src/layouts/tiling_layout.h
@@ -0,0 +1,17 @@
+#ifndef SRDWM_TILING_LAYOUT_H
+#define SRDWM_TILING_LAYOUT_H
+
+#include "layout.h"
+#include <iostream>
+#include <vector>
+
+class TilingLayout : public Layout {
+public:
+ TilingLayout();
+ ~TilingLayout();
+
+ // Implement the pure virtual method from the base class
+ void arrange_windows(const std::vector<SRDWindow*>& windows, const Monitor& monitor) override;
+};
+
+#endif // SRDWM_TILING_LAYOUT_H
diff --git a/src/main.cc b/src/main.cc
new file mode 100644
index 0000000..a1bc49c
--- /dev/null
+++ b/src/main.cc
@@ -0,0 +1,321 @@
+#include <iostream>
+#include <memory>
+#include <string>
+
+// Include Lua manager
+#include "config/lua_manager.h"
+
+// Include layout engine
+#include "layouts/layout_engine.h"
+
+// Include window manager
+#include "core/window_manager.h"
+
+// Include platform factory
+#include "platform/platform_factory.h"
+
+int main(int argc, char* argv[]) {
+ std::cout << "SRDWM starting up..." << std::endl;
+
+ // Print platform information
+ PlatformFactory::print_platform_info();
+
+ // Initialize layout engine
+ auto layout_engine = std::make_unique<LayoutEngine>();
+ std::cout << "Layout engine created" << std::endl;
+
+ // Add a default monitor
+ Monitor default_monitor{0, 0, 0, 1920, 1080, "Default", 60};
+ layout_engine->add_monitor(default_monitor);
+ std::cout << "Default monitor added to layout engine" << std::endl;
+
+ // Initialize Lua manager
+ g_lua_manager = std::make_unique<LuaManager>();
+ if (!g_lua_manager->initialize()) {
+ std::cerr << "Failed to initialize Lua manager" << std::endl;
+ return 1;
+ }
+
+ // Connect layout engine to Lua manager
+ g_lua_manager->set_layout_engine(layout_engine.get());
+ std::cout << "Layout engine connected to Lua manager" << std::endl;
+
+ // Initialize window manager
+ auto window_manager = std::make_unique<SRDWindowManager>();
+ std::cout << "SRDWindow manager created" << std::endl;
+
+ // Connect components
+ window_manager->set_layout_engine(layout_engine.get());
+ window_manager->set_lua_manager(g_lua_manager.get());
+ std::cout << "Components connected to window manager" << std::endl;
+
+ // Initialize default workspaces
+ window_manager->add_workspace("Main");
+ window_manager->add_workspace("Web");
+ window_manager->add_workspace("Code");
+ window_manager->add_workspace("Media");
+ std::cout << "Default workspaces created" << std::endl;
+
+ // Load configuration
+ std::string config_path = "./config/srdwm.lua";
+ if (!g_lua_manager->load_config_file(config_path)) {
+ std::cout << "Failed to load configuration, using defaults" << std::endl;
+ // Set default configuration
+ g_lua_manager->set_string("general.default_layout", "tiling");
+ g_lua_manager->set_bool("general.smart_placement", true);
+ g_lua_manager->set_int("general.window_gap", 8);
+ g_lua_manager->set_int("general.border_width", 2);
+ g_lua_manager->set_bool("general.animations", true);
+ g_lua_manager->set_int("general.animation_duration", 200);
+ }
+
+ // Display current configuration
+ std::cout << "\nCurrent Configuration:" << std::endl;
+ std::cout << "Default Layout: " << g_lua_manager->get_string("general.default_layout", "tiling") << std::endl;
+ std::cout << "Smart Placement: " << (g_lua_manager->get_bool("general.smart_placement", true) ? "enabled" : "disabled") << std::endl;
+ std::cout << "Window Gap: " << g_lua_manager->get_int("general.window_gap", 8) << " pixels" << std::endl;
+ std::cout << "Border Width: " << g_lua_manager->get_int("general.border_width", 2) << " pixels" << std::endl;
+ std::cout << "Animations: " << (g_lua_manager->get_bool("general.animations", true) ? "enabled" : "disabled") << std::endl;
+ std::cout << "Animation Duration: " << g_lua_manager->get_int("general.animation_duration", 200) << " ms" << std::endl;
+
+ // Platform initialization
+ std::cout << "\nInitializing platform..." << std::endl;
+
+ // Create platform with automatic detection
+ auto platform = PlatformFactory::create_platform();
+ if (!platform) {
+ std::cerr << "Failed to create platform" << std::endl;
+ return 1;
+ }
+
+ std::cout << "Platform created: " << platform->get_platform_name() << std::endl;
+
+ // Initialize platform
+ if (!platform->initialize()) {
+ std::cerr << "Failed to initialize platform" << std::endl;
+ return 1;
+ }
+
+ std::cout << "Platform initialized successfully" << std::endl;
+
+ // Connect platform to window manager
+ window_manager->set_platform(platform.get());
+
+ // Set up key bindings
+ std::cout << "\nSetting up key bindings..." << std::endl;
+
+ // Workspace switching
+ window_manager->bind_key("Mod4+1", [&]() { window_manager->switch_to_workspace(0); });
+ window_manager->bind_key("Mod4+2", [&]() { window_manager->switch_to_workspace(1); });
+ window_manager->bind_key("Mod4+3", [&]() { window_manager->switch_to_workspace(2); });
+ window_manager->bind_key("Mod4+4", [&]() { window_manager->switch_to_workspace(3); });
+
+ // Workspace management
+ window_manager->bind_key("Mod4+Shift+1", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) window_manager->move_window_to_workspace(focused, 0);
+ });
+ window_manager->bind_key("Mod4+Shift+2", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) window_manager->move_window_to_workspace(focused, 1);
+ });
+ window_manager->bind_key("Mod4+Shift+3", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) window_manager->move_window_to_workspace(focused, 2);
+ });
+ window_manager->bind_key("Mod4+Shift+4", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) window_manager->move_window_to_workspace(focused, 3);
+ });
+
+ // Window focus cycling
+ window_manager->bind_key("Mod4+Tab", [&]() {
+ window_manager->focus_next_window();
+ });
+ window_manager->bind_key("Mod4+Shift+Tab", [&]() {
+ window_manager->focus_previous_window();
+ });
+
+ // Layout switching
+ window_manager->bind_key("Mod4+t", [&]() {
+ layout_engine->set_layout(0, "tiling");
+ window_manager->arrange_windows();
+ });
+ window_manager->bind_key("Mod4+d", [&]() {
+ layout_engine->set_layout(0, "dynamic");
+ window_manager->arrange_windows();
+ });
+ window_manager->bind_key("Mod4+s", [&]() {
+ layout_engine->set_layout(0, "smart_placement");
+ window_manager->arrange_windows();
+ });
+
+ // Window management
+ window_manager->bind_key("Mod4+q", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) window_manager->close_window(focused);
+ });
+ window_manager->bind_key("Mod4+m", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) window_manager->maximize_window(focused);
+ });
+
+ // Window floating and tiling
+ window_manager->bind_key("Mod4+f", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) {
+ window_manager->toggle_window_floating(focused);
+ }
+ });
+
+ // Window movement with arrow keys
+ window_manager->bind_key("Mod4+Shift+Left", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) {
+ int new_x = focused->getX() - 50;
+ window_manager->move_window(focused, new_x, focused->getY());
+ }
+ });
+ window_manager->bind_key("Mod4+Shift+Right", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) {
+ int new_x = focused->getX() + 50;
+ window_manager->move_window(focused, new_x, focused->getY());
+ }
+ });
+ window_manager->bind_key("Mod4+Shift+Up", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) {
+ int new_y = focused->getY() - 50;
+ window_manager->move_window(focused, focused->getX(), new_y);
+ }
+ });
+ window_manager->bind_key("Mod4+Shift+Down", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) {
+ int new_y = focused->getY() + 50;
+ window_manager->move_window(focused, focused->getX(), new_y);
+ }
+ });
+
+ // Window resizing with arrow keys
+ window_manager->bind_key("Mod4+Ctrl+Left", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) {
+ int new_width = focused->getWidth() - 50;
+ if (new_width >= 100) {
+ window_manager->resize_window(focused, new_width, focused->getHeight());
+ }
+ }
+ });
+ window_manager->bind_key("Mod4+Ctrl+Right", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) {
+ int new_width = focused->getWidth() + 50;
+ window_manager->resize_window(focused, new_width, focused->getHeight());
+ }
+ });
+ window_manager->bind_key("Mod4+Ctrl+Up", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) {
+ int new_height = focused->getHeight() - 50;
+ if (new_height >= 100) {
+ window_manager->resize_window(focused, focused->getWidth(), new_height);
+ }
+ }
+ });
+ window_manager->bind_key("Mod4+Ctrl+Down", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) {
+ int new_height = focused->getHeight() + 50;
+ window_manager->resize_window(focused, focused->getWidth(), new_height);
+ }
+ });
+
+ // Additional window operations
+ window_manager->bind_key("Mod4+space", [&]() {
+ auto* focused = window_manager->get_focused_window();
+ if (focused) window_manager->minimize_window(focused);
+ });
+
+ window_manager->bind_key("Mod4+Return", [&]() {
+ // TODO: Launch terminal
+ std::cout << "Launch terminal" << std::endl;
+ });
+
+ window_manager->bind_key("Mod4+d", [&]() {
+ // TODO: Launch application launcher
+ std::cout << "Launch application launcher" << std::endl;
+ });
+
+ // Quick layout presets
+ window_manager->bind_key("Mod4+Shift+t", [&]() {
+ layout_engine->set_layout(0, "tiling");
+ window_manager->arrange_windows();
+ });
+ window_manager->bind_key("Mod4+Shift+d", [&]() {
+ layout_engine->set_layout(0, "dynamic");
+ window_manager->arrange_windows();
+ });
+ window_manager->bind_key("Mod4+Shift+s", [&]() {
+ layout_engine->set_layout(0, "smart_placement");
+ window_manager->arrange_windows();
+ });
+
+ // Exit
+ window_manager->bind_key("Mod4+Shift+q", [&]() {
+ std::cout << "Exit key combination pressed" << std::endl;
+ // TODO: Implement proper cleanup and exit
+ });
+
+ std::cout << "Key bindings configured" << std::endl;
+
+ // Set initial layout
+ std::string default_layout = g_lua_manager->get_string("general.default_layout", "tiling");
+ layout_engine->set_layout(0, default_layout);
+
+ // Arrange initial windows
+ window_manager->arrange_windows();
+
+ std::cout << "\nSRDWM initialization complete!" << std::endl;
+ std::cout << "\nAvailable Key Bindings:" << std::endl;
+ std::cout << " Mod4+1-4 - Switch to workspace 1-4" << std::endl;
+ std::cout << " Mod4+Shift+1-4 - Move focused window to workspace 1-4" << std::endl;
+ std::cout << " Mod4+t/d/s - Switch to tiling/dynamic/smart placement layout" << std::endl;
+ std::cout << " Mod4+Shift+t/d/s - Quick layout presets" << std::endl;
+ std::cout << " Mod4+Tab - Focus next window" << std::endl;
+ std::cout << " Mod4+Shift+Tab - Focus previous window" << std::endl;
+ std::cout << " Mod4+f - Toggle window floating" << std::endl;
+ std::cout << " Mod4+q - Close focused window" << std::endl;
+ std::cout << " Mod4+m - Maximize focused window" << std::endl;
+ std::cout << " Mod4+space - Minimize focused window" << std::endl;
+ std::cout << " Mod4+Shift+Arrows - Move focused window" << std::endl;
+ std::cout << " Mod4+Ctrl+Arrows - Resize focused window" << std::endl;
+ std::cout << " Mod4+Return - Launch terminal" << std::endl;
+ std::cout << " Mod4+d - Launch application launcher" << std::endl;
+ std::cout << " Mod4+Shift+q - Exit SRDWM" << std::endl;
+ std::cout << "\nMouse Controls:" << std::endl;
+ std::cout << " Left click + drag on titlebar - Move window" << std::endl;
+ std::cout << " Left click + drag on edges - Resize window" << std::endl;
+
+ // Main event loop
+ try {
+ window_manager->run();
+ } catch (const std::exception& e) {
+ std::cerr << "Error in main loop: " << e.what() << std::endl;
+ }
+
+ std::cout << "SRDWM shutting down." << std::endl;
+
+ // Clean up platform
+ platform->shutdown();
+ platform.reset();
+
+ // Clean up Lua manager
+ g_lua_manager->shutdown();
+ g_lua_manager.reset();
+
+ std::cout << "Cleanup completed." << std::endl;
+
+ return 0;
+}
diff --git a/src/platform/linux_platform.h b/src/platform/linux_platform.h
new file mode 100644
index 0000000..1237c85
--- /dev/null
+++ b/src/platform/linux_platform.h
@@ -0,0 +1,105 @@
+#ifndef SRDWM_LINUX_PLATFORM_H
+#define SRDWM_LINUX_PLATFORM_H
+
+#include "platform.h"
+#include <memory>
+#include <string>
+
+// Forward declarations for X11
+#ifdef __linux__
+struct _XDisplay;
+typedef struct _XDisplay Display;
+typedef unsigned long SRDWindow;
+typedef unsigned long Atom;
+
+// Forward declarations for Wayland
+struct wl_display;
+struct wl_registry;
+struct wl_compositor;
+struct wl_shell;
+struct wl_seat;
+struct wl_keyboard;
+struct wl_pointer;
+#endif
+
+class LinuxPlatform : public Platform {
+public:
+ enum class Backend {
+ Auto,
+ X11,
+ Wayland
+ };
+
+ explicit LinuxPlatform(Backend backend = Backend::Auto);
+ ~LinuxPlatform() override;
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ std::string get_platform_name() const override;
+ bool is_wayland() const override;
+ bool is_x11() const override;
+ bool is_windows() const override;
+ bool is_macos() const override;
+
+private:
+ Backend backend_;
+ bool initialized_;
+
+ // X11 specific members
+ Display* x11_display_;
+ SRDWindow x11_root_;
+ Atom x11_wm_delete_window_;
+ Atom x11_wm_protocols_;
+
+ // Wayland specific members
+ wl_display* wayland_display_;
+ wl_registry* wayland_registry_;
+ wl_compositor* wayland_compositor_;
+ wl_shell* wayland_shell_;
+ wl_seat* wayland_seat_;
+ wl_keyboard* wayland_keyboard_;
+ wl_pointer* wayland_pointer_;
+
+ // Common members
+ std::vector<Monitor> monitors_;
+
+ // Private methods
+ bool initialize_x11();
+ bool initialize_wayland();
+ void shutdown_x11();
+ void shutdown_wayland();
+
+ bool detect_backend();
+ void setup_x11_atoms();
+ void setup_wayland_registry();
+
+ // Event processing
+ void process_x11_event(XEvent& event, std::vector<Event>& events);
+ void process_wayland_event(wl_display* display, std::vector<Event>& events);
+};
+
+#endif // SRDWM_LINUX_PLATFORM_H
+
diff --git a/src/platform/macos_platform.cc b/src/platform/macos_platform.cc
new file mode 100644
index 0000000..d489cb7
--- /dev/null
+++ b/src/platform/macos_platform.cc
@@ -0,0 +1,480 @@
+#include "macos_platform.h"
+#include <iostream>
+#include <CoreGraphics/CoreGraphics.h>
+#include <ApplicationServices/ApplicationServices.h>
+#include <Carbon/Carbon.h>
+
+// Static member initialization
+MacOSPlatform* MacOSPlatform::instance_ = nullptr;
+
+MacOSPlatform::MacOSPlatform()
+ : event_tap_(nullptr) {
+
+ instance_ = this;
+}
+
+MacOSPlatform::~MacOSPlatform() {
+ shutdown();
+ if (instance_ == this) {
+ instance_ = nullptr;
+ }
+}
+
+bool MacOSPlatform::initialize() {
+ std::cout << "Initializing macOS platform..." << std::endl;
+
+ // Request accessibility permissions
+ if (!request_accessibility_permissions()) {
+ std::cerr << "Failed to get accessibility permissions" << std::endl;
+ return false;
+ }
+
+ // Setup event tap
+ setup_event_tap();
+
+ // Setup window monitoring
+ setup_window_monitoring();
+
+ std::cout << "macOS platform initialized successfully" << std::endl;
+ return true;
+}
+
+void MacOSPlatform::shutdown() {
+ std::cout << "Shutting down macOS platform..." << std::endl;
+
+ // Clean up event tap
+ if (event_tap_) {
+ CGEventTapEnable(event_tap_, false);
+ CFRelease(event_tap_);
+ event_tap_ = nullptr;
+ }
+
+ // Clean up windows
+ for (auto& pair : window_map_) {
+ if (pair.second) {
+ delete pair.second;
+ }
+ }
+ window_map_.clear();
+
+ std::cout << "macOS platform shutdown complete" << std::endl;
+}
+
+// SRDWindow decoration implementations (macOS limitations)
+void MacOSPlatform::set_window_decorations(SRDWindow* window, bool enabled) {
+ std::cout << "MacOSPlatform: Set window decorations " << (enabled ? "enabled" : "disabled") << std::endl;
+
+ if (!window) return;
+
+ decorations_enabled_ = enabled;
+
+ // macOS doesn't support custom window decorations like other platforms
+ // We can only work with native window properties
+ // For now, we'll just log the request
+
+ // TODO: Implement using accessibility APIs to modify window properties
+ // This would involve using AXUIElementRef to modify window attributes
+ std::cout << "Decoration state set to: " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+void MacOSPlatform::set_window_border_color(SRDWindow* window, int r, int g, int b) {
+ std::cout << "MacOSPlatform: Set border color RGB(" << r << "," << g << "," << b << ")" << std::endl;
+
+ if (!window) return;
+
+ // macOS doesn't support custom border colors through public APIs
+ // This would require private APIs or overlay windows
+ // For now, we'll just log the request
+
+ // TODO: Implement using private APIs or overlay windows
+ // This could involve:
+ // 1. Creating transparent overlay windows around the target window
+ // 2. Using private Core Graphics APIs (not recommended for production)
+ // 3. Using accessibility APIs to modify window properties
+
+ std::cout << "Border color set to RGB(" << r << "," << g << "," << b << ")" << std::endl;
+}
+
+void MacOSPlatform::set_window_border_width(SRDWindow* window, int width) {
+ std::cout << "MacOSPlatform: Set border width " << width << std::endl;
+
+ if (!window) return;
+
+ // macOS doesn't support custom border widths through public APIs
+ // This would require private APIs or overlay windows
+ // For now, we'll just log the request
+
+ // TODO: Implement using private APIs or overlay windows
+ // This could involve:
+ // 1. Creating transparent overlay windows around the target window
+ // 2. Using private Core Graphics APIs (not recommended for production)
+ // 3. Using accessibility APIs to modify window properties
+
+ std::cout << "Border width set to " << width << std::endl;
+}
+
+bool MacOSPlatform::get_window_decorations(SRDWindow* window) const {
+ if (!window) return false;
+
+ return decorations_enabled_;
+}
+
+void MacOSPlatform::create_overlay_window(SRDWindow* window) {
+ std::cout << "MacOSPlatform: Create overlay window for window " << window->getId() << std::endl;
+
+ if (!window) return;
+
+ // TODO: Implement overlay window creation for custom decorations
+ // This would involve:
+ // 1. Creating a transparent window using Core Graphics
+ // 2. Positioning it over the target window
+ // 3. Drawing custom borders/titlebar on it
+ // 4. Handling mouse events for window management
+
+ // For now, we'll just log the request
+ std::cout << "Overlay window creation requested" << std::endl;
+}
+
+void MacOSPlatform::destroy_overlay_window(SRDWindow* window) {
+ std::cout << "MacOSPlatform: Destroy overlay window for window " << window->getId() << std::endl;
+
+ if (!window) return;
+
+ // TODO: Implement overlay window destruction
+ // This would involve:
+ // 1. Finding the overlay window for this window
+ // 2. Destroying the overlay window
+ // 3. Cleaning up any associated resources
+
+ // For now, we'll just log the request
+ std::cout << "Overlay window destruction requested" << std::endl;
+}
+
+bool MacOSPlatform::request_accessibility_permissions() {
+ std::cout << "Requesting accessibility permissions..." << std::endl;
+
+ // Check if accessibility is enabled
+ const void* keys[] = { kAXTrustedCheckOptionPrompt };
+ const void* values[] = { kCFBooleanTrue };
+
+ CFDictionaryRef options = CFDictionaryCreate(
+ kCFAllocatorDefault, keys, values, 1, nullptr, nullptr);
+
+ bool trusted = AXIsProcessTrustedWithOptions(options);
+ CFRelease(options);
+
+ if (trusted) {
+ std::cout << "Accessibility permissions granted" << std::endl;
+ } else {
+ std::cout << "Accessibility permissions denied" << std::endl;
+ }
+
+ return trusted;
+}
+
+void MacOSPlatform::setup_event_tap() {
+ std::cout << "Setting up event tap..." << std::endl;
+
+ // Create event tap for global events
+ event_tap_ = CGEventTapCreate(
+ kCGSessionEventTap,
+ kCGHeadInsertEventTap,
+ kCGEventTapOptionDefault,
+ CGEventMaskBit(kCGEventKeyDown) |
+ CGEventMaskBit(kCGEventKeyUp) |
+ CGEventMaskBit(kCGEventLeftMouseDown) |
+ CGEventMaskBit(kCGEventLeftMouseUp) |
+ CGEventMaskBit(kCGEventRightMouseDown) |
+ CGEventMaskBit(kCGEventRightMouseUp) |
+ CGEventMaskBit(kCGEventMouseMoved),
+ event_tap_callback,
+ this);
+
+ if (event_tap_) {
+ CFRunLoopSourceRef run_loop_source =
+ CFMachPortCreateRunLoopSource(kCFAllocatorDefault, event_tap_, 0);
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source, kCFRunLoopCommonModes);
+ CGEventTapEnable(event_tap_, true);
+
+ std::cout << "Event tap setup complete" << std::endl;
+ } else {
+ std::cerr << "Failed to create event tap" << std::endl;
+ }
+}
+
+void MacOSPlatform::setup_window_monitoring() {
+ std::cout << "Setting up window monitoring..." << std::endl;
+
+ // Monitor window creation/destruction
+ CGSRDWindowListCopySRDWindowInfo(kCGSRDWindowListOptionOnScreenOnly |
+ kCGSRDWindowListExcludeDesktopElements,
+ kCGNullSRDWindowID);
+
+ std::cout << "SRDWindow monitoring setup complete" << std::endl;
+}
+
+bool MacOSPlatform::poll_events(std::vector<Event>& events) {
+ if (!initialized_ || !event_tap_) return false;
+
+ events.clear();
+
+ // macOS events are handled through the event tap callback
+ // The event tap callback handles event conversion
+ // For now, we'll just return any pending events
+
+ // TODO: Implement proper event queue processing
+ // This would involve processing events from the event tap callback
+
+ return false;
+}
+
+void MacOSPlatform::process_event(const Event& event) {
+ // TODO: Implement event processing
+}
+
+std::unique_ptr<SRDWindow> MacOSPlatform::create_window(const std::string& title, int x, int y, int width, int height) {
+ std::cout << "Creating macOS window: " << title << std::endl;
+
+ // TODO: Implement actual window creation using Core Graphics/AppKit
+ // For now, create a placeholder window object
+
+ auto window = std::make_unique<SRDWindow>();
+ // TODO: Set window properties
+
+ std::cout << "macOS window creation requested" << std::endl;
+ return window;
+}
+
+void MacOSPlatform::destroy_window(SRDWindow* window) {
+ std::cout << "Destroying macOS window" << std::endl;
+
+ // TODO: Implement window destruction
+}
+
+void MacOSPlatform::set_window_position(SRDWindow* window, int x, int y) {
+ // TODO: Implement window positioning using accessibility APIs
+}
+
+void MacOSPlatform::set_window_size(SRDWindow* window, int width, int height) {
+ // TODO: Implement window resizing using accessibility APIs
+}
+
+void MacOSPlatform::set_window_title(SRDWindow* window, const std::string& title) {
+ // TODO: Implement title setting
+}
+
+void MacOSPlatform::focus_window(SRDWindow* window) {
+ // TODO: Implement window focusing
+}
+
+void MacOSPlatform::minimize_window(SRDWindow* window) {
+ // TODO: Implement window minimization
+}
+
+void MacOSPlatform::maximize_window(SRDWindow* window) {
+ // TODO: Implement window maximization
+}
+
+void MacOSPlatform::close_window(SRDWindow* window) {
+ // TODO: Implement window closing
+}
+
+std::vector<Monitor> MacOSPlatform::get_monitors() {
+ std::vector<Monitor> monitors;
+
+ // Get display information using Core Graphics
+ uint32_t display_count = 0;
+ CGGetActiveDisplayList(0, nullptr, &display_count);
+
+ if (display_count > 0) {
+ std::vector<CGDirectDisplayID> display_ids(display_count);
+ CGGetActiveDisplayList(display_count, display_ids.data(), &display_count);
+
+ for (uint32_t i = 0; i < display_count; ++i) {
+ CGDirectDisplayID display_id = display_ids[i];
+
+ Monitor monitor;
+ monitor.id = static_cast<int>(display_id);
+ monitor.name = "Display " + std::to_string(i + 1);
+
+ // Get display bounds
+ CGRect bounds = CGDisplayBounds(display_id);
+ monitor.x = static_cast<int>(bounds.origin.x);
+ monitor.y = static_cast<int>(bounds.origin.y);
+ monitor.width = static_cast<int>(bounds.size.width);
+ monitor.height = static_cast<int>(bounds.size.height);
+
+ // Get refresh rate
+ CGDisplayModeRef mode = CGDisplayCopyDisplayMode(display_id);
+ if (mode) {
+ monitor.refresh_rate = static_cast<int>(CGDisplayModeGetRefreshRate(mode));
+ CGDisplayModeRelease(mode);
+ } else {
+ monitor.refresh_rate = 60; // Default
+ }
+
+ monitors.push_back(monitor);
+
+ std::cout << "Monitor " << i << ": " << monitor.width << "x" << monitor.height
+ << " @ " << monitor.refresh_rate << "Hz" << std::endl;
+ }
+ }
+
+ return monitors;
+}
+
+Monitor MacOSPlatform::get_primary_monitor() {
+ auto monitors = get_monitors();
+ if (!monitors.empty()) {
+ return monitors[0];
+ }
+
+ // Fallback to main display
+ CGDirectDisplayID main_display = CGMainDisplayID();
+ CGRect bounds = CGDisplayBounds(main_display);
+
+ Monitor monitor;
+ monitor.id = static_cast<int>(main_display);
+ monitor.name = "Main Display";
+ monitor.x = static_cast<int>(bounds.origin.x);
+ monitor.y = static_cast<int>(bounds.origin.y);
+ monitor.width = static_cast<int>(bounds.size.width);
+ monitor.height = static_cast<int>(bounds.size.height);
+ monitor.refresh_rate = 60; // Default
+
+ return monitor;
+}
+
+void MacOSPlatform::grab_keyboard() {
+ // TODO: Implement keyboard grabbing
+ std::cout << "Keyboard grabbing setup" << std::endl;
+}
+
+void MacOSPlatform::ungrab_keyboard() {
+ // TODO: Implement keyboard ungrab
+ std::cout << "Keyboard ungrab" << std::endl;
+}
+
+void MacOSPlatform::grab_pointer() {
+ // TODO: Implement pointer grabbing
+ std::cout << "Pointer grabbing setup" << std::endl;
+}
+
+void MacOSPlatform::ungrab_pointer() {
+ // TODO: Implement pointer ungrab
+ std::cout << "Pointer ungrab" << std::endl;
+}
+
+// Static callback functions
+CGEventRef MacOSPlatform::event_tap_callback(CGEventTapProxy proxy, CGEventType type,
+ CGEventRef event, void* user_info) {
+ MacOSPlatform* platform = static_cast<MacOSPlatform*>(user_info);
+ return platform->handle_event_tap(proxy, type, event);
+}
+
+CGEventRef MacOSPlatform::handle_event_tap(CGEventTapProxy proxy, CGEventType type, CGEventRef event) {
+ switch (type) {
+ case kCGEventKeyDown:
+ handle_key_event(event, true);
+ break;
+
+ case kCGEventKeyUp:
+ handle_key_event(event, false);
+ break;
+
+ case kCGEventLeftMouseDown:
+ handle_mouse_event(event, true, 1);
+ break;
+
+ case kCGEventLeftMouseUp:
+ handle_mouse_event(event, false, 1);
+ break;
+
+ case kCGEventRightMouseDown:
+ handle_mouse_event(event, true, 2);
+ break;
+
+ case kCGEventRightMouseUp:
+ handle_mouse_event(event, false, 2);
+ break;
+
+ case kCGEventMouseMoved:
+ handle_mouse_motion(event);
+ break;
+ }
+
+ return event;
+}
+
+void MacOSPlatform::handle_key_event(CGEventRef event, bool pressed) {
+ // Get key code
+ CGKeyCode key_code = static_cast<CGKeyCode>(CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode));
+
+ std::cout << "Key " << (pressed ? "press" : "release") << ": " << key_code << std::endl;
+
+ // TODO: Convert to SRDWM key event
+}
+
+void MacOSPlatform::handle_mouse_event(CGEventRef event, bool pressed, int button) {
+ // Get mouse position
+ CGPoint location = CGEventGetLocation(event);
+
+ std::cout << "Mouse button " << button << " " << (pressed ? "down" : "up")
+ << " at (" << location.x << ", " << location.y << ")" << std::endl;
+
+ // TODO: Convert to SRDWM button event
+}
+
+void MacOSPlatform::handle_mouse_motion(CGEventRef event) {
+ // Get mouse position
+ CGPoint location = CGEventGetLocation(event);
+
+ // TODO: Convert to SRDWM motion event
+}
+
+// Utility methods
+CGSRDWindowID MacOSPlatform::get_macos_window_id(SRDWindow* window) {
+ // TODO: Implement window ID retrieval
+ return 0;
+}
+
+pid_t MacOSPlatform::get_macos_pid(SRDWindow* window) {
+ // TODO: Implement PID retrieval
+ return 0;
+}
+
+void MacOSPlatform::update_window_monitoring() {
+ // TODO: Implement window monitoring update
+}
+
+void MacOSPlatform::handle_window_created(CGSRDWindowID window_id) {
+ std::cout << "SRDWindow created: " << window_id << std::endl;
+
+ // TODO: Create SRDWM window object and manage it
+}
+
+void MacOSPlatform::handle_window_destroyed(CGSRDWindowID window_id) {
+ std::cout << "SRDWindow destroyed: " << window_id << std::endl;
+
+ // TODO: Clean up SRDWM window object
+}
+
+void MacOSPlatform::handle_window_focused(CGSRDWindowID window_id) {
+ std::cout << "SRDWindow focused: " << window_id << std::endl;
+
+ // TODO: Handle window focus
+}
+
+void MacOSPlatform::handle_window_moved(CGSRDWindowID window_id, int x, int y) {
+ std::cout << "SRDWindow " << window_id << " moved to (" << x << ", " << y << ")" << std::endl;
+
+ // TODO: Handle window movement
+}
+
+void MacOSPlatform::handle_window_resized(CGSRDWindowID window_id, int width, int height) {
+ std::cout << "SRDWindow " << window_id << " resized to " << width << "x" << height << std::endl;
+
+ // TODO: Handle window resizing
+}
+
+
diff --git a/src/platform/macos_platform.h b/src/platform/macos_platform.h
new file mode 100644
index 0000000..39dc3db
--- /dev/null
+++ b/src/platform/macos_platform.h
@@ -0,0 +1,118 @@
+#ifndef SRDWM_MACOS_PLATFORM_H
+#define SRDWM_MACOS_PLATFORM_H
+
+#include "platform.h"
+#include <memory>
+#include <string>
+#include <map>
+
+// Forward declarations for macOS
+#ifdef __APPLE__
+typedef struct CGSRDWindow* CGSRDWindowRef;
+typedef struct CGEvent* CGEventRef;
+typedef struct CGDisplay* CGDirectDisplayID;
+typedef struct CGMenu* CGMenuRef;
+typedef struct CGMenuBar* CGMenuBarRef;
+#endif
+
+class MacOSPlatform : public Platform {
+public:
+ MacOSPlatform();
+ ~MacOSPlatform() override;
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ // SRDWindow decorations (macOS implementation)
+ void set_window_decorations(SRDWindow* window, bool enabled) override;
+ void set_window_border_color(SRDWindow* window, int r, int g, int b) override;
+ void set_window_border_width(SRDWindow* window, int width) override;
+ bool get_window_decorations(SRDWindow* window) const override;
+
+ // macOS-specific features
+ void setup_global_menu();
+ void update_global_menu(const std::string& app_name);
+ void set_menu_bar_visible(bool visible);
+ void set_dock_visible(bool visible);
+ void set_spaces_enabled(bool enabled);
+ void switch_to_space(int space_id);
+ int get_current_space() const;
+ std::vector<int> get_available_spaces() const;
+
+ // Mission Control and Spaces
+ void show_mission_control();
+ void show_app_expose();
+ void show_desktop();
+
+ // Window management enhancements
+ void set_window_level(SRDWindow* window, int level);
+ void set_window_shadow(SRDWindow* window, bool enabled);
+ void set_window_blur(SRDWindow* window, bool enabled);
+ void set_window_alpha(SRDWindow* window, float alpha);
+
+ std::string get_platform_name() const override;
+ bool is_wayland() const override;
+ bool is_x11() const override;
+ bool is_windows() const override;
+ bool is_macos() const override;
+
+private:
+ bool initialized_;
+ std::map<CGSRDWindowRef, SRDWindow*> window_map_;
+ std::vector<Monitor> monitors_;
+
+ // Decoration state (macOS limitations)
+ bool decorations_enabled_;
+ std::map<CGSRDWindowRef, CGSRDWindowRef> overlay_window_map_; // window -> overlay
+
+ // macOS-specific state
+ bool global_menu_enabled_;
+ bool dock_visible_;
+ bool spaces_enabled_;
+ CGMenuBarRef menu_bar_;
+ std::map<std::string, CGMenuRef> app_menus_;
+
+ // Event handling
+ void setup_event_tap();
+ void remove_event_tap();
+
+ // Monitor management
+ void update_monitors();
+
+ // Utility methods
+ SRDWindow* find_window_by_cgwindow(CGSRDWindowRef cgwindow);
+
+ // Decoration methods (macOS limitations)
+ void create_overlay_window(SRDWindow* window);
+ void destroy_overlay_window(SRDWindow* window);
+
+ // Global menu methods
+ void create_app_menu(const std::string& app_name);
+ void update_menu_bar();
+ void handle_menu_event(CGEventRef event);
+};
+
+#endif // SRDWM_MACOS_PLATFORM_H
+
diff --git a/src/platform/platform.h b/src/platform/platform.h
new file mode 100644
index 0000000..41cc6bf
--- /dev/null
+++ b/src/platform/platform.h
@@ -0,0 +1,91 @@
+#ifndef SRDWM_PLATFORM_H
+#define SRDWM_PLATFORM_H
+
+#include <memory>
+#include <vector>
+#include <string>
+#include <functional>
+
+// Forward declarations
+class SRDWindow;
+
+// Include Monitor struct definition from layouts
+#include "../layouts/layout.h"
+
+// Platform-independent event types
+enum class EventType {
+ WindowCreated,
+ WindowDestroyed,
+ WindowMoved,
+ WindowResized,
+ WindowFocused,
+ WindowUnfocused,
+ KeyPress,
+ KeyRelease,
+ MouseButtonPress,
+ MouseButtonRelease,
+ MouseMotion,
+ MonitorAdded,
+ MonitorRemoved
+};
+
+// Event structure
+struct Event {
+ EventType type;
+ void* data;
+ size_t data_size;
+};
+
+// Platform abstraction interface
+class Platform {
+public:
+ virtual ~Platform() = default;
+
+ // Initialization and cleanup
+ virtual bool initialize() = 0;
+ virtual void shutdown() = 0;
+
+ // Event handling
+ virtual bool poll_events(std::vector<Event>& events) = 0;
+ virtual void process_event(const Event& event) = 0;
+
+ // Window management
+ virtual std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) = 0;
+ virtual void destroy_window(SRDWindow* window) = 0;
+ virtual void set_window_position(SRDWindow* window, int x, int y) = 0;
+ virtual void set_window_size(SRDWindow* window, int width, int height) = 0;
+ virtual void set_window_title(SRDWindow* window, const std::string& title) = 0;
+ virtual void focus_window(SRDWindow* window) = 0;
+ virtual void minimize_window(SRDWindow* window) = 0;
+ virtual void maximize_window(SRDWindow* window) = 0;
+ virtual void close_window(SRDWindow* window) = 0;
+
+ // Window decorations (cross-platform)
+ virtual void set_window_decorations(SRDWindow* window, bool enabled) = 0;
+ virtual void set_window_border_color(SRDWindow* window, int r, int g, int b) = 0;
+ virtual void set_window_border_width(SRDWindow* window, int width) = 0;
+ virtual bool get_window_decorations(SRDWindow* window) const = 0;
+
+ // Monitor management
+ virtual std::vector<Monitor> get_monitors() = 0;
+ virtual Monitor get_primary_monitor() = 0;
+
+ // Input handling
+ virtual void grab_keyboard() = 0;
+ virtual void ungrab_keyboard() = 0;
+ virtual void grab_pointer() = 0;
+ virtual void ungrab_pointer() = 0;
+
+ // Utility
+ virtual std::string get_platform_name() const = 0;
+ virtual bool is_wayland() const = 0;
+ virtual bool is_x11() const = 0;
+ virtual bool is_windows() const = 0;
+ virtual bool is_macos() const = 0;
+};
+
+// Forward declaration
+class PlatformFactory;
+
+#endif // SRDWM_PLATFORM_H
+
diff --git a/src/platform/platform_factory.cc b/src/platform/platform_factory.cc
new file mode 100644
index 0000000..ef1981a
--- /dev/null
+++ b/src/platform/platform_factory.cc
@@ -0,0 +1,214 @@
+#include "platform_factory.h"
+#include <iostream>
+#include <cstring>
+#include <cstdlib>
+#include <algorithm>
+
+// Platform-specific includes
+#ifdef LINUX_PLATFORM
+ #include "x11_platform.h"
+ #ifdef WAYLAND_ENABLED
+ #include "wayland_platform.h"
+ #endif
+#elif defined(WIN32_PLATFORM)
+ #include "windows_platform.h"
+#elif defined(MACOS_PLATFORM)
+ #include "macos_platform.h"
+#endif
+
+std::unique_ptr<Platform> PlatformFactory::create_platform() {
+ #ifdef _WIN32
+ std::cout << "Creating SRDWindows platform..." << std::endl;
+ return std::make_unique<SRDWindowsPlatform>();
+
+ #elif defined(__APPLE__)
+ std::cout << "Creating macOS platform..." << std::endl;
+ return std::make_unique<MacOSPlatform>();
+
+ #else
+ // Linux: detect X11 vs Wayland
+ return detect_linux_platform();
+ #endif
+}
+
+std::unique_ptr<Platform> PlatformFactory::create_platform(const std::string& platform_name) {
+ std::cout << "Creating platform: " << platform_name << std::endl;
+
+ if (platform_name == "x11" || platform_name == "X11") {
+ #ifdef LINUX_PLATFORM
+ return std::make_unique<X11Platform>();
+ #else
+ std::cerr << "X11 platform not available on this system" << std::endl;
+ return nullptr;
+ #endif
+
+ } else if (platform_name == "wayland" || platform_name == "Wayland") {
+ #ifdef WAYLAND_ENABLED
+ return std::make_unique<WaylandPlatform>();
+ #else
+ std::cerr << "Wayland platform not available on this system" << std::endl;
+ return nullptr;
+ #endif
+
+ } else if (platform_name == "windows" || platform_name == "SRDWindows") {
+ #ifdef WIN32_PLATFORM
+ return std::make_unique<SRDWindowsPlatform>();
+ #else
+ std::cerr << "SRDWindows platform not available on this system" << std::endl;
+ return nullptr;
+ #endif
+
+ } else if (platform_name == "macos" || platform_name == "macOS") {
+ #ifdef MACOS_PLATFORM
+ return std::make_unique<MacOSPlatform>();
+ #else
+ std::cerr << "macOS platform not available on this system" << std::endl;
+ return nullptr;
+ #endif
+
+ } else {
+ std::cerr << "Unknown platform: " << platform_name << std::endl;
+ std::cerr << "Available platforms: x11, wayland, windows, macos" << std::endl;
+ return nullptr;
+ }
+}
+
+std::unique_ptr<Platform> PlatformFactory::detect_linux_platform() {
+ std::cout << "Detecting Linux platform..." << std::endl;
+
+ // Check environment variables for Wayland
+ const char* wayland_display = std::getenv("WAYLAND_DISPLAY");
+ const char* xdg_session_type = std::getenv("XDG_SESSION_TYPE");
+ const char* display = std::getenv("DISPLAY");
+
+ std::cout << "Environment variables:" << std::endl;
+ std::cout << " WAYLAND_DISPLAY: " << (wayland_display ? wayland_display : "not set") << std::endl;
+ std::cout << " XDG_SESSION_TYPE: " << (xdg_session_type ? xdg_session_type : "not set") << std::endl;
+ std::cout << " DISPLAY: " << (display ? display : "not set") << std::endl;
+
+ // Try Wayland first if environment suggests it
+ if (wayland_display || (xdg_session_type && strcmp(xdg_session_type, "wayland") == 0)) {
+ std::cout << "Wayland environment detected, attempting Wayland initialization..." << std::endl;
+
+ #ifdef WAYLAND_ENABLED
+ auto wayland_platform = std::make_unique<WaylandPlatform>();
+ if (wayland_platform->initialize()) {
+ std::cout << "✓ Wayland platform initialized successfully" << std::endl;
+ return wayland_platform;
+ } else {
+ std::cout << "✗ Wayland initialization failed, falling back to X11" << std::endl;
+ }
+ #else
+ std::cout << "Wayland support not compiled in, falling back to X11" << std::endl;
+ #endif
+ }
+
+ // Fall back to X11
+ std::cout << "Attempting X11 initialization..." << std::endl;
+
+ #ifdef LINUX_PLATFORM
+ auto x11_platform = std::make_unique<X11Platform>();
+ if (x11_platform->initialize()) {
+ std::cout << "✓ X11 platform initialized successfully" << std::endl;
+ return x11_platform;
+ } else {
+ std::cout << "✗ X11 initialization failed" << std::endl;
+ }
+ #else
+ std::cout << "X11 support not compiled in" << std::endl;
+ #endif
+
+ std::cerr << "Failed to initialize any platform backend" << std::endl;
+ return nullptr;
+}
+
+std::vector<std::string> PlatformFactory::get_available_platforms() {
+ std::vector<std::string> platforms;
+
+ #ifdef LINUX_PLATFORM
+ platforms.push_back("x11");
+ #ifdef WAYLAND_ENABLED
+ platforms.push_back("wayland");
+ #endif
+ #endif
+
+ #ifdef WIN32_PLATFORM
+ platforms.push_back("windows");
+ #endif
+
+ #ifdef MACOS_PLATFORM
+ platforms.push_back("macos");
+ #endif
+
+ return platforms;
+}
+
+std::string PlatformFactory::get_current_platform() {
+ #ifdef _WIN32
+ return "windows";
+ #elif defined(__APPLE__)
+ return "macos";
+ #else
+ // Check if we're running on Wayland
+ const char* wayland_display = std::getenv("WAYLAND_DISPLAY");
+ const char* xdg_session_type = std::getenv("XDG_SESSION_TYPE");
+
+ if (wayland_display || (xdg_session_type && strcmp(xdg_session_type, "wayland") == 0)) {
+ return "wayland";
+ } else {
+ return "x11";
+ }
+ #endif
+}
+
+bool PlatformFactory::is_platform_available(const std::string& platform_name) {
+ auto available = get_available_platforms();
+ return std::find(available.begin(), available.end(), platform_name) != available.end();
+}
+
+void PlatformFactory::print_platform_info() {
+ std::cout << "\n=== Platform Information ===" << std::endl;
+ std::cout << "Current platform: " << get_current_platform() << std::endl;
+
+ auto available = get_available_platforms();
+ std::cout << "Available platforms: ";
+ for (size_t i = 0; i < available.size(); ++i) {
+ if (i > 0) std::cout << ", ";
+ std::cout << available[i];
+ }
+ std::cout << std::endl;
+
+ std::cout << "Environment variables:" << std::endl;
+ const char* wayland_display = std::getenv("WAYLAND_DISPLAY");
+ const char* xdg_session_type = std::getenv("XDG_SESSION_TYPE");
+ const char* display = std::getenv("DISPLAY");
+
+ std::cout << " WAYLAND_DISPLAY: " << (wayland_display ? wayland_display : "not set") << std::endl;
+ std::cout << " XDG_SESSION_TYPE: " << (xdg_session_type ? xdg_session_type : "not set") << std::endl;
+ std::cout << " DISPLAY: " << (display ? display : "not set") << std::endl;
+
+ #ifdef LINUX_PLATFORM
+ std::cout << "Linux platform support: Enabled" << std::endl;
+ #ifdef WAYLAND_ENABLED
+ std::cout << "Wayland support: Enabled" << std::endl;
+ #else
+ std::cout << "Wayland support: Disabled" << std::endl;
+ #endif
+ #else
+ std::cout << "Linux platform support: Disabled" << std::endl;
+ #endif
+
+ #ifdef WIN32_PLATFORM
+ std::cout << "SRDWindows platform support: Enabled" << std::endl;
+ #else
+ std::cout << "SRDWindows platform support: Disabled" << std::endl;
+ #endif
+
+ #ifdef MACOS_PLATFORM
+ std::cout << "macOS platform support: Enabled" << std::endl;
+ #else
+ std::cout << "macOS platform support: Disabled" << std::endl;
+ #endif
+
+ std::cout << "=============================" << std::endl;
+}
diff --git a/src/platform/platform_factory.h b/src/platform/platform_factory.h
new file mode 100644
index 0000000..24f7586
--- /dev/null
+++ b/src/platform/platform_factory.h
@@ -0,0 +1,37 @@
+#ifndef SRDWM_PLATFORM_FACTORY_H
+#define SRDWM_PLATFORM_FACTORY_H
+
+#include "platform.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+// Platform factory for creating platform-specific implementations
+class PlatformFactory {
+public:
+ // Create platform with automatic detection
+ static std::unique_ptr<Platform> create_platform();
+
+ // Create specific platform by name
+ static std::unique_ptr<Platform> create_platform(const std::string& platform_name);
+
+ // Get list of available platforms
+ static std::vector<std::string> get_available_platforms();
+
+ // Get current platform name
+ static std::string get_current_platform();
+
+ // Check if platform is available
+ static bool is_platform_available(const std::string& platform_name);
+
+ // Print platform information
+ static void print_platform_info();
+
+private:
+ // Linux platform detection
+ static std::unique_ptr<Platform> detect_linux_platform();
+};
+
+#endif // SRDWM_PLATFORM_FACTORY_H
+
+
diff --git a/src/platform/wayland_platform.cc b/src/platform/wayland_platform.cc
new file mode 100644
index 0000000..2e4a591
--- /dev/null
+++ b/src/platform/wayland_platform.cc
@@ -0,0 +1,507 @@
+#include "wayland_platform.h"
+#include <iostream>
+#include <cstring>
+#include <cstdint>
+
+#ifndef USE_WAYLAND_STUB
+#include <wayland-server-core.h>
+extern "C" {
+ // Minimal wlroots declarations to avoid pulling C99-only headers into C++
+ struct wlr_backend;
+ struct wlr_renderer;
+ struct wlr_compositor;
+ struct wlr_seat;
+ struct wlr_xdg_shell;
+
+ // Logging
+ int wlr_log_init(int verbosity, void* callback);
+
+ // Backend
+ struct wlr_backend* wlr_backend_autocreate(struct wl_display* display, void* session);
+ bool wlr_backend_start(struct wlr_backend* backend);
+ void wlr_backend_destroy(struct wlr_backend* backend);
+ struct wlr_renderer* wlr_backend_get_renderer(struct wlr_backend* backend);
+
+ // Compositor and seat
+ struct wlr_compositor* wlr_compositor_create(struct wl_display* display, uint32_t version, struct wlr_renderer* renderer);
+ struct wlr_seat* wlr_seat_create(struct wl_display* display, const char* name);
+
+ // xdg-shell
+ struct wlr_xdg_shell* wlr_xdg_shell_create(struct wl_display* display, uint32_t version);
+ struct wlr_renderer* wlr_renderer_autocreate(struct wlr_backend* backend);
+ void wlr_renderer_init_wl_display(struct wlr_renderer* renderer, struct wl_display* display);
+
+ // Wayland display helpers (for C++ compilation)
+ struct wl_display* wl_display_create(void);
+ void wl_display_destroy(struct wl_display* display);
+ int wl_display_dispatch_pending(struct wl_display* display);
+ void wl_display_flush_clients(struct wl_display* display);
+}
+#endif
+
+// Static member initialization
+WaylandPlatform* WaylandPlatform::instance_ = nullptr;
+
+WaylandPlatform::WaylandPlatform()
+ : display_(nullptr)
+ , registry_(nullptr)
+ , compositor_(nullptr)
+ , shm_(nullptr)
+ , seat_(nullptr)
+ , output_(nullptr)
+ , shell_(nullptr)
+ , backend_(nullptr)
+ , renderer_(nullptr)
+ , wlr_compositor_(nullptr)
+ , output_layout_(nullptr)
+ , cursor_(nullptr)
+ , xcursor_manager_(nullptr)
+ , wlr_seat_(nullptr)
+ , xdg_shell_(nullptr)
+ // , layer_shell_(nullptr)
+ , event_loop_running_(false) {
+
+ instance_ = this;
+}
+
+WaylandPlatform::~WaylandPlatform() {
+ shutdown();
+ if (instance_ == this) {
+ instance_ = nullptr;
+ }
+}
+
+bool WaylandPlatform::initialize() {
+#ifndef USE_WAYLAND_STUB
+ std::cout << "Initializing Wayland platform (wlroots real backend)..." << std::endl;
+ // Create Wayland display
+ display_ = wl_display_create();
+ if (!display_) {
+ std::cerr << "Failed to create wl_display" << std::endl;
+ return false;
+ }
+
+ // Initialize wlroots logging (optional) - 2 corresponds to INFO
+ wlr_log_init(2, nullptr);
+
+ // Create backend (auto-detect e.g., DRM, Wayland, X11)
+ backend_ = wlr_backend_autocreate(display_, nullptr);
+ if (!backend_) {
+ std::cerr << "Failed to create wlr_backend" << std::endl;
+ return false;
+ }
+
+ // Create renderer and hook to display
+ renderer_ = wlr_renderer_autocreate(backend_);
+ if (!renderer_) {
+ std::cerr << "Failed to create wlr_renderer" << std::endl;
+ return false;
+ }
+ wlr_renderer_init_wl_display(renderer_, display_);
+
+ // Create compositor (wlroots 0.17 requires protocol version). Use version 6.
+ wlr_compositor_ = wlr_compositor_create(display_, 6, renderer_);
+ if (!wlr_compositor_) {
+ std::cerr << "Failed to create wlr_compositor" << std::endl;
+ return false;
+ }
+
+ // Create seat (input)
+ wlr_seat_ = wlr_seat_create(display_, "seat0");
+ if (!wlr_seat_) {
+ std::cerr << "Failed to create wlr_seat" << std::endl;
+ return false;
+ }
+
+ // Create xdg-shell (requires protocol version)
+ xdg_shell_ = wlr_xdg_shell_create(display_, 6);
+ if (!xdg_shell_) {
+ std::cerr << "Failed to create wlr_xdg_shell" << std::endl;
+ return false;
+ }
+
+ // Minimal bring-up: listeners will be wired in a follow-up
+
+ // Start backend
+ if (!wlr_backend_start(backend_)) {
+ std::cerr << "Failed to start wlr_backend" << std::endl;
+ return false;
+ }
+
+ decorations_enabled_ = true;
+ std::cout << "Wayland (wlroots) backend started." << std::endl;
+ return true;
+#else
+ // Minimal Wayland backend initialization (no wlroots API calls).
+ std::cout << "Initializing Wayland platform (minimal stub)..." << std::endl;
+ decorations_enabled_ = true;
+ std::cout << "Wayland platform initialized (stub)." << std::endl;
+ return true;
+#endif
+}
+
+void WaylandPlatform::shutdown() {
+#ifndef USE_WAYLAND_STUB
+ std::cout << "Shutting down Wayland platform (wlroots)..." << std::endl;
+ if (xdg_shell_) { xdg_shell_ = nullptr; }
+ // Seat is tied to display lifecycle; skip explicit destroy to avoid ABI issues
+ wlr_seat_ = nullptr;
+ if (wlr_compositor_) { /* wlr_compositor is owned by display, no explicit destroy */ wlr_compositor_ = nullptr; }
+ // Renderer is owned by backend in this path; no explicit destroy
+ renderer_ = nullptr;
+ if (backend_) { wlr_backend_destroy(backend_); backend_ = nullptr; }
+ if (display_) { wl_display_destroy(display_); display_ = nullptr; }
+#else
+ std::cout << "Shutting down Wayland platform (stub)..." << std::endl;
+#endif
+}
+
+bool WaylandPlatform::setup_wlroots_backend() { std::cout << "wlroots backend (stub)" << std::endl; return true; }
+
+bool WaylandPlatform::setup_compositor() { std::cout << "compositor (stub)" << std::endl; return true; }
+
+// (removed unused stub-only setup_output/setup_input in real backend path)
+
+bool WaylandPlatform::setup_shell_protocols() { std::cout << "shell protocols (stub)" << std::endl; return true; }
+
+// bool WaylandPlatform::setup_xwayland() { return true; }
+
+bool WaylandPlatform::poll_events(std::vector<Event>& events) {
+#ifndef USE_WAYLAND_STUB
+ if (!display_ || !backend_) return false;
+ events.clear();
+ // Dispatch Wayland events; non-blocking to integrate with app loop
+ wl_display_dispatch_pending(display_);
+ wl_display_flush_clients(display_);
+ return true;
+#else
+ events.clear();
+ return true;
+#endif
+}
+
+void WaylandPlatform::process_event(const Event& event) {
+ // TODO: Implement event processing
+}
+
+std::unique_ptr<SRDWindow> WaylandPlatform::create_window(const std::string& title, int x, int y, int width, int height) {
+ // TODO: Implement window creation
+ std::cout << "Creating Wayland window: " << title << std::endl;
+ return nullptr;
+}
+
+void WaylandPlatform::destroy_window(SRDWindow* window) {
+ // TODO: Implement window destruction
+ std::cout << "Destroying Wayland window" << std::endl;
+}
+
+void WaylandPlatform::set_window_position(SRDWindow* window, int x, int y) {
+ // TODO: Implement window positioning
+}
+
+void WaylandPlatform::set_window_size(SRDWindow* window, int width, int height) {
+ // TODO: Implement window resizing
+}
+
+void WaylandPlatform::set_window_title(SRDWindow* window, const std::string& title) {
+ // TODO: Implement title setting
+}
+
+void WaylandPlatform::focus_window(SRDWindow* window) {
+ // TODO: Implement window focusing
+}
+
+void WaylandPlatform::minimize_window(SRDWindow* window) {
+ // TODO: Implement window minimization
+}
+
+void WaylandPlatform::maximize_window(SRDWindow* window) {
+ // TODO: Implement window maximization
+}
+
+void WaylandPlatform::close_window(SRDWindow* window) {
+ // TODO: Implement window closing
+}
+
+std::vector<Monitor> WaylandPlatform::get_monitors() {
+ // TODO: Implement monitor detection
+ return {};
+}
+
+Monitor WaylandPlatform::get_primary_monitor() {
+ // TODO: Implement primary monitor detection
+ return Monitor{};
+}
+
+void WaylandPlatform::grab_keyboard() {
+ // TODO: Implement keyboard grabbing
+}
+
+void WaylandPlatform::ungrab_keyboard() {
+ // TODO: Implement keyboard ungrab
+}
+
+void WaylandPlatform::grab_pointer() {
+ // TODO: Implement pointer grabbing
+}
+
+void WaylandPlatform::ungrab_pointer() {
+ // TODO: Implement pointer ungrab
+}
+
+// Static callback functions
+void WaylandPlatform::registry_global_handler(void* data, struct wl_registry* registry,
+ uint32_t name, const char* interface, uint32_t version) {
+ (void)registry; (void)name; (void)interface; (void)version;
+ WaylandPlatform* platform = static_cast<WaylandPlatform*>(data);
+ platform->handle_registry_global(nullptr, 0, interface ? interface : "", 0);
+}
+
+void WaylandPlatform::registry_global_remove_handler(void* data, struct wl_registry* registry, uint32_t name) {
+ (void)registry; (void)name;
+ WaylandPlatform* platform = static_cast<WaylandPlatform*>(data);
+ platform->handle_registry_global_remove(nullptr, 0);
+}
+
+void WaylandPlatform::xdg_surface_new_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_xdg_surface_new(static_cast<struct wlr_xdg_surface*>(data));
+ }
+}
+
+void WaylandPlatform::xdg_surface_destroy_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_xdg_surface_destroy(static_cast<struct wlr_xdg_surface*>(data));
+ }
+}
+
+void WaylandPlatform::xdg_toplevel_new_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_xdg_toplevel_new(static_cast<struct wlr_xdg_toplevel*>(data));
+ }
+}
+
+void WaylandPlatform::xdg_toplevel_destroy_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_xdg_toplevel_destroy(static_cast<struct wlr_xdg_toplevel*>(data));
+ }
+}
+
+// (removed xwayland handlers; not declared while XWayland is disabled)
+
+void WaylandPlatform::output_new_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_output_new(static_cast<struct wlr_output*>(data));
+ }
+}
+
+void WaylandPlatform::output_destroy_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_output_destroy(static_cast<struct wlr_output*>(data));
+ }
+}
+
+void WaylandPlatform::output_frame_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_output_frame(static_cast<struct wlr_output*>(data));
+ }
+}
+
+void WaylandPlatform::pointer_motion_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_pointer_motion(static_cast<struct wlr_pointer_motion_event*>(data));
+ }
+}
+
+void WaylandPlatform::pointer_button_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_pointer_button(static_cast<struct wlr_pointer_button_event*>(data));
+ }
+}
+
+void WaylandPlatform::pointer_axis_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_pointer_axis(static_cast<struct wlr_pointer_axis_event*>(data));
+ }
+}
+
+void WaylandPlatform::keyboard_key_handler(struct wl_listener* listener, void* data) {
+ (void)listener;
+ if (WaylandPlatform::instance_) {
+ WaylandPlatform::instance_->handle_keyboard_key(static_cast<struct wlr_keyboard_key_event*>(data));
+ }
+}
+
+// Event handling methods
+void WaylandPlatform::handle_registry_global(struct wl_registry* registry, uint32_t name,
+ const char* interface, uint32_t version) {
+ (void)registry; (void)name; (void)version;
+ std::cout << "Registry global (stub): " << (interface ? interface : "?") << std::endl;
+}
+
+void WaylandPlatform::handle_registry_global_remove(struct wl_registry* registry, uint32_t name) {
+ (void)registry; (void)name;
+}
+
+void WaylandPlatform::handle_xdg_surface_new(struct wlr_xdg_surface* surface) {
+ std::cout << "New XDG surface" << std::endl;
+ manage_xdg_window(surface);
+}
+
+void WaylandPlatform::handle_xdg_surface_destroy(struct wlr_xdg_surface* surface) {
+ std::cout << "XDG surface destroyed" << std::endl;
+}
+
+void WaylandPlatform::handle_xdg_toplevel_new(struct wlr_xdg_toplevel* toplevel) {
+ std::cout << "New XDG toplevel" << std::endl;
+}
+
+void WaylandPlatform::handle_xdg_toplevel_destroy(struct wlr_xdg_toplevel* toplevel) {
+ std::cout << "XDG toplevel destroyed" << std::endl;
+}
+
+// void WaylandPlatform::handle_xwayland_surface_new(struct wlr_xwayland_surface* surface) {}
+
+// void WaylandPlatform::handle_xwayland_surface_destroy(struct wlr_xwayland_surface* surface) {}
+
+void WaylandPlatform::handle_output_new(struct wlr_output* output) {
+ std::cout << "New output" << std::endl;
+ handle_output_mode(output);
+}
+
+void WaylandPlatform::handle_output_destroy(struct wlr_output* output) {
+ std::cout << "Output destroyed" << std::endl;
+}
+
+void WaylandPlatform::handle_output_frame(struct wlr_output* output) {
+ // Handle output frame event
+}
+
+void WaylandPlatform::handle_pointer_motion(struct wlr_pointer_motion_event* event) {
+ // Handle pointer motion
+}
+
+void WaylandPlatform::handle_pointer_button(struct wlr_pointer_button_event* event) {
+ // Handle pointer button
+}
+
+void WaylandPlatform::handle_pointer_axis(struct wlr_pointer_axis_event* event) {
+ // Handle pointer axis
+}
+
+void WaylandPlatform::handle_keyboard_key(struct wlr_keyboard_key_event* event) {
+ // Handle keyboard key
+}
+
+void WaylandPlatform::manage_xdg_window(struct wlr_xdg_surface* surface) {
+ // TODO: Implement XDG window management
+}
+
+// void WaylandPlatform::manage_xwayland_window(struct wlr_xwayland_surface* surface) {}
+
+void WaylandPlatform::unmanage_window(SRDWindow* window) {
+ // TODO: Implement window unmanagement
+}
+
+void WaylandPlatform::handle_output_mode(struct wlr_output* output) {
+ // TODO: Implement output mode handling
+}
+
+void WaylandPlatform::handle_output_scale(struct wlr_output* output) {
+ // TODO: Implement output scale handling
+}
+
+void WaylandPlatform::handle_key_event(uint32_t key, bool pressed) {
+ // TODO: Implement key event handling
+}
+
+void WaylandPlatform::handle_button_event(uint32_t button, bool pressed) {
+ // TODO: Implement button event handling
+}
+
+void WaylandPlatform::create_surface_window(struct wlr_surface* surface) {
+ // TODO: Implement surface window creation
+}
+
+void WaylandPlatform::destroy_surface_window(struct wlr_surface* surface) {
+ // TODO: Implement surface window destruction
+}
+
+void WaylandPlatform::update_surface_window(struct wlr_surface* surface) {
+ // TODO: Implement surface window update
+}
+
+void WaylandPlatform::convert_wlroots_event_to_srdwm_event(void* event_data, EventType type) {
+ // TODO: Implement event conversion
+}
+
+void WaylandPlatform::handle_wlroots_error(const std::string& error) {
+ std::cerr << "wlroots error: " << error << std::endl;
+}
+
+// SRDWindow decoration implementations
+void WaylandPlatform::set_window_decorations(SRDWindow* window, bool enabled) {
+ // Temporary stub: wlroots xdg-decoration v1 helpers differ across versions.
+ // Keep internal state and log, skip calling decoration APIs.
+ std::cout << "WaylandPlatform: Set window decorations " << (enabled ? "enabled" : "disabled") << std::endl;
+ (void)window; // unused for now
+ decorations_enabled_ = enabled;
+}
+
+void WaylandPlatform::set_window_border_color(SRDWindow* window, int r, int g, int b) {
+ std::cout << "WaylandPlatform: Set border color RGB(" << r << "," << g << "," << b << ")" << std::endl;
+
+ if (!window || !renderer_) return;
+
+ // Store border color for this window
+ // In a full implementation, this would be stored in a window-specific data structure
+ // and applied during rendering
+
+ // For now, we'll just log the request
+ // TODO: Implement custom border rendering via wlroots rendering pipeline
+ std::cout << "Border color set for window " << window->getId()
+ << ": RGB(" << r << "," << g << "," << b << ")" << std::endl;
+}
+
+void WaylandPlatform::set_window_border_width(SRDWindow* window, int width) {
+ std::cout << "WaylandPlatform: Set border width " << width << std::endl;
+
+ if (!window) return;
+
+ // TODO: Implement when wlroots rendering is set up
+ // This would involve drawing custom borders on surfaces
+}
+
+bool WaylandPlatform::get_window_decorations(SRDWindow* window) const {
+ if (!window) return false;
+
+ return decorations_enabled_;
+}
+
+void WaylandPlatform::setup_decoration_manager() {
+ // Temporary stub: skip creating xdg-decoration manager to avoid
+ // wlroots API/ABI differences across distro versions.
+ std::cout << "Decoration manager (stub) initialized" << std::endl;
+}
+
+void WaylandPlatform::handle_decoration_request(struct wlr_xdg_surface* surface, uint32_t mode) {
+ std::cout << "Handling decoration request, mode: " << mode << std::endl;
+
+ // TODO: Implement when zxdg-decoration protocol is available
+ // This would involve:
+ // 1. Checking if server-side decorations are enabled
+ // 2. Setting the decoration mode for the surface
+ // 3. Drawing decorations if needed
+}
+
+
diff --git a/src/platform/wayland_platform.h b/src/platform/wayland_platform.h
new file mode 100644
index 0000000..3df5867
--- /dev/null
+++ b/src/platform/wayland_platform.h
@@ -0,0 +1,227 @@
+#ifndef SRDWM_WAYLAND_PLATFORM_H
+#define SRDWM_WAYLAND_PLATFORM_H
+
+#include "platform.h"
+#ifndef USE_WAYLAND_STUB
+#include <wayland-server-core.h>
+#endif
+// Forward-declare Wayland and wlroots types to avoid version-specific headers.
+struct wl_display; struct wl_registry; struct wl_compositor; struct wl_shm; struct wl_seat; struct wl_output; struct wl_shell; struct wl_listener; struct wl_surface;
+struct wlr_backend; struct wlr_renderer; struct wlr_compositor; struct wlr_output_layout; struct wlr_cursor; struct wlr_xcursor_manager; struct wlr_seat;
+struct wlr_xdg_shell; struct wlr_xdg_surface; struct wlr_xdg_toplevel;
+struct wlr_output; struct wlr_pointer_motion_event; struct wlr_pointer_button_event; struct wlr_pointer_axis_event; struct wlr_keyboard_key_event;
+struct wlr_xdg_decoration_manager_v1;
+#include <map>
+#include <memory>
+#include <vector>
+
+// Forward declarations
+class SRDWindow;
+class Monitor;
+
+// Wayland-specific platform implementation
+class WaylandPlatform : public Platform {
+public:
+ WaylandPlatform();
+ ~WaylandPlatform();
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+
+ // Event handling
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ // SRDWindow management
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ // Monitor management
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ // Input handling
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ // Utility
+ // SRDWindow decorations (Wayland implementation)
+ void set_window_decorations(SRDWindow* window, bool enabled) override;
+ void set_window_border_color(SRDWindow* window, int r, int g, int b) override;
+ void set_window_border_width(SRDWindow* window, int width) override;
+ bool get_window_decorations(SRDWindow* window) const override;
+
+ std::string get_platform_name() const override { return "Wayland"; }
+ bool is_wayland() const override { return true; }
+ bool is_x11() const override { return false; }
+ bool is_windows() const override { return false; }
+ bool is_macos() const override { return false; }
+
+private:
+ static WaylandPlatform* instance_;
+ // Wayland-specific members
+ struct wl_display* display_;
+ struct wl_registry* registry_;
+ struct wl_compositor* compositor_;
+ struct wl_shm* shm_;
+ struct wl_seat* seat_;
+ struct wl_output* output_;
+ struct wl_shell* shell_;
+
+ // wlroots backend
+ struct wlr_backend* backend_;
+ struct wlr_renderer* renderer_;
+ struct wlr_compositor* wlr_compositor_;
+ struct wlr_output_layout* output_layout_;
+ struct wlr_cursor* cursor_;
+ struct wlr_xcursor_manager* xcursor_manager_;
+ struct wlr_seat* wlr_seat_;
+
+ // Shell protocols
+ struct wlr_xdg_shell* xdg_shell_;
+ // struct wlr_layer_shell_v1* layer_shell_;
+
+ // XWayland support (temporarily disabled)
+ // struct wlr_xwayland* xwayland_;
+ // struct wlr_xwayland_server* xwayland_server_;
+
+ // SRDWindow tracking
+ std::map<struct wlr_surface*, SRDWindow*> surface_window_map_;
+ std::map<struct wlr_xdg_surface*, SRDWindow*> xdg_window_map_;
+ // std::map<struct wlr_xwayland_surface*, SRDWindow*> xwayland_window_map_;
+
+ // Monitor information
+ std::vector<Monitor> monitors_;
+ Monitor primary_monitor_;
+
+ // Event handling
+ bool event_loop_running_;
+ std::vector<Event> pending_events_;
+
+ // Private methods
+ bool setup_wlroots_backend();
+ bool setup_compositor();
+ bool setup_shell_protocols();
+ // bool setup_xwayland();
+
+ // Event handling
+ void handle_registry_global(struct wl_registry* registry, uint32_t name,
+ const char* interface, uint32_t version);
+ void handle_registry_global_remove(struct wl_registry* registry, uint32_t name);
+
+ // Shell protocol handlers
+ void handle_xdg_surface_new(struct wlr_xdg_surface* surface);
+ void handle_xdg_surface_destroy(struct wlr_xdg_surface* surface);
+ void handle_xdg_toplevel_new(struct wlr_xdg_toplevel* toplevel);
+ void handle_xdg_toplevel_destroy(struct wlr_xdg_toplevel* toplevel);
+
+ // XWayland handlers (temporarily disabled)
+ // void handle_xwayland_surface_new(struct wlr_xwayland_surface* surface);
+ // void handle_xwayland_surface_destroy(struct wlr_xwayland_surface* surface);
+
+ // Output handlers
+ void handle_output_new(struct wlr_output* output);
+ void handle_output_destroy(struct wlr_output* output);
+ void handle_output_frame(struct wlr_output* output);
+
+ // Input handlers
+ void handle_pointer_motion(struct wlr_pointer_motion_event* event);
+ void handle_pointer_button(struct wlr_pointer_button_event* event);
+ void handle_pointer_axis(struct wlr_pointer_axis_event* event);
+ void handle_keyboard_key(struct wlr_keyboard_key_event* event);
+
+ // SRDWindow management helpers
+ SRDWindow* find_window_by_surface(struct wlr_surface* surface);
+ SRDWindow* find_window_by_xdg_surface(struct wlr_xdg_surface* surface);
+ // SRDWindow* find_window_by_xwayland_surface(struct wlr_xwayland_surface* surface);
+ void manage_xdg_window(struct wlr_xdg_surface* surface);
+ // void manage_xwayland_window(struct wlr_xwayland_surface* surface);
+ void unmanage_window(SRDWindow* window);
+
+ // Monitor helpers
+ void update_monitor_info();
+ void handle_output_mode(struct wlr_output* output);
+ void handle_output_scale(struct wlr_output* output);
+
+ // Input helpers
+ void setup_keyboard_grab();
+ void setup_pointer_grab();
+ void handle_key_event(uint32_t key, bool pressed);
+ void handle_button_event(uint32_t button, bool pressed);
+
+ // Utility helpers
+ void create_surface_window(struct wlr_surface* surface);
+ void destroy_surface_window(struct wlr_surface* surface);
+ void update_surface_window(struct wlr_surface* surface);
+
+ // Event conversion
+ void convert_wlroots_event_to_srdwm_event(void* event_data, EventType type);
+
+ // Error handling
+ void handle_wlroots_error(const std::string& error);
+
+ // Decoration methods
+ void setup_decoration_manager();
+ void handle_decoration_request(struct wlr_xdg_surface* surface, uint32_t mode);
+
+ // Static callback functions
+ static void registry_global_handler(void* data, struct wl_registry* registry,
+ uint32_t name, const char* interface, uint32_t version);
+ static void registry_global_remove_handler(void* data, struct wl_registry* registry, uint32_t name);
+
+ static void xdg_surface_new_handler(struct wl_listener* listener, void* data);
+ static void xdg_surface_destroy_handler(struct wl_listener* listener, void* data);
+ static void xdg_toplevel_new_handler(struct wl_listener* listener, void* data);
+ static void xdg_toplevel_destroy_handler(struct wl_listener* listener, void* data);
+
+ // static void xwayland_surface_new_handler(struct wl_listener* listener, void* data);
+ // static void xwayland_surface_destroy_handler(struct wl_listener* listener, void* data);
+
+ static void output_new_handler(struct wl_listener* listener, void* data);
+ static void output_destroy_handler(struct wl_listener* listener, void* data);
+ static void output_frame_handler(struct wl_listener* listener, void* data);
+
+ static void pointer_motion_handler(struct wl_listener* listener, void* data);
+ static void pointer_button_handler(struct wl_listener* listener, void* data);
+ static void pointer_axis_handler(struct wl_listener* listener, void* data);
+ static void keyboard_key_handler(struct wl_listener* listener, void* data);
+
+ // Event listeners removed in stubbed build to avoid wl_listener dependency
+ // wlroots event listeners (instantiated only in real Wayland path)
+ #ifndef USE_WAYLAND_STUB
+ struct wl_listener xdg_surface_new_listener_;
+ struct wl_listener xdg_surface_destroy_listener_;
+ struct wl_listener xdg_toplevel_new_listener_;
+ struct wl_listener xdg_toplevel_destroy_listener_;
+ struct wl_listener output_new_listener_;
+ struct wl_listener output_destroy_listener_;
+ struct wl_listener output_frame_listener_;
+ struct wl_listener pointer_motion_listener_;
+ struct wl_listener pointer_button_listener_;
+ struct wl_listener pointer_axis_listener_;
+ struct wl_listener keyboard_key_listener_;
+ #endif
+
+ // Decoration state
+ bool decorations_enabled_;
+ struct wlr_xdg_decoration_manager_v1* decoration_manager_;
+
+ // struct wl_listener xwayland_new_surface;
+ // struct wl_listener xwayland_destroy;
+
+ // Additional listeners removed in stubbed build
+};
+
+#endif // SRDWM_WAYLAND_PLATFORM_H
+
+
diff --git a/src/platform/wayland_platform_stub.cc b/src/platform/wayland_platform_stub.cc
new file mode 100644
index 0000000..bdf6ee9
--- /dev/null
+++ b/src/platform/wayland_platform_stub.cc
@@ -0,0 +1,114 @@
+#include "wayland_platform.h"
+#include <iostream>
+#include <cstdint>
+
+WaylandPlatform* WaylandPlatform::instance_ = nullptr;
+
+WaylandPlatform::WaylandPlatform()
+ : display_(nullptr)
+ , registry_(nullptr)
+ , compositor_(nullptr)
+ , shm_(nullptr)
+ , seat_(nullptr)
+ , output_(nullptr)
+ , shell_(nullptr)
+ , backend_(nullptr)
+ , renderer_(nullptr)
+ , wlr_compositor_(nullptr)
+ , output_layout_(nullptr)
+ , cursor_(nullptr)
+ , xcursor_manager_(nullptr)
+ , wlr_seat_(nullptr)
+ , xdg_shell_(nullptr)
+ , event_loop_running_(false)
+ , decorations_enabled_(true)
+ , decoration_manager_(nullptr) {
+ instance_ = this;
+}
+
+WaylandPlatform::~WaylandPlatform() {
+ shutdown();
+ if (instance_ == this) instance_ = nullptr;
+}
+
+bool WaylandPlatform::initialize() {
+ std::cout << "Wayland (stub): initialize" << std::endl;
+ decorations_enabled_ = true;
+ return true;
+}
+
+void WaylandPlatform::shutdown() {
+ std::cout << "Wayland (stub): shutdown" << std::endl;
+}
+
+bool WaylandPlatform::poll_events(std::vector<Event>& events) {
+ events.clear();
+ return true;
+}
+
+void WaylandPlatform::process_event(const Event& /*event*/) {}
+
+std::unique_ptr<SRDWindow> WaylandPlatform::create_window(const std::string& title, int, int, int, int) {
+ std::cout << "Wayland (stub): create_window '" << title << "'" << std::endl;
+ return nullptr;
+}
+
+void WaylandPlatform::destroy_window(SRDWindow*) {}
+void WaylandPlatform::set_window_position(SRDWindow*, int, int) {}
+void WaylandPlatform::set_window_size(SRDWindow*, int, int) {}
+void WaylandPlatform::set_window_title(SRDWindow*, const std::string&) {}
+void WaylandPlatform::focus_window(SRDWindow*) {}
+void WaylandPlatform::minimize_window(SRDWindow*) {}
+void WaylandPlatform::maximize_window(SRDWindow*) {}
+void WaylandPlatform::close_window(SRDWindow*) {}
+std::vector<Monitor> WaylandPlatform::get_monitors() { return {}; }
+Monitor WaylandPlatform::get_primary_monitor() { return Monitor{}; }
+void WaylandPlatform::grab_keyboard() {}
+void WaylandPlatform::ungrab_keyboard() {}
+void WaylandPlatform::grab_pointer() {}
+void WaylandPlatform::ungrab_pointer() {}
+void WaylandPlatform::set_window_decorations(SRDWindow*, bool enabled) { decorations_enabled_ = enabled; }
+void WaylandPlatform::set_window_border_color(SRDWindow*, int, int, int) {}
+void WaylandPlatform::set_window_border_width(SRDWindow*, int) {}
+bool WaylandPlatform::get_window_decorations(SRDWindow*) const { return decorations_enabled_; }
+
+// Private helpers (stubs)
+bool WaylandPlatform::setup_wlroots_backend() { return true; }
+bool WaylandPlatform::setup_compositor() { return true; }
+bool WaylandPlatform::setup_shell_protocols() { return true; }
+void WaylandPlatform::handle_registry_global(struct wl_registry*, uint32_t, const char*, uint32_t) {}
+void WaylandPlatform::handle_registry_global_remove(struct wl_registry*, uint32_t) {}
+void WaylandPlatform::handle_xdg_surface_new(struct wlr_xdg_surface*) {}
+void WaylandPlatform::handle_xdg_surface_destroy(struct wlr_xdg_surface*) {}
+void WaylandPlatform::handle_xdg_toplevel_new(struct wlr_xdg_toplevel*) {}
+void WaylandPlatform::handle_xdg_toplevel_destroy(struct wlr_xdg_toplevel*) {}
+void WaylandPlatform::handle_output_new(struct wlr_output*) {}
+void WaylandPlatform::handle_output_destroy(struct wlr_output*) {}
+void WaylandPlatform::handle_output_frame(struct wlr_output*) {}
+void WaylandPlatform::handle_pointer_motion(struct wlr_pointer_motion_event*) {}
+void WaylandPlatform::handle_pointer_button(struct wlr_pointer_button_event*) {}
+void WaylandPlatform::handle_pointer_axis(struct wlr_pointer_axis_event*) {}
+void WaylandPlatform::keyboard_key_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::pointer_motion_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::pointer_button_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::pointer_axis_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::output_new_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::output_destroy_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::output_frame_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::xdg_surface_new_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::xdg_surface_destroy_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::xdg_toplevel_new_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::xdg_toplevel_destroy_handler(struct wl_listener*, void*) {}
+void WaylandPlatform::manage_xdg_window(struct wlr_xdg_surface*) {}
+void WaylandPlatform::unmanage_window(SRDWindow*) {}
+void WaylandPlatform::handle_output_mode(struct wlr_output*) {}
+void WaylandPlatform::handle_output_scale(struct wlr_output*) {}
+void WaylandPlatform::handle_key_event(uint32_t, bool) {}
+void WaylandPlatform::handle_button_event(uint32_t, bool) {}
+void WaylandPlatform::create_surface_window(struct wlr_surface*) {}
+void WaylandPlatform::destroy_surface_window(struct wlr_surface*) {}
+void WaylandPlatform::update_surface_window(struct wlr_surface*) {}
+void WaylandPlatform::convert_wlroots_event_to_srdwm_event(void*, EventType) {}
+void WaylandPlatform::handle_wlroots_error(const std::string&) {}
+void WaylandPlatform::setup_decoration_manager() {}
+void WaylandPlatform::handle_decoration_request(struct wlr_xdg_surface*, uint32_t) {}
diff --git a/src/platform/windows_platform.cc b/src/platform/windows_platform.cc
new file mode 100644
index 0000000..11cadca
--- /dev/null
+++ b/src/platform/windows_platform.cc
@@ -0,0 +1,585 @@
+#include "windows_platform.h"
+#include <iostream>
+#include <windows.h>
+#include <dwmapi.h>
+
+// Static member initialization
+SRDWindowsPlatform* SRDWindowsPlatform::instance_ = nullptr;
+
+SRDWindowsPlatform::SRDWindowsPlatform()
+ : h_instance_(nullptr)
+ , keyboard_hook_(nullptr)
+ , mouse_hook_(nullptr) {
+
+ instance_ = this;
+}
+
+SRDWindowsPlatform::~SRDWindowsPlatform() {
+ shutdown();
+ if (instance_ == this) {
+ instance_ = nullptr;
+ }
+}
+
+bool SRDWindowsPlatform::initialize() {
+ std::cout << "Initializing SRDWindows platform..." << std::endl;
+
+ // Get module handle
+ h_instance_ = GetModuleHandle(nullptr);
+ if (!h_instance_) {
+ std::cerr << "Failed to get module handle" << std::endl;
+ return false;
+ }
+
+ // Register window class
+ if (!register_window_class()) {
+ std::cerr << "Failed to register window class" << std::endl;
+ return false;
+ }
+
+ // Setup global hooks
+ setup_global_hooks();
+
+ std::cout << "SRDWindows platform initialized successfully" << std::endl;
+ return true;
+}
+
+void SRDWindowsPlatform::shutdown() {
+ std::cout << "Shutting down SRDWindows platform..." << std::endl;
+
+ // Unhook global hooks
+ if (keyboard_hook_) {
+ UnhookSRDWindowsHookEx(keyboard_hook_);
+ keyboard_hook_ = nullptr;
+ }
+
+ if (mouse_hook_) {
+ UnhookSRDWindowsHookEx(mouse_hook_);
+ mouse_hook_ = nullptr;
+ }
+
+ // Clean up windows
+ for (auto& pair : window_map_) {
+ if (pair.second) {
+ delete pair.second;
+ }
+ }
+ window_map_.clear();
+
+ std::cout << "SRDWindows platform shutdown complete" << std::endl;
+}
+
+// SRDWindow decoration implementations
+void SRDWindowsPlatform::set_window_decorations(SRDWindow* window, bool enabled) {
+ std::cout << "SRDWindowsPlatform: Set window decorations " << (enabled ? "enabled" : "disabled") << std::endl;
+
+ if (!window) return;
+
+ // Find the HWND for this window
+ HWND hwnd = nullptr;
+ for (const auto& pair : window_map_) {
+ if (pair.second == window) {
+ hwnd = pair.first;
+ break;
+ }
+ }
+
+ if (!hwnd) return;
+
+ decorations_enabled_ = enabled;
+
+ if (enabled) {
+ // Enable native window decorations
+ LONG style = GetSRDWindowLong(hwnd, GWL_STYLE);
+ style |= WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;
+ SetSRDWindowLong(hwnd, GWL_STYLE, style);
+ } else {
+ // Disable native window decorations
+ LONG style = GetSRDWindowLong(hwnd, GWL_STYLE);
+ style &= ~(WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX);
+ SetSRDWindowLong(hwnd, GWL_STYLE, style);
+ }
+
+ // Force window redraw
+ SetSRDWindowPos(hwnd, nullptr, 0, 0, 0, 0,
+ SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
+}
+
+void SRDWindowsPlatform::set_window_border_color(SRDWindow* window, int r, int g, int b) {
+ std::cout << "SRDWindowsPlatform: Set border color RGB(" << r << "," << g << "," << b << ")" << std::endl;
+
+ if (!window) return;
+
+ // Find the HWND for this window
+ HWND hwnd = nullptr;
+ for (const auto& pair : window_map_) {
+ if (pair.second == window) {
+ hwnd = pair.first;
+ break;
+ }
+ }
+
+ if (!hwnd) return;
+
+ COLORREF color = RGB(r, g, b);
+ apply_dwm_border_color(hwnd, r, g, b);
+}
+
+void SRDWindowsPlatform::set_window_border_width(SRDWindow* window, int width) {
+ std::cout << "SRDWindowsPlatform: Set border width " << width << std::endl;
+
+ if (!window) return;
+
+ border_width_ = width;
+
+ // SRDWindows doesn't support custom border widths via DWM
+ // This would need to be implemented with custom window frames
+}
+
+bool SRDWindowsPlatform::get_window_decorations(SRDWindow* window) const {
+ if (!window) return false;
+
+ return decorations_enabled_;
+}
+
+void SRDWindowsPlatform::apply_dwm_border_color(HWND hwnd, int r, int g, int b) {
+ // Use DWM API to set border color (SRDWindows 11 feature)
+ COLORREF color = RGB(r, g, b);
+
+ HRESULT result = DwmSetSRDWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));
+ if (FAILED(result)) {
+ std::cerr << "Failed to set DWM border color" << std::endl;
+ }
+}
+
+void SRDWindowsPlatform::remove_dwm_border_color(HWND hwnd) {
+ // Remove custom border color
+ COLORREF color = DWMWA_COLOR_DEFAULT;
+
+ HRESULT result = DwmSetSRDWindowAttribute(hwnd, DWMWA_BORDER_COLOR, &color, sizeof(color));
+ if (FAILED(result)) {
+ std::cerr << "Failed to remove DWM border color" << std::endl;
+ }
+}
+
+bool SRDWindowsPlatform::register_window_class() {
+ WNDCLASSEX wc = {};
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.lpfnWndProc = window_proc;
+ wc.hInstance = h_instance_;
+ wc.lpszClassName = L"SRDWM_SRDWindow";
+ wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+
+ return RegisterClassEx(&wc) != 0;
+}
+
+void SRDWindowsPlatform::setup_global_hooks() {
+ std::cout << "Setting up global hooks..." << std::endl;
+
+ // Global keyboard hook
+ keyboard_hook_ = SetSRDWindowsHookEx(WH_KEYBOARD_LL,
+ keyboard_proc, h_instance_, 0);
+ if (!keyboard_hook_) {
+ std::cerr << "Failed to set keyboard hook" << std::endl;
+ }
+
+ // Global mouse hook
+ mouse_hook_ = SetSRDWindowsHookEx(WH_MOUSE_LL,
+ mouse_proc, h_instance_, 0);
+ if (!mouse_hook_) {
+ std::cerr << "Failed to set mouse hook" << std::endl;
+ }
+
+ std::cout << "Global hooks setup complete" << std::endl;
+}
+
+LRESULT CALLBACK SRDWindowsPlatform::window_proc(HWND hwnd, UINT msg,
+ WPARAM wparam, LPARAM lparam) {
+ switch (msg) {
+ case WM_CREATE:
+ std::cout << "SRDWindow created: " << hwnd << std::endl;
+ break;
+
+ case WM_DESTROY:
+ std::cout << "SRDWindow destroyed: " << hwnd << std::endl;
+ break;
+
+ case WM_SIZE:
+ // Handle window resizing
+ break;
+
+ case WM_MOVE:
+ // Handle window moving
+ break;
+
+ case WM_SETFOCUS:
+ // Handle window focus
+ break;
+
+ case WM_KILLFOCUS:
+ // Handle window unfocus
+ break;
+
+ case WM_CLOSE:
+ // Handle window close request
+ break;
+
+ default:
+ return DefSRDWindowProc(hwnd, msg, wparam, lparam);
+ }
+ return 0;
+}
+
+LRESULT CALLBACK SRDWindowsPlatform::keyboard_proc(int nCode, WPARAM wparam, LPARAM lparam) {
+ if (nCode >= 0) {
+ KBDLLHOOKSTRUCT* kbhs = (KBDLLHOOKSTRUCT*)lparam;
+
+ if (wparam == WM_KEYDOWN || wparam == WM_SYSKEYDOWN) {
+ std::cout << "Key pressed: " << kbhs->vkCode << std::endl;
+ } else if (wparam == WM_KEYUP || wparam == WM_SYSKEYUP) {
+ std::cout << "Key released: " << kbhs->vkCode << std::endl;
+ }
+ }
+ return CallNextHookEx(nullptr, nCode, wparam, lparam);
+}
+
+LRESULT CALLBACK SRDWindowsPlatform::mouse_proc(int nCode, WPARAM wparam, LPARAM lparam) {
+ if (nCode >= 0) {
+ MSLLHOOKSTRUCT* mhs = (MSLLHOOKSTRUCT*)lparam;
+
+ switch (wparam) {
+ case WM_LBUTTONDOWN:
+ std::cout << "Left mouse button down at (" << mhs->pt.x << ", " << mhs->pt.y << ")" << std::endl;
+ break;
+
+ case WM_LBUTTONUP:
+ std::cout << "Left mouse button up at (" << mhs->pt.x << ", " << mhs->pt.y << ")" << std::endl;
+ break;
+
+ case WM_RBUTTONDOWN:
+ std::cout << "Right mouse button down at (" << mhs->pt.x << ", " << mhs->pt.y << ")" << std::endl;
+ break;
+
+ case WM_RBUTTONUP:
+ std::cout << "Right mouse button up at (" << mhs->pt.x << ", " << mhs->pt.y << ")" << std::endl;
+ break;
+
+ case WM_MOUSEMOVE:
+ // Handle mouse movement
+ break;
+ }
+ }
+ return CallNextHookEx(nullptr, nCode, wparam, lparam);
+}
+
+void SRDWindowsPlatform::convert_win32_message(UINT msg, WPARAM wparam, LPARAM lparam, std::vector<Event>& events) {
+ Event event;
+
+ switch (msg) {
+ case WM_CREATE:
+ event.type = EventType::SRDWindowCreated;
+ break;
+ case WM_DESTROY:
+ event.type = EventType::SRDWindowDestroyed;
+ break;
+ case WM_MOVE:
+ event.type = EventType::SRDWindowMoved;
+ break;
+ case WM_SIZE:
+ event.type = EventType::SRDWindowResized;
+ break;
+ case WM_SETFOCUS:
+ event.type = EventType::SRDWindowFocused;
+ break;
+ case WM_KILLFOCUS:
+ event.type = EventType::SRDWindowUnfocused;
+ break;
+ case WM_KEYDOWN:
+ event.type = EventType::KeyPress;
+ break;
+ case WM_KEYUP:
+ event.type = EventType::KeyRelease;
+ break;
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ event.type = EventType::MouseButtonPress;
+ break;
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ event.type = EventType::MouseButtonRelease;
+ break;
+ case WM_MOUSEMOVE:
+ event.type = EventType::MouseMotion;
+ break;
+ default:
+ return; // Skip unknown messages
+ }
+
+ event.data = nullptr;
+ event.data_size = 0;
+ events.push_back(event);
+}
+
+bool SRDWindowsPlatform::poll_events(std::vector<Event>& events) {
+ if (!initialized_) return false;
+
+ events.clear();
+
+ // Process SRDWindows messages
+ MSG msg;
+ while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+
+ // Convert SRDWindows message to SRDWM event
+ convert_win32_message(msg.message, msg.wParam, msg.lParam, events);
+ }
+
+ return !events.empty();
+}
+
+void SRDWindowsPlatform::process_event(const Event& event) {
+ // TODO: Implement event processing
+}
+
+std::unique_ptr<SRDWindow> SRDWindowsPlatform::create_window(const std::string& title, int x, int y, int width, int height) {
+ // Convert title to wide string
+ int title_len = MultiByteToWideChar(CP_UTF8, 0, title.c_str(), -1, nullptr, 0);
+ std::wstring wtitle(title_len, 0);
+ MultiByteToWideChar(CP_UTF8, 0, title.c_str(), -1, &wtitle[0], title_len);
+
+ // Create window
+ HWND hwnd = CreateSRDWindowEx(
+ WS_EX_OVERLAPPEDWINDOW,
+ L"SRDWM_SRDWindow",
+ wtitle.c_str(),
+ WS_OVERLAPPEDWINDOW,
+ x, y, width, height,
+ nullptr, nullptr, h_instance_, nullptr
+ );
+
+ if (!hwnd) {
+ std::cerr << "Failed to create SRDWindows window" << std::endl;
+ return nullptr;
+ }
+
+ // Create SRDWM window object
+ auto window = std::make_unique<SRDWindow>();
+ // TODO: Set window properties
+
+ // Store window mapping
+ window_map_[hwnd] = window.get();
+
+ std::cout << "Created SRDWindows window: " << hwnd << " (" << title << ")" << std::endl;
+ return window;
+}
+
+void SRDWindowsPlatform::destroy_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ DestroySRDWindow(pair.first);
+ window_map_.erase(pair.first);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::set_window_position(SRDWindow* window, int x, int y) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ SetSRDWindowPos(pair.first, nullptr, x, y, 0, 0,
+ SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::set_window_size(SRDWindow* window, int width, int height) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ SetSRDWindowPos(pair.first, nullptr, 0, 0, width, height,
+ SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::set_window_title(SRDWindow* window, const std::string& title) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ // Convert title to wide string
+ int title_len = MultiByteToWideChar(CP_UTF8, 0, title.c_str(), -1, nullptr, 0);
+ std::wstring wtitle(title_len, 0);
+ MultiByteToWideChar(CP_UTF8, 0, title.c_str(), -1, &wtitle[0], title_len);
+
+ SetSRDWindowText(pair.first, wtitle.c_str());
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::focus_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ SetForegroundSRDWindow(pair.first);
+ SetFocus(pair.first);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::minimize_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ ShowSRDWindow(pair.first, SW_MINIMIZE);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::maximize_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ ShowSRDWindow(pair.first, SW_MAXIMIZE);
+ break;
+ }
+ }
+}
+
+void SRDWindowsPlatform::close_window(SRDWindow* window) {
+ // Find window handle
+ for (auto& pair : window_map_) {
+ if (pair.second == window) {
+ PostMessage(pair.first, WM_CLOSE, 0, 0);
+ break;
+ }
+ }
+}
+
+std::vector<Monitor> SRDWindowsPlatform::get_monitors() {
+ std::vector<Monitor> monitors;
+
+ // Enumerate monitors using EnumDisplayMonitors
+ EnumDisplayMonitors(nullptr, nullptr,
+ [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL {
+ auto* monitors = reinterpret_cast<std::vector<Monitor>*>(dwData);
+
+ MONITORINFOEX monitorInfo;
+ monitorInfo.cbSize = sizeof(MONITORINFOEX);
+ GetMonitorInfo(hMonitor, &monitorInfo);
+
+ Monitor monitor;
+ monitor.id = reinterpret_cast<int>(hMonitor);
+ monitor.name = std::string(monitorInfo.szDevice);
+ monitor.x = monitorInfo.rcMonitor.left;
+ monitor.y = monitorInfo.rcMonitor.top;
+ monitor.width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
+ monitor.height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
+ monitor.refresh_rate = 60; // TODO: Get actual refresh rate
+
+ monitors->push_back(monitor);
+
+ return TRUE;
+ }, reinterpret_cast<LPARAM>(&monitors));
+
+ return monitors;
+}
+
+Monitor SRDWindowsPlatform::get_primary_monitor() {
+ auto monitors = get_monitors();
+ if (!monitors.empty()) {
+ return monitors[0];
+ }
+
+ // Fallback to primary display
+ Monitor monitor;
+ monitor.id = 0;
+ monitor.name = "Primary Display";
+ monitor.x = 0;
+ monitor.y = 0;
+ monitor.width = GetSystemMetrics(SM_CXSCREEN);
+ monitor.height = GetSystemMetrics(SM_CYSCREEN);
+ monitor.refresh_rate = 60;
+
+ return monitor;
+}
+
+void SRDWindowsPlatform::grab_keyboard() {
+ // TODO: Implement keyboard grabbing
+ std::cout << "Keyboard grabbing setup" << std::endl;
+}
+
+void SRDWindowsPlatform::ungrab_keyboard() {
+ // TODO: Implement keyboard ungrab
+ std::cout << "Keyboard ungrab" << std::endl;
+}
+
+void SRDWindowsPlatform::grab_pointer() {
+ // TODO: Implement pointer grabbing
+ std::cout << "Pointer grabbing setup" << std::endl;
+}
+
+void SRDWindowsPlatform::ungrab_pointer() {
+ // TODO: Implement pointer ungrab
+ std::cout << "Pointer ungrab" << std::endl;
+}
+
+void SRDWindowsPlatform::convert_windows_message_to_event(const MSG& msg, std::vector<Event>& events) {
+ // TODO: Convert SRDWindows messages to SRDWM events
+ switch (msg.message) {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ // Convert to key press event
+ break;
+
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ // Convert to key release event
+ break;
+
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ // Convert to button press event
+ break;
+
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ // Convert to button release event
+ break;
+
+ case WM_MOUSEMOVE:
+ // Convert to mouse motion event
+ break;
+
+ case WM_SIZE:
+ // Convert to window resize event
+ break;
+
+ case WM_MOVE:
+ // Convert to window move event
+ break;
+ }
+}
+
+void SRDWindowsPlatform::handle_global_keyboard(WPARAM wparam, KBDLLHOOKSTRUCT* kbhs) {
+ // TODO: Implement global keyboard handling
+}
+
+void SRDWindowsPlatform::handle_global_mouse(WPARAM wparam, MSLLHOOKSTRUCT* mhs) {
+ // TODO: Implement global mouse handling
+}
+
+
diff --git a/src/platform/windows_platform.h b/src/platform/windows_platform.h
new file mode 100644
index 0000000..70b7d54
--- /dev/null
+++ b/src/platform/windows_platform.h
@@ -0,0 +1,140 @@
+#ifndef SRDWM_WINDOWS_PLATFORM_H
+#define SRDWM_WINDOWS_PLATFORM_H
+
+#include "platform.h"
+#include <windows.h>
+#include <memory>
+#include <string>
+#include <map>
+
+class SRDWindowsPlatform : public Platform {
+public:
+ SRDWindowsPlatform();
+ ~SRDWindowsPlatform() override;
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ // SRDWindow decorations (SRDWindows implementation)
+ void set_window_decorations(SRDWindow* window, bool enabled) override;
+ void set_window_border_color(SRDWindow* window, int r, int g, int b) override;
+ void set_window_border_width(SRDWindow* window, int width) override;
+ bool get_window_decorations(SRDWindow* window) const override;
+
+ // Windows-specific features
+ void enable_dwm_composition(bool enabled);
+ void set_dwm_window_attribute(HWND hwnd, DWORD attribute, DWORD value);
+ void set_dwm_window_thumbnail(HWND hwnd, HWND thumbnail_hwnd);
+ void set_dwm_window_peek(HWND hwnd, bool enabled);
+
+ // Virtual Desktop support (Windows 10+)
+ void create_virtual_desktop();
+ void remove_virtual_desktop(int desktop_id);
+ void switch_to_virtual_desktop(int desktop_id);
+ int get_current_virtual_desktop() const;
+ std::vector<int> get_virtual_desktops() const;
+ void move_window_to_desktop(SRDWindow* window, int desktop_id);
+
+ // Taskbar integration
+ void set_taskbar_visible(bool visible);
+ void set_taskbar_position(int position); // 0=bottom, 1=top, 2=left, 3=right
+ void set_taskbar_auto_hide(bool enabled);
+ void update_taskbar_preview(HWND hwnd, const std::string& title);
+
+ // Aero effects
+ void enable_aero_effects(bool enabled);
+ void set_window_transparency(HWND hwnd, BYTE alpha);
+ void set_window_blur(HWND hwnd, bool enabled);
+ void set_window_shadow(HWND hwnd, bool enabled);
+
+ // System tray integration
+ void add_system_tray_icon(const std::string& tooltip, HICON icon);
+ void remove_system_tray_icon();
+ void show_system_tray_menu(HMENU menu);
+
+ std::string get_platform_name() const override;
+ bool is_wayland() const override;
+ bool is_x11() const override;
+ bool is_windows() const override;
+ bool is_macos() const override;
+
+private:
+ bool initialized_;
+ HINSTANCE h_instance_;
+ std::map<HWND, SRDWindow*> window_map_;
+ std::vector<Monitor> monitors_;
+
+ // Decoration state
+ bool decorations_enabled_;
+ int border_width_;
+ COLORREF border_color_;
+ COLORREF focused_border_color_;
+
+ // Windows-specific state
+ bool dwm_enabled_;
+ bool aero_enabled_;
+ bool taskbar_visible_;
+ bool taskbar_auto_hide_;
+ int taskbar_position_;
+ int current_virtual_desktop_;
+ std::vector<int> virtual_desktops_;
+ NOTIFYICONDATA system_tray_icon_;
+
+ // SRDWindow class registration
+ bool register_window_class();
+ void unregister_window_class();
+
+ // SRDWindow procedure
+ static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam);
+
+ // Event conversion
+ void convert_win32_message(UINT msg, WPARAM wparam, LPARAM lparam, std::vector<Event>& events);
+
+ // Monitor enumeration
+ static BOOL CALLBACK enum_monitor_proc(HMONITOR hmonitor, HDC hdc_monitor, LPRECT lprc_monitor, LPARAM dw_data);
+
+ // Utility methods
+ void update_monitors();
+ SRDWindow* find_window_by_hwnd(HWND hwnd);
+
+ // Decoration methods
+ void apply_dwm_border_color(HWND hwnd, int r, int g, int b);
+ void remove_dwm_border_color(HWND hwnd);
+
+ // Virtual Desktop methods
+ void initialize_virtual_desktops();
+ void cleanup_virtual_desktops();
+
+ // DWM methods
+ bool initialize_dwm();
+ void cleanup_dwm();
+
+ // Taskbar methods
+ void initialize_taskbar();
+ void update_taskbar();
+};
+
+#endif // SRDWM_WINDOWS_PLATFORM_H
+
diff --git a/src/platform/x11_platform.cc b/src/platform/x11_platform.cc
new file mode 100644
index 0000000..0d25369
--- /dev/null
+++ b/src/platform/x11_platform.cc
@@ -0,0 +1,1005 @@
+#include "x11_platform.h"
+#include <iostream>
+#include <cstring>
+
+X11Platform::X11Platform() {
+ std::cout << "X11Platform: Constructor called" << std::endl;
+}
+
+X11Platform::~X11Platform() {
+ std::cout << "X11Platform: Destructor called" << std::endl;
+}
+
+bool X11Platform::initialize() {
+ std::cout << "X11Platform: Initializing X11 backend..." << std::endl;
+
+ // Open X11 display
+ display_ = XOpenDisplay(nullptr);
+ if (!display_) {
+ std::cerr << "Failed to open X11 display" << std::endl;
+ return false;
+ }
+
+ // Get root window
+ root_ = DefaultRootWindow(display_);
+
+ // Check for other window manager
+ if (!check_for_other_wm()) {
+ std::cerr << "Another window manager is already running" << std::endl;
+ return false;
+ }
+
+ // Setup X11 environment
+ if (!setup_x11_environment()) {
+ std::cerr << "Failed to setup X11 environment" << std::endl;
+ return false;
+ }
+
+ // Setup event masks
+ if (!setup_event_masks()) {
+ std::cerr << "Failed to setup event masks" << std::endl;
+ return false;
+ }
+
+ // Setup atoms
+ setup_atoms();
+
+ // Setup extensions
+ setup_extensions();
+
+ // Initialize decoration state
+ decorations_enabled_ = true;
+ border_width_ = 2;
+ border_color_ = 0x2e3440; // Default border color
+ focused_border_color_ = 0x88c0d0; // Default focused border color
+
+ std::cout << "X11Platform: Initialized successfully" << std::endl;
+ return true;
+}
+
+void X11Platform::shutdown() {
+ std::cout << "X11Platform: Shutting down..." << std::endl;
+
+ // Clean up windows
+ for (auto& pair : window_map_) {
+ if (pair.second) {
+ destroy_window(pair.second);
+ }
+ }
+ window_map_.clear();
+ frame_window_map_.clear();
+
+ // Close X11 display
+ if (display_) {
+ XCloseDisplay(display_);
+ display_ = nullptr;
+ }
+
+ std::cout << "X11Platform: Shutdown complete" << std::endl;
+}
+
+bool X11Platform::poll_events(std::vector<Event>& events) {
+ if (!display_) return false;
+
+ events.clear();
+
+ // Check for pending events
+ if (XPending(display_) > 0) {
+ XEvent xevent;
+ XNextEvent(display_, &xevent);
+
+ // Handle the X11 event
+ handle_x11_event(xevent);
+
+ // Convert to SRDWM events (simplified for now)
+ Event event;
+ event.type = EventType::WindowCreated; // Placeholder
+ event.data = nullptr;
+ event.data_size = 0;
+ events.push_back(event);
+
+ return true;
+ }
+
+ return false;
+}
+
+void X11Platform::process_event(const Event& event) {
+ std::cout << "X11Platform: Process event called" << std::endl;
+}
+
+std::unique_ptr<SRDWindow> X11Platform::create_window(const std::string& title, int x, int y, int width, int height) {
+ std::cout << "X11Platform: Create window called" << std::endl;
+ // TODO: Implement actual window creation when headers are available
+ return nullptr;
+}
+
+void X11Platform::destroy_window(SRDWindow* window) {
+ std::cout << "X11Platform: Destroy window called" << std::endl;
+}
+
+void X11Platform::set_window_position(SRDWindow* window, int x, int y) {
+ std::cout << "X11Platform: Set window position to (" << x << "," << y << ")" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XMoveWindow(display_, to_x11_window(x11_window), x, y);
+ XFlush(display_);
+}
+
+void X11Platform::set_window_size(SRDWindow* window, int width, int height) {
+ std::cout << "X11Platform: Set window size to (" << width << "x" << height << ")" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XResizeWindow(display_, to_x11_window(x11_window), static_cast<unsigned int>(width), static_cast<unsigned int>(height));
+ XFlush(display_);
+}
+
+void X11Platform::set_window_title(SRDWindow* window, const std::string& title) {
+ std::cout << "X11Platform: Set window title to '" << title << "'" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XStoreName(display_, to_x11_window(x11_window), title.c_str());
+ XFlush(display_);
+}
+
+void X11Platform::focus_window(SRDWindow* window) {
+ std::cout << "X11Platform: Focus window" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XSetInputFocus(display_, to_x11_window(x11_window), RevertToParent, CurrentTime);
+ XFlush(display_);
+}
+
+void X11Platform::minimize_window(SRDWindow* window) {
+ std::cout << "X11Platform: Minimize window called" << std::endl;
+}
+
+void X11Platform::maximize_window(SRDWindow* window) {
+ std::cout << "X11Platform: Maximize window called" << std::endl;
+}
+
+void X11Platform::close_window(SRDWindow* window) {
+ std::cout << "X11Platform: Close window" << std::endl;
+ if (!window || !display_) return;
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ Atom wm_delete = XInternAtom(display_, "WM_DELETE_WINDOW", False);
+ if (wm_delete != None) {
+ XEvent ev{};
+ ev.xclient.type = ClientMessage;
+ ev.xclient.message_type = XInternAtom(display_, "WM_PROTOCOLS", False);
+ ev.xclient.display = display_;
+ ev.xclient.window = to_x11_window(x11_window);
+ ev.xclient.format = 32;
+ ev.xclient.data.l[0] = wm_delete;
+ ev.xclient.data.l[1] = CurrentTime;
+ XSendEvent(display_, to_x11_window(x11_window), False, NoEventMask, &ev);
+ XFlush(display_);
+ } else {
+ XDestroyWindow(display_, to_x11_window(x11_window));
+ XFlush(display_);
+ }
+}
+
+// EWMH (Extended Window Manager Hints) support implementation
+void X11Platform::set_ewmh_supported(bool supported) {
+ ewmh_supported_ = supported;
+ if (supported) {
+ setup_ewmh();
+ }
+ std::cout << "X11Platform: EWMH support " << (supported ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::set_window_type(SRDWindow* window, const std::string& type) {
+ if (!ewmh_supported_ || !window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ Atom window_type_atom = None;
+
+ if (type == "desktop") window_type_atom = _NET_WM_WINDOW_TYPE_DESKTOP_;
+ else if (type == "dock") window_type_atom = _NET_WM_WINDOW_TYPE_DOCK_;
+ else if (type == "toolbar") window_type_atom = _NET_WM_WINDOW_TYPE_TOOLBAR_;
+ else if (type == "menu") window_type_atom = _NET_WM_WINDOW_TYPE_MENU_;
+ else if (type == "utility") window_type_atom = _NET_WM_WINDOW_TYPE_UTILITY_;
+ else if (type == "splash") window_type_atom = _NET_WM_WINDOW_TYPE_SPLASH_;
+ else if (type == "dialog") window_type_atom = _NET_WM_WINDOW_TYPE_DIALOG_;
+ else if (type == "dropdown_menu") window_type_atom = _NET_WM_WINDOW_TYPE_DROPDOWN_MENU_;
+ else if (type == "popup_menu") window_type_atom = _NET_WM_WINDOW_TYPE_POPUP_MENU_;
+ else if (type == "tooltip") window_type_atom = _NET_WM_WINDOW_TYPE_TOOLTIP_;
+ else if (type == "notification") window_type_atom = _NET_WM_WINDOW_TYPE_NOTIFICATION_;
+ else if (type == "combo") window_type_atom = _NET_WM_WINDOW_TYPE_COMBO_;
+ else if (type == "dnd") window_type_atom = _NET_WM_WINDOW_TYPE_DND_;
+ else window_type_atom = _NET_WM_WINDOW_TYPE_NORMAL_;
+
+ if (window_type_atom != None) {
+ XChangeProperty(display_, x11_window, _NET_WM_WINDOW_TYPE_, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)&window_type_atom, 1);
+ }
+}
+
+void X11Platform::set_window_state(SRDWindow* window, const std::vector<std::string>& states) {
+ if (!ewmh_supported_ || !window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ std::vector<Atom> state_atoms;
+
+ for (const auto& state : states) {
+ Atom state_atom = None;
+ if (state == "maximized_vert") state_atom = _NET_WM_STATE_MAXIMIZED_VERT_;
+ else if (state == "maximized_horz") state_atom = _NET_WM_STATE_MAXIMIZED_HORZ_;
+ else if (state == "fullscreen") state_atom = _NET_WM_STATE_FULLSCREEN_;
+ else if (state == "above") state_atom = _NET_WM_STATE_ABOVE_;
+ else if (state == "below") state_atom = _NET_WM_STATE_BELOW_;
+
+ if (state_atom != None) {
+ state_atoms.push_back(state_atom);
+ }
+ }
+
+ if (!state_atoms.empty()) {
+ XChangeProperty(display_, x11_window, _NET_WM_STATE_, XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)state_atoms.data(), state_atoms.size());
+ }
+}
+
+void X11Platform::set_window_strut(SRDWindow* window, int left, int right, int top, int bottom) {
+ if (!ewmh_supported_ || !window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ long strut[12] = {left, right, top, bottom, 0, 0, 0, 0, 0, 0, 0, 0};
+
+ XChangeProperty(display_, x11_window, XInternAtom(display_, "_NET_WM_STRUT_PARTIAL", False),
+ XA_CARDINAL, 32, PropModeReplace, (unsigned char*)strut, 12);
+}
+
+// Virtual Desktop support implementation
+void X11Platform::create_virtual_desktop(const std::string& name) {
+ if (!ewmh_supported_) return;
+
+ int desktop_id = virtual_desktops_.size();
+ virtual_desktops_.push_back(desktop_id);
+
+ // Update EWMH desktop info
+ update_ewmh_desktop_info();
+
+ std::cout << "X11Platform: Created virtual desktop " << desktop_id << " (" << name << ")" << std::endl;
+}
+
+void X11Platform::remove_virtual_desktop(int desktop_id) {
+ if (!ewmh_supported_) return;
+
+ auto it = std::find(virtual_desktops_.begin(), virtual_desktops_.end(), desktop_id);
+ if (it != virtual_desktops_.end()) {
+ virtual_desktops_.erase(it);
+
+ // If removing current desktop, switch to first available
+ if (desktop_id == current_virtual_desktop_ && !virtual_desktops_.empty()) {
+ switch_to_virtual_desktop(virtual_desktops_[0]);
+ }
+
+ update_ewmh_desktop_info();
+ std::cout << "X11Platform: Removed virtual desktop " << desktop_id << std::endl;
+ }
+}
+
+void X11Platform::switch_to_virtual_desktop(int desktop_id) {
+ if (!ewmh_supported_) return;
+
+ auto it = std::find(virtual_desktops_.begin(), virtual_desktops_.end(), desktop_id);
+ if (it != virtual_desktops_.end()) {
+ current_virtual_desktop_ = desktop_id;
+
+ // Update EWMH current desktop
+ XChangeProperty(display_, root_, _NET_CURRENT_DESKTOP_, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&current_virtual_desktop_, 1);
+
+ std::cout << "X11Platform: Switched to virtual desktop " << desktop_id << std::endl;
+ }
+}
+
+int X11Platform::get_current_virtual_desktop() const {
+ return current_virtual_desktop_;
+}
+
+std::vector<int> X11Platform::get_virtual_desktops() const {
+ return virtual_desktops_;
+}
+
+void X11Platform::move_window_to_desktop(SRDWindow* window, int desktop_id) {
+ if (!ewmh_supported_ || !window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XChangeProperty(display_, x11_window, _NET_WM_DESKTOP_, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&desktop_id, 1);
+
+ std::cout << "X11Platform: Moved window " << window->getId() << " to desktop " << desktop_id << std::endl;
+}
+
+std::vector<Monitor> X11Platform::get_monitors() {
+ std::cout << "X11Platform: Get monitors called" << std::endl;
+ // Return a default monitor for now
+ return {Monitor{0, 0, 0, 1920, 1080}};
+}
+
+Monitor X11Platform::get_primary_monitor() {
+ std::cout << "X11Platform: Get primary monitor called" << std::endl;
+ return Monitor{0, 0, 0, 1920, 1080};
+}
+
+void X11Platform::grab_keyboard() {
+ std::cout << "X11Platform: Grab keyboard called" << std::endl;
+}
+
+void X11Platform::ungrab_keyboard() {
+ std::cout << "X11Platform: Ungrab keyboard called" << std::endl;
+}
+
+void X11Platform::grab_pointer() {
+ std::cout << "X11Platform: Grab pointer called" << std::endl;
+}
+
+void X11Platform::ungrab_pointer() {
+ std::cout << "X11Platform: Ungrab pointer called" << std::endl;
+}
+
+// Private method stubs removed - actual implementations exist below
+
+void X11Platform::setup_extensions() {
+ std::cout << "X11Platform: Setup extensions called" << std::endl;
+}
+
+bool X11Platform::check_for_other_wm() {
+ // Try to select SubstructureRedirectMask on root window
+ // If another WM is running, this will fail
+ XSelectInput(display_, root_, SubstructureRedirectMask);
+ XSync(display_, False);
+
+ // Check if the selection was successful
+ XErrorHandler old_handler = XSetErrorHandler([](Display*, XErrorEvent*) -> int {
+ return 0; // Ignore errors
+ });
+
+ XSync(display_, False);
+ XSetErrorHandler(old_handler);
+
+ return true; // Simplified check
+}
+
+bool X11Platform::setup_x11_environment() {
+ std::cout << "X11Platform: Setting up X11 environment..." << std::endl;
+
+ // Set up error handling
+ XSetErrorHandler([](Display*, XErrorEvent* e) -> int {
+ if (e->error_code == BadWindow ||
+ e->error_code == BadMatch ||
+ e->error_code == BadAccess) {
+ return 0; // Ignore common errors
+ }
+ std::cerr << "X11 error: " << e->error_code << std::endl;
+ return 0;
+ });
+
+ return true;
+}
+
+bool X11Platform::setup_event_masks() {
+ std::cout << "X11Platform: Setting up event masks..." << std::endl;
+
+ // Set up root window event mask
+ long event_mask = SubstructureRedirectMask | SubstructureNotifyMask |
+ StructureNotifyMask | PropertyChangeMask |
+ ButtonPressMask | ButtonReleaseMask |
+ KeyPressMask | KeyReleaseMask |
+ PointerMotionMask | EnterWindowMask | LeaveWindowMask;
+
+ XSelectInput(display_, root_, event_mask);
+
+ return true;
+}
+
+void X11Platform::setup_atoms() {
+ std::cout << "X11Platform: Setting up atoms..." << std::endl;
+
+ // TODO: Implement atom setup for EWMH/ICCCM
+ // This would involve creating atoms for window manager protocols
+}
+
+void X11Platform::handle_x11_event(XEvent& event) {
+ std::cout << "X11Platform: Handle X11 event called" << std::endl;
+
+ switch (event.type) {
+ case MapRequest:
+ handle_map_request(event.xmaprequest);
+ break;
+ case ConfigureRequest:
+ handle_configure_request(event.xconfigurerequest);
+ break;
+ case DestroyNotify:
+ handle_destroy_notify(event.xdestroywindow);
+ break;
+ case UnmapNotify:
+ handle_unmap_notify(event.xunmap);
+ break;
+ case KeyPress:
+ handle_key_press(event.xkey);
+ break;
+ case ButtonPress:
+ handle_button_press(event.xbutton);
+ break;
+ case MotionNotify:
+ handle_motion_notify(event.xmotion);
+ break;
+ default:
+ break;
+ }
+}
+
+void X11Platform::handle_map_request(XMapRequestEvent& event) {
+ std::cout << "X11Platform: Map request for window " << static_cast<unsigned long>(event.window) << std::endl;
+
+ // Create a SRDWindow object for this X11 window
+ auto window = std::make_unique<SRDWindow>(static_cast<int>(static_cast<unsigned long>(event.window)), "X11 Window");
+
+ // Add to window map
+ window_map_[from_x11_window(event.window)] = window.get();
+ window.release();
+
+ // Map the window
+ XMapWindow(display_, event.window);
+
+ // Apply decorations if enabled
+ if (decorations_enabled_) {
+ create_frame_window(window_map_[from_x11_window(event.window)]);
+ }
+}
+
+void X11Platform::handle_configure_request(XConfigureRequestEvent& event) {
+ std::cout << "X11Platform: Configure request for window " << static_cast<unsigned long>(event.window) << std::endl;
+
+ XWindowChanges changes;
+ changes.x = event.x;
+ changes.y = event.y;
+ changes.width = event.width;
+ changes.height = event.height;
+ changes.border_width = event.border_width;
+ changes.sibling = static_cast<::Window>(event.above);
+ changes.stack_mode = event.detail;
+
+ XConfigureWindow(display_, event.window, event.value_mask, &changes);
+}
+
+void X11Platform::handle_destroy_notify(XDestroyWindowEvent& event) {
+ std::cout << "X11Platform: Destroy notify for window " << static_cast<unsigned long>(event.window) << std::endl;
+
+ auto it = window_map_.find(from_x11_window(event.window));
+ if (it != window_map_.end()) {
+ destroy_window(it->second);
+ window_map_.erase(it);
+ }
+}
+
+void X11Platform::handle_unmap_notify(XUnmapEvent& event) {
+ std::cout << "X11Platform: Unmap notify for window " << static_cast<unsigned long>(event.window) << std::endl;
+
+ // Handle window unmapping
+}
+
+void X11Platform::handle_key_press(XKeyEvent& event) {
+ std::cout << "X11Platform: Key press event" << std::endl;
+
+ // Convert X11 key event to SRDWM event
+ // TODO: Implement key event conversion
+}
+
+void X11Platform::handle_button_press(XButtonEvent& event) {
+ std::cout << "X11Platform: Button press event" << std::endl;
+
+ // Convert X11 button event to SRDWM event
+ // TODO: Implement button event conversion
+}
+
+void X11Platform::handle_motion_notify(XMotionEvent& event) {
+ std::cout << "X11Platform: Motion notify event" << std::endl;
+
+ // Convert X11 motion event to SRDWM event
+ // TODO: Implement motion event conversion
+}
+
+// Window decoration implementations
+void X11Platform::set_window_decorations(SRDWindow* window, bool enabled) {
+ std::cout << "X11Platform: Set window decorations " << (enabled ? "enabled" : "disabled") << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+
+ if (enabled) {
+ create_frame_window(window);
+ } else {
+ destroy_frame_window(window);
+ }
+
+ decorations_enabled_ = enabled;
+}
+
+void X11Platform::set_window_border_color(SRDWindow* window, int r, int g, int b) {
+ std::cout << "X11Platform: Set border color RGB(" << r << "," << g << "," << b << ")" << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ unsigned long color = (r << 16) | (g << 8) | b;
+
+ XSetWindowBorder(display_, to_x11_window(x11_window), color);
+
+ // Update decoration state
+ if (window == get_focused_window()) {
+ focused_border_color_ = color;
+ } else {
+ border_color_ = color;
+ }
+}
+
+void X11Platform::set_window_border_width(SRDWindow* window, int width) {
+ std::cout << "X11Platform: Set border width " << width << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ XSetWindowBorderWidth(display_, to_x11_window(x11_window), width);
+
+ border_width_ = width;
+}
+
+bool X11Platform::get_window_decorations(SRDWindow* window) const {
+ if (!window) return false;
+
+ // Check if window has a frame window
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+ auto it = frame_window_map_.find(x11_window);
+
+ return it != frame_window_map_.end();
+}
+
+void X11Platform::create_frame_window(SRDWindow* window) {
+ std::cout << "X11Platform: Create frame window for window " << window->getId() << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window client_window = static_cast<X11Window>(window->getId());
+
+ // Check if frame already exists
+ if (frame_window_map_.find(client_window) != frame_window_map_.end()) {
+ return;
+ }
+
+ // Get client window attributes
+ XWindowAttributes attr;
+ attr.x = 0;
+ attr.y = 0;
+ attr.width = 0;
+ attr.height = 0;
+ attr.border_width = 0;
+ attr.depth = 0;
+ attr.visual = nullptr;
+ attr.root = 0;
+ attr.c_class = 0;
+ attr.bit_gravity = 0;
+ attr.win_gravity = 0;
+ attr.backing_store = 0;
+ attr.backing_planes = 0;
+ attr.backing_pixel = 0;
+ attr.save_under = 0;
+ attr.colormap = 0;
+ attr.map_installed = 0;
+ attr.map_state = 0;
+ attr.all_event_masks = 0;
+ attr.your_event_mask = 0;
+ attr.do_not_propagate_mask = 0;
+ attr.override_redirect = 0;
+ if (XGetWindowAttributes(display_, to_x11_window(client_window), &attr) == 0) {
+ std::cerr << "Failed to get window attributes" << std::endl;
+ return;
+ }
+
+ // Create frame window
+ X11Window frame_window = from_x11_window(XCreateSimpleWindow(
+ display_, to_x11_window(root_),
+ attr.x, attr.y,
+ attr.width + border_width_ * 2,
+ attr.height + border_width_ + 30, // Add titlebar height
+ border_width_,
+ border_color_,
+ 0x000000 // Background color
+ ));
+
+ // Set frame window properties
+ XSetWindowAttributes frame_attr;
+ frame_attr.event_mask = ButtonPressMask | ButtonReleaseMask |
+ PointerMotionMask | ExposureMask;
+ XChangeWindowAttributes(display_, to_x11_window(frame_window), CWEventMask, &frame_attr);
+
+ // Reparent client window into frame
+ XReparentWindow(display_, to_x11_window(client_window), to_x11_window(frame_window), border_width_, 30);
+
+ // Map frame window
+ XMapWindow(display_, to_x11_window(frame_window));
+
+ // Store frame window mapping
+ frame_window_map_[client_window] = frame_window;
+
+ // Draw titlebar
+ draw_titlebar(window);
+
+ std::cout << "X11Platform: Frame window created successfully" << std::endl;
+}
+
+void X11Platform::destroy_frame_window(SRDWindow* window) {
+ std::cout << "X11Platform: Destroy frame window for window " << window->getId() << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window client_window = static_cast<X11Window>(window->getId());
+
+ // Find frame window
+ auto it = frame_window_map_.find(client_window);
+ if (it == frame_window_map_.end()) {
+ return;
+ }
+
+ X11Window frame_window = it->second;
+
+ // Reparent client window back to root
+ XReparentWindow(display_, to_x11_window(client_window), to_x11_window(root_), 0, 0);
+
+ // Destroy frame window
+ XDestroyWindow(display_, to_x11_window(frame_window));
+
+ // Remove from mapping
+ frame_window_map_.erase(it);
+
+ std::cout << "X11Platform: Frame window destroyed successfully" << std::endl;
+}
+
+void X11Platform::draw_titlebar(SRDWindow* window) {
+ std::cout << "X11Platform: Draw titlebar for window " << window->getId() << std::endl;
+
+ if (!window || !display_) return;
+
+ X11Window client_window = static_cast<X11Window>(window->getId());
+
+ // Find frame window
+ auto it = frame_window_map_.find(client_window);
+ if (it == frame_window_map_.end()) {
+ return;
+ }
+
+ X11Window frame_window = it->second;
+
+ // Get window title
+ char* window_name = nullptr;
+ if (XFetchName(display_, to_x11_window(client_window), &window_name) && window_name) {
+ // Create GC for drawing
+ XGCValues gc_values;
+ gc_values.foreground = 0xFFFFFF; // White text
+ gc_values.background = 0x2E3440; // Dark background
+ gc_values.font = XLoadFont(display_, "fixed");
+
+ GC gc = XCreateGC(display_, to_x11_window(frame_window),
+ GCForeground | GCBackground | GCFont, &gc_values);
+
+ // Draw titlebar background
+ XSetForeground(display_, gc, 0x2E3440);
+ XFillRectangle(display_, to_x11_window(frame_window), gc, 0, 0, 800, 30); // Placeholder size
+
+ // Draw title text
+ XSetForeground(display_, gc, 0xFFFFFF);
+ XDrawString(display_, to_x11_window(frame_window), gc, 10, 20, window_name, strlen(window_name));
+
+ // Clean up
+ XFreeGC(display_, gc);
+ XFree(window_name);
+ }
+}
+
+void X11Platform::update_frame_geometry(SRDWindow* window) {
+ std::cout << "X11Platform: Update frame geometry" << std::endl;
+
+ // TODO: Implement when X11 headers are available
+ // Update frame window geometry when client window changes
+}
+
+SRDWindow* X11Platform::get_focused_window() const {
+ if (!display_) return nullptr;
+
+ typedef ::Window X11WindowType;
+ X11WindowType focused_window;
+ int revert_to;
+ XGetInputFocus(display_, &focused_window, &revert_to);
+
+ auto it = window_map_.find(from_x11_window(focused_window));
+ if (it != window_map_.end()) {
+ return it->second;
+ }
+
+ return nullptr;
+}
+
+// EWMH helper methods
+void X11Platform::setup_ewmh() {
+ if (!display_ || !ewmh_supported_) return;
+
+ // Set EWMH supported atoms
+ Atom supported[] = {
+ _NET_WM_STATE_,
+ _NET_WM_STATE_MAXIMIZED_VERT_,
+ _NET_WM_STATE_MAXIMIZED_HORZ_,
+ _NET_WM_STATE_FULLSCREEN_,
+ _NET_WM_STATE_ABOVE_,
+ _NET_WM_STATE_BELOW_,
+ _NET_WM_WINDOW_TYPE_,
+ _NET_WM_WINDOW_TYPE_DESKTOP_,
+ _NET_WM_WINDOW_TYPE_DOCK_,
+ _NET_WM_WINDOW_TYPE_TOOLBAR_,
+ _NET_WM_WINDOW_TYPE_MENU_,
+ _NET_WM_WINDOW_TYPE_UTILITY_,
+ _NET_WM_WINDOW_TYPE_SPLASH_,
+ _NET_WM_WINDOW_TYPE_DIALOG_,
+ _NET_WM_WINDOW_TYPE_DROPDOWN_MENU_,
+ _NET_WM_WINDOW_TYPE_POPUP_MENU_,
+ _NET_WM_WINDOW_TYPE_TOOLTIP_,
+ _NET_WM_WINDOW_TYPE_NOTIFICATION_,
+ _NET_WM_WINDOW_TYPE_COMBO_,
+ _NET_WM_WINDOW_TYPE_DND_,
+ _NET_WM_WINDOW_TYPE_NORMAL_,
+ _NET_WM_DESKTOP_,
+ _NET_NUMBER_OF_DESKTOPS_,
+ _NET_CURRENT_DESKTOP_,
+ _NET_DESKTOP_NAMES_
+ };
+
+ XChangeProperty(display_, root_, XInternAtom(display_, "_NET_SUPPORTED", False),
+ XA_ATOM, 32, PropModeReplace, (unsigned char*)supported,
+ sizeof(supported) / sizeof(supported[0]));
+
+ // Set initial desktop info
+ update_ewmh_desktop_info();
+
+ std::cout << "X11Platform: EWMH setup completed" << std::endl;
+}
+
+void X11Platform::update_ewmh_desktop_info() {
+ if (!display_ || !ewmh_supported_) return;
+
+ // Set number of desktops
+ int num_desktops = virtual_desktops_.size();
+ XChangeProperty(display_, root_, _NET_NUMBER_OF_DESKTOPS_, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&num_desktops, 1);
+
+ // Set current desktop
+ XChangeProperty(display_, root_, _NET_CURRENT_DESKTOP_, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&current_virtual_desktop_, 1);
+
+ // Set desktop names (simplified - just use numbers for now)
+ std::vector<std::string> desktop_names;
+ for (int i = 0; i < num_desktops; ++i) {
+ desktop_names.push_back("Desktop " + std::to_string(i + 1));
+ }
+
+ // Convert to X11 string format
+ std::string names_str;
+ for (const auto& name : desktop_names) {
+ names_str += name + '\0';
+ }
+
+ XChangeProperty(display_, root_, _NET_DESKTOP_NAMES_, XA_STRING, 8,
+ PropModeReplace, (unsigned char*)names_str.c_str(), names_str.length());
+}
+
+// Linux/X11-specific features implementation
+void X11Platform::enable_compositor(bool enabled) {
+ compositor_enabled_ = enabled;
+
+ if (enabled) {
+ // Try to enable compositor effects
+ // This is a simplified implementation - real compositors have more complex setup
+ std::cout << "X11Platform: Compositor effects enabled" << std::endl;
+ } else {
+ std::cout << "X11Platform: Compositor effects disabled" << std::endl;
+ }
+}
+
+void X11Platform::set_window_opacity(SRDWindow* window, unsigned char opacity) {
+ if (!window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+
+ // Set window opacity using _NET_WM_WINDOW_OPACITY atom
+ Atom opacity_atom = XInternAtom(display_, "_NET_WM_WINDOW_OPACITY", False);
+ if (opacity_atom != None) {
+ unsigned long opacity_value = (opacity << 24) | (opacity << 16) | (opacity << 8) | opacity;
+ XChangeProperty(display_, x11_window, opacity_atom, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&opacity_value, 1);
+ }
+
+ std::cout << "X11Platform: Set window " << window->getId() << " opacity to " << (int)opacity << std::endl;
+}
+
+void X11Platform::set_window_blur(SRDWindow* window, bool enabled) {
+ if (!window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+
+ // Set window blur using _NET_WM_WINDOW_BLUR atom (if supported)
+ Atom blur_atom = XInternAtom(display_, "_NET_WM_WINDOW_BLUR", False);
+ if (blur_atom != None) {
+ unsigned long blur_value = enabled ? 1 : 0;
+ XChangeProperty(display_, x11_window, blur_atom, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&blur_value, 1);
+ }
+
+ std::cout << "X11Platform: Set window " << window->getId() << " blur " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::set_window_shadow(SRDWindow* window, bool enabled) {
+ if (!window) return;
+
+ X11Window x11_window = static_cast<X11Window>(window->getId());
+
+ // Set window shadow using _NET_WM_WINDOW_SHADOW atom (if supported)
+ Atom shadow_atom = XInternAtom(display_, "_NET_WM_WINDOW_SHADOW", False);
+ if (shadow_atom != None) {
+ unsigned long shadow_value = enabled ? 1 : 0;
+ XChangeProperty(display_, x11_window, shadow_atom, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char*)&shadow_value, 1);
+ }
+
+ std::cout << "X11Platform: Set window " << window->getId() << " shadow " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+// RandR (Resize and Rotate) support implementation
+void X11Platform::enable_randr(bool enabled) {
+ randr_enabled_ = enabled;
+
+ if (enabled) {
+ initialize_randr();
+ } else {
+ cleanup_randr();
+ }
+
+ std::cout << "X11Platform: RandR support " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::set_monitor_rotation(int monitor_id, int rotation) {
+ if (!randr_enabled_) return;
+
+ // Rotation values: 0=0°, 1=90°, 2=180°, 3=270°
+ if (rotation < 0 || rotation > 3) return;
+
+ // TODO: Implement actual RandR rotation
+ std::cout << "X11Platform: Set monitor " << monitor_id << " rotation to " << (rotation * 90) << "°" << std::endl;
+}
+
+void X11Platform::set_monitor_refresh_rate(int monitor_id, int refresh_rate) {
+ if (!randr_enabled_) return;
+
+ if (refresh_rate < 30 || refresh_rate > 240) return;
+
+ // TODO: Implement actual RandR refresh rate setting
+ std::cout << "X11Platform: Set monitor " << monitor_id << " refresh rate to " << refresh_rate << " Hz" << std::endl;
+}
+
+void X11Platform::set_monitor_scale(int monitor_id, float scale) {
+ if (!randr_enabled_) return;
+
+ if (scale < 0.5f || scale > 3.0f) return;
+
+ // TODO: Implement actual RandR scaling
+ std::cout << "X11Platform: Set monitor " << monitor_id << " scale to " << scale << "x" << std::endl;
+}
+
+void X11Platform::initialize_randr() {
+ if (!display_) return;
+
+ // Check if RandR extension is available
+ int event_base, error_base;
+ if (XRRQueryExtension(display_, &event_base, &error_base)) {
+ std::cout << "X11Platform: RandR extension available" << std::endl;
+
+ // Get screen resources
+ Window root = DefaultRootWindow(display_);
+ int screen = DefaultScreen(display_);
+ XRRScreenResources* resources = XRRGetScreenResources(display_, root);
+
+ if (resources) {
+ // Process monitor information
+ for (int i = 0; i < resources->noutput; ++i) {
+ XRROutputInfo* output_info = XRRGetOutputInfo(display_, resources, resources->outputs[i]);
+ if (output_info && output_info->connection == RR_Connected) {
+ // Add monitor to our list
+ Monitor monitor;
+ monitor.id = i;
+ monitor.x = 0; // TODO: Get actual position
+ monitor.y = 0;
+ monitor.width = output_info->mm_width; // Convert mm to pixels
+ monitor.height = output_info->mm_height;
+ monitor.name = output_info->name;
+ monitor.refresh_rate = 60; // Default
+
+ monitors_.push_back(monitor);
+ }
+ if (output_info) XRRFreeOutputInfo(output_info);
+ }
+ XRRFreeScreenResources(resources);
+ }
+ } else {
+ std::cout << "X11Platform: RandR extension not available" << std::endl;
+ }
+}
+
+void X11Platform::cleanup_randr() {
+ // Clean up RandR resources if needed
+ std::cout << "X11Platform: RandR cleanup completed" << std::endl;
+}
+
+// Panel/Dock integration implementation
+void X11Platform::set_panel_visible(bool visible) {
+ panel_visible_ = visible;
+
+ // TODO: Implement actual panel visibility control
+ std::cout << "X11Platform: Panel visibility " << (visible ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::set_panel_position(int position) {
+ if (position < 0 || position > 3) return;
+
+ panel_position_ = position;
+
+ // Position values: 0=bottom, 1=top, 2=left, 3=right
+ std::string position_str;
+ switch (position) {
+ case 0: position_str = "bottom"; break;
+ case 1: position_str = "top"; break;
+ case 2: position_str = "left"; break;
+ case 3: position_str = "right"; break;
+ default: position_str = "unknown"; break;
+ }
+
+ std::cout << "X11Platform: Panel position set to " << position_str << std::endl;
+}
+
+void X11Platform::set_panel_auto_hide(bool enabled) {
+ panel_auto_hide_ = enabled;
+
+ // TODO: Implement actual panel auto-hide behavior
+ std::cout << "X11Platform: Panel auto-hide " << (enabled ? "enabled" : "disabled") << std::endl;
+}
+
+void X11Platform::update_panel_workspace_list() {
+ if (!ewmh_supported_) return;
+
+ // Update panel with current workspace information
+ // This would typically involve communicating with the panel application
+ std::cout << "X11Platform: Updated panel workspace list" << std::endl;
+}
+
+// System tray integration implementation
+void X11Platform::add_system_tray_icon(const std::string& tooltip, Pixmap icon) {
+ // TODO: Implement actual system tray icon addition
+ // This would involve using the _NET_SYSTEM_TRAY_S0 atom and related protocols
+
+ system_tray_icon_ = 1; // Placeholder
+ std::cout << "X11Platform: Added system tray icon with tooltip: " << tooltip << std::endl;
+}
+
+void X11Platform::remove_system_tray_icon() {
+ if (system_tray_icon_) {
+ // TODO: Implement actual system tray icon removal
+ system_tray_icon_ = 0;
+ std::cout << "X11Platform: Removed system tray icon" << std::endl;
+ }
+}
+
+void X11Platform::show_system_tray_menu(Window menu) {
+ // TODO: Implement system tray menu display
+ std::cout << "X11Platform: Show system tray menu" << std::endl;
+}
diff --git a/src/platform/x11_platform.h b/src/platform/x11_platform.h
new file mode 100644
index 0000000..095081e
--- /dev/null
+++ b/src/platform/x11_platform.h
@@ -0,0 +1,210 @@
+#ifndef SRDWM_X11_PLATFORM_H
+#define SRDWM_X11_PLATFORM_H
+
+#include "platform.h"
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/Xrandr.h>
+#include <X11/extensions/Xinerama.h>
+
+// X11 types are now properly included
+// Use X11Window typedef to avoid collision with our SRDWindow class
+typedef unsigned long X11Window;
+
+// Helper functions to convert between X11Window and X11's Window type
+inline ::Window to_x11_window(X11Window w) { return static_cast<::Window>(w); }
+inline X11Window from_x11_window(::Window w) { return static_cast<X11Window>(w); }
+
+class X11Platform : public Platform {
+public:
+ X11Platform();
+ ~X11Platform() override;
+
+ // Platform interface implementation
+ bool initialize() override;
+ void shutdown() override;
+ bool poll_events(std::vector<Event>& events) override;
+ void process_event(const Event& event) override;
+
+ // Window management
+ std::unique_ptr<SRDWindow> create_window(const std::string& title, int x, int y, int width, int height) override;
+ void destroy_window(SRDWindow* window) override;
+ void set_window_position(SRDWindow* window, int x, int y) override;
+ void set_window_size(SRDWindow* window, int width, int height) override;
+ void set_window_title(SRDWindow* window, const std::string& title) override;
+ void focus_window(SRDWindow* window) override;
+ void minimize_window(SRDWindow* window) override;
+ void maximize_window(SRDWindow* window) override;
+ void close_window(SRDWindow* window) override;
+
+ // Monitor management
+ std::vector<Monitor> get_monitors() override;
+ Monitor get_primary_monitor() override;
+
+ // Input handling
+ void grab_keyboard() override;
+ void ungrab_keyboard() override;
+ void grab_pointer() override;
+ void ungrab_pointer() override;
+
+ // Window decorations (X11 implementation)
+ void set_window_decorations(SRDWindow* window, bool enabled) override;
+ void set_window_border_color(SRDWindow* window, int r, int g, int b) override;
+ void set_window_border_width(SRDWindow* window, int width) override;
+ bool get_window_decorations(SRDWindow* window) const override;
+
+ // Linux/X11-specific features
+ void enable_compositor(bool enabled);
+ void set_window_opacity(SRDWindow* window, unsigned char opacity);
+ void set_window_blur(SRDWindow* window, bool enabled);
+ void set_window_shadow(SRDWindow* window, bool enabled);
+
+ // EWMH (Extended Window Manager Hints) support
+ void set_ewmh_supported(bool supported);
+ void set_window_type(SRDWindow* window, const std::string& type);
+ void set_window_state(SRDWindow* window, const std::vector<std::string>& states);
+ void set_window_strut(SRDWindow* window, int left, int right, int top, int bottom);
+
+ // Virtual Desktop support (X11 workspaces)
+ void create_virtual_desktop(const std::string& name);
+ void remove_virtual_desktop(int desktop_id);
+ void switch_to_virtual_desktop(int desktop_id);
+ int get_current_virtual_desktop() const;
+ std::vector<int> get_virtual_desktops() const;
+ void move_window_to_desktop(SRDWindow* window, int desktop_id);
+
+ // Panel/Dock integration
+ void set_panel_visible(bool visible);
+ void set_panel_position(int position); // 0=bottom, 1=top, 2=left, 3=right
+ void set_panel_auto_hide(bool enabled);
+ void update_panel_workspace_list();
+
+ // System tray integration
+ void add_system_tray_icon(const std::string& tooltip, Pixmap icon);
+ void remove_system_tray_icon();
+ void show_system_tray_menu(Window menu);
+
+ // RandR (Resize and Rotate) support
+ void enable_randr(bool enabled);
+ void set_monitor_rotation(int monitor_id, int rotation);
+ void set_monitor_refresh_rate(int monitor_id, int refresh_rate);
+ void set_monitor_scale(int monitor_id, float scale);
+
+ // Utility
+ std::string get_platform_name() const override { return "X11"; }
+ bool is_wayland() const override { return false; }
+ bool is_x11() const override { return true; }
+ bool is_windows() const override { return false; }
+ bool is_macos() const override { return false; }
+
+private:
+ // X11-specific members
+ Display* display_ = nullptr;
+ X11Window root_ = 0;
+
+ // Window tracking
+ std::map<X11Window, ::SRDWindow*> window_map_;
+ std::map<X11Window, X11Window> frame_window_map_; // client -> frame
+
+ // Monitor information
+ std::vector<Monitor> monitors_;
+
+ // Decoration state
+ bool decorations_enabled_;
+ int border_width_;
+ unsigned long border_color_;
+ unsigned long focused_border_color_;
+
+ // Linux/X11-specific state
+ bool compositor_enabled_;
+ bool ewmh_supported_;
+ bool randr_enabled_;
+ int current_virtual_desktop_;
+ std::vector<int> virtual_desktops_;
+ bool panel_visible_;
+ bool panel_auto_hide_;
+ int panel_position_;
+ Window system_tray_icon_;
+
+ // EWMH atoms
+ Atom _NET_WM_STATE_;
+ Atom _NET_WM_STATE_MAXIMIZED_VERT_;
+ Atom _NET_WM_STATE_MAXIMIZED_HORZ_;
+ Atom _NET_WM_STATE_FULLSCREEN_;
+ Atom _NET_WM_STATE_ABOVE_;
+ Atom _NET_WM_STATE_BELOW_;
+ Atom _NET_WM_WINDOW_TYPE_;
+ Atom _NET_WM_WINDOW_TYPE_DESKTOP_;
+ Atom _NET_WM_WINDOW_TYPE_DOCK_;
+ Atom _NET_WM_WINDOW_TYPE_TOOLBAR_;
+ Atom _NET_WM_WINDOW_TYPE_MENU_;
+ Atom _NET_WM_WINDOW_TYPE_UTILITY_;
+ Atom _NET_WM_WINDOW_TYPE_SPLASH_;
+ Atom _NET_WM_WINDOW_TYPE_DIALOG_;
+ Atom _NET_WM_WINDOW_TYPE_DROPDOWN_MENU_;
+ Atom _NET_WM_WINDOW_TYPE_POPUP_MENU_;
+ Atom _NET_WM_WINDOW_TYPE_TOOLTIP_;
+ Atom _NET_WM_WINDOW_TYPE_NOTIFICATION_;
+ Atom _NET_WM_WINDOW_TYPE_COMBO_;
+ Atom _NET_WM_WINDOW_TYPE_DND_;
+ Atom _NET_WM_WINDOW_TYPE_NORMAL_;
+ Atom _NET_WM_DESKTOP_;
+ Atom _NET_NUMBER_OF_DESKTOPS_;
+ Atom _NET_CURRENT_DESKTOP_;
+ Atom _NET_DESKTOP_NAMES_;
+ Atom _NET_WM_STRUT_;
+ Atom _NET_WM_STRUT_PARTIAL_;
+ Atom _NET_WM_OPACITY_;
+
+ // Helper methods
+ SRDWindow* get_focused_window() const;
+
+ // Private methods
+ bool setup_x11_environment();
+ bool setup_event_masks();
+ void handle_x11_event(XEvent& event);
+ void setup_atoms();
+ void setup_extensions();
+ bool check_for_other_wm();
+
+ // Event handlers
+ void handle_map_request(XMapRequestEvent& event);
+ void handle_configure_request(XConfigureRequestEvent& event);
+ void handle_destroy_notify(XDestroyWindowEvent& event);
+ void handle_unmap_notify(XUnmapEvent& event);
+ void handle_key_press(XKeyEvent& event);
+ void handle_button_press(XButtonEvent& event);
+ void handle_motion_notify(XMotionEvent& event);
+
+ // Decoration methods
+ void create_frame_window(SRDWindow* window);
+ void destroy_frame_window(SRDWindow* window);
+ void draw_titlebar(SRDWindow* window);
+ void update_frame_geometry(SRDWindow* window);
+
+ // EWMH methods
+ void setup_ewmh();
+ void update_ewmh_desktop_info();
+ void handle_ewmh_message(XClientMessageEvent& event);
+
+ // Virtual Desktop methods
+ void initialize_virtual_desktops();
+ void cleanup_virtual_desktops();
+
+ // RandR methods
+ void initialize_randr();
+ void cleanup_randr();
+
+ // Panel methods
+ void initialize_panel();
+ void update_panel();
+};
+
+#endif // SRDWM_X11_PLATFORM_H
+
diff --git a/src/utils/logger.cc b/src/utils/logger.cc
new file mode 100644
index 0000000..92d26d9
--- /dev/null
+++ b/src/utils/logger.cc
@@ -0,0 +1,126 @@
+#include "logger.h"
+#include <iostream>
+#include <fstream>
+#include <chrono>
+#include <iomanip>
+#include <ctime>
+
+// Global logger instance
+Logger g_logger;
+
+Logger::Logger()
+ : current_level(LogLevel::INFO)
+ , console_enabled(true)
+ , file_enabled(false) {
+}
+
+Logger::~Logger() {
+ if (file_stream) {
+ file_stream->flush();
+ }
+}
+
+void Logger::set_level(LogLevel level) {
+ current_level = level;
+}
+
+void Logger::debug(const std::string& message) {
+ log(LogLevel::DEBUG, message);
+}
+
+void Logger::info(const std::string& message) {
+ log(LogLevel::INFO, message);
+}
+
+void Logger::warning(const std::string& message) {
+ log(LogLevel::WARNING, message);
+}
+
+void Logger::error(const std::string& message) {
+ log(LogLevel::ERROR, message);
+}
+
+void Logger::fatal(const std::string& message) {
+ log(LogLevel::FATAL, message);
+}
+
+void Logger::log(LogLevel level, const std::string& message) {
+ if (level >= current_level) {
+ write_log(level, message);
+ }
+}
+
+void Logger::set_output_file(const std::string& filename) {
+ output_filename = filename;
+ if (file_enabled && !filename.empty()) {
+ file_stream = std::make_unique<std::ofstream>(filename, std::ios::app);
+ if (!file_stream->good()) {
+ std::cerr << "Failed to open log file: " << filename << std::endl;
+ file_stream.reset();
+ }
+ }
+}
+
+void Logger::enable_console(bool enable) {
+ console_enabled = enable;
+}
+
+void Logger::enable_file(bool enable) {
+ file_enabled = enable;
+ if (enable && !output_filename.empty()) {
+ set_output_file(output_filename);
+ } else if (!enable) {
+ file_stream.reset();
+ }
+}
+
+std::string Logger::level_to_string(LogLevel level) {
+ switch (level) {
+ case LogLevel::DEBUG: return "DEBUG";
+ case LogLevel::INFO: return "INFO";
+ case LogLevel::WARNING: return "WARNING";
+ case LogLevel::ERROR: return "ERROR";
+ case LogLevel::FATAL: return "FATAL";
+ default: return "UNKNOWN";
+ }
+}
+
+std::string Logger::get_timestamp() {
+ auto now = std::chrono::system_clock::now();
+ auto time_t = std::chrono::system_clock::to_time_t(now);
+ auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
+ now.time_since_epoch()) % 1000;
+
+ std::stringstream ss;
+ ss << std::put_time(std::localtime(&time_t), "%Y-%m-%d %H:%M:%S");
+ ss << '.' << std::setfill('0') << std::setw(3) << ms.count();
+ return ss.str();
+}
+
+void Logger::write_log(LogLevel level, const std::string& message) {
+ std::string timestamp = get_timestamp();
+ std::string level_str = level_to_string(level);
+ std::string log_entry = "[" + timestamp + "] [" + level_str + "] " + message + "\n";
+
+ if (console_enabled) {
+ if (level == LogLevel::ERROR || level == LogLevel::FATAL) {
+ std::cerr << log_entry;
+ } else {
+ std::cout << log_entry;
+ }
+ }
+
+ if (file_enabled && file_stream && file_stream->good()) {
+ *file_stream << log_entry;
+ file_stream->flush();
+ }
+}
+
+// LogStream implementation
+LogStream::LogStream(Logger& logger, LogLevel level)
+ : logger(logger), level(level) {
+}
+
+LogStream::~LogStream() {
+ logger.log(level, stream.str());
+}
diff --git a/src/utils/logger.h b/src/utils/logger.h
new file mode 100644
index 0000000..2896c7e
--- /dev/null
+++ b/src/utils/logger.h
@@ -0,0 +1,92 @@
+#ifndef SRDWM_LOGGER_H
+#define SRDWM_LOGGER_H
+
+#include <string>
+#include <sstream>
+#include <memory>
+
+// Log levels
+enum class LogLevel {
+ DEBUG,
+ INFO,
+ WARNING,
+ ERROR,
+ FATAL
+};
+
+// Logger class
+class Logger {
+public:
+ Logger();
+ ~Logger();
+
+ // Set log level
+ void set_level(LogLevel level);
+
+ // Logging methods
+ void debug(const std::string& message);
+ void info(const std::string& message);
+ void warning(const std::string& message);
+ void error(const std::string& message);
+ void fatal(const std::string& message);
+
+ // Log with level
+ void log(LogLevel level, const std::string& message);
+
+ // Set output file
+ void set_output_file(const std::string& filename);
+
+ // Enable/disable console output
+ void enable_console(bool enable);
+
+ // Enable/disable file output
+ void enable_file(bool enable);
+
+private:
+ LogLevel current_level;
+ bool console_enabled;
+ bool file_enabled;
+ std::string output_filename;
+ std::unique_ptr<std::ostream> file_stream;
+
+ std::string level_to_string(LogLevel level);
+ std::string get_timestamp();
+ void write_log(LogLevel level, const std::string& message);
+};
+
+// Global logger instance
+extern Logger g_logger;
+
+// Convenience macros
+#define LOG_DEBUG(msg) g_logger.debug(msg)
+#define LOG_INFO(msg) g_logger.info(msg)
+#define LOG_WARNING(msg) g_logger.warning(msg)
+#define LOG_ERROR(msg) g_logger.error(msg)
+#define LOG_FATAL(msg) g_logger.fatal(msg)
+
+// Stream-based logging
+class LogStream {
+public:
+ LogStream(Logger& logger, LogLevel level);
+ ~LogStream();
+
+ template<typename T>
+ LogStream& operator<<(const T& value) {
+ stream << value;
+ return *this;
+ }
+
+private:
+ Logger& logger;
+ LogLevel level;
+ std::ostringstream stream;
+};
+
+// Stream logging macros
+#define LOG_STREAM_DEBUG LogStream(g_logger, LogLevel::DEBUG)
+#define LOG_STREAM_INFO LogStream(g_logger, LogLevel::INFO)
+#define LOG_STREAM_WARNING LogStream(g_logger, LogLevel::WARNING)
+#define LOG_STREAM_ERROR LogStream(g_logger, LogLevel::ERROR)
+#define LOG_STREAM_FATAL LogStream(g_logger, LogLevel::FATAL)
+
+#endif // SRDWM_LOGGER_H