[clutter/wip/action-handle-event: 5/6] drag-action: Add ::drag-progress signal



commit f12c1cc382d0da6ec32550a53f51ff9600d28b1d
Author: Emmanuele Bassi <ebassi gnome org>
Date:   Sun Jun 24 12:07:40 2012 +0100

    drag-action: Add ::drag-progress signal
    
    Overriding the default behaviour of ClutterDragAction::drag-motion is
    currently a pain; you either need to subclass the ClutterDragAction and
    override the class closure for the signal, or you need to connect to the
    signal and call g_signal_stop_emission_by_name() - neither option being
    particularly nice or clean. The established pattern for these cases
    would be to have a boolean return value on the ::drag-motion signal, but
    we cannot do that without breaking ABI.
    
    To solve the issue in a backward compatible way, we should introduce a
    new signal, ::drag-progress, with a boolean return value. If the signal
    emission chain returns TRUE, the ::drag-motion signal will be emitted,
    and the default behaviour will be honoured; if the signal emission chain
    returns FALSE, instead, the ::drag-motion signal will not be emitted.

 clutter/clutter-drag-action.c |   84 ++++++++++++++++++++++++++++++++++++++--
 clutter/clutter-drag-action.h |   33 +++++++++-------
 2 files changed, 97 insertions(+), 20 deletions(-)
---
diff --git a/clutter/clutter-drag-action.c b/clutter/clutter-drag-action.c
index c89fd79..cdb7952 100644
--- a/clutter/clutter-drag-action.c
+++ b/clutter/clutter-drag-action.c
@@ -132,6 +132,7 @@ static GParamSpec *drag_props[PROP_LAST] = { NULL, };
 enum
 {
   DRAG_BEGIN,
+  DRAG_PROGRESS,
   DRAG_MOTION,
   DRAG_END,
 
@@ -214,6 +215,7 @@ emit_drag_motion (ClutterDragAction *action,
   ClutterActor *drag_handle = NULL;
   gfloat delta_x, delta_y;
   gfloat motion_x, motion_y;
+  gboolean can_emit_drag_motion = TRUE;
 
   clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_motion_y);
   priv->last_motion_state = clutter_event_get_state (event);
@@ -269,9 +271,17 @@ emit_drag_motion (ClutterDragAction *action,
         return;
     }
 
-  g_signal_emit (action, drag_signals[DRAG_MOTION], 0,
+  g_signal_emit (action, drag_signals[DRAG_PROGRESS], 0,
                  actor,
-                 delta_x, delta_y);
+                 delta_x, delta_y,
+                 &can_emit_drag_motion);
+
+  if (can_emit_drag_motion)
+    {
+      g_signal_emit (action, drag_signals[DRAG_MOTION], 0,
+                     actor,
+                     delta_x, delta_y);
+    }
 }
 
 static void
@@ -494,6 +504,15 @@ clutter_drag_action_set_actor (ClutterActorMeta *meta,
   CLUTTER_ACTOR_META_CLASS (clutter_drag_action_parent_class)->set_actor (meta, actor);
 }
 
+static gboolean
+clutter_drag_action_real_drag_progress (ClutterDragAction *action,
+                                        ClutterActor      *actor,
+                                        gfloat             delta_x,
+                                        gfloat             delta_y)
+{
+  return TRUE;
+}
+
 static void
 clutter_drag_action_real_drag_motion (ClutterDragAction *action,
                                       ClutterActor      *actor,
@@ -621,6 +640,20 @@ clutter_drag_action_dispose (GObject *gobject)
   G_OBJECT_CLASS (clutter_drag_action_parent_class)->dispose (gobject);
 }
 
+static gboolean
+drag_progress_accum (GSignalInvocationHint *ihint,
+                     GValue                *return_accu,
+                     const GValue          *handler_return,
+                     gpointer               user_data)
+{
+  gboolean continue_emission;
+
+  continue_emission = g_value_get_boolean (handler_return);
+  g_value_set_boolean (return_accu, continue_emission);
+
+  return continue_emission;
+}
+
 static void
 clutter_drag_action_class_init (ClutterDragActionClass *klass)
 {
@@ -631,6 +664,7 @@ clutter_drag_action_class_init (ClutterDragActionClass *klass)
 
   meta_class->set_actor = clutter_drag_action_set_actor;
 
+  klass->drag_progress = clutter_drag_action_real_drag_progress;
   klass->drag_motion = clutter_drag_action_real_drag_motion;
 
   /**
@@ -763,6 +797,46 @@ clutter_drag_action_class_init (ClutterDragActionClass *klass)
                   CLUTTER_TYPE_MODIFIER_TYPE);
 
   /**
+   * ClutterDragAction::drag-progress:
+   * @action: the #ClutterDragAction that emitted the signal
+   * @actor: the #ClutterActor attached to the action
+   * @delta_x: the X component of the distance between the press event
+   *   that began the dragging and the current position of the pointer,
+   *   as of the latest motion event
+   * @delta_y: the Y component of the distance between the press event
+   *   that began the dragging and the current position of the pointer,
+   *   as of the latest motion event
+   *
+   * The ::drag-progress signal is emitted for each motion event after
+   * the #ClutterDragAction::drag-begin signal has been emitted.
+   *
+   * The components of the distance between the press event and the
+   * latest motion event are computed in the actor's coordinate space,
+   * to take into account eventual transformations. If you want the
+   * stage coordinates of the latest motion event you can use
+   * clutter_drag_action_get_motion_coords().
+   *
+   * The default handler will emit #ClutterDragAction::drag-motion,
+   * if #ClutterDragAction::drag-progress emission returns %TRUE.
+   *
+   * Return value: %TRUE if the drag should continue, and %FALSE
+   *   if it should be stopped.
+   *
+   * Since: 1.12
+   */
+  drag_signals[DRAG_PROGRESS] =
+    g_signal_new (I_("drag-progress"),
+                  CLUTTER_TYPE_DRAG_ACTION,
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (ClutterDragActionClass, drag_progress),
+                  drag_progress_accum, NULL,
+                  _clutter_marshal_BOOLEAN__OBJECT_FLOAT_FLOAT,
+                  G_TYPE_BOOLEAN, 3,
+                  CLUTTER_TYPE_ACTOR,
+                  G_TYPE_FLOAT,
+                  G_TYPE_FLOAT);
+
+  /**
    * ClutterDragAction::drag-motion:
    * @action: the #ClutterDragAction that emitted the signal
    * @actor: the #ClutterActor attached to the action
@@ -785,9 +859,9 @@ clutter_drag_action_class_init (ClutterDragActionClass *klass)
    * The default handler of the signal will call clutter_actor_move_by()
    * either on @actor or, if set, of #ClutterDragAction:drag-handle using
    * the @delta_x and @delta_y components of the dragging motion. If you
-   * want to override the default behaviour, you can connect to this
-   * signal and call g_signal_stop_emission_by_name() from within your
-   * callback.
+   * want to override the default behaviour, you can connect to the
+   * #ClutterDragAction::drag-progress signal and return %FALSE from the
+   * handler.
    *
    * Since: 1.4
    */
diff --git a/clutter/clutter-drag-action.h b/clutter/clutter-drag-action.h
index 4cec121..5ef5fac 100644
--- a/clutter/clutter-drag-action.h
+++ b/clutter/clutter-drag-action.h
@@ -78,27 +78,30 @@ struct _ClutterDragActionClass
   ClutterActionClass parent_class;
 
   /*< public >*/
-  void (* drag_begin)  (ClutterDragAction   *action,
-                        ClutterActor        *actor,
-                        gfloat               event_x,
-                        gfloat               event_y,
-                        ClutterModifierType  modifiers);
-  void (* drag_motion) (ClutterDragAction   *action,
-                        ClutterActor        *actor,
-                        gfloat               delta_x,
-                        gfloat               delta_y);
-  void (* drag_end)    (ClutterDragAction   *action,
-                        ClutterActor        *actor,
-                        gfloat               event_x,
-                        gfloat               event_y,
-                        ClutterModifierType  modifiers);
+  void          (* drag_begin)          (ClutterDragAction   *action,
+                                         ClutterActor        *actor,
+                                         gfloat               event_x,
+                                         gfloat               event_y,
+                                         ClutterModifierType  modifiers);
+  void          (* drag_motion)         (ClutterDragAction   *action,
+                                         ClutterActor        *actor,
+                                         gfloat               delta_x,
+                                         gfloat               delta_y);
+  void          (* drag_end)            (ClutterDragAction   *action,
+                                         ClutterActor        *actor,
+                                         gfloat               event_x,
+                                         gfloat               event_y,
+                                         ClutterModifierType  modifiers);
+  gboolean      (* drag_progress)       (ClutterDragAction   *action,
+                                         ClutterActor        *actor,
+                                         gfloat               delta_x,
+                                         gfloat               delta_y);
 
   /*< private >*/
   void (* _clutter_drag_action1) (void);
   void (* _clutter_drag_action2) (void);
   void (* _clutter_drag_action3) (void);
   void (* _clutter_drag_action4) (void);
-  void (* _clutter_drag_action5) (void);
 };
 
 GType clutter_drag_action_get_type (void) G_GNUC_CONST;



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