[gtk/wip/chergert/quartz4u: 144/146] macos: add zoomback on drag cancel
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/quartz4u: 144/146] macos: add zoomback on drag cancel
- Date: Fri, 19 Jun 2020 18:20:55 +0000 (UTC)
commit 7656ffde0a0527fadf2c090e38c4de94a03c7c9c
Author: Christian Hergert <chergert redhat com>
Date: Thu Jun 18 16:43:36 2020 -0700
macos: add zoomback on drag cancel
gdk/macos/gdkmacosdrag-private.h | 26 ++++++++
gdk/macos/gdkmacosdrag.c | 125 ++++++++++++++++++++++++++++++---------
gdk/macos/gdkmacossurface.c | 15 +++--
3 files changed, 134 insertions(+), 32 deletions(-)
---
diff --git a/gdk/macos/gdkmacosdrag-private.h b/gdk/macos/gdkmacosdrag-private.h
index 7a7bf8a041..7abd2b2270 100644
--- a/gdk/macos/gdkmacosdrag-private.h
+++ b/gdk/macos/gdkmacosdrag-private.h
@@ -22,6 +22,8 @@
#include "gdkdragprivate.h"
+#include "gdkmacosdragsurface-private.h"
+
G_BEGIN_DECLS
#define GDK_TYPE_MACOS_DRAG (gdk_macos_drag_get_type ())
@@ -34,6 +36,30 @@ G_BEGIN_DECLS
typedef struct _GdkMacosDrag GdkMacosDrag;
typedef struct _GdkMacosDragClass GdkMacosDragClass;
+struct _GdkMacosDrag
+{
+ GdkDrag parent_instance;
+
+ GdkMacosDragSurface *drag_surface;
+
+ int hot_x;
+ int hot_y;
+
+ int last_x;
+ int last_y;
+
+ int start_x;
+ int start_y;
+
+ guint did_update : 1;
+ guint cancelled : 1;
+};
+
+struct _GdkMacosDragClass
+{
+ GdkDragClass parent_class;
+};
+
GType gdk_macos_drag_get_type (void) G_GNUC_CONST;
G_END_DECLS
diff --git a/gdk/macos/gdkmacosdrag.c b/gdk/macos/gdkmacosdrag.c
index afa488e308..6d077540a5 100644
--- a/gdk/macos/gdkmacosdrag.c
+++ b/gdk/macos/gdkmacosdrag.c
@@ -29,24 +29,14 @@
#define BIG_STEP 20
#define SMALL_STEP 1
+#define ANIM_TIME 500000 /* .5 seconds */
-struct _GdkMacosDrag
+typedef struct
{
- GdkDrag parent_instance;
-
- GdkMacosDragSurface *drag_surface;
-
- int hot_x;
- int hot_y;
-
- int last_x;
- int last_y;
-};
-
-struct _GdkMacosDragClass
-{
- GdkDragClass parent_class;
-};
+ GdkMacosDrag *drag;
+ GdkFrameClock *frame_clock;
+ gint64 start_time;
+} GdkMacosZoomback;
G_DEFINE_TYPE (GdkMacosDrag, gdk_macos_drag, GDK_TYPE_DRAG)
@@ -58,6 +48,57 @@ enum {
static GParamSpec *properties [N_PROPS];
+static double
+ease_out_cubic (double t)
+{
+ double p = t - 1;
+ return p * p * p + 1;
+}
+
+static void
+gdk_macos_zoomback_destroy (GdkMacosZoomback *zb)
+{
+ gdk_surface_hide (GDK_SURFACE (zb->drag->drag_surface));
+ g_object_unref (zb->drag);
+ g_slice_free (GdkMacosZoomback, zb);
+}
+
+static gboolean
+gdk_macos_zoomback_timeout (gpointer data)
+{
+ GdkMacosZoomback *zb = data;
+ GdkFrameClock *frame_clock;
+ GdkMacosDrag *drag;
+ gint64 current_time;
+ double f;
+ double t;
+
+ g_assert (zb != NULL);
+ g_assert (GDK_IS_MACOS_DRAG (zb->drag));
+
+ drag = zb->drag;
+ frame_clock = zb->frame_clock;
+
+ if (!frame_clock)
+ return G_SOURCE_REMOVE;
+
+ current_time = gdk_frame_clock_get_frame_time (frame_clock);
+ f = (current_time - zb->start_time) / (double) ANIM_TIME;
+ if (f >= 1.0)
+ return G_SOURCE_REMOVE;
+
+ t = ease_out_cubic (f);
+
+ _gdk_macos_surface_move (GDK_MACOS_SURFACE (drag->drag_surface),
+ (drag->last_x - drag->hot_x) +
+ (drag->start_x - drag->last_x) * t,
+ (drag->last_y - drag->hot_y) +
+ (drag->start_y - drag->last_y) * t);
+ _gdk_macos_surface_set_opacity (GDK_MACOS_SURFACE (drag->drag_surface), 1.0 - f);
+
+ return G_SOURCE_CONTINUE;
+}
+
static GdkSurface *
gdk_macos_drag_get_drag_surface (GdkDrag *drag)
{
@@ -70,13 +111,21 @@ gdk_macos_drag_set_hotspot (GdkDrag *drag,
int hot_y)
{
GdkMacosDrag *self = (GdkMacosDrag *)drag;
+ int change_x;
+ int change_y;
g_assert (GDK_IS_MACOS_DRAG (self));
+ change_x = hot_x - self->hot_x;
+ change_y = hot_y - self->hot_y;
+
self->hot_x = hot_x;
self->hot_y = hot_y;
- /* TODO: move/resize to take point into account */
+ if (change_x || change_y)
+ _gdk_macos_surface_move (GDK_MACOS_SURFACE (self->drag_surface),
+ GDK_SURFACE (self->drag_surface)->x + change_x,
+ GDK_SURFACE (self->drag_surface)->y + change_y);
}
static void
@@ -84,15 +133,31 @@ gdk_macos_drag_drop_done (GdkDrag *drag,
gboolean success)
{
GdkMacosDrag *self = (GdkMacosDrag *)drag;
+ GdkMacosZoomback *zb;
+ guint id;
g_assert (GDK_IS_MACOS_DRAG (self));
- gdk_surface_hide (GDK_SURFACE (self->drag_surface));
+ if (success)
+ {
+ gdk_surface_hide (GDK_SURFACE (self->drag_surface));
+ g_object_unref (drag);
+ return;
+ }
- /* TODO: Apple HIG suggests doing a "zoomback" animation of
- * the surface back towards the original position.
+ /* Apple HIG suggests doing a "zoomback" animation of the surface back
+ * towards the original position.
*/
-
+ zb = g_slice_new0 (GdkMacosZoomback);
+ zb->drag = g_object_ref (self);
+ zb->frame_clock = gdk_surface_get_frame_clock (GDK_SURFACE (self->drag_surface));
+ zb->start_time = gdk_frame_clock_get_frame_time (zb->frame_clock);
+
+ id = g_timeout_add_full (G_PRIORITY_DEFAULT, 17,
+ gdk_macos_zoomback_timeout,
+ zb,
+ (GDestroyNotify) gdk_macos_zoomback_destroy);
+ g_source_set_name_by_id (id, "[gtk] gdk_macos_zoomback_timeout");
g_object_unref (drag);
}
@@ -119,11 +184,9 @@ gdk_macos_drag_cancel (GdkDrag *drag,
g_assert (GDK_IS_MACOS_DRAG (self));
- g_print ("Drag cancel\n");
-
gdk_drag_drop_done (drag, FALSE);
- //g_clear_pointer ((GdkSurface **)&self->drag_surface, gdk_surface_destroy);
+ self->cancelled = TRUE;
}
static void
@@ -134,7 +197,6 @@ gdk_macos_drag_drop_performed (GdkDrag *drag,
g_assert (GDK_IS_MACOS_DRAG (self));
- //g_clear_pointer ((GdkSurface **)&self->drag_surface, gdk_surface_destroy);
}
static void
@@ -222,6 +284,13 @@ gdk_drag_update (GdkDrag *drag,
suggested_action,
possible_actions,
evtime);
+
+ if (!self->did_update)
+ {
+ self->start_x = self->last_x;
+ self->start_y = self->last_y;
+ self->did_update = TRUE;
+ }
}
static gboolean
@@ -234,6 +303,10 @@ gdk_dnd_handle_motion_event (GdkDrag *drag,
g_assert (GDK_IS_MACOS_DRAG (drag));
g_assert (event != NULL);
+ /* Ignore motion while doing zoomback */
+ if (GDK_MACOS_DRAG (drag)->cancelled)
+ return FALSE;
+
gdk_event_get_position (event, &x, &y);
x_root = event->surface->x + x;
y_root = event->surface->y + y;
@@ -444,8 +517,6 @@ gdk_macos_drag_set_property (GObject *object,
{
case PROP_DRAG_SURFACE:
self->drag_surface = g_value_dup_object (value);
- self->last_x = GDK_SURFACE (self->drag_surface)->x;
- self->last_y = GDK_SURFACE (self->drag_surface)->y;
break;
default:
diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c
index aa5d99a095..9d22ae9a53 100644
--- a/gdk/macos/gdkmacossurface.c
+++ b/gdk/macos/gdkmacossurface.c
@@ -25,6 +25,7 @@
#import "GdkMacosCairoView.h"
+#include "gdkdeviceprivate.h"
#include "gdkdisplay.h"
#include "gdkframeclockidleprivate.h"
#include "gdkinternals.h"
@@ -290,9 +291,13 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
{
GdkMacosSurface *self = (GdkMacosSurface *)surface;
GdkMacosSurface *drag_surface;
+ GdkMacosDrag *drag;
GdkCursor *cursor;
GdkSeat *seat;
- GdkDrag *drag;
+ double px;
+ double py;
+ int sx;
+ int sy;
g_assert (GDK_IS_MACOS_SURFACE (self));
g_assert (GDK_IS_MACOS_TOPLEVEL_SURFACE (self) ||
@@ -301,11 +306,12 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
g_assert (GDK_IS_CONTENT_PROVIDER (content));
seat = gdk_device_get_seat (device);
+ _gdk_device_query_state (device, surface, NULL, &px, &py, NULL);
+ _gdk_macos_surface_get_root_coords (GDK_MACOS_SURFACE (surface), &sx, &sy);
drag_surface = _gdk_macos_surface_new (GDK_MACOS_DISPLAY (surface->display),
GDK_SURFACE_TEMP,
surface,
- dx, dy,
- 1, 1);
+ -99, -99, 1, 1);
drag = g_object_new (GDK_TYPE_MACOS_DRAG,
"drag-surface", drag_surface,
"surface", surface,
@@ -317,7 +323,6 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
cursor = gdk_drag_get_cursor (GDK_DRAG (drag),
gdk_drag_get_selected_action (GDK_DRAG (drag)));
gdk_drag_set_cursor (GDK_DRAG (drag), cursor);
-
gdk_seat_ungrab (seat);
g_clear_object (&drag_surface);
@@ -325,7 +330,7 @@ gdk_macos_surface_drag_begin (GdkSurface *surface,
/* Hold a reference until drop_done is called */
g_object_ref (drag);
- return g_steal_pointer (&drag);
+ return GDK_DRAG (g_steal_pointer (&drag));
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]