[clutter] drag/drop actions: add touch event support



commit 132e4b98d18e411a8323925a557936dbd0d840fa
Author: Lionel Landwerlin <llandwerlin gmail com>
Date:   Wed Jun 13 16:02:05 2012 +0100

    drag/drop actions: add touch event support
    
    https://bugzilla.gnome.org/show_bug.cgi?id=678049

 clutter/clutter-drag-action.c   |   92 +++++++++++++++++++++++++++++++--------
 clutter/clutter-drop-action.c   |   43 +++++++++++++------
 clutter/clutter-stage-private.h |   22 ++++++---
 clutter/clutter-stage.c         |   84 ++++++++++++++++++++++++++++++-----
 4 files changed, 191 insertions(+), 50 deletions(-)
---
diff --git a/clutter/clutter-drag-action.c b/clutter/clutter-drag-action.c
index cd25ecd..c89fd79 100644
--- a/clutter/clutter-drag-action.c
+++ b/clutter/clutter-drag-action.c
@@ -93,7 +93,9 @@ struct _ClutterDragActionPrivate
   ClutterDragAxis drag_axis;
 
   ClutterInputDevice *device;
+  ClutterEventSequence *sequence;
   gulong button_press_id;
+  gulong touch_begin_id;
   gulong capture_id;
 
   gfloat press_x;
@@ -183,11 +185,18 @@ emit_drag_begin (ClutterDragAction *action,
   if (priv->stage != NULL)
     {
       clutter_stage_set_motion_events_enabled (priv->stage, FALSE);
-      _clutter_stage_add_drag_actor (priv->stage,
-                                     clutter_event_get_device (event),
-                                     priv->drag_handle != NULL
-                                       ? priv->drag_handle
-                                       : actor);
+      if (clutter_event_type (event) == CLUTTER_TOUCH_BEGIN)
+        _clutter_stage_add_touch_drag_actor (priv->stage,
+                                             clutter_event_get_event_sequence (event),
+                                             priv->drag_handle != NULL
+                                             ? priv->drag_handle
+                                             : actor);
+      else
+        _clutter_stage_add_pointer_drag_actor (priv->stage,
+                                               clutter_event_get_device (event),
+                                               priv->drag_handle != NULL
+                                               ? priv->drag_handle
+                                               : actor);
     }
 
   g_signal_emit (action, drag_signals[DRAG_BEGIN], 0,
@@ -301,7 +310,16 @@ emit_drag_end (ClutterDragAction *action,
                                            priv->motion_events_enabled);
 
   if (priv->last_motion_device != NULL)
-    _clutter_stage_remove_drag_actor (priv->stage, priv->last_motion_device);
+    {
+      if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE)
+        _clutter_stage_remove_pointer_drag_actor (priv->stage,
+                                                  priv->last_motion_device);
+      else
+        _clutter_stage_remove_touch_drag_actor (priv->stage,
+                                                priv->sequence);
+    }
+
+  priv->sequence = NULL;
 
   priv->in_drag = FALSE;
 }
@@ -313,7 +331,7 @@ on_captured_event (ClutterActor      *stage,
 {
   ClutterDragActionPrivate *priv = action->priv;
   ClutterActor *actor;
-  
+
   actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
 
   if (!priv->in_drag)
@@ -324,6 +342,11 @@ on_captured_event (ClutterActor      *stage,
 
   switch (clutter_event_type (event))
     {
+    case CLUTTER_TOUCH_UPDATE:
+      if (clutter_event_get_event_sequence (event) == priv->sequence)
+        emit_drag_motion (action, actor, event);
+      break;
+
     case CLUTTER_MOTION:
       {
         ClutterModifierType mods = clutter_event_get_state (event);
@@ -339,6 +362,12 @@ on_captured_event (ClutterActor      *stage,
       }
       break;
 
+    case CLUTTER_TOUCH_END:
+    case CLUTTER_TOUCH_CANCEL:
+      if (clutter_event_get_event_sequence (event) == priv->sequence)
+        emit_drag_end (action, actor, event);
+      break;
+
     case CLUTTER_BUTTON_RELEASE:
       if (priv->in_drag)
         emit_drag_end (action, actor, event);
@@ -358,9 +387,9 @@ on_captured_event (ClutterActor      *stage,
 }
 
 static gboolean
-on_button_press (ClutterActor      *actor,
-                 ClutterEvent      *event,
-                 ClutterDragAction *action)
+on_drag_begin (ClutterActor      *actor,
+               ClutterEvent      *event,
+               ClutterDragAction *action)
 {
   ClutterDragActionPrivate *priv = action->priv;
 
@@ -368,8 +397,22 @@ on_button_press (ClutterActor      *actor,
     return CLUTTER_EVENT_PROPAGATE;
 
   /* dragging is only performed using the primary button */
-  if (clutter_event_get_button (event) != CLUTTER_BUTTON_PRIMARY)
-    return CLUTTER_EVENT_PROPAGATE;
+  switch (clutter_event_type (event))
+    {
+    case CLUTTER_BUTTON_PRESS:
+      if (clutter_event_get_button (event) != CLUTTER_BUTTON_PRIMARY)
+        return CLUTTER_EVENT_PROPAGATE;
+      break;
+
+    case CLUTTER_TOUCH_BEGIN:
+      if (priv->sequence != NULL)
+        return CLUTTER_EVENT_PROPAGATE;
+      priv->sequence = clutter_event_get_event_sequence (event);
+      break;
+
+    default:
+      return CLUTTER_EVENT_PROPAGATE;
+    }
 
   if (priv->stage == NULL)
     priv->stage = CLUTTER_STAGE (clutter_actor_get_stage (actor));
@@ -416,9 +459,13 @@ clutter_drag_action_set_actor (ClutterActorMeta *meta,
 
       old_actor = clutter_actor_meta_get_actor (meta);
       if (old_actor != NULL)
-        g_signal_handler_disconnect (old_actor, priv->button_press_id);
-        
+        {
+          g_signal_handler_disconnect (old_actor, priv->button_press_id);
+          g_signal_handler_disconnect (old_actor, priv->touch_begin_id);
+        }
+
       priv->button_press_id = 0;
+      priv->touch_begin_id = 0;
     }
 
   if (priv->capture_id != 0)
@@ -435,9 +482,14 @@ clutter_drag_action_set_actor (ClutterActorMeta *meta,
   priv->in_drag = FALSE;
 
   if (actor != NULL)
-    priv->button_press_id = g_signal_connect (actor, "button-press-event",
-                                              G_CALLBACK (on_button_press),
-                                              meta);
+    {
+      priv->button_press_id = g_signal_connect (actor, "button-press-event",
+                                                G_CALLBACK (on_drag_begin),
+                                                meta);
+      priv->touch_begin_id = g_signal_connect (actor, "touch-event",
+                                               G_CALLBACK (on_drag_begin),
+                                               meta);
+    }
 
   CLUTTER_ACTOR_META_CLASS (clutter_drag_action_parent_class)->set_actor (meta, actor);
 }
@@ -555,9 +607,13 @@ clutter_drag_action_dispose (GObject *gobject)
 
       actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject));
       if (actor != NULL)
-        g_signal_handler_disconnect (actor, priv->button_press_id);
+        {
+          g_signal_handler_disconnect (actor, priv->button_press_id);
+          g_signal_handler_disconnect (actor, priv->touch_begin_id);
+        }
 
       priv->button_press_id = 0;
+      priv->touch_begin_id = 0;
     }
 
   clutter_drag_action_set_drag_handle (CLUTTER_DRAG_ACTION (gobject), NULL);
diff --git a/clutter/clutter-drop-action.c b/clutter/clutter-drop-action.c
index 8c4def2..adf6aeb 100644
--- a/clutter/clutter-drop-action.c
+++ b/clutter/clutter-drop-action.c
@@ -127,24 +127,40 @@ on_stage_capture (ClutterStage *stage,
 {
   DropTarget *data = user_data;
   gfloat event_x, event_y;
-  ClutterInputDevice *device;
   ClutterActor *actor, *drag_actor;
   ClutterDropAction *drop_action;
   gboolean was_reactive;
 
-  if (!(clutter_event_type (event) == CLUTTER_MOTION ||
-        clutter_event_type (event) == CLUTTER_BUTTON_RELEASE))
-    return CLUTTER_EVENT_PROPAGATE;
-
-  if (!(clutter_event_get_state (event) & CLUTTER_BUTTON1_MASK))
-    return CLUTTER_EVENT_PROPAGATE;
+  switch (clutter_event_type (event))
+    {
+    case CLUTTER_MOTION:
+    case CLUTTER_BUTTON_RELEASE:
+      {
+        ClutterInputDevice *device;
+
+        if (!(clutter_event_get_state (event) & CLUTTER_BUTTON1_MASK))
+          return CLUTTER_EVENT_PROPAGATE;
+
+        device = clutter_event_get_device (event);
+        drag_actor = _clutter_stage_get_pointer_drag_actor (stage, device);
+        if (drag_actor == NULL)
+          return CLUTTER_EVENT_PROPAGATE;
+      }
+      break;
+
+    case CLUTTER_TOUCH_UPDATE:
+    case CLUTTER_TOUCH_END:
+      drag_actor = _clutter_stage_get_touch_drag_actor (stage,
+                                                        clutter_event_get_event_sequence (event));
+      if (drag_actor == NULL)
+        return CLUTTER_EVENT_PROPAGATE;
+      break;
+
+    default:
+      return CLUTTER_EVENT_PROPAGATE;
+    }
 
   clutter_event_get_coords (event, &event_x, &event_y);
-  device = clutter_event_get_device (event);
-
-  drag_actor = _clutter_stage_get_drag_actor (stage, device);
-  if (drag_actor == NULL)
-    return CLUTTER_EVENT_PROPAGATE;
 
   /* get the actor under the cursor, excluding the dragged actor; we
    * use reactivity because it won't cause any scene invalidation
@@ -210,7 +226,8 @@ on_stage_capture (ClutterStage *stage,
     }
 
 out:
-  if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE)
+  if (clutter_event_type (event) == CLUTTER_BUTTON_RELEASE ||
+      clutter_event_type (event) == CLUTTER_TOUCH_END)
     {
       if (data->last_action != NULL)
         {
diff --git a/clutter/clutter-stage-private.h b/clutter/clutter-stage-private.h
index d2c7f78..739046e 100644
--- a/clutter/clutter-stage-private.h
+++ b/clutter/clutter-stage-private.h
@@ -101,13 +101,21 @@ void            _clutter_stage_release_pick_id          (ClutterStage *stage,
 ClutterActor *  _clutter_stage_get_actor_by_pick_id     (ClutterStage *stage,
                                                          gint32        pick_id);
 
-void            _clutter_stage_add_drag_actor           (ClutterStage       *stage,
-                                                         ClutterInputDevice *device,
-                                                         ClutterActor       *actor);
-ClutterActor *  _clutter_stage_get_drag_actor           (ClutterStage       *stage,
-                                                         ClutterInputDevice *device);
-void            _clutter_stage_remove_drag_actor        (ClutterStage       *stage,
-                                                         ClutterInputDevice *device);
+void            _clutter_stage_add_pointer_drag_actor    (ClutterStage       *stage,
+                                                          ClutterInputDevice *device,
+                                                          ClutterActor       *actor);
+ClutterActor *  _clutter_stage_get_pointer_drag_actor    (ClutterStage       *stage,
+                                                          ClutterInputDevice *device);
+void            _clutter_stage_remove_pointer_drag_actor (ClutterStage       *stage,
+                                                          ClutterInputDevice *device);
+
+void            _clutter_stage_add_touch_drag_actor    (ClutterStage         *stage,
+                                                        ClutterEventSequence *sequence,
+                                                        ClutterActor         *actor);
+ClutterActor *  _clutter_stage_get_touch_drag_actor    (ClutterStage         *stage,
+                                                        ClutterEventSequence *sequence);
+void            _clutter_stage_remove_touch_drag_actor (ClutterStage         *stage,
+                                                        ClutterEventSequence *sequence);
 
 ClutterStageState       _clutter_stage_get_state        (ClutterStage      *stage);
 gboolean                _clutter_stage_is_activated     (ClutterStage      *stage);
diff --git a/clutter/clutter-stage.c b/clutter/clutter-stage.c
index 8d01214..bf8a32f 100644
--- a/clutter/clutter-stage.c
+++ b/clutter/clutter-stage.c
@@ -4299,17 +4299,19 @@ _clutter_stage_get_actor_by_pick_id (ClutterStage *stage,
 }
 
 void
-_clutter_stage_add_drag_actor (ClutterStage       *stage,
-                               ClutterInputDevice *device,
-                               ClutterActor       *actor)
+_clutter_stage_add_pointer_drag_actor (ClutterStage       *stage,
+                                       ClutterInputDevice *device,
+                                       ClutterActor       *actor)
 {
   GHashTable *drag_actors;
 
-  drag_actors = g_object_get_data (G_OBJECT (stage), "__clutter_stage_drag_actors");
+  drag_actors = g_object_get_data (G_OBJECT (stage),
+                                   "__clutter_stage_pointer_drag_actors");
   if (drag_actors == NULL)
     {
       drag_actors = g_hash_table_new (NULL, NULL);
-      g_object_set_data_full (G_OBJECT (stage), "__clutter_stage_drag_actors",
+      g_object_set_data_full (G_OBJECT (stage),
+                              "__clutter_stage_pointer_drag_actors",
                               drag_actors,
                               (GDestroyNotify) g_hash_table_destroy);
     }
@@ -4318,12 +4320,13 @@ _clutter_stage_add_drag_actor (ClutterStage       *stage,
 }
 
 ClutterActor *
-_clutter_stage_get_drag_actor (ClutterStage       *stage,
-                               ClutterInputDevice *device)
+_clutter_stage_get_pointer_drag_actor (ClutterStage       *stage,
+                                       ClutterInputDevice *device)
 {
   GHashTable *drag_actors;
 
-  drag_actors = g_object_get_data (G_OBJECT (stage), "__clutter_stage_drag_actors");
+  drag_actors = g_object_get_data (G_OBJECT (stage),
+                                   "__clutter_stage_pointer_drag_actors");
   if (drag_actors == NULL)
     return NULL;
 
@@ -4331,19 +4334,76 @@ _clutter_stage_get_drag_actor (ClutterStage       *stage,
 }
 
 void
-_clutter_stage_remove_drag_actor (ClutterStage       *stage,
-                                  ClutterInputDevice *device)
+_clutter_stage_remove_pointer_drag_actor (ClutterStage       *stage,
+                                          ClutterInputDevice *device)
 {
   GHashTable *drag_actors;
 
-  drag_actors = g_object_get_data (G_OBJECT (stage), "__clutter_stage_drag_actors");
+  drag_actors = g_object_get_data (G_OBJECT (stage),
+                                   "__clutter_stage_pointer_drag_actors");
   if (drag_actors == NULL)
     return;
 
   g_hash_table_remove (drag_actors, device);
 
   if (g_hash_table_size (drag_actors) == 0)
-    g_object_set_data (G_OBJECT (stage), "__clutter_stage_drag_actors", NULL);
+    g_object_set_data (G_OBJECT (stage),
+                       "__clutter_stage_pointer_drag_actors",
+                       NULL);
+}
+
+void
+_clutter_stage_add_touch_drag_actor (ClutterStage         *stage,
+                                     ClutterEventSequence *sequence,
+                                     ClutterActor         *actor)
+{
+  GHashTable *drag_actors;
+
+  drag_actors = g_object_get_data (G_OBJECT (stage),
+                                   "__clutter_stage_touch_drag_actors");
+  if (drag_actors == NULL)
+    {
+      drag_actors = g_hash_table_new (NULL, NULL);
+      g_object_set_data_full (G_OBJECT (stage),
+                              "__clutter_stage_touch_drag_actors",
+                              drag_actors,
+                              (GDestroyNotify) g_hash_table_destroy);
+    }
+
+  g_hash_table_replace (drag_actors, sequence, actor);
+}
+
+ClutterActor *
+_clutter_stage_get_touch_drag_actor (ClutterStage         *stage,
+                                     ClutterEventSequence *sequence)
+{
+  GHashTable *drag_actors;
+
+  drag_actors = g_object_get_data (G_OBJECT (stage),
+                                   "__clutter_stage_touch_drag_actors");
+  if (drag_actors == NULL)
+    return NULL;
+
+  return g_hash_table_lookup (drag_actors, sequence);
+}
+
+void
+_clutter_stage_remove_touch_drag_actor (ClutterStage         *stage,
+                                        ClutterEventSequence *sequence)
+{
+  GHashTable *drag_actors;
+
+  drag_actors = g_object_get_data (G_OBJECT (stage),
+                                   "__clutter_stage_touch_drag_actors");
+  if (drag_actors == NULL)
+    return;
+
+  g_hash_table_remove (drag_actors, sequence);
+
+  if (g_hash_table_size (drag_actors) == 0)
+    g_object_set_data (G_OBJECT (stage),
+                       "__clutter_stage_touch_drag_actors",
+                       NULL);
 }
 
 /*< private >



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