diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 52225c74..5e63f3ca 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -927,6 +927,13 @@ extern "C" { */ #define GLFW_MOUSE_PASSTHROUGH 0x0002000D +/*! @brief Blur behind window hint and attribute + * + * Blur behind [window hint](@ref GLFW_BLURRED_hint) or + * [window attribute](@ref GLFW_BLURRED_attrib). + */ +#define GLFW_BLURRED 0x0002000E + /*! @brief Framebuffer bit depth hint. * * Framebuffer bit depth [hint](@ref GLFW_RED_BITS). diff --git a/src/internal.h b/src/internal.h index 7babe7e8..41f1f669 100644 --- a/src/internal.h +++ b/src/internal.h @@ -410,6 +410,7 @@ struct _GLFWwndconfig GLFWbool focusOnShow; GLFWbool mousePassthrough; GLFWbool scaleToMonitor; + GLFWbool blurred; struct { GLFWbool retina; char frameName[256]; @@ -531,6 +532,7 @@ struct _GLFWwindow GLFWbool focusOnShow; GLFWbool mousePassthrough; GLFWbool shouldClose; + GLFWbool blurred; void* userPointer; GLFWbool doublebuffer; GLFWvidmode videoMode; @@ -748,6 +750,7 @@ struct _GLFWplatform void (*getRequiredInstanceExtensions)(char**); int (*getPhysicalDevicePresentationSupport)(VkInstance,VkPhysicalDevice,uint32_t); VkResult (*createWindowSurface)(VkInstance,_GLFWwindow*,const VkAllocationCallbacks*,VkSurfaceKHR*); + void (*setWindowBlur)(_GLFWwindow*,GLFWbool); }; // Library global data diff --git a/src/null_init.c b/src/null_init.c index de4b28f3..d010e6c2 100644 --- a/src/null_init.c +++ b/src/null_init.c @@ -112,6 +112,7 @@ GLFWbool _glfwConnectNull(int platformID, _GLFWplatform* platform) _glfwGetRequiredInstanceExtensionsNull, _glfwGetPhysicalDevicePresentationSupportNull, _glfwCreateWindowSurfaceNull, + _glfwSetWindowBlurNull, }; *platform = null; diff --git a/src/null_platform.h b/src/null_platform.h index fca7c11f..ee9c97c4 100644 --- a/src/null_platform.h +++ b/src/null_platform.h @@ -51,6 +51,7 @@ typedef struct _GLFWwindowNull GLFWbool floating; GLFWbool transparent; float opacity; + GLFWbool blurred; } _GLFWwindowNull; // Null-specific per-monitor data @@ -111,6 +112,7 @@ void _glfwSetWindowFloatingNull(_GLFWwindow* window, GLFWbool enabled); void _glfwSetWindowMousePassthroughNull(_GLFWwindow* window, GLFWbool enabled); float _glfwGetWindowOpacityNull(_GLFWwindow* window); void _glfwSetWindowOpacityNull(_GLFWwindow* window, float opacity); +void _glfwSetWindowBlurNull(_GLFWwindow* window, GLFWbool enabled); void _glfwSetRawMouseMotionNull(_GLFWwindow *window, GLFWbool enabled); GLFWbool _glfwRawMouseMotionSupportedNull(void); void _glfwShowWindowNull(_GLFWwindow* window); diff --git a/src/null_window.c b/src/null_window.c index b40110b8..51c39467 100644 --- a/src/null_window.c +++ b/src/null_window.c @@ -409,6 +409,11 @@ void _glfwSetWindowOpacityNull(_GLFWwindow* window, float opacity) window->null.opacity = opacity; } +void _glfwSetWindowBlurNull(_GLFWwindow* window, GLFWbool enable) +{ + window->null.blurred = enable; +} + void _glfwSetRawMouseMotionNull(_GLFWwindow *window, GLFWbool enabled) { } diff --git a/src/window.c b/src/window.c index 621e2e64..d98baa25 100644 --- a/src/window.c +++ b/src/window.c @@ -359,6 +359,9 @@ GLFWAPI void glfwWindowHint(int hint, int value) case GLFW_MOUSE_PASSTHROUGH: _glfw.hints.window.mousePassthrough = value ? GLFW_TRUE : GLFW_FALSE; return; + case GLFW_BLURRED: + _glfw.hints.window.blurred = value ? GLFW_TRUE : GLFW_FALSE; + return; case GLFW_CLIENT_API: _glfw.hints.context.client = value; return; @@ -826,6 +829,8 @@ GLFWAPI int glfwGetWindowAttrib(GLFWwindow* handle, int attrib) return window->focusOnShow; case GLFW_MOUSE_PASSTHROUGH: return window->mousePassthrough; + case GLFW_BLURRED: + return window->blurred; case GLFW_TRANSPARENT_FRAMEBUFFER: return _glfw.platform.framebufferTransparent(window); case GLFW_RESIZABLE: @@ -907,6 +912,11 @@ GLFWAPI void glfwSetWindowAttrib(GLFWwindow* handle, int attrib, int value) window->mousePassthrough = value; _glfw.platform.setWindowMousePassthrough(window, value); return; + + case GLFW_BLURRED: + window->blurred = value; + _glfw.platform.setWindowBlur(window, value); + return; } _glfwInputError(GLFW_INVALID_ENUM, "Invalid window attribute 0x%08X", attrib); diff --git a/src/x11_init.c b/src/x11_init.c index aefa82db..21c529a9 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -972,6 +972,8 @@ static GLFWbool initExtensions(void) XInternAtom(_glfw.x11.display, "_NET_WM_WINDOW_OPACITY", False); _glfw.x11.MOTIF_WM_HINTS = XInternAtom(_glfw.x11.display, "_MOTIF_WM_HINTS", False); + _glfw.x11.KDE_NET_WM_BLUR_BEHIND_REGION = + XInternAtom(_glfw.x11.display, "_KDE_NET_WM_BLUR_BEHIND_REGION", False); // The compositing manager selection name contains the screen number { @@ -1243,6 +1245,7 @@ GLFWbool _glfwConnectX11(int platformID, _GLFWplatform* platform) _glfwGetRequiredInstanceExtensionsX11, _glfwGetPhysicalDevicePresentationSupportX11, _glfwCreateWindowSurfaceX11, + _glfwSetWindowBlurX11, }; // HACK: If the application has left the locale as "C" then both wide diff --git a/src/x11_platform.h b/src/x11_platform.h index 956104fa..082961fc 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -614,6 +614,7 @@ typedef struct _GLFWlibraryX11 Atom NET_FRAME_EXTENTS; Atom NET_REQUEST_FRAME_EXTENTS; Atom MOTIF_WM_HINTS; + Atom KDE_NET_WM_BLUR_BEHIND_REGION; // Xdnd (drag and drop) atoms Atom XdndAware; @@ -933,6 +934,7 @@ void _glfwSetWindowFloatingX11(_GLFWwindow* window, GLFWbool enabled); float _glfwGetWindowOpacityX11(_GLFWwindow* window); void _glfwSetWindowOpacityX11(_GLFWwindow* window, float opacity); void _glfwSetWindowMousePassthroughX11(_GLFWwindow* window, GLFWbool enabled); +void _glfwSetWindowBlurX11(_GLFWwindow* window, GLFWbool enabled); void _glfwSetRawMouseMotionX11(_GLFWwindow *window, GLFWbool enabled); GLFWbool _glfwRawMouseMotionSupportedX11(void); diff --git a/src/x11_window.c b/src/x11_window.c index 280dc986..26d0bf4b 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -604,6 +604,9 @@ static GLFWbool createNativeWindow(_GLFWwindow* window, if (!wndconfig->decorated) _glfwSetWindowDecoratedX11(window, GLFW_FALSE); + if (wndconfig->blurred) + _glfwSetWindowBlurX11(window, GLFW_TRUE); + if (_glfw.x11.NET_WM_STATE && !window->monitor) { Atom states[3]; @@ -2699,6 +2702,17 @@ void _glfwSetWindowOpacityX11(_GLFWwindow* window, float opacity) PropModeReplace, (unsigned char*) &value, 1); } +void _glfwSetWindowBlurX11(_GLFWwindow* window, GLFWbool enable) +{ + if (enable) + XChangeProperty(_glfw.x11.display, window->x11.handle, + _glfw.x11.KDE_NET_WM_BLUR_BEHIND_REGION, XA_CARDINAL, 32, + PropModeReplace, NULL, 0); + else + XDeleteProperty(_glfw.x11.display, window->x11.handle, + _glfw.x11.KDE_NET_WM_BLUR_BEHIND_REGION); +} + void _glfwSetRawMouseMotionX11(_GLFWwindow *window, GLFWbool enabled) { if (!_glfw.x11.xi.available) diff --git a/tests/window.c b/tests/window.c index 83baff46..49303df3 100644 --- a/tests/window.c +++ b/tests/window.c @@ -406,6 +406,10 @@ int main(int argc, char** argv) if (nk_checkbox_label(nk, "Auto Iconify", &auto_iconify)) glfwSetWindowAttrib(window, GLFW_AUTO_ICONIFY, auto_iconify); + int blurred = glfwGetWindowAttrib(window, GLFW_BLURRED); + if (nk_checkbox_label(nk, "Blur", &blurred)) + glfwSetWindowAttrib(window, GLFW_BLURRED, blurred); + nk_value_bool(nk, "Focused", glfwGetWindowAttrib(window, GLFW_FOCUSED)); nk_value_bool(nk, "Hovered", glfwGetWindowAttrib(window, GLFW_HOVERED)); nk_value_bool(nk, "Visible", glfwGetWindowAttrib(window, GLFW_VISIBLE));