[gtk+] wayland: Implement DND icon hotspot API



commit 3ab9d96623bc30678cbffc3bf9ec5133e714e87c
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Tue Dec 8 18:19:33 2015 +0800

    wayland: Implement DND icon hotspot API
    
    In Wayland, the hotspot of a DND icon is set using the buffer offset in
    wl_buffer.attach. To implement this, add a private API to cause the
    next wl_surface.attach to offset the new buffer with a given offset.
    Setting a DND icon hotspot sets this offset while also queuing a redraw
    of the window to trigger the wl_surface.attach.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=759168

 gdk/wayland/gdkdnd-wayland.c     |   26 ++++++++++++++++++++++++--
 gdk/wayland/gdkprivate-wayland.h |    4 ++++
 gdk/wayland/gdkwindow-wayland.c  |   33 ++++++++++++++++++++++++++++++++-
 3 files changed, 60 insertions(+), 3 deletions(-)
---
diff --git a/gdk/wayland/gdkdnd-wayland.c b/gdk/wayland/gdkdnd-wayland.c
index f20a0e7..0bb3279 100644
--- a/gdk/wayland/gdkdnd-wayland.c
+++ b/gdk/wayland/gdkdnd-wayland.c
@@ -24,6 +24,7 @@
 #include "gdkproperty.h"
 #include "gdkprivate-wayland.h"
 #include "gdkdisplay-wayland.h"
+#include "gdkwaylandwindow.h"
 
 #include "gdkdeviceprivate.h"
 
@@ -48,6 +49,8 @@ struct _GdkWaylandDragContext
   uint32_t serial;
   gdouble x;
   gdouble y;
+  gint prev_hot_x;
+  gint prev_hot_y;
   gint hot_x;
   gint hot_y;
 };
@@ -306,8 +309,27 @@ gdk_wayland_drag_context_set_hotspot (GdkDragContext *context,
                                       gint            hot_x,
                                       gint            hot_y)
 {
-  GDK_WAYLAND_DRAG_CONTEXT (context)->hot_x = hot_x;
-  GDK_WAYLAND_DRAG_CONTEXT (context)->hot_y = hot_y;
+  GdkWaylandDragContext *context_wayland = GDK_WAYLAND_DRAG_CONTEXT (context);
+
+  context_wayland->prev_hot_x = context_wayland->hot_x;
+  context_wayland->prev_hot_y = context_wayland->hot_x;
+  context_wayland->hot_x = hot_x;
+  context_wayland->hot_y = hot_y;
+
+  if (context_wayland->prev_hot_x == hot_x &&
+      context_wayland->prev_hot_x == hot_x)
+    return;
+
+  _gdk_wayland_window_offset_next_wl_buffer (context_wayland->dnd_window,
+                                             -hot_x, -hot_y);
+  gdk_window_invalidate_rect (context_wayland->dnd_window,
+                              &(GdkRectangle) {
+                                .x = 0,
+                                .y = 0,
+                                .width = 1,
+                                .height = 1,
+                              },
+                              FALSE);
 }
 
 static void
diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h
index 00db37f..c4b5185 100644
--- a/gdk/wayland/gdkprivate-wayland.h
+++ b/gdk/wayland/gdkprivate-wayland.h
@@ -104,6 +104,10 @@ void            _gdk_wayland_window_register_dnd (GdkWindow *window);
 GdkDragContext *_gdk_wayland_window_drag_begin (GdkWindow *window,
                                                GdkDevice *device,
                                                GList     *targets);
+void            _gdk_wayland_window_offset_next_wl_buffer (GdkWindow *window,
+                                                           int        x,
+                                                           int        y);
+
 GdkDragContext * _gdk_wayland_drop_context_new (struct wl_data_device *data_device);
 void _gdk_wayland_drag_context_set_source_window (GdkDragContext *context,
                                                   GdkWindow      *window);
diff --git a/gdk/wayland/gdkwindow-wayland.c b/gdk/wayland/gdkwindow-wayland.c
index 60dfc59..9a01d42 100644
--- a/gdk/wayland/gdkwindow-wayland.c
+++ b/gdk/wayland/gdkwindow-wayland.c
@@ -121,6 +121,8 @@ struct _GdkWindowImplWayland
   GdkWindow *transient_for;
 
   cairo_surface_t *cairo_surface;
+  int pending_buffer_offset_x;
+  int pending_buffer_offset_y;
 
   gchar *title;
 
@@ -564,7 +566,10 @@ gdk_wayland_window_attach_image (GdkWindow *window)
   /* Attach this new buffer to the surface */
   wl_surface_attach (impl->surface,
                      _gdk_wayland_shm_surface_get_wl_buffer (impl->cairo_surface),
-                     0, 0);
+                     impl->pending_buffer_offset_x,
+                     impl->pending_buffer_offset_y);
+  impl->pending_buffer_offset_x = 0;
+  impl->pending_buffer_offset_y = 0;
 
   /* Only set the buffer scale if supported by the compositor */
   display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
@@ -2564,6 +2569,32 @@ gdk_wayland_window_get_wl_surface (GdkWindow *window)
   return GDK_WINDOW_IMPL_WAYLAND (window->impl)->surface;
 }
 
+/**
+ * gdk_wayland_window_offset_next_wl_buffer:
+ * @window (type GdkWaylandWindow): a #GdkWindow
+ * @x: x offset which the next buffer should be attached at
+ * @y: y offset which the next buffer should be attached at
+ *
+ * Make GDK attach the next buffer at the given offset. This is useful for
+ * DND icons which may have a hotspot other than (0, 0).
+ *
+ * Since: 3.20
+ */
+void
+gdk_wayland_window_offset_next_wl_buffer (GdkWindow *window,
+                                          int        x,
+                                          int        y)
+{
+  GdkWindowImplWayland *impl;
+
+  g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
+
+  impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+
+  impl->pending_buffer_offset_x = x;
+  impl->pending_buffer_offset_y = y;
+}
+
 static struct wl_egl_window *
 gdk_wayland_window_get_wl_egl_window (GdkWindow *window)
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]