From 0c7b1431d7e1157c389d3cf1e895eaf5aaaa62fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 29 Jul 2021 03:55:36 +0200 Subject: [PATCH] gdk/toplevel: Add gdk_toplevel_titlebar_gesture() Where supported, this allows delegating the titlebar action to the compositor instead of trying to replicate its behavior client-side. https://gitlab.gnome.org/GNOME/mutter/-/issues/602 --- gdk/gdktoplevel.c | 18 ++++++++ gdk/gdktoplevel.h | 11 +++++ gdk/gdktoplevelprivate.h | 2 + gdk/wayland/gdkdisplay-wayland.c | 2 +- gdk/wayland/gdksurface-wayland.c | 67 ++++++++++++++++++++++++++++++ gdk/wayland/protocol/gtk-shell.xml | 21 +++++++++- 6 files changed, 118 insertions(+), 3 deletions(-) diff --git a/gdk/gdktoplevel.c b/gdk/gdktoplevel.c index d50a88675d..f020d81765 100644 --- a/gdk/gdktoplevel.c +++ b/gdk/gdktoplevel.c @@ -78,6 +78,13 @@ gdk_toplevel_default_show_window_menu (GdkToplevel *toplevel, return FALSE; } +static gboolean +gdk_toplevel_default_titlebar_gesture (GdkToplevel *toplevel, + GdkTitlebarGesture gesture) +{ + return FALSE; +} + static gboolean gdk_toplevel_default_supports_edge_constraints (GdkToplevel *toplevel) { @@ -114,6 +121,7 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface) iface->supports_edge_constraints = gdk_toplevel_default_supports_edge_constraints; iface->inhibit_system_shortcuts = gdk_toplevel_default_inhibit_system_shortcuts; iface->restore_system_shortcuts = gdk_toplevel_default_restore_system_shortcuts; + iface->titlebar_gesture = gdk_toplevel_default_titlebar_gesture; /** * GdkToplevel:state: (attributes org.gtk.Property.get=gdk_toplevel_get_state) @@ -716,3 +724,13 @@ gdk_toplevel_begin_move (GdkToplevel *toplevel, x, y, timestamp); } + +gboolean +gdk_toplevel_titlebar_gesture (GdkToplevel *toplevel, + GdkTitlebarGesture gesture) +{ + g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE); + + return GDK_TOPLEVEL_GET_IFACE (toplevel)->titlebar_gesture (toplevel, + gesture); +} diff --git a/gdk/gdktoplevel.h b/gdk/gdktoplevel.h index 1d3f9c627d..68613a9024 100644 --- a/gdk/gdktoplevel.h +++ b/gdk/gdktoplevel.h @@ -115,6 +115,13 @@ typedef enum GDK_TOPLEVEL_STATE_LEFT_RESIZABLE = 1 << 15 } GdkToplevelState; +typedef enum +{ + GDK_TITLEBAR_GESTURE_DOUBLE_CLICK = 1, + GDK_TITLEBAR_GESTURE_RIGHT_CLICK = 2, + GDK_TITLEBAR_GESTURE_MIDDLE_CLICK = 3 +} GdkTitlebarGesture; + #define GDK_TYPE_TOPLEVEL (gdk_toplevel_get_type ()) @@ -196,6 +203,10 @@ void gdk_toplevel_begin_move (GdkToplevel *toplevel, double y, guint32 timestamp); +GDK_AVAILABLE_IN_4_4 +gboolean gdk_toplevel_titlebar_gesture (GdkToplevel *toplevel, + GdkTitlebarGesture gesture); + G_END_DECLS #endif /* __GDK_TOPLEVEL_H__ */ diff --git a/gdk/gdktoplevelprivate.h b/gdk/gdktoplevelprivate.h index 52dcdca0ad..2d1f0122f3 100644 --- a/gdk/gdktoplevelprivate.h +++ b/gdk/gdktoplevelprivate.h @@ -38,6 +38,8 @@ struct _GdkToplevelInterface double x, double y, guint32 timestamp); + gboolean (* titlebar_gesture) (GdkToplevel *toplevel, + GdkTitlebarGesture gesture); }; typedef enum diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index 0312411e0c..ad033076b4 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -87,7 +87,7 @@ #define MIN_SYSTEM_BELL_DELAY_MS 20 -#define GTK_SHELL1_VERSION 4 +#define GTK_SHELL1_VERSION 5 #define OUTPUT_VERSION_WITH_DONE 2 #define NO_XDG_OUTPUT_DONE_SINCE_VERSION 3 #define XDG_ACTIVATION_VERSION 1 diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c index 5689241c7d..84ec54a335 100644 --- a/gdk/wayland/gdksurface-wayland.c +++ b/gdk/wayland/gdksurface-wayland.c @@ -4190,6 +4190,65 @@ gdk_wayland_surface_show_window_menu (GdkSurface *surface, return TRUE; } +static gboolean +translate_gesture (GdkTitlebarGesture gesture, + enum gtk_surface1_gesture *out_gesture) +{ + switch (gesture) + { + case GDK_TITLEBAR_GESTURE_DOUBLE_CLICK: + *out_gesture = GTK_SURFACE1_GESTURE_DOUBLE_CLICK; + break; + + case GDK_TITLEBAR_GESTURE_RIGHT_CLICK: + *out_gesture = GTK_SURFACE1_GESTURE_RIGHT_CLICK; + break; + + case GDK_TITLEBAR_GESTURE_MIDDLE_CLICK: + *out_gesture = GTK_SURFACE1_GESTURE_MIDDLE_CLICK; + break; + + default: + g_warning ("Not handling unknown titlebar gesture %u", gesture); + return FALSE; + } + + return TRUE; +} + +static gboolean +gdk_wayland_surface_titlebar_gesture (GdkSurface *surface, + GdkTitlebarGesture gesture) +{ + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + struct gtk_surface1 *gtk_surface = impl->display_server.gtk_surface; + enum gtk_surface1_gesture gtk_gesture; + GdkSeat *seat; + struct wl_seat *wl_seat; + uint32_t serial; + + if (!gtk_surface) + return FALSE; + + if (gtk_surface1_get_version (gtk_surface) < GTK_SURFACE1_TITLEBAR_GESTURE_SINCE_VERSION) + return FALSE; + + if (!translate_gesture (gesture, >k_gesture)) + return FALSE; + + seat = gdk_display_get_default_seat (surface->display); + wl_seat = gdk_wayland_seat_get_wl_seat (seat); + + serial = _gdk_wayland_seat_get_last_implicit_grab_serial (GDK_WAYLAND_SEAT (seat), NULL); + + gtk_surface1_titlebar_gesture (impl->display_server.gtk_surface, + serial, + wl_seat, + gtk_gesture); + + return TRUE; +} + static gboolean gdk_wayland_surface_supports_edge_constraints (GdkSurface *surface) { @@ -4987,6 +5046,13 @@ gdk_wayland_toplevel_show_window_menu (GdkToplevel *toplevel, return gdk_wayland_surface_show_window_menu (GDK_SURFACE (toplevel), event); } +static gboolean +gdk_wayland_toplevel_titlebar_gesture (GdkToplevel *toplevel, + GdkTitlebarGesture gesture) +{ + return gdk_wayland_surface_titlebar_gesture (GDK_SURFACE (toplevel), gesture); +} + static gboolean gdk_wayland_toplevel_supports_edge_constraints (GdkToplevel *toplevel) { @@ -5065,6 +5131,7 @@ gdk_wayland_toplevel_iface_init (GdkToplevelInterface *iface) iface->lower = gdk_wayland_toplevel_lower; iface->focus = gdk_wayland_toplevel_focus; iface->show_window_menu = gdk_wayland_toplevel_show_window_menu; + iface->titlebar_gesture = gdk_wayland_toplevel_titlebar_gesture; iface->supports_edge_constraints = gdk_wayland_toplevel_supports_edge_constraints; iface->inhibit_system_shortcuts = gdk_wayland_toplevel_inhibit_system_shortcuts; iface->restore_system_shortcuts = gdk_wayland_toplevel_restore_system_shortcuts; diff --git a/gdk/wayland/protocol/gtk-shell.xml b/gdk/wayland/protocol/gtk-shell.xml index 1aab593c42..a8d51c65d3 100644 --- a/gdk/wayland/protocol/gtk-shell.xml +++ b/gdk/wayland/protocol/gtk-shell.xml @@ -1,6 +1,6 @@ - + gtk_shell is a protocol extension providing additional features for clients implementing it. @@ -35,7 +35,7 @@ - + @@ -85,6 +85,23 @@ + + + + + + + + + + + + + + + + +