diff options
-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 | ||||
-rw-r--r-- | gtk/gtkshortcutssection.c | 10 |
7 files changed, 155 insertions, 7 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; } diff --git a/gtk/gtkshortcutssection.c b/gtk/gtkshortcutssection.c index 7aef6791f5..5f5be70582 100644 --- a/gtk/gtkshortcutssection.c +++ b/gtk/gtkshortcutssection.c @@ -543,21 +543,20 @@ gtk_shortcuts_section_reflow_groups (GtkShortcutsSection *self) { GtkWidget *column; - for (column = gtk_widget_get_first_child (page); + for (column = gtk_widget_get_last_child (page); column != NULL; - column = gtk_widget_get_next_sibling (column)) + column = gtk_widget_get_prev_sibling (column)) { GtkWidget *group; - for (group = gtk_widget_get_first_child (column); + for (group = gtk_widget_get_last_child (column); group != NULL; - group = gtk_widget_get_next_sibling (group)) + group = gtk_widget_get_prev_sibling (group)) { groups = g_list_prepend (groups, group); } } } - groups = g_list_reverse (groups); /* create new pages */ current_page = NULL; @@ -642,7 +641,6 @@ gtk_shortcuts_section_reflow_groups (GtkShortcutsSection *self) child != NULL; child = gtk_widget_get_prev_sibling (child)) content = g_list_prepend (content, child); - content = g_list_reverse (content); n = 0; for (g = g_list_last (content); g; g = g->prev) |