From 21a392341034169fff18db626e1c356545289af5 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Thu, 28 Nov 2019 13:41:07 +0100 Subject: [PATCH] Add an `OS.is_window_focused()` getter This makes it possible to know whether the window is focused at a given time, without having to track the focus state manually using `NOTIFICATION_WM_FOCUS_IN` and `NOTIFICATION_WM_FOCUS_OUT`. This partially addresses #33928. --- core/bind/core_bind.cpp | 5 +++++ core/bind/core_bind.h | 1 + core/os/os.h | 1 + doc/classes/OS.xml | 8 ++++++++ platform/osx/os_osx.h | 2 ++ platform/osx/os_osx.mm | 18 +++++++++++++----- platform/windows/os_windows.cpp | 8 ++++++++ platform/windows/os_windows.h | 2 ++ platform/x11/os_x11.cpp | 8 ++++++++ platform/x11/os_x11.h | 2 ++ 10 files changed, 50 insertions(+), 5 deletions(-) diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp index 1544503045..082c220aec 100644 --- a/core/bind/core_bind.cpp +++ b/core/bind/core_bind.cpp @@ -400,6 +400,10 @@ bool _OS::is_window_always_on_top() const { return OS::get_singleton()->is_window_always_on_top(); } +bool _OS::is_window_focused() const { + return OS::get_singleton()->is_window_focused(); +} + void _OS::set_borderless_window(bool p_borderless) { OS::get_singleton()->set_borderless_window(p_borderless); } @@ -1213,6 +1217,7 @@ void _OS::_bind_methods() { ClassDB::bind_method(D_METHOD("is_window_maximized"), &_OS::is_window_maximized); ClassDB::bind_method(D_METHOD("set_window_always_on_top", "enabled"), &_OS::set_window_always_on_top); ClassDB::bind_method(D_METHOD("is_window_always_on_top"), &_OS::is_window_always_on_top); + ClassDB::bind_method(D_METHOD("is_window_focused"), &_OS::is_window_focused); ClassDB::bind_method(D_METHOD("request_attention"), &_OS::request_attention); ClassDB::bind_method(D_METHOD("get_real_window_size"), &_OS::get_real_window_size); ClassDB::bind_method(D_METHOD("center_window"), &_OS::center_window); diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h index 18182860c6..06fd162149 100644 --- a/core/bind/core_bind.h +++ b/core/bind/core_bind.h @@ -198,6 +198,7 @@ public: virtual bool is_window_maximized() const; virtual void set_window_always_on_top(bool p_enabled); virtual bool is_window_always_on_top() const; + virtual bool is_window_focused() const; virtual void request_attention(); virtual void center_window(); virtual void move_window_to_foreground(); diff --git a/core/os/os.h b/core/os/os.h index 687ccaaba5..d4d8a6f415 100644 --- a/core/os/os.h +++ b/core/os/os.h @@ -217,6 +217,7 @@ public: virtual bool is_window_maximized() const { return true; } virtual void set_window_always_on_top(bool p_enabled) {} virtual bool is_window_always_on_top() const { return false; } + virtual bool is_window_focused() const { return true; } virtual void set_console_visible(bool p_enabled) {} virtual bool is_console_visible() const { return false; } virtual void request_attention() {} diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml index 6da0547352..df96954902 100644 --- a/doc/classes/OS.xml +++ b/doc/classes/OS.xml @@ -636,6 +636,14 @@ Returns [code]true[/code] if the window should always be on top of other windows. + + + + + Returns [code]true[/code] if the window is currently focused. + [b]Note:[/b] Only implemented on desktop platforms. On other platforms, it will always return [code]true[/code]. + + diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h index a61b9234d1..61fa7ef27c 100644 --- a/platform/osx/os_osx.h +++ b/platform/osx/os_osx.h @@ -124,6 +124,7 @@ public: bool maximized; bool zoomed; bool resizable; + bool window_focused; Size2 window_size; Rect2 restore_rect; @@ -277,6 +278,7 @@ public: virtual bool is_window_maximized() const; virtual void set_window_always_on_top(bool p_enabled); virtual bool is_window_always_on_top() const; + virtual bool is_window_focused() const; virtual void request_attention(); virtual String get_joy_guid(int p_device) const; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index dac6721fb4..17836e9f94 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -397,9 +397,6 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto } - (void)windowDidBecomeKey:(NSNotification *)notification { - //_GodotInputWindowFocus(window, GL_TRUE); - //_GodotPlatformSetCursorMode(window, window->cursorMode); - if (OS_OSX::singleton->get_main_loop()) { get_mouse_pos( [OS_OSX::singleton->window_object mouseLocationOutsideOfEventStream], @@ -408,25 +405,31 @@ static Vector2 get_mouse_pos(NSPoint locationInWindow, CGFloat backingScaleFacto OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); } + + OS_OSX::singleton->window_focused = true; } - (void)windowDidResignKey:(NSNotification *)notification { - //_GodotInputWindowFocus(window, GL_FALSE); - //_GodotPlatformSetCursorMode(window, Godot_CURSOR_NORMAL); if (OS_OSX::singleton->get_main_loop()) OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); + + OS_OSX::singleton->window_focused = false; } - (void)windowDidMiniaturize:(NSNotification *)notification { OS_OSX::singleton->wm_minimized(true); if (OS_OSX::singleton->get_main_loop()) OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); + + OS_OSX::singleton->window_focused = false; }; - (void)windowDidDeminiaturize:(NSNotification *)notification { OS_OSX::singleton->wm_minimized(false); if (OS_OSX::singleton->get_main_loop()) OS_OSX::singleton->get_main_loop()->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); + + OS_OSX::singleton->window_focused = true; }; @end @@ -2618,6 +2621,10 @@ bool OS_OSX::is_window_always_on_top() const { return [window_object level] == NSFloatingWindowLevel; } +bool OS_OSX::is_window_focused() const { + return window_focused; +} + void OS_OSX::request_attention() { [NSApp requestUserAttention:NSCriticalRequest]; @@ -3070,6 +3077,7 @@ OS_OSX::OS_OSX() { window_size = Vector2(1024, 600); zoomed = false; resizable = false; + window_focused = true; Vector loggers; loggers.push_back(memnew(OSXTerminalLogger)); diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index 429657f332..0eddde077e 100755 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -352,12 +352,14 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) { main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); + window_focused = true; alt_mem = false; control_mem = false; shift_mem = false; } else { // WM_INACTIVE input->release_pressed_events(); main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); + window_focused = false; alt_mem = false; }; @@ -2097,6 +2099,11 @@ bool OS_Windows::is_window_always_on_top() const { return video_mode.always_on_top; } +bool OS_Windows::is_window_focused() const { + + return window_focused; +} + void OS_Windows::set_console_visible(bool p_enabled) { if (console_visible == p_enabled) return; @@ -3374,6 +3381,7 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) { meta_mem = false; minimized = false; was_maximized = false; + window_focused = true; console_visible = IsWindowVisible(GetConsoleWindow()); //Note: Functions for pen input, available on Windows 8+ diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index ce279fb033..fbd5961379 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -276,6 +276,7 @@ protected: bool maximized; bool minimized; bool borderless; + bool window_focused; bool console_visible; bool was_maximized; @@ -324,6 +325,7 @@ public: virtual bool is_window_maximized() const; virtual void set_window_always_on_top(bool p_enabled); virtual bool is_window_always_on_top() const; + virtual bool is_window_focused() const; virtual void set_console_visible(bool p_enabled); virtual bool is_console_visible() const; virtual void request_attention(); diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index 54d3759cc5..d4b7538fc8 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1689,6 +1689,10 @@ bool OS_X11::is_window_always_on_top() const { return current_videomode.always_on_top; } +bool OS_X11::is_window_focused() const { + return window_focused; +} + void OS_X11::set_borderless_window(bool p_borderless) { if (get_borderless_window() == p_borderless) @@ -2281,6 +2285,8 @@ void OS_X11::process_xevents() { minimized = false; window_has_focus = true; main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_IN); + window_focused = true; + if (mouse_mode_grab) { // Show and update the cursor if confined and the window regained focus. if (mouse_mode == MOUSE_MODE_CONFINED) @@ -2308,6 +2314,7 @@ void OS_X11::process_xevents() { window_has_focus = false; input->release_pressed_events(); main_loop->notification(MainLoop::NOTIFICATION_WM_FOCUS_OUT); + window_focused = false; if (mouse_mode_grab) { //dear X11, I try, I really try, but you never work, you do whathever you want. @@ -3502,6 +3509,7 @@ OS_X11::OS_X11() { xi.last_relative_time = 0; layered_window = false; minimized = false; + window_focused = true; xim_style = 0L; mouse_mode = MOUSE_MODE_VISIBLE; } diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h index a5576f4402..178598d3c7 100644 --- a/platform/x11/os_x11.h +++ b/platform/x11/os_x11.h @@ -198,6 +198,7 @@ class OS_X11 : public OS_Unix { int video_driver_index; bool maximized; + bool window_focused; //void set_wm_border(bool p_enabled); void set_wm_fullscreen(bool p_enabled); void set_wm_above(bool p_enabled); @@ -287,6 +288,7 @@ public: virtual bool is_window_maximized() const; virtual void set_window_always_on_top(bool p_enabled); virtual bool is_window_always_on_top() const; + virtual bool is_window_focused() const; virtual void request_attention(); virtual void set_borderless_window(bool p_borderless);