From b965ad198bc65700b17b4b1c5652d8a3ddbc756b Mon Sep 17 00:00:00 2001 From: Foaly Date: Sun, 12 Jan 2014 16:26:21 +0100 Subject: [PATCH 1/8] Added window methods to request and to check focus Signed-off-by: Stefan Schindler Signed-off-by: Jan Haller --- include/SFML/Window/Window.hpp | 32 +++++++++++++++ src/SFML/Window/OSX/WindowImplCocoa.hpp | 17 ++++++++ src/SFML/Window/OSX/WindowImplCocoa.mm | 14 +++++++ src/SFML/Window/Unix/WindowImplX11.cpp | 50 ++++++++++++++++------- src/SFML/Window/Unix/WindowImplX11.hpp | 17 ++++++++ src/SFML/Window/Win32/WindowImplWin32.cpp | 14 +++++++ src/SFML/Window/Win32/WindowImplWin32.hpp | 17 ++++++++ src/SFML/Window/Window.cpp | 19 +++++++++ src/SFML/Window/WindowImpl.hpp | 17 ++++++++ 9 files changed, 182 insertions(+), 15 deletions(-) diff --git a/include/SFML/Window/Window.hpp b/include/SFML/Window/Window.hpp index 2076f8e09..3a98971d2 100644 --- a/include/SFML/Window/Window.hpp +++ b/include/SFML/Window/Window.hpp @@ -403,6 +403,7 @@ public: /// on the previous thread first if it was active. /// Only one window can be active on a thread at a time, thus /// the window previously active (if any) automatically gets deactivated. + /// This is not to be confused with requestFocus(). /// /// \param active True to activate, false to deactivate /// @@ -411,6 +412,37 @@ public: //////////////////////////////////////////////////////////// bool setActive(bool active = true) const; + //////////////////////////////////////////////////////////// + /// \brief Request the current window to be made the active + /// foreground window + /// + /// At any given time, only one window may have the input focus + /// to receive input events such as keystrokes or mouse + /// events. + /// If a window requests focus, it only hints to the operating + /// system, that it would like to be focused. The operating system + /// is free to deny the request. For example under Windows OS + /// windows are not allowed to steal focus. But the user + /// will be notified through a flashing taskbar button. + /// This is not to be confused with setActive(). + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + bool requestFocus(); + + //////////////////////////////////////////////////////////// + /// \brief Determine whether the window has the input focus + /// + /// At any given time, only one window may have the input focus + /// to receive input events such as keystrokes or most mouse + /// events. + /// + /// \return True if window has focus, false otherwise + /// + //////////////////////////////////////////////////////////// + bool hasFocus() const; + //////////////////////////////////////////////////////////// /// \brief Display on screen what has been rendered to the window so far /// diff --git a/src/SFML/Window/OSX/WindowImplCocoa.hpp b/src/SFML/Window/OSX/WindowImplCocoa.hpp index 723fee71d..f65d63ed7 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.hpp +++ b/src/SFML/Window/OSX/WindowImplCocoa.hpp @@ -320,6 +320,23 @@ public: //////////////////////////////////////////////////////////// virtual void setKeyRepeatEnabled(bool enabled); + //////////////////////////////////////////////////////////// + /// \brief Request the current window to be made the active + /// foreground window + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool requestFocus(); + + //////////////////////////////////////////////////////////// + /// \brief Determine whether the window has the input focus + /// + /// \return True if window has focus, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool hasFocus() const; + protected: //////////////////////////////////////////////////////////// diff --git a/src/SFML/Window/OSX/WindowImplCocoa.mm b/src/SFML/Window/OSX/WindowImplCocoa.mm index 6b1c8be16..5dbf0f460 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.mm +++ b/src/SFML/Window/OSX/WindowImplCocoa.mm @@ -552,6 +552,20 @@ void WindowImplCocoa::setKeyRepeatEnabled(bool enabled) } +//////////////////////////////////////////////////////////// +bool WindowImplCocoa::requestFocus() +{ + return [m_delegate requestFocus]; +} + + +//////////////////////////////////////////////////////////// +bool WindowImplCocoa::hasFocus() const +{ + return [m_delegate hasFocus]; +} + + } // namespace priv } // namespace sf diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index a9f2f0c3a..7efacc192 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -192,7 +192,7 @@ m_useSizeHints(false) { static const unsigned long MWM_HINTS_FUNCTIONS = 1 << 0; static const unsigned long MWM_HINTS_DECORATIONS = 1 << 1; - + //static const unsigned long MWM_DECOR_ALL = 1 << 0; static const unsigned long MWM_DECOR_BORDER = 1 << 1; static const unsigned long MWM_DECOR_RESIZEH = 1 << 2; @@ -207,7 +207,7 @@ m_useSizeHints(false) static const unsigned long MWM_FUNC_MINIMIZE = 1 << 3; static const unsigned long MWM_FUNC_MAXIMIZE = 1 << 4; static const unsigned long MWM_FUNC_CLOSE = 1 << 5; - + struct WMHints { unsigned long flags; @@ -216,7 +216,7 @@ m_useSizeHints(false) long inputMode; unsigned long state; }; - + WMHints hints; hints.flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS; hints.decorations = 0; @@ -250,11 +250,11 @@ m_useSizeHints(false) sizeHints->flags = PMinSize | PMaxSize; sizeHints->min_width = sizeHints->max_width = width; sizeHints->min_height = sizeHints->max_height = height; - XSetWMNormalHints(m_display, m_window, sizeHints); + XSetWMNormalHints(m_display, m_window, sizeHints); XFree(sizeHints); } } - + // Set the window's WM class (this can be used by window managers) char windowClass[512]; findExecutableName(windowClass, sizeof(windowClass)); @@ -365,7 +365,7 @@ void WindowImplX11::setSize(const Vector2u& size) sizeHints->flags = PMinSize | PMaxSize; sizeHints->min_width = sizeHints->max_width = size.x; sizeHints->min_height = sizeHints->max_height = size.y; - XSetWMNormalHints(m_display, m_window, sizeHints); + XSetWMNormalHints(m_display, m_window, sizeHints); XFree(sizeHints); } @@ -379,17 +379,17 @@ void WindowImplX11::setTitle(const String& title) { // Bare X11 has no Unicode window title support. // There is however an option to tell the window manager your unicode title via hints. - + // Convert to UTF-8 encoding. std::basic_string utf8Title; Utf32::toUtf8(title.begin(), title.end(), std::back_inserter(utf8Title)); - + // Set the _NET_WM_NAME atom, which specifies a UTF-8 encoded window title. Atom wmName = XInternAtom(m_display, "_NET_WM_NAME", False); Atom useUtf8 = XInternAtom(m_display, "UTF8_STRING", False); XChangeProperty(m_display, m_window, wmName, useUtf8, 8, PropModeReplace, utf8Title.c_str(), utf8Title.size()); - + // Set the non-Unicode title as a fallback for window managers who don't support _NET_WM_NAME. XStoreName(m_display, m_window, title.toAnsiString().c_str()); } @@ -437,7 +437,7 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8 if (i * 8 + k < width) { Uint8 opacity = (pixels[(i * 8 + k + j * width) * 4 + 3] > 0) ? 1 : 0; - maskPixels[i + j * pitch] |= (opacity << k); + maskPixels[i + j * pitch] |= (opacity << k); } } } @@ -483,6 +483,26 @@ void WindowImplX11::setKeyRepeatEnabled(bool enabled) } +//////////////////////////////////////////////////////////// +bool WindowImplX11::requestFocus() +{ + XRaiseWindow(m_display, m_window); + XSetInputFocus(m_display, m_window, RevertToPointerRoot, CurrentTime); + return true; +} + + +//////////////////////////////////////////////////////////// +bool WindowImplX11::hasFocus() const +{ + ::Window focusedWindow = 0; + int revertToReturn = 0; + XGetInputFocus(m_display, &focusedWindow, &revertToReturn); + + return m_window == focusedWindow; +} + + //////////////////////////////////////////////////////////// void WindowImplX11::switchToFullscreen(const VideoMode& mode) { @@ -599,7 +619,7 @@ void WindowImplX11::cleanup() { // Get current screen info XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen)); - if (config) + if (config) { // Get the current rotation Rotation currentRotation; @@ -610,7 +630,7 @@ void WindowImplX11::cleanup() // Free the configuration instance XRRFreeScreenConfigInfo(config); - } + } // Reset the fullscreen window fullscreenWindow = NULL; @@ -717,7 +737,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) // Close event case ClientMessage: { - if ((windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(m_atomClose)) + if ((windowEvent.xclient.format == 32) && (windowEvent.xclient.data.l[0]) == static_cast(m_atomClose)) { Event event; event.type = Event::Closed; @@ -823,7 +843,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) case Button2: event.mouseButton.button = Mouse::Middle; break; case Button3: event.mouseButton.button = Mouse::Right; break; case 8: event.mouseButton.button = Mouse::XButton1; break; - case 9: event.mouseButton.button = Mouse::XButton2; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } @@ -846,7 +866,7 @@ bool WindowImplX11::processEvent(XEvent windowEvent) case Button2: event.mouseButton.button = Mouse::Middle; break; case Button3: event.mouseButton.button = Mouse::Right; break; case 8: event.mouseButton.button = Mouse::XButton1; break; - case 9: event.mouseButton.button = Mouse::XButton2; break; + case 9: event.mouseButton.button = Mouse::XButton2; break; } pushEvent(event); } diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp index 7e2b48526..0605cdf9a 100644 --- a/src/SFML/Window/Unix/WindowImplX11.hpp +++ b/src/SFML/Window/Unix/WindowImplX11.hpp @@ -154,6 +154,23 @@ public: //////////////////////////////////////////////////////////// virtual void setKeyRepeatEnabled(bool enabled); + //////////////////////////////////////////////////////////// + /// \brief Request the current window to be made the active + /// foreground window + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool requestFocus(); + + //////////////////////////////////////////////////////////// + /// \brief Determine whether the window has the input focus + /// + /// \return True if window has focus, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool hasFocus() const; + protected: //////////////////////////////////////////////////////////// diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index 6d9ac28c0..32aec6daf 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -366,6 +366,20 @@ void WindowImplWin32::setKeyRepeatEnabled(bool enabled) } +//////////////////////////////////////////////////////////// +bool WindowImplWin32::requestFocus() +{ + return SetForegroundWindow(m_handle); +} + + +//////////////////////////////////////////////////////////// +bool WindowImplWin32::hasFocus() const +{ + return m_handle == GetForegroundWindow(); +} + + //////////////////////////////////////////////////////////// void WindowImplWin32::registerWindowClass() { diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp index 3678d79e2..e95bfa9fb 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.hpp +++ b/src/SFML/Window/Win32/WindowImplWin32.hpp @@ -153,6 +153,23 @@ public: //////////////////////////////////////////////////////////// virtual void setKeyRepeatEnabled(bool enabled); + //////////////////////////////////////////////////////////// + /// \brief Request the current window to be made the active + /// foreground window + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool requestFocus(); + + //////////////////////////////////////////////////////////// + /// \brief Determine whether the window has the input focus + /// + /// \return True if window has focus, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool hasFocus() const; + protected: //////////////////////////////////////////////////////////// diff --git a/src/SFML/Window/Window.cpp b/src/SFML/Window/Window.cpp index 397cbbf2d..574c0549b 100644 --- a/src/SFML/Window/Window.cpp +++ b/src/SFML/Window/Window.cpp @@ -337,6 +337,25 @@ bool Window::setActive(bool active) const //////////////////////////////////////////////////////////// +bool Window::requestFocus() +{ + if (m_impl) + return m_impl->requestFocus(); + return false; +} + + +//////////////////////////////////////////////////////////// +bool Window::hasFocus() const +{ + if (m_impl) + return m_impl->hasFocus(); + return false; +} + + +//////////////////////////////////////////////////////////// + void Window::display() { // Display the backbuffer on screen diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp index b4d715edd..50ef17237 100644 --- a/src/SFML/Window/WindowImpl.hpp +++ b/src/SFML/Window/WindowImpl.hpp @@ -194,6 +194,23 @@ public: //////////////////////////////////////////////////////////// virtual void setKeyRepeatEnabled(bool enabled) = 0; + //////////////////////////////////////////////////////////// + /// \brief Request the current window to be made the active + /// foreground window + /// + /// \return True if operation was successful, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool requestFocus() = 0; + + //////////////////////////////////////////////////////////// + /// \brief Determine whether the window has the input focus + /// + /// \return True if window has focus, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool hasFocus() const = 0; + protected: //////////////////////////////////////////////////////////// From 85291debb45b907630ed36e86c30da435e1bf46d Mon Sep 17 00:00:00 2001 From: Marco Antognini Date: Wed, 23 Apr 2014 11:26:44 +0200 Subject: [PATCH 2/8] Added OS X impl of requestFocus and hasFocus Signed-off-by: Foaly Signed-off-by: Jan Haller --- src/SFML/Window/OSX/SFViewController.mm | 22 +++++++++++++++++++ src/SFML/Window/OSX/SFWindowController.mm | 19 ++++++++++++++++ .../Window/OSX/WindowImplDelegateProtocol.h | 17 ++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/src/SFML/Window/OSX/SFViewController.mm b/src/SFML/Window/OSX/SFViewController.mm index 2b7676914..a2898da84 100644 --- a/src/SFML/Window/OSX/SFViewController.mm +++ b/src/SFML/Window/OSX/SFViewController.mm @@ -187,6 +187,28 @@ } +//////////////////////////////////////////////////////// +-(BOOL)requestFocus +{ + // Note: this doesn't imply that the view will get any event. + // The user has to make sure events are forwarded to the view + // with the usual responder chain. + [[m_view window] makeKeyAndOrderFront:nil]; + + // In case the app is not active, make its dock icon bounce for one sec + [NSApp requestUserAttention:NSInformationalRequest]; + + return [self hasFocus]; +} + + +//////////////////////////////////////////////////////////// +-(BOOL)hasFocus +{ + return [NSApp keyWindow] == [m_view window]; +} + + //////////////////////////////////////////////////////// -(void)enableKeyRepeat { diff --git a/src/SFML/Window/OSX/SFWindowController.mm b/src/SFML/Window/OSX/SFWindowController.mm index 1b0a0de7c..2fae92592 100644 --- a/src/SFML/Window/OSX/SFWindowController.mm +++ b/src/SFML/Window/OSX/SFWindowController.mm @@ -451,6 +451,25 @@ } +//////////////////////////////////////////////////////// +-(BOOL)requestFocus +{ + [m_window makeKeyAndOrderFront:nil]; + + // In case the app is not active, make its dock icon bounce for one sec + [NSApp requestUserAttention:NSInformationalRequest]; + + return [self hasFocus]; +} + + +//////////////////////////////////////////////////////////// +-(BOOL)hasFocus +{ + return [NSApp keyWindow] == m_window; +} + + //////////////////////////////////////////////////////// -(void)enableKeyRepeat { diff --git a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h index b43805a64..e33f91a1b 100644 --- a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h +++ b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h @@ -166,6 +166,23 @@ namespace sf { //////////////////////////////////////////////////////////// -(void)closeWindow; +//////////////////////////////////////////////////////////// +/// \brief Request the current window to be made the active +/// foreground window +/// +/// \return True if operation was successful, false otherwise +/// +//////////////////////////////////////////////////////////// +-(BOOL)requestFocus; + +//////////////////////////////////////////////////////////// +/// \brief Determine whether the window has the input focus +/// +/// \return True if window has focus, false otherwise +/// +//////////////////////////////////////////////////////////// +-(BOOL)hasFocus; + //////////////////////////////////////////////////////////// /// \brief Enable key repeat /// From 6a24eb5eec347af5bdcdd5a3c33753f34bd64771 Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Sat, 3 May 2014 14:25:00 +0200 Subject: [PATCH 3/8] Slightly adapted window focus documentation --- include/SFML/Window/Window.hpp | 11 +++++------ src/SFML/Window/OSX/WindowImplCocoa.hpp | 2 +- src/SFML/Window/OSX/WindowImplDelegateProtocol.h | 2 +- src/SFML/Window/Unix/WindowImplX11.hpp | 2 +- src/SFML/Window/Win32/WindowImplWin32.hpp | 2 +- src/SFML/Window/WindowImpl.hpp | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/include/SFML/Window/Window.hpp b/include/SFML/Window/Window.hpp index 3a98971d2..0ba0477b9 100644 --- a/include/SFML/Window/Window.hpp +++ b/include/SFML/Window/Window.hpp @@ -417,28 +417,27 @@ public: /// foreground window /// /// At any given time, only one window may have the input focus - /// to receive input events such as keystrokes or mouse - /// events. + /// to receive input events such as keystrokes or mouse events. /// If a window requests focus, it only hints to the operating /// system, that it would like to be focused. The operating system - /// is free to deny the request. For example under Windows OS - /// windows are not allowed to steal focus. But the user - /// will be notified through a flashing taskbar button. + /// is free to deny the request. /// This is not to be confused with setActive(). /// /// \return True if operation was successful, false otherwise + /// \see hasFocus /// //////////////////////////////////////////////////////////// bool requestFocus(); //////////////////////////////////////////////////////////// - /// \brief Determine whether the window has the input focus + /// \brief Check whether the window has the input focus /// /// At any given time, only one window may have the input focus /// to receive input events such as keystrokes or most mouse /// events. /// /// \return True if window has focus, false otherwise + /// \see requestFocus /// //////////////////////////////////////////////////////////// bool hasFocus() const; diff --git a/src/SFML/Window/OSX/WindowImplCocoa.hpp b/src/SFML/Window/OSX/WindowImplCocoa.hpp index f65d63ed7..1dfc680f6 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.hpp +++ b/src/SFML/Window/OSX/WindowImplCocoa.hpp @@ -330,7 +330,7 @@ public: virtual bool requestFocus(); //////////////////////////////////////////////////////////// - /// \brief Determine whether the window has the input focus + /// \brief Check whether the window has the input focus /// /// \return True if window has focus, false otherwise /// diff --git a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h index e33f91a1b..6c38f5900 100644 --- a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h +++ b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h @@ -176,7 +176,7 @@ namespace sf { -(BOOL)requestFocus; //////////////////////////////////////////////////////////// -/// \brief Determine whether the window has the input focus +/// \brief Check whether the window has the input focus /// /// \return True if window has focus, false otherwise /// diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp index 0605cdf9a..9f354e9f6 100644 --- a/src/SFML/Window/Unix/WindowImplX11.hpp +++ b/src/SFML/Window/Unix/WindowImplX11.hpp @@ -164,7 +164,7 @@ public: virtual bool requestFocus(); //////////////////////////////////////////////////////////// - /// \brief Determine whether the window has the input focus + /// \brief Check whether the window has the input focus /// /// \return True if window has focus, false otherwise /// diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp index e95bfa9fb..d06aae77a 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.hpp +++ b/src/SFML/Window/Win32/WindowImplWin32.hpp @@ -163,7 +163,7 @@ public: virtual bool requestFocus(); //////////////////////////////////////////////////////////// - /// \brief Determine whether the window has the input focus + /// \brief Check whether the window has the input focus /// /// \return True if window has focus, false otherwise /// diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp index 50ef17237..1b5251e88 100644 --- a/src/SFML/Window/WindowImpl.hpp +++ b/src/SFML/Window/WindowImpl.hpp @@ -204,7 +204,7 @@ public: virtual bool requestFocus() = 0; //////////////////////////////////////////////////////////// - /// \brief Determine whether the window has the input focus + /// \brief Check whether the window has the input focus /// /// \return True if window has focus, false otherwise /// From 4155b2e449e1448ccbe7a1c958e5cd686b1aba11 Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Thu, 29 May 2014 11:39:04 +0200 Subject: [PATCH 4/8] Changed Window::requestFocus() return type from bool to void Reasons: * Consistent with other sf::Window methods * User can test whether focus succeeded by subsequent hasFocus() call * Implementation would have to call hasFocus() anyway on some systems Also: minor code style change in Window::hasFocus() --- include/SFML/Window/Window.hpp | 3 +-- src/SFML/Window/OSX/SFViewController.mm | 4 +--- src/SFML/Window/OSX/SFWindowController.mm | 4 +--- src/SFML/Window/OSX/WindowImplCocoa.hpp | 4 +--- src/SFML/Window/OSX/WindowImplCocoa.mm | 4 ++-- src/SFML/Window/OSX/WindowImplDelegateProtocol.h | 4 +--- src/SFML/Window/Unix/WindowImplX11.cpp | 3 +-- src/SFML/Window/Unix/WindowImplX11.hpp | 4 +--- src/SFML/Window/Win32/WindowImplWin32.cpp | 4 ++-- src/SFML/Window/Win32/WindowImplWin32.hpp | 4 +--- src/SFML/Window/Window.cpp | 9 +++------ src/SFML/Window/WindowImpl.hpp | 4 +--- 12 files changed, 16 insertions(+), 35 deletions(-) diff --git a/include/SFML/Window/Window.hpp b/include/SFML/Window/Window.hpp index 0ba0477b9..6d4ecf79b 100644 --- a/include/SFML/Window/Window.hpp +++ b/include/SFML/Window/Window.hpp @@ -423,11 +423,10 @@ public: /// is free to deny the request. /// This is not to be confused with setActive(). /// - /// \return True if operation was successful, false otherwise /// \see hasFocus /// //////////////////////////////////////////////////////////// - bool requestFocus(); + void requestFocus(); //////////////////////////////////////////////////////////// /// \brief Check whether the window has the input focus diff --git a/src/SFML/Window/OSX/SFViewController.mm b/src/SFML/Window/OSX/SFViewController.mm index a2898da84..ba2e8a0f1 100644 --- a/src/SFML/Window/OSX/SFViewController.mm +++ b/src/SFML/Window/OSX/SFViewController.mm @@ -188,7 +188,7 @@ //////////////////////////////////////////////////////// --(BOOL)requestFocus +-(void)requestFocus { // Note: this doesn't imply that the view will get any event. // The user has to make sure events are forwarded to the view @@ -197,8 +197,6 @@ // In case the app is not active, make its dock icon bounce for one sec [NSApp requestUserAttention:NSInformationalRequest]; - - return [self hasFocus]; } diff --git a/src/SFML/Window/OSX/SFWindowController.mm b/src/SFML/Window/OSX/SFWindowController.mm index 2fae92592..afdd31872 100644 --- a/src/SFML/Window/OSX/SFWindowController.mm +++ b/src/SFML/Window/OSX/SFWindowController.mm @@ -452,14 +452,12 @@ //////////////////////////////////////////////////////// --(BOOL)requestFocus +-(void)requestFocus { [m_window makeKeyAndOrderFront:nil]; // In case the app is not active, make its dock icon bounce for one sec [NSApp requestUserAttention:NSInformationalRequest]; - - return [self hasFocus]; } diff --git a/src/SFML/Window/OSX/WindowImplCocoa.hpp b/src/SFML/Window/OSX/WindowImplCocoa.hpp index 1dfc680f6..4a66d743c 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.hpp +++ b/src/SFML/Window/OSX/WindowImplCocoa.hpp @@ -324,10 +324,8 @@ public: /// \brief Request the current window to be made the active /// foreground window /// - /// \return True if operation was successful, false otherwise - /// //////////////////////////////////////////////////////////// - virtual bool requestFocus(); + virtual void requestFocus(); //////////////////////////////////////////////////////////// /// \brief Check whether the window has the input focus diff --git a/src/SFML/Window/OSX/WindowImplCocoa.mm b/src/SFML/Window/OSX/WindowImplCocoa.mm index 5dbf0f460..0ddfa78fc 100644 --- a/src/SFML/Window/OSX/WindowImplCocoa.mm +++ b/src/SFML/Window/OSX/WindowImplCocoa.mm @@ -553,9 +553,9 @@ void WindowImplCocoa::setKeyRepeatEnabled(bool enabled) //////////////////////////////////////////////////////////// -bool WindowImplCocoa::requestFocus() +void WindowImplCocoa::requestFocus() { - return [m_delegate requestFocus]; + [m_delegate requestFocus]; } diff --git a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h index 6c38f5900..0132f4018 100644 --- a/src/SFML/Window/OSX/WindowImplDelegateProtocol.h +++ b/src/SFML/Window/OSX/WindowImplDelegateProtocol.h @@ -170,10 +170,8 @@ namespace sf { /// \brief Request the current window to be made the active /// foreground window /// -/// \return True if operation was successful, false otherwise -/// //////////////////////////////////////////////////////////// --(BOOL)requestFocus; +-(void)requestFocus; //////////////////////////////////////////////////////////// /// \brief Check whether the window has the input focus diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index 7efacc192..f43644df4 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -484,11 +484,10 @@ void WindowImplX11::setKeyRepeatEnabled(bool enabled) //////////////////////////////////////////////////////////// -bool WindowImplX11::requestFocus() +void WindowImplX11::requestFocus() { XRaiseWindow(m_display, m_window); XSetInputFocus(m_display, m_window, RevertToPointerRoot, CurrentTime); - return true; } diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp index 9f354e9f6..19de32f0c 100644 --- a/src/SFML/Window/Unix/WindowImplX11.hpp +++ b/src/SFML/Window/Unix/WindowImplX11.hpp @@ -158,10 +158,8 @@ public: /// \brief Request the current window to be made the active /// foreground window /// - /// \return True if operation was successful, false otherwise - /// //////////////////////////////////////////////////////////// - virtual bool requestFocus(); + virtual void requestFocus(); //////////////////////////////////////////////////////////// /// \brief Check whether the window has the input focus diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index 32aec6daf..5dcfc3e0c 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -367,9 +367,9 @@ void WindowImplWin32::setKeyRepeatEnabled(bool enabled) //////////////////////////////////////////////////////////// -bool WindowImplWin32::requestFocus() +void WindowImplWin32::requestFocus() { - return SetForegroundWindow(m_handle); + SetForegroundWindow(m_handle); } diff --git a/src/SFML/Window/Win32/WindowImplWin32.hpp b/src/SFML/Window/Win32/WindowImplWin32.hpp index d06aae77a..0bb3ce840 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.hpp +++ b/src/SFML/Window/Win32/WindowImplWin32.hpp @@ -157,10 +157,8 @@ public: /// \brief Request the current window to be made the active /// foreground window /// - /// \return True if operation was successful, false otherwise - /// //////////////////////////////////////////////////////////// - virtual bool requestFocus(); + virtual void requestFocus(); //////////////////////////////////////////////////////////// /// \brief Check whether the window has the input focus diff --git a/src/SFML/Window/Window.cpp b/src/SFML/Window/Window.cpp index 574c0549b..7487ea6ef 100644 --- a/src/SFML/Window/Window.cpp +++ b/src/SFML/Window/Window.cpp @@ -337,20 +337,17 @@ bool Window::setActive(bool active) const //////////////////////////////////////////////////////////// -bool Window::requestFocus() +void Window::requestFocus() { if (m_impl) - return m_impl->requestFocus(); - return false; + m_impl->requestFocus(); } //////////////////////////////////////////////////////////// bool Window::hasFocus() const { - if (m_impl) - return m_impl->hasFocus(); - return false; + return m_impl && m_impl->hasFocus(); } diff --git a/src/SFML/Window/WindowImpl.hpp b/src/SFML/Window/WindowImpl.hpp index 1b5251e88..dbf7170d8 100644 --- a/src/SFML/Window/WindowImpl.hpp +++ b/src/SFML/Window/WindowImpl.hpp @@ -198,10 +198,8 @@ public: /// \brief Request the current window to be made the active /// foreground window /// - /// \return True if operation was successful, false otherwise - /// //////////////////////////////////////////////////////////// - virtual bool requestFocus() = 0; + virtual void requestFocus() = 0; //////////////////////////////////////////////////////////// /// \brief Check whether the window has the input focus From 93d2789f700a8b26b47661933029d95a238aacac Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Tue, 13 May 2014 16:18:14 +0200 Subject: [PATCH 5/8] Window focus: Added empty implementations for Android and iOS --- src/SFML/Window/Android/WindowImplAndroid.cpp | 15 +++++++++++++++ src/SFML/Window/Android/WindowImplAndroid.hpp | 15 +++++++++++++++ src/SFML/Window/iOS/WindowImplUIKit.hpp | 15 +++++++++++++++ src/SFML/Window/iOS/WindowImplUIKit.mm | 15 +++++++++++++++ 4 files changed, 60 insertions(+) diff --git a/src/SFML/Window/Android/WindowImplAndroid.cpp b/src/SFML/Window/Android/WindowImplAndroid.cpp index 1b1a1a4ba..22cf60cab 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.cpp +++ b/src/SFML/Window/Android/WindowImplAndroid.cpp @@ -181,6 +181,21 @@ void WindowImplAndroid::setKeyRepeatEnabled(bool enabled) } +//////////////////////////////////////////////////////////// +void WindowImplAndroid::requestFocus() +{ + // Not applicable +} + + +//////////////////////////////////////////////////////////// +bool WindowImplAndroid::hasFocus() const +{ + // Not applicable + return false; +} + + //////////////////////////////////////////////////////////// void WindowImplAndroid::forwardEvent(const Event& event) { diff --git a/src/SFML/Window/Android/WindowImplAndroid.hpp b/src/SFML/Window/Android/WindowImplAndroid.hpp index 7786248be..f5106e3ae 100644 --- a/src/SFML/Window/Android/WindowImplAndroid.hpp +++ b/src/SFML/Window/Android/WindowImplAndroid.hpp @@ -154,6 +154,21 @@ public: //////////////////////////////////////////////////////////// virtual void setKeyRepeatEnabled(bool enabled); + //////////////////////////////////////////////////////////// + /// \brief Request the current window to be made the active + /// foreground window + /// + //////////////////////////////////////////////////////////// + virtual void requestFocus(); + + //////////////////////////////////////////////////////////// + /// \brief Check whether the window has the input focus + /// + /// \return True if window has focus, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool hasFocus() const; + static void forwardEvent(const Event& event); static WindowImplAndroid* singleInstance; diff --git a/src/SFML/Window/iOS/WindowImplUIKit.hpp b/src/SFML/Window/iOS/WindowImplUIKit.hpp index 9f56fe906..61d082886 100644 --- a/src/SFML/Window/iOS/WindowImplUIKit.hpp +++ b/src/SFML/Window/iOS/WindowImplUIKit.hpp @@ -157,6 +157,21 @@ public: //////////////////////////////////////////////////////////// virtual void setKeyRepeatEnabled(bool enabled); + //////////////////////////////////////////////////////////// + /// \brief Request the current window to be made the active + /// foreground window + /// + //////////////////////////////////////////////////////////// + virtual void requestFocus(); + + //////////////////////////////////////////////////////////// + /// \brief Check whether the window has the input focus + /// + /// \return True if window has focus, false otherwise + /// + //////////////////////////////////////////////////////////// + virtual bool hasFocus() const; + public: using WindowImpl::pushEvent; diff --git a/src/SFML/Window/iOS/WindowImplUIKit.mm b/src/SFML/Window/iOS/WindowImplUIKit.mm index 12b91aa41..7ccf7b318 100644 --- a/src/SFML/Window/iOS/WindowImplUIKit.mm +++ b/src/SFML/Window/iOS/WindowImplUIKit.mm @@ -169,6 +169,21 @@ void WindowImplUIKit::setKeyRepeatEnabled(bool enabled) // Not applicable } + +//////////////////////////////////////////////////////////// +void WindowImplUIKit::requestFocus() +{ + // Not applicable +} + + +//////////////////////////////////////////////////////////// +bool WindowImplUIKit::hasFocus() const +{ + // Not applicable + return false; +} + //////////////////////////////////////////////////////////// SFView* WindowImplUIKit::getGlView() const From c98bd1eaba78bff97870207af23ee6da8450dfa0 Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Tue, 13 May 2014 16:25:07 +0200 Subject: [PATCH 6/8] Window focus on X11: check if window is viewable --- src/SFML/Window/Unix/WindowImplX11.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index f43644df4..bd1fb2c87 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -486,6 +486,16 @@ void WindowImplX11::setKeyRepeatEnabled(bool enabled) //////////////////////////////////////////////////////////// void WindowImplX11::requestFocus() { + // Check if window is viewable (not on other desktop, minimized, ...) + XWindowAttributes attributes; + if (XGetWindowAttributes(m_display, m_window, &attributes) == 0) + return; // error getting attribute + + // Not viewable: Can't set focus + if (attributes.map_state != IsViewable) + return; + + // Bring window to the front and give it input focus XRaiseWindow(m_display, m_window); XSetInputFocus(m_display, m_window, RevertToPointerRoot, CurrentTime); } From c4435b8a31432fa93a8b1d1762155902cc0af198 Mon Sep 17 00:00:00 2001 From: Alexandre Bodelot Date: Thu, 3 Jul 2014 13:59:55 +0200 Subject: [PATCH 7/8] X11: Notify instead of force focus Signed-off-by: Jan Haller --- src/SFML/Window/Unix/WindowImplX11.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index bd1fb2c87..e01d4920c 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -486,18 +486,19 @@ void WindowImplX11::setKeyRepeatEnabled(bool enabled) //////////////////////////////////////////////////////////// void WindowImplX11::requestFocus() { - // Check if window is viewable (not on other desktop, minimized, ...) - XWindowAttributes attributes; - if (XGetWindowAttributes(m_display, m_window, &attributes) == 0) - return; // error getting attribute - - // Not viewable: Can't set focus - if (attributes.map_state != IsViewable) - return; - - // Bring window to the front and give it input focus - XRaiseWindow(m_display, m_window); - XSetInputFocus(m_display, m_window, RevertToPointerRoot, CurrentTime); + // Ensure WM hints exist + XWMHints* hints = XGetWMHints(m_display, m_window); + if (hints == NULL) + { + hints = XAllocWMHints(); + } + else + { + // Add Urgency Hint flag (visual notification) + hints->flags |= XUrgencyHint; + XSetWMHints(m_display, m_window, hints); + XFree(hints); + } } From 60c4f957956fe4f77ada109efd55a1e205fcaa12 Mon Sep 17 00:00:00 2001 From: Jan Haller Date: Mon, 11 Aug 2014 22:47:02 +0200 Subject: [PATCH 8/8] Implemented case differentiation for window focus/notification on Windows and X11 --- src/SFML/Window/Unix/WindowImplX11.cpp | 69 +++++++++++++++++++---- src/SFML/Window/Win32/WindowImplWin32.cpp | 22 +++++++- 2 files changed, 80 insertions(+), 11 deletions(-) diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp index e01d4920c..e4dfe775a 100644 --- a/src/SFML/Window/Unix/WindowImplX11.cpp +++ b/src/SFML/Window/Unix/WindowImplX11.cpp @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef SFML_OPENGL_ES #include @@ -54,10 +55,11 @@ //////////////////////////////////////////////////////////// namespace { - sf::priv::WindowImplX11* fullscreenWindow = NULL; - unsigned long eventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | - PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | - EnterWindowMask | LeaveWindowMask; + sf::priv::WindowImplX11* fullscreenWindow = NULL; + std::vector allWindows; + unsigned long eventMask = FocusChangeMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | + PointerMotionMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | + EnterWindowMask | LeaveWindowMask; // Filter the events received by windows (only allow those matching a specific window) Bool checkEvent(::Display*, XEvent* event, XPointer userData) @@ -303,6 +305,9 @@ WindowImplX11::~WindowImplX11() // Close the connection with the X server CloseDisplay(m_display); + + // Remove this window from the global list of windows (required for focus request) + allWindows.erase(std::find(allWindows.begin(), allWindows.end(), this)); } @@ -486,19 +491,50 @@ void WindowImplX11::setKeyRepeatEnabled(bool enabled) //////////////////////////////////////////////////////////// void WindowImplX11::requestFocus() { - // Ensure WM hints exist - XWMHints* hints = XGetWMHints(m_display, m_window); - if (hints == NULL) + // Focus is only stolen among SFML windows, not between applications + // Check the global list of windows to find out whether an SFML window has the focus + // Note: can't handle console and other non-SFML windows belonging to the application. + bool sfmlWindowFocused = false; + for (std::vector::iterator itr = allWindows.begin(); itr != allWindows.end(); ++itr) { - hints = XAllocWMHints(); + if ((*itr)->hasFocus()) + { + sfmlWindowFocused = true; + break; + } + } + + // Check if window is viewable (not on other desktop, ...) + // TODO: Check also if minimized + XWindowAttributes attributes; + if (XGetWindowAttributes(m_display, m_window, &attributes) == 0) + { + sf::err() << "Failed to check if window is viewable while requesting focus" << std::endl; + return; // error getting attribute + } + + bool windowViewable = (attributes.map_state == IsViewable); + + if (sfmlWindowFocused && windowViewable) + { + // Another SFML window of this application has the focus and the current window is viewable: + // steal focus (i.e. bring window to the front and give it input focus) + XRaiseWindow(m_display, m_window); + XSetInputFocus(m_display, m_window, RevertToPointerRoot, CurrentTime); } else { - // Add Urgency Hint flag (visual notification) + // Otherwise: display urgency hint (flashing application logo) + // Ensure WM hints exist, allocate if necessary + XWMHints* hints = XGetWMHints(m_display, m_window); + if (hints == NULL) + hints = XAllocWMHints(); + + // Add urgency (notification) flag to hints hints->flags |= XUrgencyHint; XSetWMHints(m_display, m_window, hints); XFree(hints); - } + } } @@ -598,6 +634,9 @@ void WindowImplX11::initialize() // Flush the commands queue XFlush(m_display); + + // Add this window to the global list of windows (required for focus request) + allWindows.push_back(this); } @@ -710,6 +749,16 @@ bool WindowImplX11::processEvent(XEvent windowEvent) Event event; event.type = Event::GainedFocus; pushEvent(event); + + // If the window has been previously marked urgent (notification) as a result of a focus request, undo that + XWMHints* hints = XGetWMHints(m_display, m_window); + if (hints != NULL) + { + // Remove urgency (notification) flag from hints + hints->flags &= ~XUrgencyHint; + XSetWMHints(m_display, m_window, hints); + XFree(hints); + } break; } diff --git a/src/SFML/Window/Win32/WindowImplWin32.cpp b/src/SFML/Window/Win32/WindowImplWin32.cpp index 5dcfc3e0c..5ebc8a80c 100644 --- a/src/SFML/Window/Win32/WindowImplWin32.cpp +++ b/src/SFML/Window/Win32/WindowImplWin32.cpp @@ -369,7 +369,27 @@ void WindowImplWin32::setKeyRepeatEnabled(bool enabled) //////////////////////////////////////////////////////////// void WindowImplWin32::requestFocus() { - SetForegroundWindow(m_handle); + // Allow focus stealing only within the same process; compare PIDs of current and foreground window + DWORD thisPid = GetWindowThreadProcessId(m_handle, NULL); + DWORD foregroundPid = GetWindowThreadProcessId(GetForegroundWindow(), NULL); + + if (thisPid == foregroundPid) + { + // The window requesting focus belongs to the same process as the current window: steal focus + SetForegroundWindow(m_handle); + } + else + { + // Different process: don't steal focus, but create a taskbar notification ("flash") + FLASHWINFO info; + info.cbSize = sizeof(info); + info.hwnd = m_handle; + info.dwFlags = FLASHW_TRAY; + info.dwTimeout = 0; + info.uCount = 3; + + FlashWindowEx(&info); + } }