From 35682ec3fae90a14ef2038a1fcf534b0ec291b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Camilla=20L=C3=B6wy?= Date: Mon, 19 Feb 2018 19:02:36 +0100 Subject: [PATCH] X11: Add support for org.freedesktop.ScreenSaver Related to #854. --- CMake/modules/FindDBus.cmake | 21 ++++++++++++++++ CMakeLists.txt | 5 ++++ README.md | 1 + docs/compile.dox | 9 ++++--- src/x11_init.c | 48 ++++++++++++++++++++++++++++++++++++ src/x11_platform.h | 43 ++++++++++++++++++++++++++++++++ src/x11_window.c | 45 +++++++++++++++++++++++++++++++++ 7 files changed, 168 insertions(+), 4 deletions(-) create mode 100644 CMake/modules/FindDBus.cmake diff --git a/CMake/modules/FindDBus.cmake b/CMake/modules/FindDBus.cmake new file mode 100644 index 00000000..40d0be4f --- /dev/null +++ b/CMake/modules/FindDBus.cmake @@ -0,0 +1,21 @@ +# Find libdbus +# +# DBUS_INCLUDE_DIRS +# DBUS_LIBRARY +# DBUS_FOUND + +find_package(PkgConfig) +if (PKG_CONFIG_FOUND) + + pkg_check_modules(PC_DBUS dbus-1 QUIET) + if (PC_DBUS_FOUND) + set(DBUS_INCLUDE_DIRS ${PC_DBUS_INCLUDE_DIRS}) + find_library(DBUS_LIBRARY dbus-1 PATHS ${PC_DBUS_LIBRARY_DIRS}) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(DBus DEFAULT_MSG DBUS_LIBRARY DBUS_INCLUDE_DIRS) + mark_as_advanced(DBUS_INCLUDE_DIRS DBUS_LIBRARY) + endif() + +endif() + diff --git a/CMakeLists.txt b/CMakeLists.txt index a50c6e3e..a2167deb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -215,6 +215,11 @@ if (UNIX AND NOT APPLE) list(APPEND glfw_LIBRARIES "${CMAKE_DL_LIBS}") list(APPEND glfw_PKG_LIBS "-l${CMAKE_DL_LIBS}") endif() + + find_package(DBus) + if (DBUS_FOUND) + list(APPEND glfw_INCLUDE_DIRS ${DBUS_INCLUDE_DIRS}) + endif() endif() #-------------------------------------------------------------------- diff --git a/README.md b/README.md index b2d0d01a..d367308c 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,7 @@ information on what to include when reporting a bug. - [Win32] Bugfix: The HID device notification was not unregistered (#1170) - [Win32] Bugfix: `glfwCreateWindow` activated window even with `GLFW_FOCUSED` hint set to false (#1179,#1180) +- [X11] Added support for `org.freedesktop.ScreenSaver` (#854) - [X11] Moved to XI2 `XI_RawMotion` for disable cursor mode motion input (#125) - [X11] Replaced `_GLFW_HAS_XF86VM` compile-time option with dynamic loading - [X11] Bugfix: `glfwGetVideoMode` would segfault on Cygwin/X diff --git a/docs/compile.dox b/docs/compile.dox index 0eed2411..945f8b7a 100644 --- a/docs/compile.dox +++ b/docs/compile.dox @@ -88,10 +88,11 @@ Once you have Xcode installed, move on to @ref compile_generate. @subsubsection compile_deps_x11 Dependencies for Linux and X11 -To compile GLFW for X11, you need to have the X11 packages installed, as well as -the basic development tools like GCC and make. For example, on Ubuntu and other -distributions based on Debian GNU/Linux, you need to install the `xorg-dev` -package, which pulls in all X.org header packages. +To compile GLFW for X11, you need to have the X11 and libdbus development +packages installed, as well as the basic development tools like GCC and make. +For example, on Ubuntu and other distributions based on Debian GNU/Linux, you +need to install the `xorg-dev` and `libdbus-1-dev` packages. The `xorg-dev` +package in turn pulls in all X.org header packages. Once you have installed the necessary packages, move on to @ref compile_generate. diff --git a/src/x11_init.c b/src/x11_init.c index af4fb7ed..f3a5c3b7 100644 --- a/src/x11_init.c +++ b/src/x11_init.c @@ -674,6 +674,45 @@ static GLFWbool initExtensions(void) } } +#if defined(__CYGWIN__) + _glfw.x11.dbus.handle = _glfw_dlopen("libdbus-1-3.so"); +#else + _glfw.x11.dbus.handle = _glfw_dlopen("libdbus-1.so.3"); +#endif + if (_glfw.x11.dbus.handle) + { + DBusError error; + + _glfw.x11.dbus.error_init = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_error_init"); + _glfw.x11.dbus.error_is_set = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_error_is_set"); + _glfw.x11.dbus.bus_get_private = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_bus_get_private"); + _glfw.x11.dbus.connection_set_exit_on_disconnect = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_connection_set_exit_on_disconnect"); + _glfw.x11.dbus.connection_send_with_reply_and_block = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_connection_send_with_reply_and_block"); + _glfw.x11.dbus.connection_close = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_connection_close"); + _glfw.x11.dbus.connection_unref = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_connection_unref"); + _glfw.x11.dbus.message_new_method_call = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_message_new_method_call"); + _glfw.x11.dbus.message_append_args = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_message_append_args"); + _glfw.x11.dbus.message_get_args = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_message_get_args"); + _glfw.x11.dbus.message_unref = + _glfw_dlsym(_glfw.x11.dbus.handle, "dbus_message_unref"); + + dbus_error_init(&error); + + _glfw.x11.dbus.session = dbus_bus_get_private(DBUS_BUS_SESSION, &error); + if (!dbus_error_is_set(&error)) + dbus_connection_set_exit_on_disconnect(_glfw.x11.dbus.session, FALSE); + } + // Update the key code LUT // FIXME: We should listen to XkbMapNotify events to track changes to // the keyboard mapping. @@ -1024,6 +1063,15 @@ void _glfwPlatformTerminate(void) _glfw.x11.xinerama.handle = NULL; } + if (_glfw.x11.dbus.session) + { + dbus_connection_close(_glfw.x11.dbus.session); + dbus_connection_unref(_glfw.x11.dbus.session); + } + + if (_glfw.x11.dbus.handle) + _glfw_dlclose(_glfw.x11.dbus.handle); + // NOTE: These need to be unloaded after XCloseDisplay, as they register // cleanup callbacks that get called by that function _glfwTerminateEGL(); diff --git a/src/x11_platform.h b/src/x11_platform.h index c37c740e..7acbf575 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -47,6 +47,9 @@ // The XInput extension provides raw mouse motion input #include +// DBus is used to inhibit the screensaver +#include + typedef XRRCrtcGamma* (* PFN_XRRAllocGamma)(int); typedef void (* PFN_XRRFreeCrtcInfo)(XRRCrtcInfo*); typedef void (* PFN_XRRFreeGamma)(XRRCrtcGamma*); @@ -123,6 +126,29 @@ typedef XRenderPictFormat* (* PFN_XRenderFindVisualFormat)(Display*,Visual const #define XRenderQueryVersion _glfw.x11.xrender.QueryVersion #define XRenderFindVisualFormat _glfw.x11.xrender.FindVisualFormat +typedef void (*PFN_dbus_error_init)(DBusError*); +typedef dbus_bool_t (*PFN_dbus_error_is_set)(const DBusError*); +typedef DBusConnection* (*PFN_dbus_bus_get_private)(DBusBusType,DBusError*); +typedef void (*PFN_dbus_connection_set_exit_on_disconnect)(DBusConnection*,dbus_bool_t); +typedef void (*PFN_dbus_connection_close)(DBusConnection*); +typedef void (*PFN_dbus_connection_unref)(DBusConnection*); +typedef DBusMessage* (*PFN_dbus_connection_send_with_reply_and_block)(DBusConnection*,DBusMessage*,int,DBusError*); +typedef DBusMessage* (*PFN_dbus_message_new_method_call)(const char*,const char*,const char*,const char*); +typedef dbus_bool_t (*PFN_dbus_message_append_args)(DBusMessage*,int,...); +typedef dbus_bool_t (*PFN_dbus_message_get_args)(DBusMessage*,DBusError*,int,...); +typedef void (*PFN_dbus_message_unref)(DBusMessage*); +#define dbus_error_init _glfw.x11.dbus.error_init +#define dbus_error_is_set _glfw.x11.dbus.error_is_set +#define dbus_bus_get_private _glfw.x11.dbus.bus_get_private +#define dbus_connection_set_exit_on_disconnect _glfw.x11.dbus.connection_set_exit_on_disconnect +#define dbus_connection_close _glfw.x11.dbus.connection_close +#define dbus_connection_unref _glfw.x11.dbus.connection_unref +#define dbus_connection_send_with_reply_and_block _glfw.x11.dbus.connection_send_with_reply_and_block +#define dbus_message_new_method_call _glfw.x11.dbus.message_new_method_call +#define dbus_message_append_args _glfw.x11.dbus.message_append_args +#define dbus_message_get_args _glfw.x11.dbus.message_get_args +#define dbus_message_unref _glfw.x11.dbus.message_unref + typedef VkFlags VkXlibSurfaceCreateFlagsKHR; typedef VkFlags VkXcbSurfaceCreateFlagsKHR; @@ -399,6 +425,23 @@ typedef struct _GLFWlibraryX11 PFN_XRenderFindVisualFormat FindVisualFormat; } xrender; + struct { + void* handle; + DBusConnection* session; + uint32_t cookie; + PFN_dbus_error_init error_init; + PFN_dbus_error_is_set error_is_set; + PFN_dbus_bus_get_private bus_get_private; + PFN_dbus_connection_set_exit_on_disconnect connection_set_exit_on_disconnect; + PFN_dbus_connection_close connection_close; + PFN_dbus_connection_unref connection_unref; + PFN_dbus_connection_send_with_reply_and_block connection_send_with_reply_and_block; + PFN_dbus_message_new_method_call message_new_method_call; + PFN_dbus_message_append_args message_append_args; + PFN_dbus_message_get_args message_get_args; + PFN_dbus_message_unref message_unref; + } dbus; + } _GLFWlibraryX11; // X11-specific per-monitor data diff --git a/src/x11_window.c b/src/x11_window.c index f3014ec9..95b5837a 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -1090,6 +1090,37 @@ static void acquireMonitor(_GLFWwindow* window) // Disable screen saver XSetScreenSaver(_glfw.x11.display, 0, 0, DontPreferBlanking, DefaultExposures); + + if (_glfw.x11.dbus.session) + { + DBusError error; + DBusMessage* call; + DBusMessage* reply; + const char* name = "GLFW"; + const char* reason = "Active fullscreen window"; + + call = dbus_message_new_method_call("org.freedesktop.ScreenSaver", + "/org/freedesktop/ScreenSaver", + "org.freedesktop.ScreenSaver", + "Inhibit"); + dbus_message_append_args(call, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &reason, + DBUS_TYPE_INVALID); + dbus_error_init(&error); + reply = dbus_connection_send_with_reply_and_block(_glfw.x11.dbus.session, + call, 100, &error); + dbus_message_unref(call); + + if (!dbus_error_is_set(&error)) + { + dbus_error_init(&error); + dbus_message_get_args(reply, &error, + DBUS_TYPE_UINT32, &_glfw.x11.dbus.cookie, + DBUS_TYPE_INVALID); + dbus_message_unref(reply); + } + } } if (!window->monitor->window) @@ -1133,6 +1164,20 @@ static void releaseMonitor(_GLFWwindow* window) _glfw.x11.saver.interval, _glfw.x11.saver.blanking, _glfw.x11.saver.exposure); + + if (_glfw.x11.dbus.session) + { + DBusMessage* call; + + call = dbus_message_new_method_call("org.freedesktop.ScreenSaver", + "/org/freedesktop/ScreenSaver", + "org.freedesktop.ScreenSaver", + "UnInhibit"); + dbus_message_append_args(call, + DBUS_TYPE_UINT32, &_glfw.x11.dbus.cookie, + DBUS_TYPE_INVALID); + dbus_message_unref(call); + } } }