[gtk/wip/otte/dnd: 113/126] textview: Move drop scrolling to drop motion controller



commit b799bc5ce1adaa27d26a410f8ed446a5868e4b10
Author: Benjamin Otte <otte redhat com>
Date:   Sat Feb 29 04:37:16 2020 +0100

    textview: Move drop scrolling to drop motion controller
    
    Don't confuse the drop target with it.

 gtk/gtktextview.c | 220 +++++++++++++++++++++++++++++-------------------------
 1 file changed, 119 insertions(+), 101 deletions(-)
---
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index d80a94eee7..a6cb66ceb5 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -33,6 +33,7 @@
 #include "gtkbindings.h"
 #include "gtkcsscolorvalueprivate.h"
 #include "gtkdebug.h"
+#include "gtkdropcontrollermotion.h"
 #include "gtkintl.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
@@ -661,6 +662,118 @@ G_DEFINE_TYPE_WITH_CODE (GtkTextView, gtk_text_view, GTK_TYPE_CONTAINER,
                          G_ADD_PRIVATE (GtkTextView)
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_SCROLLABLE, NULL))
 
+static GtkTextBuffer*
+get_buffer (GtkTextView *text_view)
+{
+  if (text_view->priv->buffer == NULL)
+    {
+      GtkTextBuffer *b;
+      b = GTK_TEXT_VIEW_GET_CLASS (text_view)->create_buffer (text_view);
+      gtk_text_view_set_buffer (text_view, b);
+      g_object_unref (b);
+    }
+
+  return text_view->priv->buffer;
+}
+
+#define UPPER_OFFSET_ANCHOR 0.8
+#define LOWER_OFFSET_ANCHOR 0.2
+
+static gboolean
+check_scroll (gdouble offset, GtkAdjustment *adjustment)
+{
+  if ((offset > UPPER_OFFSET_ANCHOR &&
+       gtk_adjustment_get_value (adjustment) + gtk_adjustment_get_page_size (adjustment) < 
gtk_adjustment_get_upper (adjustment)) ||
+      (offset < LOWER_OFFSET_ANCHOR &&
+       gtk_adjustment_get_value (adjustment) > gtk_adjustment_get_lower (adjustment)))
+    return TRUE;
+
+  return FALSE;
+}
+
+static int
+gtk_text_view_drop_motion_scroll_timeout (gpointer data)
+{
+  GtkTextView *text_view;
+  GtkTextViewPrivate *priv;
+  GtkTextIter newplace;
+  gdouble pointer_xoffset, pointer_yoffset;
+
+  text_view = GTK_TEXT_VIEW (data);
+  priv = text_view->priv;
+
+  gtk_text_layout_get_iter_at_pixel (priv->layout,
+                                     &newplace,
+                                     priv->dnd_x + priv->xoffset,
+                                     priv->dnd_y + priv->yoffset);
+
+  gtk_text_buffer_move_mark (get_buffer (text_view), priv->dnd_mark, &newplace);
+
+  pointer_xoffset = (gdouble) priv->dnd_x / text_window_get_width (priv->text_window);
+  pointer_yoffset = (gdouble) priv->dnd_y / text_window_get_height (priv->text_window);
+
+  if (check_scroll (pointer_xoffset, priv->hadjustment) ||
+      check_scroll (pointer_yoffset, priv->vadjustment))
+    {
+      /* do not make offsets surpass lower nor upper anchors, this makes
+       * scrolling speed relative to the distance of the pointer to the
+       * anchors when it moves beyond them.
+       */
+      pointer_xoffset = CLAMP (pointer_xoffset, LOWER_OFFSET_ANCHOR, UPPER_OFFSET_ANCHOR);
+      pointer_yoffset = CLAMP (pointer_yoffset, LOWER_OFFSET_ANCHOR, UPPER_OFFSET_ANCHOR);
+
+      gtk_text_view_scroll_to_mark (text_view,
+                                    priv->dnd_mark,
+                                    0., TRUE, pointer_xoffset, pointer_yoffset);
+    }
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+gtk_text_view_drop_scroll_motion (GtkDropControllerMotion *motion,
+                                  double                   x,
+                                  double                   y,
+                                  GtkTextView             *self)
+{
+  GtkTextViewPrivate *priv = self->priv;
+  GdkRectangle target_rect;
+
+  target_rect = priv->text_window->allocation;
+  
+  if (x < target_rect.x ||
+      y < target_rect.y ||
+      x > (target_rect.x + target_rect.width) ||
+      y > (target_rect.y + target_rect.height))
+    {
+      priv->dnd_x = priv->dnd_y = -1;
+      g_clear_handle_id (&priv->scroll_timeout, g_source_remove);
+      return;
+    }
+
+  /* DnD uses text window coords, so subtract extra widget
+   * coords that happen e.g. when displaying line numbers.
+   */
+  priv->dnd_x = x - target_rect.x;
+  priv->dnd_y = y - target_rect.y;
+
+  if (!priv->scroll_timeout)
+  {
+    priv->scroll_timeout = g_timeout_add (100, gtk_text_view_drop_motion_scroll_timeout, self);
+    g_source_set_name_by_id (priv->scroll_timeout, "[gtk] gtk_text_view_drop_motion_scroll_timeout");
+  }
+}
+
+static void
+gtk_text_view_drop_scroll_leave (GtkDropControllerMotion *motion,
+                                 GtkTextView             *self)
+{
+  GtkTextViewPrivate *priv = self->priv;
+
+  priv->dnd_x = priv->dnd_y = -1;
+  g_clear_handle_id (&priv->scroll_timeout, g_source_remove);
+}
+
 static void
 add_move_binding (GtkBindingSet  *binding_set,
                   guint           keyval,
@@ -1645,6 +1758,12 @@ gtk_text_view_init (GtkTextView *text_view)
   g_signal_connect (dest, "drag-drop", G_CALLBACK (gtk_text_view_drag_drop), text_view);
   gtk_widget_add_controller (GTK_WIDGET (text_view), GTK_EVENT_CONTROLLER (dest));
 
+  controller = gtk_drop_controller_motion_new ();
+  g_signal_connect (controller, "enter", G_CALLBACK (gtk_text_view_drop_scroll_motion), text_view);
+  g_signal_connect (controller, "motion", G_CALLBACK (gtk_text_view_drop_scroll_motion), text_view);
+  g_signal_connect (controller, "leave", G_CALLBACK (gtk_text_view_drop_scroll_leave), text_view);
+  gtk_widget_add_controller (GTK_WIDGET (text_view), controller);
+
   priv->virtual_cursor_x = -1;
   priv->virtual_cursor_y = -1;
 
@@ -1950,20 +2069,6 @@ gtk_text_view_create_buffer (GtkTextView *text_view)
   return gtk_text_buffer_new (NULL);
 }
 
-static GtkTextBuffer*
-get_buffer (GtkTextView *text_view)
-{
-  if (text_view->priv->buffer == NULL)
-    {
-      GtkTextBuffer *b;
-      b = GTK_TEXT_VIEW_GET_CLASS (text_view)->create_buffer (text_view);
-      gtk_text_view_set_buffer (text_view, b);
-      g_object_unref (b);
-    }
-
-  return text_view->priv->buffer;
-}
-
 /**
  * gtk_text_view_get_buffer:
  * @text_view: a #GtkTextView
@@ -6896,60 +7001,6 @@ selection_scan_timeout (gpointer data)
   return TRUE; /* remain installed. */
 }
 
-#define UPPER_OFFSET_ANCHOR 0.8
-#define LOWER_OFFSET_ANCHOR 0.2
-
-static gboolean
-check_scroll (gdouble offset, GtkAdjustment *adjustment)
-{
-  if ((offset > UPPER_OFFSET_ANCHOR &&
-       gtk_adjustment_get_value (adjustment) + gtk_adjustment_get_page_size (adjustment) < 
gtk_adjustment_get_upper (adjustment)) ||
-      (offset < LOWER_OFFSET_ANCHOR &&
-       gtk_adjustment_get_value (adjustment) > gtk_adjustment_get_lower (adjustment)))
-    return TRUE;
-
-  return FALSE;
-}
-
-static gint
-drag_scan_timeout (gpointer data)
-{
-  GtkTextView *text_view;
-  GtkTextViewPrivate *priv;
-  GtkTextIter newplace;
-  gdouble pointer_xoffset, pointer_yoffset;
-
-  text_view = GTK_TEXT_VIEW (data);
-  priv = text_view->priv;
-
-  gtk_text_layout_get_iter_at_pixel (priv->layout,
-                                     &newplace,
-                                     priv->dnd_x + priv->xoffset,
-                                     priv->dnd_y + priv->yoffset);
-
-  gtk_text_buffer_move_mark (get_buffer (text_view), priv->dnd_mark, &newplace);
-
-  pointer_xoffset = (gdouble) priv->dnd_x / text_window_get_width (priv->text_window);
-  pointer_yoffset = (gdouble) priv->dnd_y / text_window_get_height (priv->text_window);
-
-  if (check_scroll (pointer_xoffset, priv->hadjustment) ||
-      check_scroll (pointer_yoffset, priv->vadjustment))
-    {
-      /* do not make offsets surpass lower nor upper anchors, this makes
-       * scrolling speed relative to the distance of the pointer to the
-       * anchors when it moves beyond them.
-       */
-      pointer_xoffset = CLAMP (pointer_xoffset, LOWER_OFFSET_ANCHOR, UPPER_OFFSET_ANCHOR);
-      pointer_yoffset = CLAMP (pointer_yoffset, LOWER_OFFSET_ANCHOR, UPPER_OFFSET_ANCHOR);
-
-      gtk_text_view_scroll_to_mark (text_view,
-                                    priv->dnd_mark,
-                                    0., TRUE, pointer_xoffset, pointer_yoffset);
-    }
-
-  return TRUE;
-}
-
 static void
 extend_selection (GtkTextView          *text_view,
                   SelectionGranularity  granularity,
@@ -7743,13 +7794,6 @@ gtk_text_view_drag_leave (GtkDropTarget *dest,
   GtkTextViewPrivate *priv = text_view->priv;
 
   gtk_text_mark_set_visible (priv->dnd_mark, FALSE);
-
-  priv->dnd_x = priv->dnd_y = -1;
-
-  if (priv->scroll_timeout != 0)
-    g_source_remove (priv->scroll_timeout);
-
-  priv->scroll_timeout = 0;
 }
 
 static gboolean
@@ -7763,18 +7807,9 @@ gtk_text_view_drag_motion (GtkDropTarget *dest,
   GtkTextIter newplace;
   GtkTextIter start;
   GtkTextIter end;
-  GdkRectangle target_rect;
   gint bx, by;
   gboolean can_accept = FALSE;
 
-  target_rect = priv->text_window->allocation;
-  
-  if (x < target_rect.x ||
-      y < target_rect.y ||
-      x > (target_rect.x + target_rect.width) ||
-      y > (target_rect.y + target_rect.height))
-    return FALSE; /* outside the text window, allow parent widgets to handle event */
-
   gtk_text_view_window_to_buffer_coords (text_view,
                                          GTK_TEXT_WINDOW_WIDGET,
                                          x, y,
@@ -7807,18 +7842,6 @@ gtk_text_view_drag_motion (GtkDropTarget *dest,
       gtk_text_mark_set_visible (priv->dnd_mark, FALSE);
     }
 
-  /* DnD uses text window coords, so subtract extra widget
-   * coords that happen e.g. when displaying line numbers.
-   */
-  priv->dnd_x = x - target_rect.x;
-  priv->dnd_y = y - target_rect.y;
-
-  if (!priv->scroll_timeout)
-  {
-    priv->scroll_timeout = g_timeout_add (100, drag_scan_timeout, text_view);
-    g_source_set_name_by_id (text_view->priv->scroll_timeout, "[gtk] drag_scan_timeout");
-  }
-
   /* TRUE return means don't propagate the drag motion to parent
    * widgets that may also be drop sites.
    */
@@ -7900,11 +7923,6 @@ gtk_text_view_drag_drop (GtkDropTarget *dest,
   GtkTextIter drop_point;
   GtkTextBuffer *buffer = NULL;
 
-  if (priv->scroll_timeout != 0)
-    g_source_remove (priv->scroll_timeout);
-
-  priv->scroll_timeout = 0;
-
   gtk_text_mark_set_visible (priv->dnd_mark, FALSE);
 
   buffer = get_buffer (text_view);


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