From c8de3a54c6bda5dfe5479e5c7c16db3cb9c5a803 Mon Sep 17 00:00:00 2001 From: Markus Sauermann <6299227+Sauermann@users.noreply.github.com> Date: Sun, 9 Jul 2023 23:36:55 +0200 Subject: [PATCH] Expose getters for the currently focused Window Replace the last focused Window by the currently focused Window on Linux, Windows and macOS. --- doc/classes/DisplayServer.xml | 6 ++++++ doc/classes/Viewport.xml | 6 ++++++ platform/linuxbsd/x11/display_server_x11.cpp | 5 +++-- platform/linuxbsd/x11/display_server_x11.h | 4 ++-- platform/macos/display_server_macos.h | 6 +++--- platform/macos/display_server_macos.mm | 6 +++--- platform/macos/godot_window_delegate.mm | 6 ++++-- platform/windows/display_server_windows.cpp | 14 +++++++------- platform/windows/display_server_windows.h | 4 ++-- scene/main/viewport.cpp | 5 +++++ scene/main/viewport.h | 1 + servers/display_server.cpp | 9 +++++++++ servers/display_server.h | 5 +++++ 13 files changed, 56 insertions(+), 21 deletions(-) diff --git a/doc/classes/DisplayServer.xml b/doc/classes/DisplayServer.xml index c2f81ba1094b..72d2537c55e7 100644 --- a/doc/classes/DisplayServer.xml +++ b/doc/classes/DisplayServer.xml @@ -194,6 +194,12 @@ [b]Note:[/b] This doesn't affect native dialogs such as the ones spawned by [method DisplayServer.dialog_show]. + + + + Returns the [method Object.get_instance_id] of the top [Popup] if available or of the currently focused [Window]. + + diff --git a/doc/classes/Viewport.xml b/doc/classes/Viewport.xml index 43640916f442..041d76f94344 100644 --- a/doc/classes/Viewport.xml +++ b/doc/classes/Viewport.xml @@ -104,6 +104,12 @@ [/codeblock] + + + + Returns the top [Popup] if available or the currently focused [Window]. + + diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index f38a9dd27833..6d3f9b6aeebb 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -3741,7 +3741,7 @@ DisplayServer::WindowID DisplayServerX11::_get_focused_window_or_popup() const { return E->get(); } - return last_focused_window; + return currently_focused_window; } void DisplayServerX11::_dispatch_input_events(const Ref &p_event) { @@ -4346,7 +4346,7 @@ void DisplayServerX11::process_events() { } WindowData &wd = windows[window_id]; - last_focused_window = window_id; + currently_focused_window = window_id; wd.focused = true; // Keep track of focus order for overlapping windows. @@ -4401,6 +4401,7 @@ void DisplayServerX11::process_events() { im_selection = Vector2i(); OS_Unix::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE); } + currently_focused_window = INVALID_WINDOW_ID; wd.focused = false; Input::get_singleton()->release_pressed_events(); diff --git a/platform/linuxbsd/x11/display_server_x11.h b/platform/linuxbsd/x11/display_server_x11.h index 71beddce7623..70811fd15f71 100644 --- a/platform/linuxbsd/x11/display_server_x11.h +++ b/platform/linuxbsd/x11/display_server_x11.h @@ -226,7 +226,7 @@ class DisplayServerX11 : public DisplayServer { List popup_list; WindowID window_mouseover_id = INVALID_WINDOW_ID; - WindowID last_focused_window = INVALID_WINDOW_ID; + WindowID currently_focused_window = INVALID_WINDOW_ID; WindowID window_id_counter = MAIN_WINDOW_ID; WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, uint32_t p_flags, const Rect2i &p_rect); @@ -348,7 +348,7 @@ class DisplayServerX11 : public DisplayServer { Context context = CONTEXT_ENGINE; - WindowID _get_focused_window_or_popup() const; + virtual WindowID _get_focused_window_or_popup() const override; void _send_window_event(const WindowData &wd, WindowEvent p_event); static void _dispatch_input_events(const Ref &p_event); diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index 69f600804353..d8ba57947bd7 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -172,7 +172,7 @@ class DisplayServerMacOS : public DisplayServer { bool keyboard_layout_dirty = true; WindowID window_mouseover_id = INVALID_WINDOW_ID; - WindowID last_focused_window = INVALID_WINDOW_ID; + WindowID currently_focused_window = INVALID_WINDOW_ID; WindowID window_id_counter = MAIN_WINDOW_ID; float display_max_scale = 1.f; Point2i origin; @@ -233,14 +233,14 @@ class DisplayServerMacOS : public DisplayServer { void push_to_key_event_buffer(const KeyEvent &p_event); void pop_last_key_event(); void update_im_text(const Point2i &p_selection, const String &p_text); - void set_last_focused_window(WindowID p_window); + void set_currently_focused_window(WindowID p_window); bool mouse_process_popups(bool p_close = false); void popup_open(WindowID p_window); void popup_close(WindowID p_window); void set_is_resizing(bool p_is_resizing); bool get_is_resizing() const; void reparent_check(WindowID p_window); - WindowID _get_focused_window_or_popup() const; + virtual WindowID _get_focused_window_or_popup() const override; void mouse_enter_window(WindowID p_window); void mouse_exit_window(WindowID p_window); diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index e79d6acc3f89..d91521be63ca 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -363,7 +363,7 @@ return E->get(); } - return last_focused_window; + return currently_focused_window; } void DisplayServerMacOS::mouse_enter_window(WindowID p_window) { @@ -718,8 +718,8 @@ OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_OS_IME_UPDATE); } -void DisplayServerMacOS::set_last_focused_window(WindowID p_window) { - last_focused_window = p_window; +void DisplayServerMacOS::set_currently_focused_window(WindowID p_window) { + currently_focused_window = p_window; } void DisplayServerMacOS::set_is_resizing(bool p_is_resizing) { diff --git a/platform/macos/godot_window_delegate.mm b/platform/macos/godot_window_delegate.mm index 46355b4ae8fa..8c3e06f54625 100644 --- a/platform/macos/godot_window_delegate.mm +++ b/platform/macos/godot_window_delegate.mm @@ -316,7 +316,7 @@ - (void)windowDidBecomeKey:(NSNotification *)notification { [self windowDidResize:notification]; // Emit resize event, to ensure content is resized if the window was resized while it was hidden. wd.focused = true; - ds->set_last_focused_window(window_id); + ds->set_currently_focused_window(window_id); ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN); } @@ -333,6 +333,7 @@ - (void)windowDidResignKey:(NSNotification *)notification { } wd.focused = false; + ds->set_currently_focused_window(DisplayServerMacOS::INVALID_WINDOW_ID); ds->release_pressed_events(); ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT); } @@ -346,6 +347,7 @@ - (void)windowDidMiniaturize:(NSNotification *)notification { DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); wd.focused = false; + ds->set_currently_focused_window(DisplayServerMacOS::INVALID_WINDOW_ID); ds->release_pressed_events(); ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_OUT); } @@ -359,7 +361,7 @@ - (void)windowDidDeminiaturize:(NSNotification *)notification { DisplayServerMacOS::WindowData &wd = ds->get_window(window_id); if ([wd.window_object isKeyWindow]) { wd.focused = true; - ds->set_last_focused_window(window_id); + ds->set_currently_focused_window(window_id); ds->send_window_event(wd, DisplayServerMacOS::WINDOW_EVENT_FOCUS_IN); } } diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 5863a75324ff..94016e23481e 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -158,7 +158,7 @@ DisplayServer::WindowID DisplayServerWindows::_get_focused_window_or_popup() con return E->get(); } - return last_focused_window; + return currently_focused_window; } void DisplayServerWindows::_register_raw_input_devices(WindowID p_target_window) { @@ -476,10 +476,10 @@ String DisplayServerWindows::clipboard_get() const { Ref DisplayServerWindows::clipboard_get_image() const { Ref image; - if (!windows.has(last_focused_window)) { + if (!windows.has(currently_focused_window)) { return image; // No focused window? } - if (!OpenClipboard(windows[last_focused_window].hWnd)) { + if (!OpenClipboard(windows[currently_focused_window].hWnd)) { ERR_FAIL_V_MSG(image, "Unable to open clipboard."); } UINT png_format = RegisterClipboardFormatA("PNG"); @@ -1082,8 +1082,8 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) { DestroyWindow(windows[p_window].hWnd); windows.erase(p_window); - if (last_focused_window == p_window) { - last_focused_window = INVALID_WINDOW_ID; + if (currently_focused_window == p_window) { + currently_focused_window = INVALID_WINDOW_ID; } } @@ -2843,7 +2843,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } break; case WM_SETFOCUS: { windows[window_id].window_has_focus = true; - last_focused_window = window_id; + currently_focused_window = window_id; // Restore mouse mode. _set_mouse_mode_impl(mouse_mode); @@ -2857,7 +2857,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } break; case WM_KILLFOCUS: { windows[window_id].window_has_focus = false; - last_focused_window = window_id; + currently_focused_window = INVALID_WINDOW_ID; // Release capture unconditionally because it can be set due to dragging, in addition to captured mode. ReleaseCapture(); diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 59c444260410..89a1c8a38a6f 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -438,7 +438,7 @@ class DisplayServerWindows : public DisplayServer { WindowID window_id_counter = MAIN_WINDOW_ID; RBMap windows; - WindowID last_focused_window = INVALID_WINDOW_ID; + WindowID currently_focused_window = INVALID_WINDOW_ID; HCURSOR hCursor; @@ -476,7 +476,7 @@ class DisplayServerWindows : public DisplayServer { void _update_real_mouse_position(WindowID p_window); void _set_mouse_mode_impl(MouseMode p_mode); - WindowID _get_focused_window_or_popup() const; + virtual WindowID _get_focused_window_or_popup() const override; void _register_raw_input_devices(WindowID p_target_window); void _process_activate_event(WindowID p_window_id, WPARAM wParam, LPARAM lParam); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index dac600d5d9a9..a78c520d584f 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2450,6 +2450,10 @@ Window *Viewport::get_base_window() const { return w; } +Window *Viewport::get_top_popup_or_focused_window() const { + return gui.subwindow_focused; +} + void Viewport::_gui_remove_focus_for_window(Node *p_window) { if (get_base_window() == p_window) { gui_release_focus(); @@ -4427,6 +4431,7 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_embedding_subwindows", "enable"), &Viewport::set_embedding_subwindows); ClassDB::bind_method(D_METHOD("is_embedding_subwindows"), &Viewport::is_embedding_subwindows); ClassDB::bind_method(D_METHOD("get_embedded_subwindows"), &Viewport::get_embedded_subwindows); + ClassDB::bind_method(D_METHOD("get_top_popup_or_focused_window"), &Viewport::get_top_popup_or_focused_window); ClassDB::bind_method(D_METHOD("set_canvas_cull_mask", "mask"), &Viewport::set_canvas_cull_mask); ClassDB::bind_method(D_METHOD("get_canvas_cull_mask"), &Viewport::get_canvas_cull_mask); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 6fb9a6c510cd..665e73ee1d73 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -662,6 +662,7 @@ class Viewport : public Node { Viewport *get_parent_viewport() const; Window *get_base_window() const; + Window *get_top_popup_or_focused_window() const; void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control); diff --git a/servers/display_server.cpp b/servers/display_server.cpp index f41238b07547..26f157b75ad0 100644 --- a/servers/display_server.cpp +++ b/servers/display_server.cpp @@ -435,6 +435,14 @@ void DisplayServer::delete_sub_window(WindowID p_id) { ERR_FAIL_MSG("Sub-windows not supported by this display server."); } +ObjectID DisplayServer::get_top_popup_or_focused_window() const { + WindowID wid = _get_focused_window_or_popup(); + if (wid == INVALID_WINDOW_ID) { + return ObjectID(); + } + return window_get_attached_instance_id(wid); +} + void DisplayServer::window_set_exclusive(WindowID p_window, bool p_exclusive) { // Do nothing, if not supported. } @@ -689,6 +697,7 @@ void DisplayServer::_bind_methods() { ClassDB::bind_method(D_METHOD("get_window_list"), &DisplayServer::get_window_list); ClassDB::bind_method(D_METHOD("get_window_at_screen_position", "position"), &DisplayServer::get_window_at_screen_position); + ClassDB::bind_method(D_METHOD("get_top_popup_or_focused_window"), &DisplayServer::get_top_popup_or_focused_window); ClassDB::bind_method(D_METHOD("window_get_native_handle", "handle_type", "window_id"), &DisplayServer::window_get_native_handle, DEFVAL(MAIN_WINDOW_ID)); ClassDB::bind_method(D_METHOD("window_get_active_popup"), &DisplayServer::window_get_active_popup); diff --git a/servers/display_server.h b/servers/display_server.h index 85f92706965e..1ac500ea386b 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -330,6 +330,10 @@ class DisplayServer : public Object { typedef int WindowID; +private: + virtual WindowID _get_focused_window_or_popup() const { return MAIN_WINDOW_ID; }; + +public: virtual Vector get_window_list() const = 0; enum WindowFlags { @@ -367,6 +371,7 @@ class DisplayServer : public Object { virtual int64_t window_get_native_handle(HandleType p_handle_type, WindowID p_window = MAIN_WINDOW_ID) const; virtual WindowID get_window_at_screen_position(const Point2i &p_position) const = 0; + ObjectID get_top_popup_or_focused_window() const; virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) = 0; virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const = 0;