From b965ad198bc65700b17b4b1c5652d8a3ddbc756b Mon Sep 17 00:00:00 2001 From: Foaly Date: Sun, 12 Jan 2014 16:26:21 +0100 Subject: [PATCH] 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 2076f8e0..3a98971d 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 723fee71..f65d63ed 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 6b1c8be1..5dbf0f46 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 a9f2f0c3..7efacc19 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 7e2b4852..0605cdf9 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 6d9ac28c..32aec6da 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 3678d79e..e95bfa9f 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 397cbbf2..574c0549 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 b4d715ed..50ef1723 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: ////////////////////////////////////////////////////////////