From 301a84c4f5c644697ebc36b27812ba3d972a778f Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Tue, 21 Mar 2017 10:02:57 -0300 Subject: [PATCH 01/10] Initial implementation of window attention for X11 --- include/GLFW/glfw3.h | 2 ++ src/internal.h | 1 + src/window.c | 10 ++++++++++ src/x11_window.c | 18 ++++++++++++++++++ 4 files changed, 31 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 8b2efcec2..73a139df4 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -2698,6 +2698,8 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); */ GLFWAPI void glfwShowWindow(GLFWwindow* window); +GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window); + /*! @brief Hides the specified window. * * This function hides the specified window if it was previously visible. If diff --git a/src/internal.h b/src/internal.h index be9ced898..00b362544 100644 --- a/src/internal.h +++ b/src/internal.h @@ -629,6 +629,7 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window); void _glfwPlatformRestoreWindow(_GLFWwindow* window); void _glfwPlatformMaximizeWindow(_GLFWwindow* window); void _glfwPlatformShowWindow(_GLFWwindow* window); +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window); void _glfwPlatformHideWindow(_GLFWwindow* window); void _glfwPlatformFocusWindow(_GLFWwindow* window); void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor, int xpos, int ypos, int width, int height, int refreshRate); diff --git a/src/window.c b/src/window.c index bf98723ea..546d233d8 100644 --- a/src/window.c +++ b/src/window.c @@ -675,6 +675,16 @@ GLFWAPI void glfwShowWindow(GLFWwindow* handle) _glfwPlatformFocusWindow(window); } +GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle) +{ + _GLFWwindow* window = (_GLFWwindow*) handle; + assert(window != NULL); + + _GLFW_REQUIRE_INIT(); + + _glfwPlatformRequestWindowAttention(window); +} + GLFWAPI void glfwHideWindow(GLFWwindow* handle) { _GLFWwindow* window = (_GLFWwindow*) handle; diff --git a/src/x11_window.c b/src/x11_window.c index 907fa7946..48c30edb3 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2072,6 +2072,24 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) waitForVisibilityNotify(window); } +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +{ + XEvent xev; + + Atom wm_state = XInternAtom(_glfw.x11.display, "_NET_WM_STATE", False); + Atom wm_attention = XInternAtom(_glfw.x11.display, "_NET_WM_STATE_DEMANDS_ATTENTION", False); + + memset(&xev, 0, sizeof(xev)); + xev.type = ClientMessage; + xev.xclient.window = window->x11.handle; + xev.xclient.message_type = wm_state; + xev.xclient.format = 32; + xev.xclient.data.l[0] = 1; /* _NET_WM_STATE_ADD */ + xev.xclient.data.l[1] = wm_attention; + + XSendEvent(_glfw.x11.display, DefaultRootWindow(_glfw.x11.display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); +} + void _glfwPlatformHideWindow(_GLFWwindow* window) { XUnmapWindow(_glfw.x11.display, window->x11.handle); From aaebcc51411df4d403b3950aac887fc075df0fba Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Thu, 6 Apr 2017 19:46:53 -0300 Subject: [PATCH 02/10] Update attention request on X11 and update example The macro ```_NET_WM_STATE_ADD``` is passed to ```xev.xclient.data.l[0]```, instead of a constant `1`. The example ```simple.c``` was update to make a attention request every 10 seconds. --- examples/simple.c | 7 +++++++ src/null_window.c | 5 +++++ src/x11_window.c | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/examples/simple.c b/examples/simple.c index 7752a3655..6c78acf45 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -79,6 +79,7 @@ int main(void) GLFWwindow* window; GLuint vertex_buffer, vertex_shader, fragment_shader, program; GLint mvp_location, vpos_location, vcol_location; + double start; glfwSetErrorCallback(error_callback); @@ -131,12 +132,18 @@ int main(void) glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (void*) (sizeof(float) * 2)); + start = glfwGetTime(); while (!glfwWindowShouldClose(window)) { float ratio; int width, height; mat4x4 m, p, mvp; + if (glfwGetTime() - start > 10.0) { + glfwRequestWindowAttention(window); + start = glfwGetTime(); + } + glfwGetFramebufferSize(window, &width, &height); ratio = width / (float) height; diff --git a/src/null_window.c b/src/null_window.c index 7f0101d44..137f80c8f 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -172,6 +172,11 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) { } + +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +{ +} + void _glfwPlatformUnhideWindow(_GLFWwindow* window) { } diff --git a/src/x11_window.c b/src/x11_window.c index 48c30edb3..55d5316a8 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2084,7 +2084,7 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) xev.xclient.window = window->x11.handle; xev.xclient.message_type = wm_state; xev.xclient.format = 32; - xev.xclient.data.l[0] = 1; /* _NET_WM_STATE_ADD */ + xev.xclient.data.l[0] = _NET_WM_STATE_ADD; xev.xclient.data.l[1] = wm_attention; XSendEvent(_glfw.x11.display, DefaultRootWindow(_glfw.x11.display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); From ec22abcd067c295eee36d8f2711ec67554a08641 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Thu, 6 Apr 2017 20:09:07 -0300 Subject: [PATCH 03/10] Add attention request for Windows --- src/win32_window.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/win32_window.c b/src/win32_window.c index 363ef0f32..f9eca060d 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1311,6 +1311,11 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) ShowWindow(window->win32.handle, SW_SHOW); } +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +{ + FlashWindow(window->win32.handle, TRUE); +} + void _glfwPlatformHideWindow(_GLFWwindow* window) { ShowWindow(window->win32.handle, SW_HIDE); From 584958222c2007899c2ea7ad7733ba386a4fd489 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Thu, 6 Apr 2017 21:18:25 -0300 Subject: [PATCH 04/10] Add attention request function for each platform Add stub functions ```_glfwPlatformRequestWindowAttention``` for the platforms Cocoa, Mir, and Wayland, which still lack the implementation of attention request. --- src/cocoa_window.m | 4 ++++ src/mir_window.c | 4 ++++ src/wl_window.c | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index d2aab85f9..a5ea57ee5 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1272,6 +1272,10 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) [window->ns.object orderFront:nil]; } +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +{ +} + void _glfwPlatformHideWindow(_GLFWwindow* window) { [window->ns.object orderOut:nil]; diff --git a/src/mir_window.c b/src/mir_window.c index 00d50ada9..42e2f4b1a 100644 --- a/src/mir_window.c +++ b/src/mir_window.c @@ -567,6 +567,10 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) mir_surface_spec_release(spec); } +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +{ +} + void _glfwPlatformFocusWindow(_GLFWwindow* window) { _glfwInputError(GLFW_PLATFORM_ERROR, diff --git a/src/wl_window.c b/src/wl_window.c index e6c554527..6a13717da 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -589,6 +589,10 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) } } +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +{ +} + void _glfwPlatformHideWindow(_GLFWwindow* window) { if (!window->monitor) From 49c4227b0d97f7e7959116c87db214199526c00e Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Thu, 6 Apr 2017 21:39:07 -0300 Subject: [PATCH 05/10] Mention attention request function in README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 76b384a37..55a93a18d 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,8 @@ information on what to include when reporting a bug. ## Changelog +- Added `glfwRequestWindowAttention` function that request attention to the + non-focused or minimized window - Added `glfwGetKeyScancode` function that allows retrieving platform dependent scancodes for keys (#830) - Added `glfwSetWindowMaximizeCallback` and `GLFWwindowmaximizefun` for From a3ad2537e2b6123dcfe4a01ec56f868aa9948a5b Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Fri, 7 Apr 2017 03:32:32 -0300 Subject: [PATCH 06/10] Add attention request function for Cocoa --- src/cocoa_window.m | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cocoa_window.m b/src/cocoa_window.m index a5ea57ee5..f2ee319d8 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1274,6 +1274,7 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) { + [window->ns.object requestUserAttention:NSInformationalRequest]; } void _glfwPlatformHideWindow(_GLFWwindow* window) From 82afc48fab0aca0cbde8a8125efec09dfcff8058 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Fri, 7 Apr 2017 03:51:19 -0300 Subject: [PATCH 07/10] Documentation for attention request --- include/GLFW/glfw3.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 73a139df4..4c0483530 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -2698,6 +2698,21 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); */ GLFWAPI void glfwShowWindow(GLFWwindow* window); +/*! @brief Request attention to the specified window. + * + * This function makes the specified window to request attention. + * + * @param[in] window The window to request attention. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @thread_safety This function must only be called from the main thread. + * + * @since Added in version 3.3. + * + * @ingroup window + */ GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window); /*! @brief Hides the specified window. From 26628af183c12914994c6f71ffe5414ea8db4474 Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Fri, 7 Apr 2017 04:03:32 -0300 Subject: [PATCH 08/10] Use stored X11 atoms for attention request The function to request window attention was using ```XInternAtom```. Now, the atoms are stored and retrieved from the ```_GLFWlibraryX11``` structure. --- src/x11_init.c | 2 ++ src/x11_platform.h | 1 + src/x11_window.c | 7 ++----- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/x11_init.c b/src/x11_init.c index ca271546b..c66040392 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -438,6 +438,8 @@ static void detectEWMH(void) getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_VERT"); _glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ = getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_MAXIMIZED_HORZ"); + _glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION = + getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE_DEMANDS_ATTENTION"); _glfw.x11.NET_WM_FULLSCREEN_MONITORS = getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_FULLSCREEN_MONITORS"); _glfw.x11.NET_WM_WINDOW_TYPE = diff --git a/src/x11_platform.h b/src/x11_platform.h index 4ca5a1dae..465fe578d 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -194,6 +194,7 @@ typedef struct _GLFWlibraryX11 Atom NET_WM_STATE_FULLSCREEN; Atom NET_WM_STATE_MAXIMIZED_VERT; Atom NET_WM_STATE_MAXIMIZED_HORZ; + Atom NET_WM_STATE_DEMANDS_ATTENTION; Atom NET_WM_BYPASS_COMPOSITOR; Atom NET_WM_FULLSCREEN_MONITORS; Atom NET_ACTIVE_WINDOW; diff --git a/src/x11_window.c b/src/x11_window.c index 55d5316a8..40a76dfd3 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2076,16 +2076,13 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) { XEvent xev; - Atom wm_state = XInternAtom(_glfw.x11.display, "_NET_WM_STATE", False); - Atom wm_attention = XInternAtom(_glfw.x11.display, "_NET_WM_STATE_DEMANDS_ATTENTION", False); - memset(&xev, 0, sizeof(xev)); xev.type = ClientMessage; xev.xclient.window = window->x11.handle; - xev.xclient.message_type = wm_state; + xev.xclient.message_type = _glfw.x11.NET_WM_STATE; xev.xclient.format = 32; xev.xclient.data.l[0] = _NET_WM_STATE_ADD; - xev.xclient.data.l[1] = wm_attention; + xev.xclient.data.l[1] = _glfw.x11.NET_WM_STATE_DEMANDS_ATTENTION; XSendEvent(_glfw.x11.display, DefaultRootWindow(_glfw.x11.display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); } From a29f9f5ea4f0cb33bbe583fd654fabe407c9605b Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Sat, 8 Apr 2017 19:55:16 -0300 Subject: [PATCH 09/10] Update attention request For Cocoa, the attention request is made via the ```NSApp```. The functions for each platform were moved, and the documentation improved. --- include/GLFW/glfw3.h | 37 ++++++++++++++++++++----------------- src/cocoa_window.m | 10 +++++----- src/win32_window.c | 10 +++++----- src/wl_window.c | 8 ++++---- src/x11_window.c | 12 ++++++------ 5 files changed, 40 insertions(+), 37 deletions(-) diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 4c0483530..434b24ad6 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -2698,23 +2698,6 @@ GLFWAPI void glfwMaximizeWindow(GLFWwindow* window); */ GLFWAPI void glfwShowWindow(GLFWwindow* window); -/*! @brief Request attention to the specified window. - * - * This function makes the specified window to request attention. - * - * @param[in] window The window to request attention. - * - * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref - * GLFW_PLATFORM_ERROR. - * - * @thread_safety This function must only be called from the main thread. - * - * @since Added in version 3.3. - * - * @ingroup window - */ -GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window); - /*! @brief Hides the specified window. * * This function hides the specified window if it was previously visible. If @@ -2768,6 +2751,26 @@ GLFWAPI void glfwHideWindow(GLFWwindow* window); */ GLFWAPI void glfwFocusWindow(GLFWwindow* window); +/*! @brief Request attention to the specified window. + * + * This function makes the specified window to request attention. + * + * @param[in] window The window to request attention. + * + * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref + * GLFW_PLATFORM_ERROR. + * + * @remark @macos The attention request will be made for the application and + * not the window passed in the argument. + * + * @thread_safety This function must only be called from the main thread. + * + * @since Added in version 3.3. + * + * @ingroup window + */ +GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window); + /*! @brief Returns the monitor that the window uses for full screen mode. * * This function returns the handle of the monitor that the specified window is diff --git a/src/cocoa_window.m b/src/cocoa_window.m index f2ee319d8..d2b207bb9 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -1272,16 +1272,16 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) [window->ns.object orderFront:nil]; } -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) -{ - [window->ns.object requestUserAttention:NSInformationalRequest]; -} - void _glfwPlatformHideWindow(_GLFWwindow* window) { [window->ns.object orderOut:nil]; } +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +{ + [NSApp requestUserAttention:NSInformationalRequest]; +} + void _glfwPlatformFocusWindow(_GLFWwindow* window) { // Make us the active application diff --git a/src/win32_window.c b/src/win32_window.c index f9eca060d..6d691e196 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -1311,16 +1311,16 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) ShowWindow(window->win32.handle, SW_SHOW); } -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) -{ - FlashWindow(window->win32.handle, TRUE); -} - void _glfwPlatformHideWindow(_GLFWwindow* window) { ShowWindow(window->win32.handle, SW_HIDE); } +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +{ + FlashWindow(window->win32.handle, TRUE); +} + void _glfwPlatformFocusWindow(_GLFWwindow* window) { BringWindowToTop(window->win32.handle); diff --git a/src/wl_window.c b/src/wl_window.c index 6a13717da..9dace92a7 100644 --- a/src/wl_window.c +++ b/src/wl_window.c @@ -589,10 +589,6 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) } } -void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) -{ -} - void _glfwPlatformHideWindow(_GLFWwindow* window) { if (!window->monitor) @@ -603,6 +599,10 @@ void _glfwPlatformHideWindow(_GLFWwindow* window) } } +void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) +{ +} + void _glfwPlatformFocusWindow(_GLFWwindow* window) { _glfwInputError(GLFW_PLATFORM_ERROR, diff --git a/src/x11_window.c b/src/x11_window.c index 40a76dfd3..db5ac83f0 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -2072,6 +2072,12 @@ void _glfwPlatformShowWindow(_GLFWwindow* window) waitForVisibilityNotify(window); } +void _glfwPlatformHideWindow(_GLFWwindow* window) +{ + XUnmapWindow(_glfw.x11.display, window->x11.handle); + XFlush(_glfw.x11.display); +} + void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) { XEvent xev; @@ -2087,12 +2093,6 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) XSendEvent(_glfw.x11.display, DefaultRootWindow(_glfw.x11.display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev); } -void _glfwPlatformHideWindow(_GLFWwindow* window) -{ - XUnmapWindow(_glfw.x11.display, window->x11.handle); - XFlush(_glfw.x11.display); -} - void _glfwPlatformFocusWindow(_GLFWwindow* window) { if (_glfw.x11.NET_ACTIVE_WINDOW) From 2050f1b7d89b50bf11e4e8d1c020d13c551811ee Mon Sep 17 00:00:00 2001 From: Felipe Ferreira da Silva Date: Sun, 9 Apr 2017 13:30:34 -0300 Subject: [PATCH 10/10] Revert example ```simple.c``` --- examples/simple.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/examples/simple.c b/examples/simple.c index 6c78acf45..7752a3655 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -79,7 +79,6 @@ int main(void) GLFWwindow* window; GLuint vertex_buffer, vertex_shader, fragment_shader, program; GLint mvp_location, vpos_location, vcol_location; - double start; glfwSetErrorCallback(error_callback); @@ -132,18 +131,12 @@ int main(void) glVertexAttribPointer(vcol_location, 3, GL_FLOAT, GL_FALSE, sizeof(vertices[0]), (void*) (sizeof(float) * 2)); - start = glfwGetTime(); while (!glfwWindowShouldClose(window)) { float ratio; int width, height; mat4x4 m, p, mvp; - if (glfwGetTime() - start > 10.0) { - glfwRequestWindowAttention(window); - start = glfwGetTime(); - } - glfwGetFramebufferSize(window, &width, &height); ratio = width / (float) height;