mirror of
https://github.com/encounter/SDL.git
synced 2025-12-09 05:27:48 +00:00
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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user