mirror of https://github.com/encounter/SDL.git
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.
This commit is contained in:
parent
7ff3832e4d
commit
bd553ea868
|
@ -50,6 +50,7 @@
|
||||||
#include "xdg-decoration-unstable-v1-client-protocol.h"
|
#include "xdg-decoration-unstable-v1-client-protocol.h"
|
||||||
#include "org-kde-kwin-server-decoration-manager-client-protocol.h"
|
#include "org-kde-kwin-server-decoration-manager-client-protocol.h"
|
||||||
#include "keyboard-shortcuts-inhibit-unstable-v1-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"
|
#define WAYLANDVID_DRIVER_NAME "wayland"
|
||||||
|
|
||||||
|
@ -179,6 +180,7 @@ Wayland_CreateDevice(int devindex)
|
||||||
device->SetDisplayMode = Wayland_SetDisplayMode;
|
device->SetDisplayMode = Wayland_SetDisplayMode;
|
||||||
device->GetDisplayModes = Wayland_GetDisplayModes;
|
device->GetDisplayModes = Wayland_GetDisplayModes;
|
||||||
device->GetWindowWMInfo = Wayland_GetWindowWMInfo;
|
device->GetWindowWMInfo = Wayland_GetWindowWMInfo;
|
||||||
|
device->SuspendScreenSaver = Wayland_SuspendScreenSaver;
|
||||||
|
|
||||||
device->PumpEvents = Wayland_PumpEvents;
|
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);
|
Wayland_display_add_pointer_constraints(d, id);
|
||||||
} else if (strcmp(interface, "zwp_keyboard_shortcuts_inhibit_manager_v1") == 0) {
|
} 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);
|
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) {
|
} 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));
|
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) {
|
} else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
|
||||||
|
@ -456,6 +460,10 @@ Wayland_VideoInit(_THIS)
|
||||||
|
|
||||||
WAYLAND_wl_display_flush(data->display);
|
WAYLAND_wl_display_flush(data->display);
|
||||||
|
|
||||||
|
#if SDL_USE_LIBDBUS
|
||||||
|
SDL_DBus_Init();
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,6 +505,9 @@ Wayland_VideoQuit(_THIS)
|
||||||
Wayland_display_destroy_pointer_constraints(data);
|
Wayland_display_destroy_pointer_constraints(data);
|
||||||
Wayland_display_destroy_relative_pointer_manager(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)
|
if (data->key_inhibitor_manager)
|
||||||
zwp_keyboard_shortcuts_inhibit_manager_v1_destroy(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)
|
if (data->registry)
|
||||||
wl_registry_destroy(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);
|
SDL_free(data->classname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,8 @@
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include "wayland-util.h"
|
#include "wayland-util.h"
|
||||||
|
|
||||||
|
#include "../../core/linux/SDL_dbus.h"
|
||||||
|
|
||||||
struct xkb_context;
|
struct xkb_context;
|
||||||
struct SDL_WaylandInput;
|
struct SDL_WaylandInput;
|
||||||
|
|
||||||
|
@ -65,6 +67,7 @@ typedef struct {
|
||||||
struct zxdg_decoration_manager_v1 *decoration_manager;
|
struct zxdg_decoration_manager_v1 *decoration_manager;
|
||||||
struct org_kde_kwin_server_decoration_manager *kwin_server_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_keyboard_shortcuts_inhibit_manager_v1 *key_inhibitor_manager;
|
||||||
|
struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager;
|
||||||
|
|
||||||
EGLDisplay edpy;
|
EGLDisplay edpy;
|
||||||
EGLContext context;
|
EGLContext context;
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "xdg-shell-unstable-v6-client-protocol.h"
|
#include "xdg-shell-unstable-v6-client-protocol.h"
|
||||||
#include "xdg-decoration-unstable-v1-client-protocol.h"
|
#include "xdg-decoration-unstable-v1-client-protocol.h"
|
||||||
#include "org-kde-kwin-server-decoration-manager-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) {
|
static float get_window_scale_factor(SDL_Window *window) {
|
||||||
return ((SDL_WindowData*)window->driverdata)->scale_factor;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -916,6 +920,44 @@ void Wayland_SetWindowTitle(_THIS, SDL_Window * window)
|
||||||
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
|
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)
|
void Wayland_DestroyWindow(_THIS, SDL_Window *window)
|
||||||
{
|
{
|
||||||
SDL_VideoData *data = _this->driverdata;
|
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);
|
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 (data->shell.xdg) {
|
||||||
if (wind->shell_surface.xdg.roleobj.toplevel) {
|
if (wind->shell_surface.xdg.roleobj.toplevel) {
|
||||||
xdg_toplevel_destroy(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 zxdg_toplevel_decoration_v1 *server_decoration;
|
||||||
struct org_kde_kwin_server_decoration *kwin_server_decoration;
|
struct org_kde_kwin_server_decoration *kwin_server_decoration;
|
||||||
struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor;
|
struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor;
|
||||||
|
struct zwp_idle_inhibitor_v1 *idle_inhibitor;
|
||||||
|
|
||||||
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
|
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
|
||||||
struct qt_extended_surface *extended_surface;
|
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_SetWindowSize(_THIS, SDL_Window * window);
|
||||||
extern void Wayland_SetWindowTitle(_THIS, SDL_Window * window);
|
extern void Wayland_SetWindowTitle(_THIS, SDL_Window * window);
|
||||||
extern void Wayland_DestroyWindow(_THIS, SDL_Window *window);
|
extern void Wayland_DestroyWindow(_THIS, SDL_Window *window);
|
||||||
|
extern void Wayland_SuspendScreenSaver(_THIS);
|
||||||
|
|
||||||
extern SDL_bool
|
extern SDL_bool
|
||||||
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
|
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