diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-07-15 01:38:55 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-07-15 01:38:55 +0000 |
commit | 5af7d6bff3d2920aca118a36f13b23cbb68c1641 (patch) | |
tree | 72de1ffeece20df48a837aff067d6ae89b349989 | |
parent | de0f4b0f5b8984c58279211ce122c8d900915d1d (diff) | |
parent | 966ab1152dc9f803024d7f9b9d95f595a8c2b211 (diff) | |
download | gtk+-5af7d6bff3d2920aca118a36f13b23cbb68c1641.tar.gz |
Merge branch 'idle-inhibit' into 'master'
Add support for idle inhibition on Wayland
Closes #2202
See merge request GNOME/gtk!2226
-rw-r--r-- | gdk/wayland/gdkdisplay-wayland.c | 6 | ||||
-rw-r--r-- | gdk/wayland/gdkdisplay-wayland.h | 2 | ||||
-rw-r--r-- | gdk/wayland/gdksurface-wayland.c | 36 | ||||
-rw-r--r-- | gdk/wayland/gdkwaylandsurface.h | 3 | ||||
-rw-r--r-- | gdk/wayland/meson.build | 1 | ||||
-rw-r--r-- | gtk/gtkapplication-wayland.c | 104 |
6 files changed, 151 insertions, 1 deletions
diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index af30f9cfc2..45f937dfab 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -544,6 +544,12 @@ gdk_registry_handle_global (void *data, gdk_wayland_display_init_xdg_output (display_wayland); _gdk_wayland_display_async_roundtrip (display_wayland); } + else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0) + { + display_wayland->idle_inhibit_manager = + wl_registry_bind (display_wayland->wl_registry, id, + &zwp_idle_inhibit_manager_v1_interface, 1); + } g_hash_table_insert (display_wayland->known_globals, GUINT_TO_POINTER (id), g_strdup (interface)); diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 5ace0f2744..db5e6a4fb3 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -35,6 +35,7 @@ #include <gdk/wayland/keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h> #include <gdk/wayland/server-decoration-client-protocol.h> #include <gdk/wayland/xdg-output-unstable-v1-client-protocol.h> +#include <gdk/wayland/idle-inhibit-unstable-v1-client-protocol.h> #include <glib.h> #include <gdk/gdkkeys.h> @@ -109,6 +110,7 @@ struct _GdkWaylandDisplay struct zwp_keyboard_shortcuts_inhibit_manager_v1 *keyboard_shortcuts_inhibit; struct org_kde_kwin_server_decoration_manager *server_decoration_manager; struct zxdg_output_manager_v1 *xdg_output_manager; + struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; GList *async_roundtrips; diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c index ef3f277664..46fec90c8e 100644 --- a/gdk/wayland/gdksurface-wayland.c +++ b/gdk/wayland/gdksurface-wayland.c @@ -191,6 +191,9 @@ struct _GdkWaylandSurface struct zxdg_imported_v1 *imported_transient_for; GHashTable *shortcuts_inhibitors; + + struct zwp_idle_inhibitor_v1 *idle_inhibitor; + size_t idle_inhibitor_refcount; }; struct _GdkWaylandSurfaceClass @@ -1984,6 +1987,39 @@ gdk_wayland_surface_announce_csd (GdkSurface *surface) ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_CLIENT); } +gboolean +gdk_wayland_surface_inhibit_idle (GdkSurface *surface) +{ + GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface)); + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + + if (!display_wayland->idle_inhibit_manager) + return false; + if (!impl->idle_inhibitor) + { + g_assert (impl->idle_inhibitor_refcount == 0); + impl->idle_inhibitor = + zwp_idle_inhibit_manager_v1_create_inhibitor (display_wayland->idle_inhibit_manager, + impl->display_server.wl_surface); + } + ++impl->idle_inhibitor_refcount; + return true; +} + +void +gdk_wayland_surface_uninhibit_idle (GdkSurface *surface) +{ + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + + g_assert (impl->idle_inhibitor && impl->idle_inhibitor_refcount > 0); + + if (--impl->idle_inhibitor_refcount == 0) + { + zwp_idle_inhibitor_v1_destroy (impl->idle_inhibitor); + impl->idle_inhibitor = NULL; + } +} + static void calculate_popup_rect (GdkSurface *surface, GdkPopupLayout *layout, diff --git a/gdk/wayland/gdkwaylandsurface.h b/gdk/wayland/gdkwaylandsurface.h index 4af358c33e..54e0c6ff49 100644 --- a/gdk/wayland/gdkwaylandsurface.h +++ b/gdk/wayland/gdkwaylandsurface.h @@ -80,6 +80,9 @@ void gdk_wayland_surface_set_application_id (GdkSurface *sur void gdk_wayland_surface_announce_csd (GdkSurface *surface); +gboolean gdk_wayland_surface_inhibit_idle (GdkSurface *surface); +void gdk_wayland_surface_uninhibit_idle (GdkSurface *surface); + G_END_DECLS #endif /* __GDK_WAYLAND_SURFACE_H__ */ diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build index 14267f4ccc..67ebb63da5 100644 --- a/gdk/wayland/meson.build +++ b/gdk/wayland/meson.build @@ -54,6 +54,7 @@ proto_sources = [ ['keyboard-shortcuts-inhibit', 'unstable', 'v1', ], ['server-decoration', 'private' ], ['xdg-output', 'unstable', 'v1', ], + ['idle-inhibit', 'unstable', 'v1', ], ] gdk_wayland_gen_headers = [] diff --git a/gtk/gtkapplication-wayland.c b/gtk/gtkapplication-wayland.c index 34d85e31bb..face15505c 100644 --- a/gtk/gtkapplication-wayland.c +++ b/gtk/gtkapplication-wayland.c @@ -1,6 +1,7 @@ /* * Copyright © 2010 Codethink Limited * Copyright © 2013 Canonical Limited + * Copyright © 2020 Emmanuel Gil Peyrot * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,12 +25,42 @@ #include "gtknative.h" #include <gdk/wayland/gdkwayland.h> +#include <gdk/wayland/gdkdisplay-wayland.h> +#include <gdk/wayland/idle-inhibit-unstable-v1-client-protocol.h> -typedef GtkApplicationImplDBusClass GtkApplicationImplWaylandClass; +typedef struct +{ + GtkApplicationImplDBusClass parent_class; + + /* stores the dbus version of the overriden methods */ + guint (*dbus_inhibit) (GtkApplicationImpl *impl, + GtkWindow *window, + GtkApplicationInhibitFlags flags, + const gchar *reason); + void (*dbus_uninhibit) (GtkApplicationImpl *impl, + guint cookie); +} GtkApplicationImplWaylandClass; + +typedef struct +{ + guint cookie; + guint dbus_cookie; + GtkApplicationInhibitFlags flags; + GdkSurface *surface; + +} GtkApplicationWaylandInhibitor; + +static void +gtk_application_wayland_inhibitor_free (GtkApplicationWaylandInhibitor *inhibitor) +{ + g_slice_free (GtkApplicationWaylandInhibitor, inhibitor); +} typedef struct { GtkApplicationImplDBus dbus; + GSList *inhibitors; + guint next_cookie; } GtkApplicationImplWayland; @@ -72,6 +103,70 @@ gtk_application_impl_wayland_before_emit (GtkApplicationImpl *impl, gdk_wayland_display_set_startup_notification_id (gdk_display_get_default (), startup_notification_id); } +static guint +gtk_application_impl_wayland_inhibit (GtkApplicationImpl *impl, + GtkWindow *window, + GtkApplicationInhibitFlags flags, + const gchar *reason) +{ + GtkApplicationImplWayland *wayland = (GtkApplicationImplWayland *) impl; + GdkSurface *surface; + GtkApplicationWaylandInhibitor *inhibitor; + gboolean success; + + if (!flags) + return 0; + + inhibitor = g_slice_new (GtkApplicationWaylandInhibitor); + inhibitor->cookie = ++wayland->next_cookie; + inhibitor->flags = flags; + wayland->inhibitors = g_slist_prepend (wayland->inhibitors, inhibitor); + + if (flags & GTK_APPLICATION_INHIBIT_IDLE) + { + surface = gtk_native_get_surface (GTK_NATIVE (window)); + if (GDK_IS_WAYLAND_SURFACE (surface)) + { + success = gdk_wayland_surface_inhibit_idle (surface); + if (success) + { + flags &= ~GTK_APPLICATION_INHIBIT_IDLE; + inhibitor->surface = surface; + } + } + } + + inhibitor->dbus_cookie = ((GtkApplicationImplWaylandClass *) G_OBJECT_GET_CLASS (wayland))->dbus_inhibit (impl, window, flags, reason); + + return inhibitor->cookie; +} + +static void +gtk_application_impl_wayland_uninhibit (GtkApplicationImpl *impl, + guint cookie) +{ + GtkApplicationImplWayland *wayland = (GtkApplicationImplWayland *) impl; + GSList *iter; + + for (iter = wayland->inhibitors; iter; iter = iter->next) + { + GtkApplicationWaylandInhibitor *inhibitor = iter->data; + + if (inhibitor->cookie == cookie) + { + if (inhibitor->dbus_cookie) + ((GtkApplicationImplWaylandClass *) G_OBJECT_GET_CLASS (wayland))->dbus_uninhibit (impl, inhibitor->dbus_cookie); + if (inhibitor->surface) + gdk_wayland_surface_uninhibit_idle (inhibitor->surface); + gtk_application_wayland_inhibitor_free (inhibitor); + wayland->inhibitors = g_slist_delete_link (wayland->inhibitors, iter); + return; + } + } + + g_warning ("Invalid inhibitor cookie"); +} + static void gtk_application_impl_wayland_init (GtkApplicationImplWayland *wayland) { @@ -82,8 +177,15 @@ gtk_application_impl_wayland_class_init (GtkApplicationImplWaylandClass *class) { GtkApplicationImplClass *impl_class = GTK_APPLICATION_IMPL_CLASS (class); + class->dbus_inhibit = impl_class->inhibit; + class->dbus_uninhibit = impl_class->uninhibit; + impl_class->handle_window_realize = gtk_application_impl_wayland_handle_window_realize; impl_class->before_emit = gtk_application_impl_wayland_before_emit; + impl_class->inhibit = + gtk_application_impl_wayland_inhibit; + impl_class->uninhibit = + gtk_application_impl_wayland_uninhibit; } |