diff options
Diffstat (limited to 'platform/windows')
-rw-r--r-- | platform/windows/display_server_windows.cpp | 253 | ||||
-rw-r--r-- | platform/windows/display_server_windows.h | 18 | ||||
-rw-r--r-- | platform/windows/export/export.cpp | 79 | ||||
-rw-r--r-- | platform/windows/export/export_plugin.cpp | 109 | ||||
-rw-r--r-- | platform/windows/export/export_plugin.h | 4 | ||||
-rw-r--r-- | platform/windows/gl_manager_windows.h | 13 | ||||
-rw-r--r-- | platform/windows/godot.ico | bin | 110755 -> 359559 bytes | |||
-rw-r--r-- | platform/windows/joypad_windows.cpp | 10 | ||||
-rw-r--r-- | platform/windows/joypad_windows.h | 4 | ||||
-rw-r--r-- | platform/windows/os_windows.cpp | 14 | ||||
-rw-r--r-- | platform/windows/os_windows.h | 4 |
11 files changed, 356 insertions, 152 deletions
diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 41295d41d2..31bad0f053 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -150,7 +150,7 @@ DisplayServer::MouseMode DisplayServerWindows::mouse_get_mode() const { return mouse_mode; } -void DisplayServerWindows::mouse_warp_to_position(const Point2i &p_to) { +void DisplayServerWindows::warp_mouse(const Point2i &p_position) { _THREAD_SAFE_METHOD_ if (!windows.has(last_focused_window)) { @@ -158,12 +158,12 @@ void DisplayServerWindows::mouse_warp_to_position(const Point2i &p_to) { } if (mouse_mode == MOUSE_MODE_CAPTURED) { - old_x = p_to.x; - old_y = p_to.y; + old_x = p_position.x; + old_y = p_position.y; } else { POINT p; - p.x = p_to.x; - p.y = p_to.y; + p.x = p_position.x; + p.y = p_position.y; ClientToScreen(windows[last_focused_window].hWnd, &p); SetCursorPos(p.x, p.y); @@ -430,9 +430,8 @@ static int QueryDpiForMonitor(HMONITOR hmon, _MonitorDpiType dpiType = MDT_Defau } UINT x = 0, y = 0; - HRESULT hr = E_FAIL; if (hmon && (Shcore != (HMODULE)INVALID_HANDLE_VALUE)) { - hr = getDPIForMonitor(hmon, dpiType /*MDT_Effective_DPI*/, &x, &y); + HRESULT hr = getDPIForMonitor(hmon, dpiType /*MDT_Effective_DPI*/, &x, &y); if (SUCCEEDED(hr) && (x > 0) && (y > 0)) { dpiX = (int)x; dpiY = (int)y; @@ -546,6 +545,9 @@ 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_POPUP_BIT) { + wd.is_popup = 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); @@ -563,13 +565,14 @@ void DisplayServerWindows::show_window(WindowID p_id) { ERR_FAIL_COND(!windows.has(p_id)); WindowData &wd = windows[p_id]; + popup_open(p_id); if (p_id != MAIN_WINDOW_ID) { _update_window_style(p_id); } - ShowWindow(wd.hWnd, wd.no_focus ? SW_SHOWNOACTIVATE : SW_SHOW); // Show the window. - if (!wd.no_focus) { + ShowWindow(wd.hWnd, (wd.no_focus || wd.is_popup) ? SW_SHOWNOACTIVATE : SW_SHOW); // Show the window. + if (!wd.no_focus && !wd.is_popup) { SetForegroundWindow(wd.hWnd); // Slightly higher priority. SetFocus(wd.hWnd); // Set keyboard focus. } @@ -581,6 +584,8 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) { ERR_FAIL_COND(!windows.has(p_window)); ERR_FAIL_COND_MSG(p_window == MAIN_WINDOW_ID, "Main window cannot be deleted."); + popup_close(p_window); + WindowData &wd = windows[p_window]; while (wd.transient_children.size()) { @@ -838,8 +843,8 @@ void DisplayServerWindows::window_set_exclusive(WindowID p_window, bool p_exclus if (wd.exclusive != p_exclusive) { wd.exclusive = p_exclusive; if (wd.transient_parent != INVALID_WINDOW_ID) { - WindowData &wd_parent = windows[wd.transient_parent]; if (wd.exclusive) { + WindowData &wd_parent = windows[wd.transient_parent]; SetWindowLongPtr(wd.hWnd, GWLP_HWNDPARENT, (LONG_PTR)wd_parent.hWnd); } else { SetWindowLongPtr(wd.hWnd, GWLP_HWNDPARENT, (LONG_PTR) nullptr); @@ -1019,6 +1024,7 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre r_style_ex = WS_EX_WINDOWEDGE; if (p_main_window) { r_style_ex |= WS_EX_APPWINDOW; + r_style |= WS_VISIBLE; } if (p_fullscreen || p_borderless) { @@ -1037,13 +1043,15 @@ void DisplayServerWindows::_get_window_style(bool p_main_window, bool p_fullscre r_style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU; } } - if (!p_borderless) { - r_style |= WS_VISIBLE; - } if (p_no_activate_focus) { r_style_ex |= WS_EX_TOPMOST | WS_EX_NOACTIVATE; } + + if (!p_borderless && !p_no_activate_focus) { + r_style |= WS_VISIBLE; + } + r_style |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS; r_style_ex |= WS_EX_ACCEPTFILES; } @@ -1057,12 +1065,12 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain DWORD style = 0; DWORD style_ex = 0; - _get_window_style(p_window == MAIN_WINDOW_ID, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.maximized, wd.no_focus, style, style_ex); + _get_window_style(p_window == MAIN_WINDOW_ID, wd.fullscreen, wd.multiwindow_fs, wd.borderless, wd.resizable, wd.maximized, wd.no_focus || wd.is_popup, style, style_ex); SetWindowLongPtr(wd.hWnd, GWL_STYLE, style); SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex); - SetWindowPos(wd.hWnd, wd.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | (wd.no_focus ? SWP_NOACTIVATE : 0)); + SetWindowPos(wd.hWnd, wd.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | ((wd.no_focus || wd.is_popup) ? SWP_NOACTIVATE : 0)); if (p_repaint) { RECT rect; @@ -1213,6 +1221,7 @@ void DisplayServerWindows::window_set_flag(WindowFlags p_flag, bool p_enabled, W wd.borderless = p_enabled; _update_window_style(p_window); _update_window_mouse_passthrough(p_window); + ShowWindow(wd.hWnd, (wd.no_focus || wd.is_popup) ? SW_SHOWNOACTIVATE : SW_SHOW); // Show the window. } break; case WINDOW_FLAG_ALWAYS_ON_TOP: { ERR_FAIL_COND_MSG(wd.transient_parent != INVALID_WINDOW_ID && p_enabled, "Transient windows can't become on top"); @@ -1226,6 +1235,11 @@ 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_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."); + wd.is_popup = p_enabled; + } break; case WINDOW_FLAG_MAX: break; } @@ -1252,6 +1266,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_POPUP: { + return wd.is_popup; + } break; case WINDOW_FLAG_MAX: break; } @@ -1263,7 +1280,7 @@ void DisplayServerWindows::window_request_attention(WindowID p_window) { _THREAD_SAFE_METHOD_ ERR_FAIL_COND(!windows.has(p_window)); - WindowData &wd = windows[p_window]; + const WindowData &wd = windows[p_window]; FLASHWINFO info; info.cbSize = sizeof(FLASHWINFO); @@ -1280,7 +1297,9 @@ void DisplayServerWindows::window_move_to_foreground(WindowID p_window) { ERR_FAIL_COND(!windows.has(p_window)); WindowData &wd = windows[p_window]; - SetForegroundWindow(wd.hWnd); + if (!wd.no_focus && !wd.is_popup) { + SetForegroundWindow(wd.hWnd); + } } bool DisplayServerWindows::window_can_draw(WindowID p_window) const { @@ -1542,13 +1561,8 @@ void DisplayServerWindows::cursor_set_custom_image(const RES &p_cursor, CursorSh } } - if (hAndMask != nullptr) { - DeleteObject(hAndMask); - } - - if (hXorMask != nullptr) { - DeleteObject(hXorMask); - } + DeleteObject(hAndMask); + DeleteObject(hXorMask); memfree(buffer); DeleteObject(bitmap); @@ -1751,8 +1765,8 @@ void DisplayServerWindows::swap_buffers() { void DisplayServerWindows::set_native_icon(const String &p_filename) { _THREAD_SAFE_METHOD_ - FileAccess *f = FileAccess::open(p_filename, FileAccess::READ); - ERR_FAIL_COND_MSG(!f, "Cannot open file with icon '" + p_filename + "'."); + Ref<FileAccess> f = FileAccess::open(p_filename, FileAccess::READ); + ERR_FAIL_COND_MSG(f.is_null(), "Cannot open file with icon '" + p_filename + "'."); ICONDIR *icon_dir = (ICONDIR *)memalloc(sizeof(ICONDIR)); int pos = 0; @@ -1838,7 +1852,6 @@ void DisplayServerWindows::set_native_icon(const String &p_filename) { err = GetLastError(); ERR_FAIL_COND_MSG(err, "Error setting ICON_BIG: " + format_error_message(err) + "."); - memdelete(f); memdelete(icon_dir); } @@ -1897,16 +1910,14 @@ 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) - // TODO disabling for now - //context_vulkan->set_vsync_mode(p_window, p_vsync_mode); + 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) - //TODO disabling for now - //return context_vulkan->get_vsync_mode(p_window); + return context_vulkan->get_vsync_mode(p_window); #endif return DisplayServer::VSYNC_ENABLED; } @@ -1976,7 +1987,7 @@ void DisplayServerWindows::_send_window_event(const WindowData &wd, WindowEvent } void DisplayServerWindows::_dispatch_input_events(const Ref<InputEvent> &p_event) { - ((DisplayServerWindows *)(get_singleton()))->_dispatch_input_event(p_event); + static_cast<DisplayServerWindows *>(get_singleton())->_dispatch_input_event(p_event); } void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) { @@ -1991,33 +2002,155 @@ void DisplayServerWindows::_dispatch_input_event(const Ref<InputEvent> &p_event) Variant ret; Callable::CallError ce; + { + List<WindowID>::Element *E = popup_list.back(); + if (E && Object::cast_to<InputEventKey>(*p_event)) { + // Redirect keyboard input to active popup. + if (windows.has(E->get())) { + Callable callable = windows[E->get()].input_event_callback; + if (callable.is_valid()) { + callable.call((const Variant **)&evp, 1, ret, ce); + } + } + in_dispatch_input_event = false; + return; + } + } + Ref<InputEventFromWindow> event_from_window = p_event; if (event_from_window.is_valid() && event_from_window->get_window_id() != INVALID_WINDOW_ID) { // Send to a single window. - if (!windows.has(event_from_window->get_window_id())) { - in_dispatch_input_event = false; - ERR_FAIL_MSG("DisplayServerWindows: Invalid window id in input event."); - } - Callable callable = windows[event_from_window->get_window_id()].input_event_callback; - if (callable.is_null()) { - in_dispatch_input_event = false; - return; + if (windows.has(event_from_window->get_window_id())) { + Callable callable = windows[event_from_window->get_window_id()].input_event_callback; + if (callable.is_valid()) { + callable.call((const Variant **)&evp, 1, ret, ce); + } } - callable.call((const Variant **)&evp, 1, ret, ce); } else { // Send to all windows. for (const KeyValue<WindowID, WindowData> &E : windows) { const Callable callable = E.value.input_event_callback; - if (callable.is_null()) { - continue; + if (callable.is_valid()) { + callable.call((const Variant **)&evp, 1, ret, ce); } - callable.call((const Variant **)&evp, 1, ret, ce); } } in_dispatch_input_event = false; } +LRESULT CALLBACK MouseProc(int code, WPARAM wParam, LPARAM lParam) { + DisplayServerWindows *ds_win = static_cast<DisplayServerWindows *>(DisplayServer::get_singleton()); + if (ds_win) { + return ds_win->MouseProc(code, wParam, lParam); + } else { + return ::CallNextHookEx(nullptr, code, wParam, lParam); + } +} + +DisplayServer::WindowID DisplayServerWindows::window_get_active_popup() const { + const List<WindowID>::Element *E = popup_list.back(); + if (E) { + return E->get(); + } else { + return INVALID_WINDOW_ID; + } +} + +void DisplayServerWindows::window_set_popup_safe_rect(WindowID p_window, const Rect2i &p_rect) { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND(!windows.has(p_window)); + WindowData &wd = windows[p_window]; + wd.parent_safe_rect = p_rect; +} + +Rect2i DisplayServerWindows::window_get_popup_safe_rect(WindowID p_window) const { + _THREAD_SAFE_METHOD_ + + ERR_FAIL_COND_V(!windows.has(p_window), Rect2i()); + const WindowData &wd = windows[p_window]; + return wd.parent_safe_rect; +} + +void DisplayServerWindows::popup_open(WindowID p_window) { + _THREAD_SAFE_METHOD_ + + const WindowData &wd = windows[p_window]; + if (wd.is_popup) { + // Find current popup parent, or root popup if new window is not transient. + List<WindowID>::Element *C = nullptr; + List<WindowID>::Element *E = popup_list.back(); + while (E) { + if (wd.transient_parent != E->get() || wd.transient_parent == INVALID_WINDOW_ID) { + C = E; + E = E->prev(); + } else { + break; + } + } + if (C) { + _send_window_event(windows[C->get()], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST); + } + + time_since_popup = OS::get_singleton()->get_ticks_msec(); + popup_list.push_back(p_window); + } +} + +void DisplayServerWindows::popup_close(WindowID p_window) { + _THREAD_SAFE_METHOD_ + + List<WindowID>::Element *E = popup_list.find(p_window); + while (E) { + List<WindowID>::Element *F = E->next(); + WindowID win_id = E->get(); + popup_list.erase(E); + + _send_window_event(windows[win_id], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST); + E = F; + } +} + +LRESULT DisplayServerWindows::MouseProc(int code, WPARAM wParam, LPARAM lParam) { + _THREAD_SAFE_METHOD_ + + uint64_t delta = OS::get_singleton()->get_ticks_msec() - time_since_popup; + if (delta > 250) { + switch (wParam) { + case WM_NCLBUTTONDOWN: + case WM_NCRBUTTONDOWN: + case WM_NCMBUTTONDOWN: + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: { + MOUSEHOOKSTRUCT *ms = (MOUSEHOOKSTRUCT *)lParam; + Point2i pos = Point2i(ms->pt.x, ms->pt.y); + List<WindowID>::Element *C = nullptr; + List<WindowID>::Element *E = popup_list.back(); + // Find top popup to close. + while (E) { + // Popup window area. + Rect2i win_rect = Rect2i(window_get_position(E->get()), window_get_size(E->get())); + // Area of the parent window, which responsible for opening sub-menu. + Rect2i safe_rect = window_get_popup_safe_rect(E->get()); + if (win_rect.has_point(pos)) { + break; + } else if (safe_rect != Rect2i() && safe_rect.has_point(pos)) { + break; + } else { + C = E; + E = E->prev(); + } + } + if (C) { + _send_window_event(windows[C->get()], DisplayServerWindows::WINDOW_EVENT_CLOSE_REQUEST); + } + } break; + } + } + return ::CallNextHookEx(mouse_monitor, code, wParam, lParam); +} + // Our default window procedure to handle processing of window-related system messages/events. // Also known as DefProc or DefWindowProc. // See: https://docs.microsoft.com/en-us/windows/win32/winmsg/window-procedures @@ -2050,6 +2183,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA // Process window messages. switch (uMsg) { + case WM_MOUSEACTIVATE: { + if (windows[window_id].no_focus) { + return MA_NOACTIVATEANDEAT; // Do not activate, and discard mouse messages. + } else if (windows[window_id].is_popup) { + return MA_NOACTIVATE; // Do not activate, but process mouse messages. + } + } break; case WM_SETFOCUS: { windows[window_id].window_has_focus = true; last_focused_window = window_id; @@ -2311,7 +2451,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); old_x = mm->get_position().x; old_y = mm->get_position().y; - if (windows[window_id].window_has_focus) { + if (windows[window_id].window_has_focus || window_get_active_popup() == window_id) { Input::get_singleton()->parse_input_event(mm); } } @@ -2453,7 +2593,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); old_x = mm->get_position().x; old_y = mm->get_position().y; - if (windows[window_id].window_has_focus) { + if (windows[window_id].window_has_focus || window_get_active_popup() == window_id) { Input::get_singleton()->parse_input_event(mm); } @@ -2553,7 +2693,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA mm->set_relative(Vector2(mm->get_position() - Vector2(old_x, old_y))); old_x = mm->get_position().x; old_y = mm->get_position().y; - if (windows[window_id].window_has_focus) { + if (windows[window_id].window_has_focus || window_get_active_popup() == window_id) { Input::get_singleton()->parse_input_event(mm); } @@ -2713,7 +2853,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } } } else { - // For reasons unknown to mankind, wheel comes in screen coordinates. + // For reasons unknown to humanity, wheel comes in screen coordinates. POINT coords; coords.x = mb->get_position().x; coords.y = mb->get_position().y; @@ -3347,7 +3487,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win shift_mem = false; control_mem = false; meta_mem = false; - hInstance = ((OS_Windows *)OS::get_singleton())->get_hinstance(); + hInstance = static_cast<OS_Windows *>(OS::get_singleton())->get_hinstance(); pressrc = 0; old_invalid = true; @@ -3459,11 +3599,12 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win return; } - //gl_manager->set_use_vsync(current_videomode.use_vsync); RasterizerGLES3::make_current(); } #endif + mouse_monitor = SetWindowsHookEx(WH_MOUSE, ::MouseProc, nullptr, GetCurrentThreadId()); + Point2i window_position( (screen_get_size(0).width - p_resolution.width) / 2, (screen_get_size(0).height - p_resolution.height) / 2); @@ -3489,7 +3630,11 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win } #endif - if (!OS::get_singleton()->is_in_low_processor_usage_mode()) { + if (!Engine::get_singleton()->is_editor_hint() && !OS::get_singleton()->is_in_low_processor_usage_mode()) { + // Increase priority for projects that are not in low-processor mode (typically games) + // to reduce the risk of frame stuttering. + // This is not done for the editor to prevent importers or resource bakers + // from making the system unresponsive. SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS); DWORD index = 0; HANDLE handle = AvSetMmThreadCharacteristics("Games", &index); @@ -3510,7 +3655,7 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win r_error = OK; - ((OS_Windows *)OS::get_singleton())->set_main_window(windows[MAIN_WINDOW_ID].hWnd); + static_cast<OS_Windows *>(OS::get_singleton())->set_main_window(windows[MAIN_WINDOW_ID].hWnd); Input::get_singleton()->set_event_dispatch_function(_dispatch_input_events); } @@ -3547,6 +3692,10 @@ DisplayServerWindows::~DisplayServerWindows() { cursors_cache.clear(); + if (mouse_monitor) { + UnhookWindowsHookEx(mouse_monitor); + } + if (user_proc) { SetWindowLongPtr(windows[MAIN_WINDOW_ID].hWnd, GWLP_WNDPROC, (LONG_PTR)user_proc); } diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 7561f9bb77..fcf4b5a728 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -387,9 +387,15 @@ class DisplayServerWindows : public DisplayServer { WindowID transient_parent = INVALID_WINDOW_ID; Set<WindowID> transient_children; + + bool is_popup = false; + Rect2i parent_safe_rect; }; - JoypadWindows *joypad; + JoypadWindows *joypad = nullptr; + HHOOK mouse_monitor = nullptr; + List<WindowID> popup_list; + uint64_t time_since_popup = 0; WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect); WindowID window_id_counter = MAIN_WINDOW_ID; @@ -440,6 +446,10 @@ class DisplayServerWindows : public DisplayServer { public: LRESULT WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + LRESULT MouseProc(int code, WPARAM wParam, LPARAM lParam); + + void popup_open(WindowID p_window); + void popup_close(WindowID p_window); virtual bool has_feature(Feature p_feature) const override; virtual String get_name() const override; @@ -447,7 +457,7 @@ public: virtual void mouse_set_mode(MouseMode p_mode) override; virtual MouseMode mouse_get_mode() const override; - virtual void mouse_warp_to_position(const Point2i &p_to) override; + virtual void warp_mouse(const Point2i &p_position) override; virtual Point2i mouse_get_position() const override; virtual MouseButton mouse_get_button_state() const override; @@ -474,6 +484,10 @@ public: virtual void show_window(WindowID p_window) override; virtual void delete_sub_window(WindowID p_window) override; + virtual WindowID window_get_active_popup() const override; + virtual void window_set_popup_safe_rect(WindowID p_window, const Rect2i &p_rect) override; + virtual Rect2i window_get_popup_safe_rect(WindowID p_window) const override; + virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const override; virtual WindowID get_window_at_screen_position(const Point2i &p_position) const override; diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp index 17a24c08bf..0fa2913218 100644 --- a/platform/windows/export/export.cpp +++ b/platform/windows/export/export.cpp @@ -32,8 +32,6 @@ #include "export_plugin.h" -static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size); - void register_windows_exporter() { EDITOR_DEF("export/windows/rcedit", ""); EditorSettings::get_singleton()->add_property_hint(PropertyInfo(Variant::STRING, "export/windows/rcedit", PROPERTY_HINT_GLOBAL_FILE, "*.exe")); @@ -57,84 +55,7 @@ void register_windows_exporter() { logo->create_from_image(img); platform->set_logo(logo); platform->set_name("Windows Desktop"); - platform->set_extension("exe"); - platform->set_release_32("windows_32_release.exe"); - platform->set_debug_32("windows_32_debug.exe"); - platform->set_release_64("windows_64_release.exe"); - platform->set_debug_64("windows_64_debug.exe"); platform->set_os_name("Windows"); - platform->set_fixup_embedded_pck_func(&fixup_embedded_pck); EditorExport::get_singleton()->add_export_platform(platform); } - -static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { - // Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data - - FileAccess *f = FileAccess::open(p_path, FileAccess::READ_WRITE); - if (!f) { - return ERR_CANT_OPEN; - } - - // Jump to the PE header and check the magic number - { - f->seek(0x3c); - uint32_t pe_pos = f->get_32(); - - f->seek(pe_pos); - uint32_t magic = f->get_32(); - if (magic != 0x00004550) { - f->close(); - return ERR_FILE_CORRUPT; - } - } - - // Process header - - int num_sections; - { - int64_t header_pos = f->get_position(); - - f->seek(header_pos + 2); - num_sections = f->get_16(); - f->seek(header_pos + 16); - uint16_t opt_header_size = f->get_16(); - - // Skip rest of header + optional header to go to the section headers - f->seek(f->get_position() + 2 + opt_header_size); - } - - // Search for the "pck" section - - int64_t section_table_pos = f->get_position(); - - bool found = false; - for (int i = 0; i < num_sections; ++i) { - int64_t section_header_pos = section_table_pos + i * 40; - f->seek(section_header_pos); - - uint8_t section_name[9]; - f->get_buffer(section_name, 8); - section_name[8] = '\0'; - - if (strcmp((char *)section_name, "pck") == 0) { - // "pck" section found, let's patch! - - // Set virtual size to a little to avoid it taking memory (zero would give issues) - f->seek(section_header_pos + 8); - f->store_32(8); - - f->seek(section_header_pos + 16); - f->store_32(p_embedded_size); - f->seek(section_header_pos + 20); - f->store_32(p_embedded_start); - - found = true; - break; - } - } - - f->close(); - - return found ? OK : ERR_FILE_CORRUPT; -} diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 5ebc930735..917a0af90b 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -41,6 +41,18 @@ Error EditorExportPlatformWindows::sign_shared_object(const Ref<EditorExportPres } } +Error EditorExportPlatformWindows::_export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path) { + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE); + ERR_FAIL_COND_V(f.is_null(), ERR_CANT_CREATE); + + f->store_line("@echo off"); + f->store_line("title \"" + p_app_name + "\""); + f->store_line("\"%~dp0" + p_pkg_name + "\" \"%*\""); + f->store_line("pause > nul"); + + return OK; +} + Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) { Error err = EditorExportPlatformPC::export_project(p_preset, p_debug, p_path, p_flags); @@ -54,9 +66,36 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset> err = _code_sign(p_preset, p_path); } + String app_name; + if (String(ProjectSettings::get_singleton()->get("application/config/name")) != "") { + app_name = String(ProjectSettings::get_singleton()->get("application/config/name")); + } else { + app_name = "Unnamed"; + } + app_name = OS::get_singleton()->get_safe_dir_name(app_name); + + // Save console script. + if (err == OK) { + int con_scr = p_preset->get("debug/export_console_script"); + if ((con_scr == 1 && p_debug) || (con_scr == 2)) { + String scr_path = p_path.get_basename() + ".cmd"; + err = _export_debug_script(p_preset, app_name, p_path.get_file(), scr_path); + } + } + return err; } +String EditorExportPlatformWindows::get_template_file_name(const String &p_target, const String &p_arch) const { + return "windows_" + p_arch + "_" + p_target + ".exe"; +} + +List<String> EditorExportPlatformWindows::get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const { + List<String> list; + list.push_back("exe"); + return list; +} + bool EditorExportPlatformWindows::get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const { // This option is not supported by "osslsigncode", used on non-Windows host. if (!OS::get_singleton()->has_feature("windows") && p_option == "codesign/identity_type") { @@ -320,7 +359,7 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p } #ifndef WINDOWS_ENABLED - DirAccessRef tmp_dir = DirAccess::create_for_path(p_path.get_base_dir()); + Ref<DirAccess> tmp_dir = DirAccess::create_for_path(p_path.get_base_dir()); err = tmp_dir->remove(p_path); ERR_FAIL_COND_V(err != OK, err); @@ -374,3 +413,71 @@ bool EditorExportPlatformWindows::can_export(const Ref<EditorExportPreset> &p_pr return valid; } + +Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) const { + // Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data + + Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ_WRITE); + if (f.is_null()) { + return ERR_CANT_OPEN; + } + + // Jump to the PE header and check the magic number + { + f->seek(0x3c); + uint32_t pe_pos = f->get_32(); + + f->seek(pe_pos); + uint32_t magic = f->get_32(); + if (magic != 0x00004550) { + return ERR_FILE_CORRUPT; + } + } + + // Process header + + int num_sections; + { + int64_t header_pos = f->get_position(); + + f->seek(header_pos + 2); + num_sections = f->get_16(); + f->seek(header_pos + 16); + uint16_t opt_header_size = f->get_16(); + + // Skip rest of header + optional header to go to the section headers + f->seek(f->get_position() + 2 + opt_header_size); + } + + // Search for the "pck" section + + int64_t section_table_pos = f->get_position(); + + bool found = false; + for (int i = 0; i < num_sections; ++i) { + int64_t section_header_pos = section_table_pos + i * 40; + f->seek(section_header_pos); + + uint8_t section_name[9]; + f->get_buffer(section_name, 8); + section_name[8] = '\0'; + + if (strcmp((char *)section_name, "pck") == 0) { + // "pck" section found, let's patch! + + // Set virtual size to a little to avoid it taking memory (zero would give issues) + f->seek(section_header_pos + 8); + f->store_32(8); + + f->seek(section_header_pos + 16); + f->store_32(p_embedded_size); + f->seek(section_header_pos + 20); + f->store_32(p_embedded_start); + + found = true; + break; + } + } + + return found ? OK : ERR_FILE_CORRUPT; +} diff --git a/platform/windows/export/export_plugin.h b/platform/windows/export/export_plugin.h index 86e9d49b05..39d1cf4c77 100644 --- a/platform/windows/export/export_plugin.h +++ b/platform/windows/export/export_plugin.h @@ -40,13 +40,17 @@ class EditorExportPlatformWindows : public EditorExportPlatformPC { void _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path); Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path); + Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path); public: virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override; virtual Error sign_shared_object(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path) override; + virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override; virtual void get_export_options(List<ExportOption> *r_options) override; virtual bool get_export_option_visibility(const String &p_option, const Map<StringName, Variant> &p_options) const override; virtual bool can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const override; + virtual String get_template_file_name(const String &p_target, const String &p_arch) const override; + virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) const override; }; #endif diff --git a/platform/windows/gl_manager_windows.h b/platform/windows/gl_manager_windows.h index 6423c54855..dc411983e8 100644 --- a/platform/windows/gl_manager_windows.h +++ b/platform/windows/gl_manager_windows.h @@ -52,19 +52,18 @@ public: private: // any data specific to the window struct GLWindow { - GLWindow() { in_use = false; } - bool in_use; + bool in_use = false; // the external ID .. should match the GL window number .. unused I think - DisplayServer::WindowID window_id; - int width; - int height; + DisplayServer::WindowID window_id = DisplayServer::INVALID_WINDOW_ID; + int width = 0; + int height = 0; // windows specific HDC hDC; HWND hwnd; - int gldisplay_id; + int gldisplay_id = 0; }; struct GLDisplay { @@ -75,7 +74,7 @@ private: LocalVector<GLWindow> _windows; LocalVector<GLDisplay> _displays; - GLWindow *_current_window; + GLWindow *_current_window = nullptr; PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; PFNWGLGETSWAPINTERVALEXTPROC wglGetSwapIntervalEXT; diff --git a/platform/windows/godot.ico b/platform/windows/godot.ico Binary files differindex dd611e07da..25830ffdc6 100644 --- a/platform/windows/godot.ico +++ b/platform/windows/godot.ico diff --git a/platform/windows/joypad_windows.cpp b/platform/windows/joypad_windows.cpp index 494e0b9105..d039fd13a7 100644 --- a/platform/windows/joypad_windows.cpp +++ b/platform/windows/joypad_windows.cpp @@ -250,7 +250,7 @@ void JoypadWindows::setup_joypad_object(const DIDEVICEOBJECTINSTANCE *ob, int p_ } BOOL CALLBACK JoypadWindows::enumCallback(const DIDEVICEINSTANCE *p_instance, void *p_context) { - JoypadWindows *self = (JoypadWindows *)p_context; + JoypadWindows *self = static_cast<JoypadWindows *>(p_context); if (self->is_xinput_device(&p_instance->guidProduct)) { return DIENUM_CONTINUE; } @@ -258,9 +258,9 @@ BOOL CALLBACK JoypadWindows::enumCallback(const DIDEVICEINSTANCE *p_instance, vo return DIENUM_CONTINUE; } -BOOL CALLBACK JoypadWindows::objectsCallback(const DIDEVICEOBJECTINSTANCE *instance, void *context) { - JoypadWindows *self = (JoypadWindows *)context; - self->setup_joypad_object(instance, self->id_to_change); +BOOL CALLBACK JoypadWindows::objectsCallback(const DIDEVICEOBJECTINSTANCE *p_instance, void *p_context) { + JoypadWindows *self = static_cast<JoypadWindows *>(p_context); + self->setup_joypad_object(p_instance, self->id_to_change); return DIENUM_CONTINUE; } @@ -404,7 +404,7 @@ void JoypadWindows::process_joypads() { // on mingw, these constants are not constants int count = 8; - LONG axes[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, (LONG)DIJOFS_SLIDER(0), (LONG)DIJOFS_SLIDER(1) }; + const LONG axes[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, (LONG)DIJOFS_SLIDER(0), (LONG)DIJOFS_SLIDER(1) }; int values[] = { js.lX, js.lY, js.lZ, js.lRx, js.lRy, js.lRz, js.rglSlider[0], js.rglSlider[1] }; for (int j = 0; j < joy->joy_axis.size(); j++) { diff --git a/platform/windows/joypad_windows.h b/platform/windows/joypad_windows.h index 4f15bcf080..d239471a5c 100644 --- a/platform/windows/joypad_windows.h +++ b/platform/windows/joypad_windows.h @@ -105,10 +105,10 @@ private: typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex, XINPUT_STATE *pState); typedef DWORD(WINAPI *XInputSetState_t)(DWORD dwUserIndex, XINPUT_VIBRATION *pVibration); - HWND *hWnd; + HWND *hWnd = nullptr; HANDLE xinput_dll; LPDIRECTINPUT8 dinput; - Input *input; + Input *input = nullptr; int id_to_change; int slider_count; diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 13e3aa7883..b4669e452a 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -264,12 +264,19 @@ OS::Date OS_Windows::get_date(bool p_utc) const { GetLocalTime(&systemtime); } + //Get DST information from Windows, but only if p_utc is false. + TIME_ZONE_INFORMATION info; + bool daylight = false; + if (!p_utc && GetTimeZoneInformation(&info) == TIME_ZONE_ID_DAYLIGHT) { + daylight = true; + } + Date date; date.day = systemtime.wDay; date.month = Month(systemtime.wMonth); date.weekday = Weekday(systemtime.wDayOfWeek); date.year = systemtime.wYear; - date.dst = false; + date.dst = daylight; return date; } @@ -295,16 +302,19 @@ OS::TimeZoneInfo OS_Windows::get_time_zone_info() const { daylight = true; } + // Daylight Bias needs to be added to the bias if DST is in effect, or else it will not properly update. TimeZoneInfo ret; if (daylight) { ret.name = info.DaylightName; + ret.bias = info.Bias + info.DaylightBias; } else { ret.name = info.StandardName; + ret.bias = info.Bias + info.StandardBias; } // Bias value returned by GetTimeZoneInformation is inverted of what we expect // For example, on GMT-3 GetTimeZoneInformation return a Bias of 180, so invert the value to get -180 - ret.bias = -info.Bias; + ret.bias = -ret.bias; return ret; } diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 5bfd24327e..adeecf37c5 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -60,14 +60,14 @@ class JoypadWindows; class OS_Windows : public OS { #ifdef STDOUT_FILE - FILE *stdo; + FILE *stdo = nullptr; #endif uint64_t ticks_start; uint64_t ticks_per_second; HINSTANCE hInstance; - MainLoop *main_loop; + MainLoop *main_loop = nullptr; #ifdef WASAPI_ENABLED AudioDriverWASAPI driver_wasapi; |