[mutter/wip/dnd-surface2: 10/18] backend: Add "DnD failed" animation



commit 79fdbbfe1a8b91a609fb482b268b2bdc59329afc
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Sep 30 16:53:21 2014 +0200

    backend: Add "DnD failed" animation
    
    This is currently handled by the MetaStage, when DnD is hinted to be
    failed, the current overlay will be copied and used on the snap back/
    fade out animation, after the animation is finished, the extra overlay
    will be freed.

 src/backends/meta-stage.c |  102 +++++++++++++++++++++++++++++++++++++++++++++
 src/backends/meta-stage.h |    5 ++
 2 files changed, 107 insertions(+), 0 deletions(-)
---
diff --git a/src/backends/meta-stage.c b/src/backends/meta-stage.c
index 72c5091..109778f 100644
--- a/src/backends/meta-stage.c
+++ b/src/backends/meta-stage.c
@@ -28,6 +28,8 @@
 #include <meta/meta-backend.h>
 #include <meta/util.h>
 
+#define DRAG_FAILED_MSECS 500
+
 typedef struct {
   gboolean enabled;
 
@@ -39,9 +41,20 @@ typedef struct {
   gboolean previous_is_valid;
 } MetaOverlay;
 
+typedef struct {
+  MetaStage *stage;
+  MetaOverlay overlay;
+  ClutterTimeline *timeline;
+  int orig_x;
+  int orig_y;
+  int dest_x;
+  int dest_y;
+} MetaDragFailedAnimation;
+
 struct _MetaStagePrivate {
   MetaOverlay dnd_overlay;
   MetaOverlay cursor_overlay;
+  GList *drag_failed_animations;
 };
 typedef struct _MetaStagePrivate MetaStagePrivate;
 
@@ -131,9 +144,17 @@ meta_stage_paint (ClutterActor *actor)
 {
   MetaStage *stage = META_STAGE (actor);
   MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+  MetaDragFailedAnimation *animation;
+  GList *l;
 
   CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
 
+  for (l = priv->drag_failed_animations; l; l = l->next)
+    {
+      animation = l->data;
+      meta_overlay_paint (&animation->overlay);
+    }
+
   meta_overlay_paint (&priv->dnd_overlay);
   meta_overlay_paint (&priv->cursor_overlay);
 }
@@ -221,3 +242,84 @@ meta_stage_set_cursor (MetaStage     *stage,
   meta_overlay_set (&priv->cursor_overlay, texture, rect);
   queue_redraw_for_overlay (stage, &priv->cursor_overlay);
 }
+
+static void
+drag_failed_animation_frame_cb (ClutterTimeline *timeline,
+                                guint            pos,
+                                gpointer         user_data)
+{
+  MetaDragFailedAnimation *data = user_data;
+  gdouble progress = clutter_timeline_get_progress (timeline);
+  CoglColor color;
+
+  cogl_color_init_from_4f (&color, 0, 0, 0, 1 - progress);
+  cogl_pipeline_set_layer_combine_constant (data->overlay.pipeline, 0, &color);
+
+  data->overlay.current_rect.x = data->orig_x + ((data->dest_x - data->orig_x) * progress);
+  data->overlay.current_rect.y = data->orig_y + ((data->dest_y - data->orig_y) * progress);
+  queue_redraw_for_overlay (data->stage, &data->overlay);
+}
+
+static void
+meta_drag_failed_animation_free (MetaDragFailedAnimation *data)
+{
+  MetaStage *stage = data->stage;
+  MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+
+  priv->drag_failed_animations =
+    g_list_remove (priv->drag_failed_animations, data);
+
+  g_object_unref (data->timeline);
+  meta_overlay_free (&data->overlay);
+  g_slice_free (MetaDragFailedAnimation, data);
+}
+
+static MetaDragFailedAnimation *
+meta_drag_failed_animation_new (MetaStage *stage,
+                                int        dest_x,
+                                int        dest_y)
+{
+  MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+  MetaDragFailedAnimation *data;
+
+  data = g_slice_new0 (MetaDragFailedAnimation);
+  data->stage = stage;
+  data->orig_x = priv->dnd_overlay.current_rect.x;
+  data->orig_y = priv->dnd_overlay.current_rect.y;
+  data->dest_x = dest_x;
+  data->dest_y = dest_y;
+
+  meta_overlay_copy (&priv->dnd_overlay, &data->overlay);
+
+  data->timeline = clutter_timeline_new (DRAG_FAILED_MSECS);
+  clutter_timeline_set_progress_mode (data->timeline, CLUTTER_EASE_OUT_CUBIC);
+  g_signal_connect (data->timeline, "new-frame",
+                    G_CALLBACK (drag_failed_animation_frame_cb), data);
+  g_signal_connect_swapped (data->timeline, "completed",
+                            G_CALLBACK (meta_drag_failed_animation_free), data);
+
+  priv->drag_failed_animations =
+    g_list_prepend (priv->drag_failed_animations, data);
+
+  cogl_pipeline_set_layer_combine (data->overlay.pipeline, 0,
+                                   "RGBA = MODULATE (TEXTURE, CONSTANT[A])",
+                                   NULL);
+  return data;
+}
+
+void
+meta_stage_dnd_failed (MetaStage *stage,
+                       int        dest_x,
+                       int        dest_y)
+{
+  MetaStagePrivate *priv = meta_stage_get_instance_private (stage);
+  MetaDragFailedAnimation *data;
+
+  g_assert (meta_is_wayland_compositor ());
+
+  if (!priv->dnd_overlay.enabled)
+    return;
+
+  data = meta_drag_failed_animation_new (stage, dest_x, dest_y);
+  clutter_timeline_start (data->timeline);
+}
diff --git a/src/backends/meta-stage.h b/src/backends/meta-stage.h
index 572530d..6e7d0df 100644
--- a/src/backends/meta-stage.h
+++ b/src/backends/meta-stage.h
@@ -58,6 +58,11 @@ void meta_stage_set_dnd_surface (MetaStage     *stage,
 void meta_stage_set_cursor (MetaStage     *stage,
                             CoglTexture   *texture,
                             MetaRectangle *rect);
+
+void meta_stage_dnd_failed (MetaStage *stage,
+                            int        dest_x,
+                            int        dest_y);
+
 G_END_DECLS
 
 #endif /* META_STAGE_H */


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