diff options
Diffstat (limited to 'platform/windows/display_server_windows.cpp')
| -rw-r--r-- | platform/windows/display_server_windows.cpp | 245 |
1 files changed, 209 insertions, 36 deletions
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 99b80c2e2a..521bf85b27 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -735,9 +735,23 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod if (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) { wd.no_focus = true; } + if (p_flags & WINDOW_FLAG_MOUSE_PASSTHROUGH_BIT) { + wd.mpass = true; + } if (p_flags & WINDOW_FLAG_POPUP_BIT) { wd.is_popup = true; } + if (p_flags & WINDOW_FLAG_TRANSPARENT_BIT) { + DWM_BLURBEHIND bb; + ZeroMemory(&bb, sizeof(bb)); + HRGN hRgn = CreateRectRgn(0, 0, -1, -1); + bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION; + bb.hRgnBlur = hRgn; + bb.fEnable = TRUE; + DwmEnableBlurBehindWindow(wd.hWnd, &bb); + + wd.layered_window = true; + } // Inherit icons from MAIN_WINDOW for all sub windows. HICON mainwindow_icon = (HICON)SendMessage(windows[MAIN_WINDOW_ID].hWnd, WM_GETICON, ICON_SMALL, 0); @@ -775,6 +789,9 @@ void DisplayServerWindows::show_window(WindowID p_id) { SetForegroundWindow(wd.hWnd); // Slightly higher priority. SetFocus(wd.hWnd); // Set keyboard focus. } + if (wd.always_on_top) { + SetWindowPos(wd.hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ((wd.no_focus || wd.is_popup) ? SWP_NOACTIVATE : 0)); + } } void DisplayServerWindows::delete_sub_window(WindowID p_window) { @@ -918,7 +935,7 @@ void DisplayServerWindows::window_set_mouse_passthrough(const Vector<Vector2> &p void DisplayServerWindows::_update_window_mouse_passthrough(WindowID p_window) { ERR_FAIL_COND(!windows.has(p_window)); - if (windows[p_window].mpath.size() == 0) { + if (windows[p_window].mpass || windows[p_window].mpath.size() == 0) { SetWindowRgn(windows[p_window].hWnd, nullptr, TRUE); } else { POINT *points = (POINT *)memalloc(sizeof(POINT) * windows[p_window].mpath.size()); @@ -1499,6 +1516,10 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W wd.no_focus = p_enabled; _update_window_style(p_window); } break; + case WINDOW_FLAG_MOUSE_PASSTHROUGH: { + wd.mpass = p_enabled; + _update_window_mouse_passthrough(p_window); + } break; case WINDOW_FLAG_POPUP: { ERR_FAIL_COND_MSG(p_window == MAIN_WINDOW_ID, "Main window can't be popup."); ERR_FAIL_COND_MSG(IsWindowVisible(wd.hWnd) && (wd.is_popup != p_enabled), "Popup flag can't changed while window is opened."); @@ -1530,6 +1551,9 @@ bool DisplayServerWindows::window_get_flag(WindowFlags p_flag, WindowID p_window case WINDOW_FLAG_NO_FOCUS: { return wd.no_focus; } break; + case WINDOW_FLAG_MOUSE_PASSTHROUGH: { + return wd.mpass; + } break; case WINDOW_FLAG_POPUP: { return wd.is_popup; } break; @@ -1586,6 +1610,58 @@ bool DisplayServerWindows::can_any_window_draw() const { return false; } +Vector2i DisplayServerWindows::ime_get_selection() const { + _THREAD_SAFE_METHOD_ + + DisplayServer::WindowID window_id = _get_focused_window_or_popup(); + const WindowData &wd = windows[window_id]; + if (!wd.ime_active) { + return Vector2i(); + } + + int cursor = ImmGetCompositionStringW(wd.im_himc, GCS_CURSORPOS, nullptr, 0); + + int32_t length = ImmGetCompositionStringW(wd.im_himc, GCS_COMPSTR, nullptr, 0); + wchar_t *string = reinterpret_cast<wchar_t *>(memalloc(length)); + ImmGetCompositionStringW(wd.im_himc, GCS_COMPSTR, string, length); + + int32_t utf32_cursor = 0; + for (int32_t i = 0; i < length / sizeof(wchar_t); i++) { + if ((string[i] & 0xfffffc00) == 0xd800) { + i++; + } + if (i < cursor) { + utf32_cursor++; + } else { + break; + } + } + + memdelete(string); + + return Vector2i(utf32_cursor, 0); +} + +String DisplayServerWindows::ime_get_text() const { + _THREAD_SAFE_METHOD_ + + DisplayServer::WindowID window_id = _get_focused_window_or_popup(); + const WindowData &wd = windows[window_id]; + if (!wd.ime_active) { + return String(); + } + + String ret; + int32_t length = ImmGetCompositionStringW(wd.im_himc, GCS_COMPSTR, nullptr, 0); + wchar_t *string = reinterpret_cast<wchar_t *>(memalloc(length)); + ImmGetCompositionStringW(wd.im_himc, GCS_COMPSTR, string, length); + ret.parse_utf16((char16_t *)string, length / sizeof(wchar_t)); + + memdelete(string); + + return ret; +} + void DisplayServerWindows::window_set_ime_active(const bool p_active, WindowID p_window) { _THREAD_SAFE_METHOD_ @@ -1593,11 +1669,12 @@ void DisplayServerWindows::window_set_ime_active(const bool p_active, WindowID p WindowData &wd = windows[p_window]; if (p_active) { + wd.ime_active = true; ImmAssociateContext(wd.hWnd, wd.im_himc); - window_set_ime_position(wd.im_position, p_window); } else { ImmAssociateContext(wd.hWnd, (HIMC)0); + wd.ime_active = false; } } @@ -1615,7 +1692,7 @@ void DisplayServerWindows::window_set_ime_position(const Point2i &p_pos, WindowI } COMPOSITIONFORM cps; - cps.dwStyle = CFS_FORCE_POSITION; + cps.dwStyle = CFS_POINT; cps.ptCurrentPos.x = wd.im_position.x; cps.ptCurrentPos.y = wd.im_position.y; ImmSetCompositionWindow(himc, &cps); @@ -2464,6 +2541,11 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA // Process window messages. switch (uMsg) { + case WM_NCHITTEST: { + if (windows[window_id].mpass) { + return HTTRANSPARENT; + } + } break; case WM_MOUSEACTIVATE: { if (windows[window_id].no_focus) { return MA_NOACTIVATEANDEAT; // Do not activate, and discard mouse messages. @@ -2543,6 +2625,25 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA return 0; } } break; + case WM_ERASEBKGND: { + Color early_color; + if (!_get_window_early_clear_override(early_color)) { + break; + } + bool must_recreate_brush = !window_bkg_brush || window_bkg_brush_color != early_color.to_argb32(); + if (must_recreate_brush) { + if (window_bkg_brush) { + DeleteObject(window_bkg_brush); + } + window_bkg_brush = CreateSolidBrush(RGB(early_color.get_r8(), early_color.get_g8(), early_color.get_b8())); + } + HDC hdc = (HDC)wParam; + RECT rect = {}; + if (GetUpdateRect(hWnd, &rect, true)) { + FillRect(hdc, &rect, window_bkg_brush); + } + return 1; + } break; case WM_PAINT: { Main::force_redraw(); } break; @@ -3305,10 +3406,18 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA windows[window_id].focus_timer_id = 0U; } } break; - case WM_SYSKEYDOWN: case WM_SYSKEYUP: case WM_KEYUP: + if (windows[window_id].ime_suppress_next_keyup) { + windows[window_id].ime_suppress_next_keyup = false; + break; + } + [[fallthrough]]; + case WM_SYSKEYDOWN: case WM_KEYDOWN: { + if (windows[window_id].ime_in_progress) { + break; + } if (wParam == VK_SHIFT) { shift_mem = (uMsg == WM_KEYDOWN || uMsg == WM_SYSKEYDOWN); } @@ -3331,6 +3440,9 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA [[fallthrough]]; } case WM_CHAR: { + if (windows[window_id].ime_in_progress) { + break; + } ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE); // Make sure we don't include modifiers for the modifier key itself. @@ -3354,9 +3466,43 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA key_event_buffer[key_event_pos++] = ke; } break; + case WM_IME_COMPOSITION: { + CANDIDATEFORM cf; + cf.dwIndex = 0; + cf.dwStyle = CFS_EXCLUDE; + cf.ptCurrentPos.x = windows[window_id].im_position.x; + cf.ptCurrentPos.y = windows[window_id].im_position.y; + cf.rcArea.left = windows[window_id].im_position.x; + cf.rcArea.right = windows[window_id].im_position.x; + cf.rcArea.top = windows[window_id].im_position.y; + cf.rcArea.bottom = windows[window_id].im_position.y; + ImmSetCandidateWindow(windows[window_id].im_himc, &cf); + if (windows[window_id].ime_active) { + OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE); + } + } break; case WM_INPUTLANGCHANGEREQUEST: { // FIXME: Do something? } break; + case WM_IME_STARTCOMPOSITION: { + if (windows[window_id].ime_active) { + windows[window_id].ime_in_progress = true; + if (key_event_pos > 0) { + key_event_pos--; + } + } + return 0; + } break; + case WM_IME_ENDCOMPOSITION: { + if (windows[window_id].ime_active) { + windows[window_id].ime_in_progress = false; + windows[window_id].ime_suppress_next_keyup = true; + } + return 0; + } break; + case WM_IME_NOTIFY: { + return 0; + } break; case WM_TOUCH: { BOOL bHandled = FALSE; UINT cInputs = LOWORD(wParam); @@ -3465,6 +3611,7 @@ void DisplayServerWindows::_process_activate_event(WindowID p_window_id, WPARAM alt_mem = false; control_mem = false; shift_mem = false; + gr_mem = false; // Restore mouse mode. _set_mouse_mode_impl(mouse_mode); @@ -3508,24 +3655,36 @@ void DisplayServerWindows::_process_key_events() { Ref<InputEventKey> k; k.instantiate(); + Key keycode = KeyMappingWindows::get_keysym(MapVirtualKey((ke.lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK)); + Key key_label = keycode; + Key physical_keycode = KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)); + + static BYTE keyboard_state[256]; + memset(keyboard_state, 0, 256); + wchar_t chars[256] = {}; + UINT extended_code = MapVirtualKey((ke.lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK_EX); + if (!(ke.lParam & (1 << 24)) && ToUnicodeEx(extended_code, (ke.lParam >> 16) & 0xFF, keyboard_state, chars, 255, 0, GetKeyboardLayout(0)) > 0) { + String keysym = String::utf16((char16_t *)chars, 255); + if (!keysym.is_empty()) { + key_label = fix_key_label(keysym[0], keycode); + } + } + k->set_window_id(ke.window_id); k->set_shift_pressed(ke.shift); k->set_alt_pressed(ke.alt); k->set_ctrl_pressed(ke.control); k->set_meta_pressed(ke.meta); k->set_pressed(true); - k->set_keycode((Key)KeyMappingWindows::get_keysym(MapVirtualKey((ke.lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK))); - k->set_physical_keycode((Key)(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)))); - k->set_unicode(unicode); + k->set_keycode(keycode); + k->set_physical_keycode(physical_keycode); + k->set_key_label(key_label); + k->set_unicode(fix_unicode(unicode)); if (k->get_unicode() && gr_mem) { k->set_alt_pressed(false); k->set_ctrl_pressed(false); } - if (k->get_unicode() < 32) { - k->set_unicode(0); - } - Input::get_singleton()->parse_input_event(k); } else { // Do nothing. @@ -3544,14 +3703,28 @@ void DisplayServerWindows::_process_key_events() { k->set_pressed(ke.uMsg == WM_KEYDOWN); + Key keycode = KeyMappingWindows::get_keysym(ke.wParam); if ((ke.lParam & (1 << 24)) && (ke.wParam == VK_RETURN)) { // Special case for Numpad Enter key. - k->set_keycode(Key::KP_ENTER); - } else { - k->set_keycode((Key)KeyMappingWindows::get_keysym(ke.wParam)); + keycode = Key::KP_ENTER; + } + Key key_label = keycode; + Key physical_keycode = KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)); + + static BYTE keyboard_state[256]; + memset(keyboard_state, 0, 256); + wchar_t chars[256] = {}; + UINT extended_code = MapVirtualKey((ke.lParam >> 16) & 0xFF, MAPVK_VSC_TO_VK_EX); + if (!(ke.lParam & (1 << 24)) && ToUnicodeEx(extended_code, (ke.lParam >> 16) & 0xFF, keyboard_state, chars, 255, 0, GetKeyboardLayout(0)) > 0) { + String keysym = String::utf16((char16_t *)chars, 255); + if (!keysym.is_empty()) { + key_label = fix_key_label(keysym[0], keycode); + } } - k->set_physical_keycode((Key)(KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)))); + k->set_keycode(keycode); + k->set_physical_keycode(physical_keycode); + k->set_key_label(key_label); if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR) { char32_t unicode = key_event_buffer[i + 1].wParam; @@ -3572,17 +3745,13 @@ void DisplayServerWindows::_process_key_events() { } else { prev_wck = 0; } - k->set_unicode(unicode); + k->set_unicode(fix_unicode(unicode)); } if (k->get_unicode() && gr_mem) { k->set_alt_pressed(false); k->set_ctrl_pressed(false); } - if (k->get_unicode() < 32) { - k->set_unicode(0); - } - k->set_echo((ke.uMsg == WM_KEYDOWN && (ke.lParam & (1 << 30)))); Input::get_singleton()->parse_input_event(k); @@ -3637,7 +3806,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, DWORD dwExStyle; DWORD dwStyle; - _get_window_style(window_id_counter == MAIN_WINDOW_ID, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), dwStyle, dwExStyle); + _get_window_style(window_id_counter == MAIN_WINDOW_ID, (p_mode == WINDOW_MODE_FULLSCREEN || p_mode == WINDOW_MODE_EXCLUSIVE_FULLSCREEN), p_mode != WINDOW_MODE_EXCLUSIVE_FULLSCREEN, p_flags & WINDOW_FLAG_BORDERLESS_BIT, !(p_flags & WINDOW_FLAG_RESIZE_DISABLED_BIT), p_mode == WINDOW_MODE_MAXIMIZED, (p_flags & WINDOW_FLAG_NO_FOCUS_BIT) | (p_flags & WINDOW_FLAG_POPUP), dwStyle, dwExStyle); RECT WindowRect; @@ -3793,7 +3962,7 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode, // IME. wd.im_himc = ImmGetContext(wd.hWnd); - ImmReleaseContext(wd.hWnd, wd.im_himc); + ImmAssociateContext(wd.hWnd, (HIMC)0); wd.im_position = Vector2(); @@ -3887,6 +4056,8 @@ void DisplayServerWindows::tablet_set_current_driver(const String &p_driver) { } DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Vector2i *p_position, const Vector2i &p_resolution, int p_screen, Error &r_error) { + KeyMappingWindows::initialize(); + drop_events = false; key_event_pos = 0; @@ -3982,7 +4153,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win memset(&wc, 0, sizeof(WNDCLASSEXW)); wc.cbSize = sizeof(WNDCLASSEXW); - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; + wc.style = CS_OWNDC | CS_DBLCLKS; wc.lpfnWndProc = (WNDPROC)::WndProc; wc.cbClsExtra = 0; wc.cbWndExtra = 0; @@ -3994,7 +4165,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win wc.lpszClassName = L"Engine"; if (!RegisterClassExW(&wc)) { - MessageBox(nullptr, "Failed To Register The Window Class.", "ERROR", MB_OK | MB_ICONEXCLAMATION); + MessageBoxW(nullptr, L"Failed To Register The Window Class.", L"ERROR", MB_OK | MB_ICONEXCLAMATION); r_error = ERR_UNAVAILABLE; return; } @@ -4073,7 +4244,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win // from making the system unresponsive. SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); DWORD index = 0; - HANDLE handle = AvSetMmThreadCharacteristics("Games", &index); + HANDLE handle = AvSetMmThreadCharacteristicsW(L"Games", &index); if (handle) { AvSetMmThreadPriority(handle, AVRT_PRIORITY_CRITICAL); } @@ -4111,18 +4282,20 @@ DisplayServer *DisplayServerWindows::create_func(const String &p_rendering_drive if (r_error != OK) { if (p_rendering_driver == "vulkan") { String executable_name = OS::get_singleton()->get_executable_path().get_file(); - OS::get_singleton()->alert("Your video card driver does not support the selected Vulkan version.\n" - "Please try updating your GPU driver or try using the OpenGL 3 driver.\n" - "You can enable the OpenGL 3 driver by starting the engine from the\n" - "command line with the command:\n'./" + - executable_name + " --rendering-driver opengl3'.\n " - "If you have updated your graphics drivers recently, try rebooting.", - "Unable to initialize Video driver"); + OS::get_singleton()->alert( + vformat("Your video card drivers seem not to support the required Vulkan version.\n\n" + "If possible, consider updating your video card drivers or using the OpenGL 3 driver.\n\n" + "You can enable the OpenGL 3 driver by starting the engine from the\n" + "command line with the command:\n'%s --rendering-driver opengl3'\n\n" + "If you have recently updated your video card drivers, try rebooting.", + executable_name), + "Unable to initialize Vulkan video driver"); } else { - OS::get_singleton()->alert("Your video card driver does not support the selected OpenGL version.\n" - "Please try updating your GPU driver.\n" - "If you have updated your graphics drivers recently, try rebooting.", - "Unable to initialize Video driver"); + OS::get_singleton()->alert( + "Your video card drivers seem not to support the required OpenGL 3.3 version.\n\n" + "If possible, consider updating your video card drivers.\n\n" + "If you have recently updated your video card drivers, try rebooting.", + "Unable to initialize OpenGL video driver"); } } return ds; |