Implement support for inhibiting the screensaver on Wayland
We support both the org.freedesktop.ScreenSaver D-Bus API (same as the X11 backend) and the Wayland idle_inhibit_unstable_v1 protocol. Some Wayland compositors only support one or the other, so we need both to for broad compatibility.main
parent
7ff3832e4d
commit
bd553ea868
|
@ -50,6 +50,7 @@
|
|||
#include "xdg-decoration-unstable-v1-client-protocol.h"
|
||||
#include "org-kde-kwin-server-decoration-manager-client-protocol.h"
|
||||
#include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h"
|
||||
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
||||
|
||||
#define WAYLANDVID_DRIVER_NAME "wayland"
|
||||
|
||||
|
@ -179,6 +180,7 @@ Wayland_CreateDevice(int devindex)
|
|||
device->SetDisplayMode = Wayland_SetDisplayMode;
|
||||
device->GetDisplayModes = Wayland_GetDisplayModes;
|
||||
device->GetWindowWMInfo = Wayland_GetWindowWMInfo;
|
||||
device->SuspendScreenSaver = Wayland_SuspendScreenSaver;
|
||||
|
||||
device->PumpEvents = Wayland_PumpEvents;
|
||||
|
||||
|
@ -397,6 +399,8 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
|
|||
Wayland_display_add_pointer_constraints(d, id);
|
||||
} else if (strcmp(interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0) {
|
||||
d->key_inhibitor_manager = wl_registry_bind(d->registry, id, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1);
|
||||
} else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0) {
|
||||
d->idle_inhibit_manager = wl_registry_bind(d->registry, id, &zwp_idle_inhibit_manager_v1_interface, 1);
|
||||
} else if (strcmp(interface, "wl_data_device_manager") == 0) {
|
||||
d->data_device_manager = wl_registry_bind(d->registry, id, &wl_data_device_manager_interface, SDL_min(3, version));
|
||||
} else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
|
||||
|
@ -456,6 +460,10 @@ Wayland_VideoInit(_THIS)
|
|||
|
||||
WAYLAND_wl_display_flush(data->display);
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
SDL_DBus_Init();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -497,6 +505,9 @@ Wayland_VideoQuit(_THIS)
|
|||
Wayland_display_destroy_pointer_constraints(data);
|
||||
Wayland_display_destroy_relative_pointer_manager(data);
|
||||
|
||||
if (data->idle_inhibit_manager)
|
||||
zwp_idle_inhibit_manager_v1_destroy(data->idle_inhibit_manager);
|
||||
|
||||
if (data->key_inhibitor_manager)
|
||||
zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(data->key_inhibitor_manager);
|
||||
|
||||
|
@ -535,6 +546,12 @@ Wayland_VideoQuit(_THIS)
|
|||
if (data->registry)
|
||||
wl_registry_destroy(data->registry);
|
||||
|
||||
/* !!! FIXME: other subsystems use D-Bus, so we shouldn't quit it here;
|
||||
have SDL.c do this at a higher level, or add refcounting. */
|
||||
#if SDL_USE_LIBDBUS
|
||||
SDL_DBus_Quit();
|
||||
#endif
|
||||
|
||||
SDL_free(data->classname);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include <EGL/egl.h>
|
||||
#include "wayland-util.h"
|
||||
|
||||
#include "../../core/linux/SDL_dbus.h"
|
||||
|
||||
struct xkb_context;
|
||||
struct SDL_WaylandInput;
|
||||
|
||||
|
@ -65,6 +67,7 @@ typedef struct {
|
|||
struct zxdg_decoration_manager_v1 *decoration_manager;
|
||||
struct org_kde_kwin_server_decoration_manager *kwin_server_decoration_manager;
|
||||
struct zwp_keyboard_shortcuts_inhibit_manager_v1 *key_inhibitor_manager;
|
||||
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
|
||||
|
||||
EGLDisplay edpy;
|
||||
EGLContext context;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "xdg-shell-unstable-v6-client-protocol.h"
|
||||
#include "xdg-decoration-unstable-v1-client-protocol.h"
|
||||
#include "org-kde-kwin-server-decoration-manager-client-protocol.h"
|
||||
#include "idle-inhibit-unstable-v1-client-protocol.h"
|
||||
|
||||
static float get_window_scale_factor(SDL_Window *window) {
|
||||
return ((SDL_WindowData*)window->driverdata)->scale_factor;
|
||||
|
@ -838,6 +839,9 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
|
|||
}
|
||||
}
|
||||
|
||||
/* We may need to create an idle inhibitor for this new window */
|
||||
Wayland_SuspendScreenSaver(_this);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -916,6 +920,44 @@ void Wayland_SetWindowTitle(_THIS, SDL_Window * window)
|
|||
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
|
||||
}
|
||||
|
||||
void
|
||||
Wayland_SuspendScreenSaver(_THIS)
|
||||
{
|
||||
SDL_VideoData *data = (SDL_VideoData *)_this->driverdata;
|
||||
|
||||
#if SDL_USE_LIBDBUS
|
||||
if (SDL_DBus_ScreensaverInhibit(_this->suspend_screensaver)) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The idle_inhibit_unstable_v1 protocol suspends the screensaver
|
||||
on a per wl_surface basis, but SDL assumes that suspending
|
||||
the screensaver can be done independently of any window.
|
||||
|
||||
To reconcile these differences, we propagate the idle inhibit
|
||||
state to each window. If there is no window active, we will
|
||||
be able to inhibit idle once the first window is created.
|
||||
*/
|
||||
if (data->idle_inhibit_manager) {
|
||||
SDL_Window *window = _this->windows;
|
||||
while (window) {
|
||||
SDL_WindowData *win_data = window->driverdata;
|
||||
|
||||
if (_this->suspend_screensaver && !win_data->idle_inhibitor) {
|
||||
win_data->idle_inhibitor =
|
||||
zwp_idle_inhibit_manager_v1_create_inhibitor(data->idle_inhibit_manager,
|
||||
win_data->surface);
|
||||
} else if (!_this->suspend_screensaver && win_data->idle_inhibitor) {
|
||||
zwp_idle_inhibitor_v1_destroy(win_data->idle_inhibitor);
|
||||
win_data->idle_inhibitor = NULL;
|
||||
}
|
||||
|
||||
window = window->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Wayland_DestroyWindow(_THIS, SDL_Window *window)
|
||||
{
|
||||
SDL_VideoData *data = _this->driverdata;
|
||||
|
@ -937,6 +979,10 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window)
|
|||
org_kde_kwin_server_decoration_release(wind->kwin_server_decoration);
|
||||
}
|
||||
|
||||
if (wind->idle_inhibitor) {
|
||||
zwp_idle_inhibitor_v1_destroy(wind->idle_inhibitor);
|
||||
}
|
||||
|
||||
if (data->shell.xdg) {
|
||||
if (wind->shell_surface.xdg.roleobj.toplevel) {
|
||||
xdg_toplevel_destroy(wind->shell_surface.xdg.roleobj.toplevel);
|
||||
|
|
|
@ -66,6 +66,7 @@ typedef struct {
|
|||
struct zxdg_toplevel_decoration_v1 *server_decoration;
|
||||
struct org_kde_kwin_server_decoration *kwin_server_decoration;
|
||||
struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor;
|
||||
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
|
||||
struct qt_extended_surface *extended_surface;
|
||||
|
@ -97,6 +98,7 @@ extern int Wayland_CreateWindow(_THIS, SDL_Window *window);
|
|||
extern void Wayland_SetWindowSize(_THIS, SDL_Window * window);
|
||||
extern void Wayland_SetWindowTitle(_THIS, SDL_Window * window);
|
||||
extern void Wayland_DestroyWindow(_THIS, SDL_Window *window);
|
||||
extern void Wayland_SuspendScreenSaver(_THIS);
|
||||
|
||||
extern SDL_bool
|
||||
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="idle_inhibit_unstable_v1">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2015 Samsung Electronics Co., Ltd
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice (including the next
|
||||
paragraph) shall be included in all copies or substantial portions of the
|
||||
Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
</copyright>
|
||||
|
||||
<interface name="zwp_idle_inhibit_manager_v1" version="1">
|
||||
<description summary="control behavior when display idles">
|
||||
This interface permits inhibiting the idle behavior such as screen
|
||||
blanking, locking, and screensaving. The client binds the idle manager
|
||||
globally, then creates idle-inhibitor objects for each surface.
|
||||
|
||||
Warning! The protocol described in this file is experimental and
|
||||
backward incompatible changes may be made. Backward compatible changes
|
||||
may be added together with the corresponding interface version bump.
|
||||
Backward incompatible changes are done by bumping the version number in
|
||||
the protocol and interface names and resetting the interface version.
|
||||
Once the protocol is to be declared stable, the 'z' prefix and the
|
||||
version number in the protocol and interface names are removed and the
|
||||
interface version number is reset.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the idle inhibitor object">
|
||||
Destroy the inhibit manager.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="create_inhibitor">
|
||||
<description summary="create a new inhibitor object">
|
||||
Create a new inhibitor object associated with the given surface.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="zwp_idle_inhibitor_v1"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"
|
||||
summary="the surface that inhibits the idle behavior"/>
|
||||
</request>
|
||||
|
||||
</interface>
|
||||
|
||||
<interface name="zwp_idle_inhibitor_v1" version="1">
|
||||
<description summary="context object for inhibiting idle behavior">
|
||||
An idle inhibitor prevents the output that the associated surface is
|
||||
visible on from being set to a state where it is not visually usable due
|
||||
to lack of user interaction (e.g. blanked, dimmed, locked, set to power
|
||||
save, etc.) Any screensaver processes are also blocked from displaying.
|
||||
|
||||
If the surface is destroyed, unmapped, becomes occluded, loses
|
||||
visibility, or otherwise becomes not visually relevant for the user, the
|
||||
idle inhibitor will not be honored by the compositor; if the surface
|
||||
subsequently regains visibility the inhibitor takes effect once again.
|
||||
Likewise, the inhibitor isn't honored if the system was already idled at
|
||||
the time the inhibitor was established, although if the system later
|
||||
de-idles and re-idles the inhibitor will take effect.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the idle inhibitor object">
|
||||
Remove the inhibitor effect from the associated wl_surface.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
</interface>
|
||||
</protocol>
|
Loading…
Reference in New Issue