From 641761ddb076296d6a8c52d4eac84cf23323049f Mon Sep 17 00:00:00 2001 From: Camilla Berglund Date: Fri, 26 Dec 2014 12:25:48 +0100 Subject: [PATCH] Changed state attribs to direct access. Changed the window states (focused, iconified and visible) to query the system directly. THIS IS A BREAKING CHANGE, although a fairly obscure one. It affects applications that both care about telling actual key events from synthetic ones, and are implemented in a non-self-synchronizing way, and that poll the GLFW_FOCUSED window attribute instead of using the window focus callback. If you maintain one of these, please feel free to drop me an email and I'll help any way I can to transition your application to 3.1. Fixes #189. Fixes #204. --- README.md | 2 + src/cocoa_window.m | 36 +++++++--------- src/internal.h | 25 ++++++----- src/mir_window.c | 21 +++++++++ src/win32_window.c | 104 ++++++++++++++++----------------------------- src/window.c | 15 ++----- src/wl_window.c | 18 ++++++++ src/x11_window.c | 77 ++++++++++++++++++++------------- 8 files changed, 159 insertions(+), 139 deletions(-) diff --git a/README.md b/README.md index c51fa054..67702c47 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,8 @@ GLFW bundles a number of dependencies in the `deps/` directory. - Added `GLFW_FOCUSED` window hint for controlling initial input focus - Added *partial and experimental* support for Wayland - Added *partial and experimental* support for Mir + - Changed the window states (focused, iconified and visible) to query the + system directly - Changed the default of `GLFW_REFRESH_RATE` to `GLFW_DONT_CARE` to maintain the default behavior - Changed static library to build as position independent code for easier use diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 7c04af9f..f84a8f69 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -226,25 +226,6 @@ static NSRect convertRectToBacking(_GLFWwindow* window, NSRect contentRect) return NSTerminateCancel; } -- (void)applicationDidHide:(NSNotification *)notification -{ - _GLFWwindow* window; - - for (window = _glfw.windowListHead; window; window = window->next) - _glfwInputWindowVisibility(window, GL_FALSE); -} - -- (void)applicationDidUnhide:(NSNotification *)notification -{ - _GLFWwindow* window; - - for (window = _glfw.windowListHead; window; window = window->next) - { - if ([window->ns.object isVisible]) - _glfwInputWindowVisibility(window, GL_TRUE); - } -} - - (void)applicationDidChangeScreenParameters:(NSNotification *) notification { _glfwInputMonitorChange(); @@ -1047,13 +1028,26 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) void _glfwPlatformUnhideWindow(_GLFWwindow* window) { [window->ns.object orderFront:nil]; - _glfwInputWindowVisibility(window, GL_TRUE); } void _glfwPlatformHideWindow(_GLFWwindow* window) { [window->ns.object orderOut:nil]; - _glfwInputWindowVisibility(window, GL_FALSE); +} + +int _glfwPlatformWindowFocused(_GLFWwindow* window) +{ + return [window->ns.object isKeyWindow]; +} + +int _glfwPlatformWindowIconified(_GLFWwindow* window) +{ + return [window->ns.object isMiniaturized]; +} + +int _glfwPlatformWindowVisible(_GLFWwindow* window) +{ + return [window->ns.object isVisible]; } void _glfwPlatformPollEvents(void) diff --git a/src/internal.h b/src/internal.h index 26fcf2a5..8852b617 100644 --- a/src/internal.h +++ b/src/internal.h @@ -219,12 +219,10 @@ struct _GLFWwindow struct _GLFWwindow* next; // Window settings and state - GLboolean iconified; GLboolean resizable; GLboolean decorated; GLboolean autoIconify; GLboolean floating; - GLboolean visible; GLboolean closed; void* userPointer; GLFWvidmode videoMode; @@ -575,6 +573,21 @@ void _glfwPlatformUnhideWindow(_GLFWwindow* window); */ void _glfwPlatformHideWindow(_GLFWwindow* window); +/*! @brief Returns whether the window is focused. + * @ingroup platform + */ +int _glfwPlatformWindowFocused(_GLFWwindow* window); + +/*! @brief Returns whether the window is iconified. + * @ingroup platform + */ +int _glfwPlatformWindowIconified(_GLFWwindow* window); + +/*! @brief Returns whether the window is visible. + * @ingroup platform + */ +int _glfwPlatformWindowVisible(_GLFWwindow* window); + /*! @copydoc glfwPollEvents * @ingroup platform */ @@ -685,14 +698,6 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height); */ void _glfwInputWindowIconify(_GLFWwindow* window, int iconified); -/*! @brief Notifies shared code of a window show/hide event. - * @param[in] window The window that received the event. - * @param[in] visible `GL_TRUE` if the window was shown, or `GL_FALSE` if it - * was hidden. - * @ingroup event - */ -void _glfwInputWindowVisibility(_GLFWwindow* window, int visible); - /*! @brief Notifies shared code of a window damage event. * @param[in] window The window that received the event. */ diff --git a/src/mir_window.c b/src/mir_window.c index 2c8547fb..e972662b 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -565,6 +565,27 @@ void _glfwPlatformUnhideWindow(_GLFWwindow* window) "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__); } +int _glfwPlatformWindowFocused(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__); + return GL_FALSE; +} + +int _glfwPlatformWindowIconified(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__); + return GL_FALSE; +} + +int _glfwPlatformWindowVisible(_GLFWwindow* window) +{ + _glfwInputError(GLFW_PLATFORM_ERROR, + "Mir: Unsupported Function %s!", __PRETTY_FUNCTION__); + return GL_FALSE; +} + void _glfwPlatformPollEvents(void) { EventNode* node = NULL; diff --git a/src/win32_window.c b/src/win32_window.c index df0ea7f8..923900e8 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -257,86 +257,33 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, break; } - case WM_ACTIVATE: + case WM_SETFOCUS: { - // Window was (de)focused and/or (de)iconified + if (window->cursorMode != GLFW_CURSOR_NORMAL) + _glfwPlatformApplyCursorMode(window); - BOOL focused = LOWORD(wParam) != WA_INACTIVE; - BOOL iconified = HIWORD(wParam) ? TRUE : FALSE; + if (window->monitor && window->autoIconify) + enterFullscreenMode(window); - if (focused && iconified) - { - if (window->iconified && _glfw.focusedWindow != window) - { - // This is a workaround for window restoration using the - // Win+D hot key leading to windows being told they're - // focused and iconified and then never told they're - // restored - iconified = FALSE; - } - else - { - // This is a workaround for window iconification using the - // taskbar leading to windows being told they're focused and - // iconified and then never told they're defocused - focused = FALSE; - } - } - - if (!focused && _glfw.focusedWindow == window) - { - // The window was defocused (or iconified, see above) - - if (window->cursorMode != GLFW_CURSOR_NORMAL) - restoreCursor(window); - - if (window->monitor && window->autoIconify) - { - if (!iconified) - { - // Iconify the (on top, borderless, oddly positioned) - // window or the user will be annoyed - _glfwPlatformIconifyWindow(window); - } - - leaveFullscreenMode(window); - } - } - else if (focused && _glfw.focusedWindow != window) - { - // The window was focused - - if (window->cursorMode != GLFW_CURSOR_NORMAL) - _glfwPlatformApplyCursorMode(window); - - if (window->monitor && window->autoIconify) - enterFullscreenMode(window); - } - - _glfwInputWindowFocus(window, focused); - _glfwInputWindowIconify(window, iconified); + _glfwInputWindowFocus(window, GL_TRUE); return 0; } - case WM_ACTIVATEAPP: + case WM_KILLFOCUS: { - if (!wParam && IsIconic(hWnd)) + if (window->cursorMode != GLFW_CURSOR_NORMAL) + restoreCursor(window); + + if (window->monitor && window->autoIconify) { - // This is a workaround for full screen windows losing focus - // through Alt+Tab leading to windows being told they're - // unfocused and restored and then never told they're iconified - _glfwInputWindowIconify(window, GL_TRUE); + _glfwPlatformIconifyWindow(window); + leaveFullscreenMode(window); } + _glfwInputWindowFocus(window, GL_FALSE); return 0; } - case WM_SHOWWINDOW: - { - _glfwInputWindowVisibility(window, wParam ? GL_TRUE : GL_FALSE); - break; - } - case WM_SYSCOMMAND: { switch (wParam & 0xfff0) @@ -560,6 +507,11 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_SIZE: { + if (wParam == SIZE_MINIMIZED) + _glfwInputWindowIconify(window, GL_TRUE); + else if (wParam == SIZE_RESTORED) + _glfwInputWindowIconify(window, GL_FALSE); + if (_glfw.focusedWindow == window) { if (window->cursorMode == GLFW_CURSOR_DISABLED) @@ -1041,6 +993,21 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) ShowWindow(window->win32.handle, SW_HIDE); } +int _glfwPlatformWindowFocused(_GLFWwindow* window) +{ + return window->win32.handle == GetActiveWindow(); +} + +int _glfwPlatformWindowIconified(_GLFWwindow* window) +{ + return IsIconic(window->win32.handle); +} + +int _glfwPlatformWindowVisible(_GLFWwindow* window) +{ + return IsWindowVisible(window->win32.handle); +} + void _glfwPlatformPollEvents(void) { MSG msg; @@ -1238,7 +1205,8 @@ void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) // the following condition is not met. That way it should be safe to destroy the // cursor after calling glfwSetCursor(window, NULL) on all windows using the cursor. - if (window->cursorMode == GLFW_CURSOR_NORMAL && _glfw.focusedWindow == window && + if (_glfw.focusedWindow == window && + window->cursorMode == GLFW_CURSOR_NORMAL && window->win32.cursorInside) { if (cursor) diff --git a/src/window.c b/src/window.c index dcb7d003..a7ca2c8c 100644 --- a/src/window.c +++ b/src/window.c @@ -84,8 +84,6 @@ void _glfwInputWindowSize(_GLFWwindow* window, int width, int height) void _glfwInputWindowIconify(_GLFWwindow* window, int iconified) { - window->iconified = iconified; - if (window->callbacks.iconify) window->callbacks.iconify((GLFWwindow*) window, iconified); } @@ -96,11 +94,6 @@ void _glfwInputFramebufferSize(_GLFWwindow* window, int width, int height) window->callbacks.fbsize((GLFWwindow*) window, width, height); } -void _glfwInputWindowVisibility(_GLFWwindow* window, int visible) -{ - window->visible = visible; -} - void _glfwInputWindowDamage(_GLFWwindow* window) { if (window->callbacks.refresh) @@ -600,17 +593,17 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) switch (attrib) { case GLFW_FOCUSED: - return window == _glfw.focusedWindow; + return _glfwPlatformWindowFocused(window); case GLFW_ICONIFIED: - return window->iconified; + return _glfwPlatformWindowIconified(window); + case GLFW_VISIBLE: + return _glfwPlatformWindowVisible(window); case GLFW_RESIZABLE: return window->resizable; case GLFW_DECORATED: return window->decorated; case GLFW_FLOATING: return window->floating; - case GLFW_VISIBLE: - return window->visible; case GLFW_CLIENT_API: return window->context.api; case GLFW_CONTEXT_VERSION_MAJOR: diff --git a/src/wl_window.c b/src/wl_window.c index ce71dbd5..916ba683 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -307,6 +307,24 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) wl_surface_commit(window->wl.surface); } +int _glfwPlatformWindowFocused(_GLFWwindow* window) +{ + // TODO + return GL_FALSE; +} + +int _glfwPlatformWindowIconified(_GLFWwindow* window) +{ + // TODO + return GL_FALSE; +} + +int _glfwPlatformWindowVisible(_GLFWwindow* window) +{ + // TODO + return GL_FALSE; +} + void _glfwPlatformPollEvents(void) { struct wl_display* display = _glfw.wl.display; diff --git a/src/x11_window.c b/src/x11_window.c index 83734874..09e63dcd 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -57,6 +57,28 @@ typedef struct #define MWM_HINTS_DECORATIONS (1L << 1) +// Returns whether the window is iconified +// +static int getWindowState(_GLFWwindow* window) +{ + int result = WithdrawnState; + struct { + CARD32 state; + Window icon; + } *state = NULL; + + if (_glfwGetWindowProperty(window->x11.handle, + _glfw.x11.WM_STATE, + _glfw.x11.WM_STATE, + (unsigned char**) &state) >= 2) + { + result = state->state; + } + + XFree(state); + return result; +} + // Returns whether the event is a selection event // static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer) @@ -1229,18 +1251,6 @@ static void processEvent(XEvent *event) break; } - case MapNotify: - { - _glfwInputWindowVisibility(window, GL_TRUE); - break; - } - - case UnmapNotify: - { - _glfwInputWindowVisibility(window, GL_FALSE); - break; - } - case FocusIn: { if (event->xfocus.mode == NotifyNormal) @@ -1278,23 +1288,11 @@ static void processEvent(XEvent *event) if (event->xproperty.atom == _glfw.x11.WM_STATE && event->xproperty.state == PropertyNewValue) { - struct { - CARD32 state; - Window icon; - } *state = NULL; - - if (_glfwGetWindowProperty(window->x11.handle, - _glfw.x11.WM_STATE, - _glfw.x11.WM_STATE, - (unsigned char**) &state) >= 2) - { - if (state->state == IconicState) - _glfwInputWindowIconify(window, GL_TRUE); - else if (state->state == NormalState) - _glfwInputWindowIconify(window, GL_FALSE); - } - - XFree(state); + const int state = getWindowState(window); + if (state == IconicState) + _glfwInputWindowIconify(window, GL_TRUE); + else if (state == NormalState) + _glfwInputWindowIconify(window, GL_FALSE); } break; @@ -1671,6 +1669,27 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) XFlush(_glfw.x11.display); } +int _glfwPlatformWindowFocused(_GLFWwindow* window) +{ + Window focused; + int state; + + XGetInputFocus(_glfw.x11.display, &focused, &state); + return window->x11.handle == focused; +} + +int _glfwPlatformWindowIconified(_GLFWwindow* window) +{ + return getWindowState(window) == IconicState; +} + +int _glfwPlatformWindowVisible(_GLFWwindow* window) +{ + XWindowAttributes wa; + XGetWindowAttributes(_glfw.x11.display, window->x11.handle, &wa); + return wa.map_state == IsViewable; +} + void _glfwPlatformPollEvents(void) { int count = XPending(_glfw.x11.display);