diff --git a/gdk/gdk-private.c b/gdk/gdk-private.c index 750edcd374..0a7438162c 100644 --- a/gdk/gdk-private.c +++ b/gdk/gdk-private.c @@ -22,7 +22,8 @@ gdk__private__ (void) gdk_get_desktop_autostart_id, gdk_profiler_is_running, gdk_profiler_start, - gdk_profiler_stop + gdk_profiler_stop, + gdk_window_titlebar_gesture, }; return &table; diff --git a/gdk/gdk-private.h b/gdk/gdk-private.h index c71abe4634..4b616370b7 100644 --- a/gdk/gdk-private.h +++ b/gdk/gdk-private.h @@ -66,6 +66,9 @@ typedef struct { gboolean (* gdk_profiler_is_running) (void); void (* gdk_profiler_start) (int fd); void (* gdk_profiler_stop) (void); + + gboolean (* gdk_window_titlebar_gesture) (GdkWindow *window, + GdkTitlebarGesture gesture); } GdkPrivateVTable; GDK_AVAILABLE_IN_ALL diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index e2c1d10c9c..468d328c22 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -557,6 +557,9 @@ void _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_win gboolean _gdk_window_has_impl (GdkWindow *window); GdkWindow * _gdk_window_get_impl_window (GdkWindow *window); +gboolean gdk_window_titlebar_gesture (GdkWindow *window, + GdkTitlebarGesture gesture); + /***************************** * offscreen window routines * *****************************/ diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 2d0ed0f963..727b0cf1f4 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -11998,3 +11998,20 @@ gdk_window_show_window_menu (GdkWindow *window, else return FALSE; } + +gboolean +gdk_window_titlebar_gesture (GdkWindow *window, + GdkTitlebarGesture gesture) +{ + GdkWindowImplClass *impl_class; + + g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE); + g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), FALSE); + + impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl); + + if (impl_class->titlebar_gesture) + return impl_class->titlebar_gesture (window, gesture); + else + return FALSE; +} diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h index c72472372d..1993e12083 100644 --- a/gdk/gdkwindowimpl.h +++ b/gdk/gdkwindowimpl.h @@ -30,6 +30,13 @@ G_BEGIN_DECLS +typedef enum +{ + GDK_TITLEBAR_GESTURE_DOUBLE_CLICK = 1, + GDK_TITLEBAR_GESTURE_RIGHT_CLICK = 2, + GDK_TITLEBAR_GESTURE_MIDDLE_CLICK = 3 +} GdkTitlebarGesture; + #define GDK_TYPE_WINDOW_IMPL (gdk_window_impl_get_type ()) #define GDK_WINDOW_IMPL(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW_IMPL, GdkWindowImpl)) #define GDK_WINDOW_IMPL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW_IMPL, GdkWindowImplClass)) @@ -315,6 +322,9 @@ struct _GdkWindowImplClass const cairo_region_t *region); void (* destroy_draw_context) (GdkWindow *window, GdkDrawingContext *context); + + gboolean (* titlebar_gesture) (GdkWindow *window, + GdkTitlebarGesture gesture); }; /* Interface Functions */ diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index cabf7d5568..55c0388ec6 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -84,7 +84,7 @@ #define MIN_SYSTEM_BELL_DELAY_MS 20 -#define GTK_SHELL1_VERSION 4 +#define GTK_SHELL1_VERSION 5 #ifdef HAVE_XDG_ACTIVATION #define XDG_ACTIVATION_VERSION 1 #endif diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c index fec8e1e7a5..619f7982cb 100644 --- a/gdk/wayland/gdkwindow-wayland.c +++ b/gdk/wayland/gdkwindow-wayland.c @@ -4878,6 +4878,65 @@ gdk_wayland_window_show_window_menu (GdkWindow *window, 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_window_titlebar_gesture (GdkWindow *window, + GdkTitlebarGesture gesture) +{ + GdkWindowImplWayland *impl = GDK_WINDOW_IMPL_WAYLAND (window->impl); + 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 (gdk_window_get_display (window)); + wl_seat = gdk_wayland_seat_get_wl_seat (seat); + + serial = _gdk_wayland_seat_get_last_implicit_grab_serial (seat, NULL); + + gtk_surface1_titlebar_gesture (impl->display_server.gtk_surface, + serial, + wl_seat, + gtk_gesture); + + return TRUE; +} + static void _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass) { @@ -4969,6 +5028,7 @@ _gdk_window_impl_wayland_class_init (GdkWindowImplWaylandClass *klass) impl_class->show_window_menu = gdk_wayland_window_show_window_menu; impl_class->create_gl_context = gdk_wayland_window_create_gl_context; impl_class->invalidate_for_new_frame = gdk_wayland_window_invalidate_for_new_frame; + impl_class->titlebar_gesture = gdk_wayland_window_titlebar_gesture; signals[COMMITTED] = g_signal_new ("committed", G_TYPE_FROM_CLASS (object_class), 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 @@ + + + + + + + + + + + + + + + + + diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 22b99876d6..e1b09a3658 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -1385,10 +1385,34 @@ gtk_window_titlebar_action (GtkWindow *window, guint button, gint n_press) { + GdkTitlebarGesture gesture = 0; + GdkWindow *gdk_window; GtkSettings *settings; gchar *action = NULL; gboolean retval = TRUE; + switch (button) + { + case GDK_BUTTON_PRIMARY: + if (n_press == 2) + gesture = GDK_TITLEBAR_GESTURE_DOUBLE_CLICK; + break; + case GDK_BUTTON_MIDDLE: + gesture = GDK_TITLEBAR_GESTURE_MIDDLE_CLICK; + break; + case GDK_BUTTON_SECONDARY: + gesture = GDK_TITLEBAR_GESTURE_RIGHT_CLICK; + break; + } + + gdk_window = _gtk_widget_get_window (GTK_WIDGET (window)); + if (gesture && + GDK_PRIVATE_CALL (gdk_window_titlebar_gesture (gdk_window, gesture))) + { + retval = TRUE; + goto out; + } + settings = gtk_widget_get_settings (GTK_WIDGET (window)); switch (button) { @@ -1434,6 +1458,7 @@ gtk_window_titlebar_action (GtkWindow *window, g_free (action); +out: return retval; }