diff options
Diffstat (limited to 'platform/windows/display_server_windows.cpp')
-rw-r--r-- | platform/windows/display_server_windows.cpp | 248 |
1 files changed, 164 insertions, 84 deletions
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 6402702415..899cf5dfad 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -38,7 +38,15 @@ #include <avrt.h> -#ifdef DEBUG_ENABLED +#if defined(GLES3_ENABLED) +#include "drivers/gles3/rasterizer_gles3.h" +#endif + +#if defined(__GNUC__) +// Workaround GCC warning from -Wcast-function-type. +#define GetProcAddress (void *)GetProcAddress +#endif + static String format_error_message(DWORD id) { LPWSTR messageBuffer = nullptr; size_t size = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, @@ -50,7 +58,6 @@ static String format_error_message(DWORD id) { return msg; } -#endif // DEBUG_ENABLED bool DisplayServerWindows::has_feature(Feature p_feature) const { switch (p_feature) { @@ -454,8 +461,8 @@ Vector<DisplayServer::WindowID> DisplayServerWindows::get_window_list() const { _THREAD_SAFE_METHOD_ Vector<DisplayServer::WindowID> ret; - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - ret.push_back(E->key()); + for (const KeyValue<WindowID, WindowData> &E : windows) { + ret.push_back(E.key); } return ret; } @@ -465,9 +472,9 @@ DisplayServer::WindowID DisplayServerWindows::get_window_at_screen_position(cons p.x = p_position.x; p.y = p_position.y; HWND hwnd = WindowFromPoint(p); - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - if (E->get().hWnd == hwnd) { - return E->key(); + for (const KeyValue<WindowID, WindowData> &E : windows) { + if (E.value.hWnd == hwnd) { + return E.key; } } @@ -531,10 +538,15 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) { } #ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { + if (context_vulkan) { context_vulkan->window_destroy(p_window); } #endif +#ifdef GLES3_ENABLED + if (gl_manager) { + gl_manager->window_destroy(p_window); + } +#endif if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window].wtctx) { wintab_WTClose(windows[p_window].wtctx); @@ -544,6 +556,12 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) { windows.erase(p_window); } +void DisplayServerWindows::gl_window_make_current(DisplayServer::WindowID p_window_id) { +#if defined(GLES3_ENABLED) + gl_manager->window_make_current(p_window_id); +#endif +} + void DisplayServerWindows::window_attach_instance_id(ObjectID p_instance, WindowID p_window) { _THREAD_SAFE_METHOD_ @@ -810,10 +828,15 @@ void DisplayServerWindows::window_set_size(const Size2i p_size, WindowID p_windo wd.height = h; #if defined(VULKAN_ENABLED) - if (rendering_driver == "vulkan") { + if (context_vulkan) { context_vulkan->window_resize(p_window, w, h); } #endif +#if defined(GLES3_ENABLED) + if (gl_manager) { + gl_manager->window_resize(p_window, w, h); + } +#endif if (wd.fullscreen) { return; @@ -1131,8 +1154,8 @@ bool DisplayServerWindows::window_can_draw(WindowID p_window) const { bool DisplayServerWindows::can_any_window_draw() const { _THREAD_SAFE_METHOD_ - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - if (!E->get().minimized) { + for (const KeyValue<WindowID, WindowData> &E : windows) { + if (!E.value.minimized) { return true; } } @@ -1181,8 +1204,11 @@ void DisplayServerWindows::console_set_visible(bool p_enabled) { if (console_visible == p_enabled) { return; } - ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE); - console_visible = p_enabled; + if (!((OS_Windows *)OS::get_singleton())->_is_win11_terminal()) { + // GetConsoleWindow is not supported by the Windows Terminal. + ShowWindow(GetConsoleWindow(), p_enabled ? SW_SHOW : SW_HIDE); + console_visible = p_enabled; + } } bool DisplayServerWindows::is_console_visible() const { @@ -1210,7 +1236,7 @@ void DisplayServerWindows::cursor_set_shape(CursorShape p_shape) { IDC_CROSS, IDC_WAIT, IDC_APPSTARTING, - IDC_ARROW, + IDC_SIZEALL, IDC_ARROW, IDC_NO, IDC_SIZENS, @@ -1476,6 +1502,42 @@ String DisplayServerWindows::keyboard_get_layout_language(int p_index) const { return String::utf16((const char16_t *)buf).substr(0, 2); } +Key DisplayServerWindows::keyboard_get_keycode_from_physical(Key p_keycode) const { + Key modifiers = p_keycode & KeyModifierMask::MODIFIER_MASK; + Key keycode_no_mod = (Key)(p_keycode & KeyModifierMask::CODE_MASK); + + if (keycode_no_mod == Key::PRINT || + keycode_no_mod == Key::KP_ADD || + keycode_no_mod == Key::KP_5 || + (keycode_no_mod >= Key::KEY_0 && keycode_no_mod <= Key::KEY_9)) { + return p_keycode; + } + + unsigned int scancode = KeyMappingWindows::get_scancode(keycode_no_mod); + if (scancode == 0) { + return p_keycode; + } + + HKL current_layout = GetKeyboardLayout(0); + UINT vk = MapVirtualKeyEx(scancode, MAPVK_VSC_TO_VK, current_layout); + if (vk == 0) { + return p_keycode; + } + + UINT char_code = MapVirtualKeyEx(vk, MAPVK_VK_TO_CHAR, current_layout) & 0x7FFF; + // Unlike a similar Linux/BSD check which matches full Latin-1 range, + // we limit these to ASCII to fix some layouts, including Arabic ones + if (char_code >= 32 && char_code <= 127) { + // Godot uses 'braces' instead of 'brackets' + if (char_code == (unsigned int)Key::BRACKETLEFT || char_code == (unsigned int)Key::BRACKETRIGHT) { + char_code += 32; + } + return (Key)(char_code | (unsigned int)modifiers); + } + + return (Key)(KeyMappingWindows::get_keysym(vk) | modifiers); +} + String _get_full_layout_name_from_registry(HKL p_layout) { String id = "SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\" + String::num_int64((int64_t)p_layout, 16, false).lpad(8, "0"); String ret; @@ -1506,7 +1568,7 @@ String DisplayServerWindows::keyboard_get_layout_name(int p_index) const { GetKeyboardLayoutList(layout_count, layouts); String ret = _get_full_layout_name_from_registry(layouts[p_index]); // Try reading full name from Windows registry, fallback to locale name if failed (e.g. on Wine). - if (ret == String()) { + if (ret.is_empty()) { WCHAR buf[LOCALE_NAME_MAX_LENGTH]; memset(buf, 0, LOCALE_NAME_MAX_LENGTH * sizeof(WCHAR)); LCIDToLocaleName(MAKELCID(LOWORD(layouts[p_index]), SORT_DEFAULT), buf, LOCALE_NAME_MAX_LENGTH, 0); @@ -1557,6 +1619,9 @@ void DisplayServerWindows::make_rendering_thread() { } void DisplayServerWindows::swap_buffers() { +#if defined(GLES3_ENABLED) + gl_manager->swap_buffers(); +#endif } void DisplayServerWindows::set_native_icon(const String &p_filename) { @@ -1708,17 +1773,18 @@ void DisplayServerWindows::set_icon(const Ref<Image> &p_icon) { void DisplayServerWindows::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mode, WindowID p_window) { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) - context_vulkan->set_vsync_mode(p_window, p_vsync_mode); + // TODO disabling for now + //context_vulkan->set_vsync_mode(p_window, p_vsync_mode); #endif } DisplayServer::VSyncMode DisplayServerWindows::window_get_vsync_mode(WindowID p_window) const { _THREAD_SAFE_METHOD_ #if defined(VULKAN_ENABLED) - return context_vulkan->get_vsync_mode(p_window); -#else - return DisplayServer::VSYNC_ENABLED; + //TODO disabling for now + //return context_vulkan->get_vsync_mode(p_window); #endif + return DisplayServer::VSYNC_ENABLED; } void DisplayServerWindows::set_context(Context p_context) { @@ -1816,8 +1882,8 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) callable.call((const Variant **)&evp, 1, ret, ce); } else { // Send to all windows. - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - Callable callable = E->get().input_event_callback; + for (const KeyValue<WindowID, WindowData> &E : windows) { + const Callable callable = E.value.input_event_callback; if (callable.is_null()) { continue; } @@ -1844,9 +1910,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA bool window_created = false; // Check whether window exists. - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - if (E->get().hWnd == hWnd) { - window_id = E->key(); + for (const KeyValue<WindowID, WindowData> &E : windows) { + if (E.value.hWnd == hWnd) { + window_id = E.key; window_created = true; break; } @@ -1882,8 +1948,8 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA ReleaseCapture(); // Release every touch to avoid sticky points. - for (Map<int, Vector2>::Element *E = touch_state.front(); E; E = E->next()) { - _touch_event(window_id, false, E->get().x, E->get().y, E->key()); + for (const KeyValue<int, Vector2> &E : touch_state) { + _touch_event(window_id, false, E.value.x, E.value.y, E.key); } touch_state.clear(); @@ -2403,41 +2469,41 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA switch (uMsg) { case WM_LBUTTONDOWN: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_LEFT); + mb->set_button_index(MouseButton::LEFT); } break; case WM_LBUTTONUP: { mb->set_pressed(false); - mb->set_button_index(MOUSE_BUTTON_LEFT); + mb->set_button_index(MouseButton::LEFT); } break; case WM_MBUTTONDOWN: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_MIDDLE); + mb->set_button_index(MouseButton::MIDDLE); } break; case WM_MBUTTONUP: { mb->set_pressed(false); - mb->set_button_index(MOUSE_BUTTON_MIDDLE); + mb->set_button_index(MouseButton::MIDDLE); } break; case WM_RBUTTONDOWN: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_RIGHT); + mb->set_button_index(MouseButton::RIGHT); } break; case WM_RBUTTONUP: { mb->set_pressed(false); - mb->set_button_index(MOUSE_BUTTON_RIGHT); + mb->set_button_index(MouseButton::RIGHT); } break; case WM_LBUTTONDBLCLK: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_LEFT); + mb->set_button_index(MouseButton::LEFT); mb->set_double_click(true); } break; case WM_RBUTTONDBLCLK: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_RIGHT); + mb->set_button_index(MouseButton::RIGHT); mb->set_double_click(true); } break; case WM_MBUTTONDBLCLK: { mb->set_pressed(true); - mb->set_button_index(MOUSE_BUTTON_MIDDLE); + mb->set_button_index(MouseButton::MIDDLE); mb->set_double_click(true); } break; case WM_MOUSEWHEEL: { @@ -2448,9 +2514,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } if (motion > 0) { - mb->set_button_index(MOUSE_BUTTON_WHEEL_UP); + mb->set_button_index(MouseButton::WHEEL_UP); } else { - mb->set_button_index(MOUSE_BUTTON_WHEEL_DOWN); + mb->set_button_index(MouseButton::WHEEL_DOWN); } mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); } break; @@ -2462,34 +2528,34 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } if (motion < 0) { - mb->set_button_index(MOUSE_BUTTON_WHEEL_LEFT); + mb->set_button_index(MouseButton::WHEEL_LEFT); } else { - mb->set_button_index(MOUSE_BUTTON_WHEEL_RIGHT); + mb->set_button_index(MouseButton::WHEEL_RIGHT); } mb->set_factor(fabs((double)motion / (double)WHEEL_DELTA)); } break; case WM_XBUTTONDOWN: { mb->set_pressed(true); if (HIWORD(wParam) == XBUTTON1) { - mb->set_button_index(MOUSE_BUTTON_XBUTTON1); + mb->set_button_index(MouseButton::MB_XBUTTON1); } else { - mb->set_button_index(MOUSE_BUTTON_XBUTTON2); + mb->set_button_index(MouseButton::MB_XBUTTON2); } } break; case WM_XBUTTONUP: { mb->set_pressed(false); if (HIWORD(wParam) == XBUTTON1) { - mb->set_button_index(MOUSE_BUTTON_XBUTTON1); + mb->set_button_index(MouseButton::MB_XBUTTON1); } else { - mb->set_button_index(MOUSE_BUTTON_XBUTTON2); + mb->set_button_index(MouseButton::MB_XBUTTON2); } } break; case WM_XBUTTONDBLCLK: { mb->set_pressed(true); if (HIWORD(wParam) == XBUTTON1) { - mb->set_button_index(MOUSE_BUTTON_XBUTTON1); + mb->set_button_index(MouseButton::MB_XBUTTON1); } else { - mb->set_button_index(MOUSE_BUTTON_XBUTTON2); + mb->set_button_index(MouseButton::MB_XBUTTON2); } mb->set_double_click(true); } break; @@ -2503,9 +2569,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mb->set_alt_pressed(alt_mem); // mb->is_alt_pressed()=(wParam&MK_MENU)!=0; if (mb->is_pressed()) { - last_button_state |= MouseButton(1 << (mb->get_button_index() - 1)); + last_button_state |= mouse_button_to_mask(mb->get_button_index()); } else { - last_button_state &= (MouseButton) ~(1 << (mb->get_button_index() - 1)); + last_button_state &= ~mouse_button_to_mask(mb->get_button_index()); } mb->set_button_mask(last_button_state); @@ -2541,11 +2607,11 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mb->set_global_position(mb->get_position()); Input::get_singleton()->parse_input_event(mb); - if (mb->is_pressed() && mb->get_button_index() > 3 && mb->get_button_index() < 8) { + if (mb->is_pressed() && mb->get_button_index() >= MouseButton::WHEEL_UP && mb->get_button_index() <= MouseButton::WHEEL_RIGHT) { // Send release for mouse wheel. Ref<InputEventMouseButton> mbd = mb->duplicate(); mbd->set_window_id(window_id); - last_button_state &= (MouseButton) ~(1 << (mbd->get_button_index() - 1)); + last_button_state &= ~mouse_button_to_mask(mbd->get_button_index()); mbd->set_button_mask(last_button_state); mbd->set_pressed(false); Input::get_singleton()->parse_input_event(mbd); @@ -2580,7 +2646,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA windows[window_id].height = window_h; #if defined(VULKAN_ENABLED) - if ((rendering_driver == "vulkan") && window_created) { + if (context_vulkan && window_created) { context_vulkan->window_resize(window_id, windows[window_id].width, windows[window_id].height); } #endif @@ -2895,7 +2961,7 @@ void DisplayServerWindows::_process_key_events() { if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) { // Special case for Numpad Enter key. - k->set_keycode(KEY_KP_ENTER); + k->set_keycode(Key::KP_ENTER); } else { k->set_keycode((Key)KeyMappingWindows::get_keysym(ke.wParam)); } @@ -2943,8 +3009,8 @@ void DisplayServerWindows::_process_key_events() { } void DisplayServerWindows::_update_tablet_ctx(const String &p_old_driver, const String &p_new_driver) { - for (Map<WindowID, WindowData>::Element *E = windows.front(); E; E = E->next()) { - WindowData &wd = E->get(); + for (KeyValue<WindowID, WindowData> &E : windows) { + WindowData &wd = E.value; wd.block_mm = false; if ((p_old_driver == "wintab") && wintab_available && wd.wtctx) { wintab_WTEnable(wd.wtctx, false); @@ -3042,7 +3108,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, } #ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { + if (context_vulkan) { if (context_vulkan->window_create(id, p_vsync_mode, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top) == -1) { memdelete(context_vulkan); context_vulkan = nullptr; @@ -3052,6 +3118,13 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, } #endif +#ifdef GLES3_ENABLED + if (gl_manager) { + Error err = gl_manager->window_create(id, wd.hWnd, hInstance, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top); + ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Failed to create an OpenGL window."); + } +#endif + RegisterTouchWindow(wd.hWnd, 0); TRACKMOUSEEVENT tme; @@ -3182,6 +3255,8 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win outside = true; + rendering_driver = p_rendering_driver; + // Note: Wacom WinTab driver API for pen input, for devices incompatible with Windows Ink. HMODULE wintab_lib = LoadLibraryW(L"wintab32.dll"); if (wintab_lib) { @@ -3258,8 +3333,6 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win use_raw_input = false; } - rendering_driver = "vulkan"; - #if defined(VULKAN_ENABLED) if (rendering_driver == "vulkan") { context_vulkan = memnew(VulkanContextWindows); @@ -3271,27 +3344,23 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } } #endif + // Init context and rendering device +#if defined(GLES3_ENABLED) -#if defined(OPENGL_ENABLED) - if (rendering_driver_index == VIDEO_DRIVER_GLES2) { - context_gles2 = memnew(ContextGL_Windows(hWnd, false)); - - if (context_gles2->initialize() != OK) { - memdelete(context_gles2); - context_gles2 = nullptr; - ERR_FAIL_V(ERR_UNAVAILABLE); - } + if (rendering_driver == "opengl3") { + GLManager_Windows::ContextType opengl_api_type = GLManager_Windows::GLES_3_0_COMPATIBLE; - context_gles2->set_use_vsync(video_mode.use_vsync); + gl_manager = memnew(GLManager_Windows(opengl_api_type)); - if (RasterizerGLES2::is_viable() == OK) { - RasterizerGLES2::register_config(); - RasterizerGLES2::make_current(); - } else { - memdelete(context_gles2); - context_gles2 = nullptr; - ERR_FAIL_V(ERR_UNAVAILABLE); + if (gl_manager->initialize() != OK) { + memdelete(gl_manager); + gl_manager = nullptr; + r_error = ERR_UNAVAILABLE; + return; } + + // gl_manager->set_use_vsync(current_videomode.use_vsync); + RasterizerGLES3::make_current(); } #endif @@ -3352,8 +3421,8 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() { #ifdef VULKAN_ENABLED drivers.push_back("vulkan"); #endif -#ifdef OPENGL_ENABLED - drivers.push_back("opengl"); +#ifdef GLES3_ENABLED + drivers.push_back("opengl3"); #endif return drivers; @@ -3362,7 +3431,7 @@ Vector<String> DisplayServerWindows::get_rendering_drivers_func() { DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i &p_resolution, Error &r_error) { DisplayServer *ds = memnew(DisplayServerWindows(p_rendering_driver, p_mode, p_vsync_mode, p_flags, p_resolution, r_error)); if (r_error != OK) { - OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan versions.\n" + OS::get_singleton()->alert("Your video card driver does not support any of the supported Vulkan or OpenGL versions.\n" "Please update your drivers or if you have a very old or integrated GPU upgrade it.", "Unable to initialize Video driver"); } @@ -3383,9 +3452,13 @@ DisplayServerWindows::~DisplayServerWindows() { SetWindowLongPtr(windows[MAIN_WINDOW_ID].hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc); }; +#ifdef GLES3_ENABLED + // destroy windows .. NYI? +#endif + if (windows.has(MAIN_WINDOW_ID)) { #ifdef VULKAN_ENABLED - if (rendering_driver == "vulkan") { + if (context_vulkan) { context_vulkan->window_destroy(MAIN_WINDOW_ID); } #endif @@ -3397,18 +3470,25 @@ DisplayServerWindows::~DisplayServerWindows() { } #if defined(VULKAN_ENABLED) - if (rendering_driver == "vulkan") { - if (rendering_device_vulkan) { - rendering_device_vulkan->finalize(); - memdelete(rendering_device_vulkan); - } + if (rendering_device_vulkan) { + rendering_device_vulkan->finalize(); + memdelete(rendering_device_vulkan); + rendering_device_vulkan = nullptr; + } - if (context_vulkan) - memdelete(context_vulkan); + if (context_vulkan) { + memdelete(context_vulkan); + context_vulkan = nullptr; } #endif if (restore_mouse_trails > 1) { SystemParametersInfoA(SPI_SETMOUSETRAILS, restore_mouse_trails, 0, 0); } +#ifdef GLES3_ENABLED + if (gl_manager) { + memdelete(gl_manager); + gl_manager = nullptr; + } +#endif } |