From e4a0432383331e013808a97b7c24707e4ddc4726 Mon Sep 17 00:00:00 2001 From: srdusr Date: Fri, 26 Sep 2025 12:23:19 +0200 Subject: Initial Commit --- src/platform/windows_platform.cc | 585 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 585 insertions(+) create mode 100644 src/platform/windows_platform.cc (limited to 'src/platform/windows_platform.cc') 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 +#include +#include + +// 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& 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& 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 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(); + // 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 SRDWindowsPlatform::get_monitors() { + std::vector monitors; + + // Enumerate monitors using EnumDisplayMonitors + EnumDisplayMonitors(nullptr, nullptr, + [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL { + auto* monitors = reinterpret_cast*>(dwData); + + MONITORINFOEX monitorInfo; + monitorInfo.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfo(hMonitor, &monitorInfo); + + Monitor monitor; + monitor.id = reinterpret_cast(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(&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& 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 +} + + -- cgit v1.2.3