X11: Add support for org.freedesktop.ScreenSaver

Related to #854.
This commit is contained in:
Camilla Löwy 2018-02-19 19:02:36 +01:00
parent f4cd470bcb
commit 35682ec3fa
7 changed files with 168 additions and 4 deletions

View File

@ -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()

View File

@ -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()
#--------------------------------------------------------------------

View File

@ -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

View File

@ -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.

View File

@ -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();

View File

@ -47,6 +47,9 @@
// The XInput extension provides raw mouse motion input
#include <X11/extensions/XInput2.h>
// DBus is used to inhibit the screensaver
#include <dbus/dbus.h>
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

View File

@ -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);
}
}
}