diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index af30f9cfc2770feaa3cabf240db799148d950c2a..45f937dfaba32db4f8583da2bba5bce07b8fe664 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 5ace0f27445749e74844b2b68aae49e8f790066e..db5e6a4fb3d98a76afa28691e753b2e6ba7b8fa1 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -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 ef3f277664ee363ca38fbe4e516104adbade955b..46fec90c8e013dcf71a74be9eb1c56c6fe659be4 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 4af358c33e47d6c1f0d0a4d513b750a3b70c0535..54e0c6ff491763a687fc6a8cd45ac254450d9209 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 14267f4ccc007625ac47fe45410d61f27918335d..67ebb63da53cd2d7919ba7d16239d8d3b8cd70fa 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 34d85e31bbafb663aba9799c0c3c5c16abdbb999..face15505cc85befd0aa41f8ac0040a2f01f8939 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 +#include +#include -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; }