Wayland: Add support for the idle-inhibit protocol
Closes #955.
diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h
index 157a482..dfff8d3 100644
--- a/include/GLFW/glfw3.h
+++ b/include/GLFW/glfw3.h
@@ -2358,7 +2358,8 @@
* icons, the window will inherit the one defined in the application's
* desktop file, so this function emits @ref GLFW_PLATFORM_ERROR.
*
- * @remark @wayland Screensaver inhibition is currently unimplemented.
+ * @remark @wayland Screensaver inhibition requires the idle-inhibit protocol
+ * to be implemented in the user's compositor.
*
* @thread_safety This function must only be called from the main thread.
*
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b14512c..01c0105 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -47,6 +47,10 @@
PROTOCOL
"${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
BASENAME pointer-constraints-unstable-v1)
+ ecm_add_wayland_client_protocol(glfw_SOURCES
+ PROTOCOL
+ ${WAYLAND_PROTOCOLS_PKGDATADIR}/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml
+ BASENAME idle-inhibit-unstable-v1)
elseif (_GLFW_MIR)
set(glfw_HEADERS ${common_HEADERS} mir_platform.h linux_joystick.h
posix_time.h posix_thread.h xkb_unicode.h egl_context.h
diff --git a/src/wl_init.c b/src/wl_init.c
index d6832aa..ec25f20 100644
--- a/src/wl_init.c
+++ b/src/wl_init.c
@@ -501,6 +501,13 @@
&zwp_pointer_constraints_v1_interface,
1);
}
+ else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0)
+ {
+ _glfw.wl.idleInhibitManager =
+ wl_registry_bind(registry, name,
+ &zwp_idle_inhibit_manager_v1_interface,
+ 1);
+ }
}
static void registryHandleGlobalRemove(void *data,
@@ -786,6 +793,8 @@
zwp_relative_pointer_manager_v1_destroy(_glfw.wl.relativePointerManager);
if (_glfw.wl.pointerConstraints)
zwp_pointer_constraints_v1_destroy(_glfw.wl.pointerConstraints);
+ if (_glfw.wl.idleInhibitManager)
+ zwp_idle_inhibit_manager_v1_destroy(_glfw.wl.idleInhibitManager);
if (_glfw.wl.registry)
wl_registry_destroy(_glfw.wl.registry);
if (_glfw.wl.display)
diff --git a/src/wl_platform.h b/src/wl_platform.h
index 96c0a99..516c84b 100644
--- a/src/wl_platform.h
+++ b/src/wl_platform.h
@@ -54,6 +54,7 @@
#include "wayland-relative-pointer-unstable-v1-client-protocol.h"
#include "wayland-pointer-constraints-unstable-v1-client-protocol.h"
+#include "wayland-idle-inhibit-unstable-v1-client-protocol.h"
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
@@ -138,6 +139,9 @@
struct zwp_relative_pointer_v1* relativePointer;
struct zwp_locked_pointer_v1* lockedPointer;
} pointerLock;
+
+ struct zwp_idle_inhibitor_v1* idleInhibitor;
+
} _GLFWwindowWayland;
// Wayland-specific global data
@@ -154,6 +158,7 @@
struct wl_keyboard* keyboard;
struct zwp_relative_pointer_manager_v1* relativePointerManager;
struct zwp_pointer_constraints_v1* pointerConstraints;
+ struct zwp_idle_inhibit_manager_v1* idleInhibitManager;
int compositorVersion;
diff --git a/src/wl_window.c b/src/wl_window.c
index b2ae7aa..9759ba2 100644
--- a/src/wl_window.c
+++ b/src/wl_window.c
@@ -189,6 +189,24 @@
wl_region_destroy(region);
}
+static void setIdleInhibitor(_GLFWwindow* window, GLFWbool enable)
+{
+ if (enable && !window->wl.idleInhibitor && _glfw.wl.idleInhibitManager)
+ {
+ window->wl.idleInhibitor =
+ zwp_idle_inhibit_manager_v1_create_inhibitor(
+ _glfw.wl.idleInhibitManager, window->wl.surface);
+ if (!window->wl.idleInhibitor)
+ _glfwInputError(GLFW_PLATFORM_ERROR,
+ "Wayland: Idle inhibitor creation failed");
+ }
+ else if (!enable && window->wl.idleInhibitor)
+ {
+ zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
+ window->wl.idleInhibitor = NULL;
+ }
+}
+
static GLFWbool createSurface(_GLFWwindow* window,
const _GLFWwndconfig* wndconfig)
{
@@ -239,14 +257,17 @@
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0,
window->monitor->wl.output);
+ setIdleInhibitor(window, GLFW_TRUE);
}
else if (window->wl.maximized)
{
wl_shell_surface_set_maximized(window->wl.shellSurface, NULL);
+ setIdleInhibitor(window, GLFW_FALSE);
}
else
{
wl_shell_surface_set_toplevel(window->wl.shellSurface);
+ setIdleInhibitor(window, GLFW_FALSE);
}
wl_surface_commit(window->wl.surface);
@@ -452,6 +473,9 @@
_glfwInputWindowFocus(window, GLFW_FALSE);
}
+ if (window->wl.idleInhibitor)
+ zwp_idle_inhibitor_v1_destroy(window->wl.idleInhibitor);
+
if (window->context.destroy)
window->context.destroy(window);
@@ -637,10 +661,12 @@
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
refreshRate * 1000, // Convert Hz to mHz.
monitor->wl.output);
+ setIdleInhibitor(window, GLFW_TRUE);
}
else
{
wl_shell_surface_set_toplevel(window->wl.shellSurface);
+ setIdleInhibitor(window, GLFW_FALSE);
}
_glfwInputWindowMonitor(window, monitor);
}