[mutter] dnd: Implement DnD handling code in Wayland



commit 65e9c89ed9bf2d8cc6d4d5b76884ace85149be58
Author: Hyungwon Hwang <hyungwon hwang7 gmail com>
Date:   Mon Jan 2 23:12:34 2017 +0900

    dnd: Implement DnD handling code in Wayland
    
    No XDnD events which notify DnD status change comes in Wayland. To emulate XDnD
    behavior, MetaDnd checks whether there is a grab or not when the modal window
    starts showing. When there is a grab, it processes the raw events from
    compositor, and emits DnD signals for plugin.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=765003

 src/backends/meta-dnd-private.h        |    4 +
 src/compositor/compositor.c            |    3 +
 src/compositor/meta-dnd.c              |  120 +++++++++++++++++++++++++++++++-
 src/wayland/meta-wayland-data-device.c |   14 ++++
 src/wayland/meta-wayland-data-device.h |    6 ++
 5 files changed, 146 insertions(+), 1 deletions(-)
---
diff --git a/src/backends/meta-dnd-private.h b/src/backends/meta-dnd-private.h
index 41aa2a0..3026d65 100644
--- a/src/backends/meta-dnd-private.h
+++ b/src/backends/meta-dnd-private.h
@@ -27,4 +27,8 @@ gboolean meta_dnd_handle_xdnd_event (MetaBackend    *backend,
                                      MetaDisplay    *display,
                                      XEvent         *xev);
 
+#ifdef HAVE_WAYLAND
+void meta_dnd_wayland_handle_begin_modal (MetaCompositor *compositor);
+#endif
+
 #endif /* META_DND_PRIVATE_H */
diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c
index a1c83db..fc43713 100644
--- a/src/compositor/compositor.c
+++ b/src/compositor/compositor.c
@@ -71,6 +71,7 @@
 #include "window-private.h" /* to check window->hidden */
 #include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */
 #include "util-private.h"
+#include "backends/meta-dnd-private.h"
 #include "frame.h"
 #include <X11/extensions/shape.h>
 #include <X11/extensions/Xcomposite.h>
@@ -386,6 +387,8 @@ meta_begin_modal_for_plugin (MetaCompositor   *compositor,
     {
       meta_display_sync_wayland_input_focus (display);
       meta_display_cancel_touch (display);
+
+      meta_dnd_wayland_handle_begin_modal (compositor);
     }
 
   return TRUE;
diff --git a/src/compositor/meta-dnd.c b/src/compositor/meta-dnd.c
index fa29490..2ba69c4 100644
--- a/src/compositor/meta-dnd.c
+++ b/src/compositor/meta-dnd.c
@@ -33,12 +33,34 @@ struct _MetaDndClass
   GObjectClass parent_class;
 };
 
+#ifdef HAVE_WAYLAND
+#include "wayland/meta-wayland-private.h"
+#include "wayland/meta-wayland-data-device.h"
+#endif
+
+typedef struct _MetaDndPrivate MetaDndPrivate;
+
+struct _MetaDndPrivate
+{
+#ifdef HAVE_WAYLAND
+  gulong handler_id[3];
+
+  MetaCompositor *compositor;
+  MetaWaylandCompositor *wl_compositor;
+#else
+  /* to avoid warnings (g_type_class_add_private: assertion `private_size > 0' failed) */
+  gchar dummy;
+#endif
+};
+
 struct _MetaDnd
 {
   GObject parent;
+
+  MetaDndPrivate *priv;
 };
 
-G_DEFINE_TYPE (MetaDnd, meta_dnd, G_TYPE_OBJECT);
+G_DEFINE_TYPE_WITH_PRIVATE (MetaDnd, meta_dnd, G_TYPE_OBJECT);
 
 enum
 {
@@ -169,3 +191,99 @@ meta_dnd_handle_xdnd_event (MetaBackend    *backend,
 
     return FALSE;
 }
+
+#ifdef HAVE_WAYLAND
+static void
+meta_dnd_wayland_on_motion_event (ClutterActor *actor,
+                                  ClutterEvent *event,
+                                  MetaDnd      *dnd)
+{
+  MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd);
+  MetaWaylandDragGrab *current_grab;
+  gfloat event_x, event_y;
+
+  g_return_if_fail (event != NULL);
+
+  clutter_event_get_coords (event, &event_x, &event_y);
+  meta_dnd_notify_dnd_position_change (dnd, (int)event_x, (int)event_y);
+
+  current_grab = meta_wayland_data_device_get_current_grab (&priv->wl_compositor->seat->data_device);
+  if (current_grab)
+    meta_wayland_drag_grab_update_feedback_actor (current_grab, event);
+}
+
+static void
+meta_dnd_wayland_end_notify (ClutterActor *actor,
+                             ClutterEvent *event,
+                             MetaDnd      *dnd)
+{
+  MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd);
+  unsigned int i;
+
+  meta_wayland_data_device_end_drag (&priv->wl_compositor->seat->data_device);
+
+  for (i = 0; i < G_N_ELEMENTS (priv->handler_id); i++)
+    {
+      g_signal_handler_disconnect (priv->compositor->stage, priv->handler_id[i]);
+      priv->handler_id[i] = 0;
+    }
+
+  priv->compositor = NULL;
+  priv->wl_compositor = NULL;
+
+  meta_dnd_notify_dnd_leave (dnd);
+}
+
+static void
+meta_dnd_wayland_on_button_released (ClutterActor *actor,
+                                     ClutterEvent *event,
+                                     MetaDnd      *dnd)
+{
+  meta_dnd_wayland_end_notify (actor, event, dnd);
+}
+
+static void
+meta_dnd_wayland_on_key_pressed (ClutterActor *actor,
+                                 ClutterEvent *event,
+                                 MetaDnd      *dnd)
+{
+  guint key = clutter_event_get_key_symbol (event);
+
+  if (key != CLUTTER_KEY_Escape)
+    return;
+
+  meta_dnd_wayland_end_notify (actor, event, dnd);
+}
+
+void
+meta_dnd_wayland_handle_begin_modal (MetaCompositor *compositor)
+{
+  MetaWaylandCompositor *wl_compositor = meta_wayland_compositor_get_default ();
+  MetaDnd *dnd = meta_backend_get_dnd (meta_get_backend ());
+  MetaDndPrivate *priv = meta_dnd_get_instance_private (dnd);
+
+  if (priv->handler_id[0] == 0 &&
+      meta_wayland_data_device_get_current_grab (&wl_compositor->seat->data_device) != NULL)
+    {
+      priv->compositor = compositor;
+      priv->wl_compositor = wl_compositor;
+
+      priv->handler_id[0] = g_signal_connect (compositor->stage,
+                                              "motion-event",
+                                              G_CALLBACK (meta_dnd_wayland_on_motion_event),
+                                              dnd);
+
+      priv->handler_id[1] = g_signal_connect (compositor->stage,
+                                              "button-release-event",
+                                              G_CALLBACK (meta_dnd_wayland_on_button_released),
+                                              dnd);
+
+      priv->handler_id[2] = g_signal_connect (compositor->stage,
+                                              "key-press-event",
+                                              G_CALLBACK (meta_dnd_wayland_on_key_pressed),
+                                              dnd);
+
+      meta_dnd_notify_dnd_enter (dnd);
+    }
+}
+#endif
diff --git a/src/wayland/meta-wayland-data-device.c b/src/wayland/meta-wayland-data-device.c
index 4a25844..06356c1 100644
--- a/src/wayland/meta-wayland-data-device.c
+++ b/src/wayland/meta-wayland-data-device.c
@@ -816,6 +816,14 @@ meta_wayland_drag_grab_get_focus (MetaWaylandDragGrab *drag_grab)
   return drag_grab->drag_focus;
 }
 
+void
+meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab,
+                                              ClutterEvent        *event)
+{
+  meta_feedback_actor_update (META_FEEDBACK_ACTOR (drag_grab->feedback_actor),
+                              event);
+}
+
 static void
 drag_grab_focus (MetaWaylandPointerGrab *grab,
                  MetaWaylandSurface     *surface)
@@ -1899,6 +1907,12 @@ meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
     data_device->current_grab->drag_surface == surface;
 }
 
+MetaWaylandDragGrab *
+meta_wayland_data_device_get_current_grab (MetaWaylandDataDevice *data_device)
+{
+  return data_device->current_grab;
+}
+
 gboolean
 meta_wayland_data_source_has_mime_type (const MetaWaylandDataSource *source,
                                         const gchar                 *mime_type)
diff --git a/src/wayland/meta-wayland-data-device.h b/src/wayland/meta-wayland-data-device.h
index f48b135..326a598 100644
--- a/src/wayland/meta-wayland-data-device.h
+++ b/src/wayland/meta-wayland-data-device.h
@@ -27,6 +27,7 @@
 #include <glib-object.h>
 
 #include "meta-wayland-types.h"
+#include "clutter/clutter.h"
 
 typedef struct _MetaWaylandDragGrab MetaWaylandDragGrab;
 typedef struct _MetaWaylandDataSourceFuncs MetaWaylandDataSourceFuncs;
@@ -79,6 +80,9 @@ void meta_wayland_data_device_set_keyboard_focus (MetaWaylandDataDevice *data_de
 gboolean meta_wayland_data_device_is_dnd_surface (MetaWaylandDataDevice *data_device,
                                                   MetaWaylandSurface    *surface);
 
+MetaWaylandDragGrab *
+     meta_wayland_data_device_get_current_grab   (MetaWaylandDataDevice *data_device);
+
 void meta_wayland_data_device_set_dnd_source     (MetaWaylandDataDevice *data_device,
                                                   MetaWaylandDataSource *source);
 void meta_wayland_data_device_set_selection      (MetaWaylandDataDevice *data_device,
@@ -133,5 +137,7 @@ void     meta_wayland_drag_grab_set_focus        (MetaWaylandDragGrab
                                                   MetaWaylandSurface              *surface);
 MetaWaylandSurface *
          meta_wayland_drag_grab_get_focus        (MetaWaylandDragGrab             *drag_grab);
+void     meta_wayland_drag_grab_update_feedback_actor (MetaWaylandDragGrab *drag_grab,
+                                                       ClutterEvent        *event);
 
 #endif /* META_WAYLAND_DATA_DEVICE_H */


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