[gtksourceview] map: make scrolling from drag immediate



commit 2c6e950174ec84d54c874299a66de369c1561dc1
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jun 21 20:26:49 2021 -0700

    map: make scrolling from drag immediate
    
    The animation from GtkTextView -> GtkAdjustment can cause quite a bit of
    delay given the scroll animation easing. This instead just jumps to the
    position immediately which has a bit nicer effect from the map.

 gtksourceview/gtksourcemap.c           |   6 +-
 gtksourceview/gtksourceutils-private.h |  10 ++-
 gtksourceview/gtksourceutils.c         | 133 +++++++++++++++++++++++++++++++++
 3 files changed, 146 insertions(+), 3 deletions(-)
---
diff --git a/gtksourceview/gtksourcemap.c b/gtksourceview/gtksourcemap.c
index fd51617e..038f90e7 100644
--- a/gtksourceview/gtksourcemap.c
+++ b/gtksourceview/gtksourcemap.c
@@ -669,8 +669,8 @@ scroll_to_child_point (GtkSourceMap *map,
 
                gtk_widget_get_allocation (GTK_WIDGET (map), &alloc);
                gtk_text_view_get_iter_at_location (GTK_TEXT_VIEW (map), &iter, x, y);
-               gtk_text_view_scroll_to_iter (GTK_TEXT_VIEW (priv->view), &iter,
-                                             0.0, TRUE, 1.0, 0.5);
+               _gtk_source_view_jump_to_iter (GTK_TEXT_VIEW (priv->view), &iter,
+                                              0.0, TRUE, 1.0, 0.5);
        }
 }
 
@@ -900,6 +900,8 @@ gtk_source_map_drag_update (GtkSourceMap   *map,
                return;
        }
 
+       y = ceil (y);
+
        priv->reached_drag_threshold = TRUE;
 
        gtk_widget_get_allocation (GTK_WIDGET (map), &alloc);
diff --git a/gtksourceview/gtksourceutils-private.h b/gtksourceview/gtksourceutils-private.h
index 283eddd0..3658513b 100644
--- a/gtksourceview/gtksourceutils-private.h
+++ b/gtksourceview/gtksourceutils-private.h
@@ -21,8 +21,8 @@
 
 #pragma once
 
-#include <glib.h>
 #include <pango/pango.h>
+#include <gtk/gtk.h>
 
 G_BEGIN_DECLS
 
@@ -45,4 +45,12 @@ G_GNUC_INTERNAL
 gchar   *_gtk_source_utils_dgettext                      (const gchar                 *domain,
                                                           const gchar                 *msgid) 
G_GNUC_FORMAT(2);
 
+G_GNUC_INTERNAL
+void     _gtk_source_view_jump_to_iter                   (GtkTextView                 *view,
+                                                          const GtkTextIter           *iter,
+                                                          double                       within_margin,
+                                                          gboolean                     use_align,
+                                                          double                       xalign,
+                                                          double                       yalign);
+
 G_END_DECLS
diff --git a/gtksourceview/gtksourceutils.c b/gtksourceview/gtksourceutils.c
index 72e00616..e8880289 100644
--- a/gtksourceview/gtksourceutils.c
+++ b/gtksourceview/gtksourceutils.c
@@ -622,3 +622,136 @@ _gtk_source_utils_int_to_string (guint         value,
 
        return fi.len;
 }
+
+/*
+ * The goal of this function is to be like gtk_text_view_scroll_to_iter() but
+ * without any of the scrolling animation. We use it from the source map where
+ * the updates are so fast the scrolling animation makes it feel very delayed.
+ *
+ * Many parts of this function were taken from gtk_text_view_scroll_to_iter ()
+ * https://developer.gnome.org/gtk3/stable/GtkTextView.html#gtk-text-view-scroll-to-iter
+ */
+void
+_gtk_source_view_jump_to_iter (GtkTextView       *text_view,
+                               const GtkTextIter *iter,
+                               double             within_margin,
+                               gboolean           use_align,
+                               double             xalign,
+                               double             yalign)
+{
+  GtkAdjustment *hadj;
+  GtkAdjustment *vadj;
+  GdkRectangle rect;
+  GdkRectangle screen;
+  int xvalue = 0;
+  int yvalue = 0;
+  int scroll_dest;
+  int screen_bottom;
+  int screen_right;
+  int screen_xoffset;
+  int screen_yoffset;
+  int current_x_scroll;
+  int current_y_scroll;
+
+  g_return_if_fail (GTK_IS_TEXT_VIEW (text_view));
+  g_return_if_fail (iter != NULL);
+  g_return_if_fail (within_margin >= 0.0 && within_margin <= 0.5);
+  g_return_if_fail (xalign >= 0.0 && xalign <= 1.0);
+  g_return_if_fail (yalign >= 0.0 && yalign <= 1.0);
+
+  hadj = gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (text_view));
+  vadj = gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (text_view));
+
+  gtk_text_view_get_iter_location (text_view, iter, &rect);
+  gtk_text_view_get_visible_rect (text_view, &screen);
+
+  current_x_scroll = screen.x;
+  current_y_scroll = screen.y;
+
+  screen_xoffset = screen.width * within_margin;
+  screen_yoffset = screen.height * within_margin;
+
+  screen.x += screen_xoffset;
+  screen.y += screen_yoffset;
+  screen.width -= screen_xoffset * 2;
+  screen.height -= screen_yoffset * 2;
+
+
+  /* paranoia check */
+  if (screen.width < 1)
+    screen.width = 1;
+  if (screen.height < 1)
+    screen.height = 1;
+
+  /* The -1 here ensures that we leave enough space to draw the cursor
+   * when this function is used for horizontal scrolling.
+   */
+  screen_right = screen.x + screen.width - 1;
+  screen_bottom = screen.y + screen.height;
+
+
+  /* The alignment affects the point in the target character that we
+   * choose to align. If we're doing right/bottom alignment, we align
+   * the right/bottom edge of the character the mark is at; if we're
+   * doing left/top we align the left/top edge of the character; if
+   * we're doing center alignment we align the center of the
+   * character.
+   */
+
+  /* Vertical alignment */
+  scroll_dest = current_y_scroll;
+  if (use_align)
+    {
+      scroll_dest = rect.y + (rect.height * yalign) - (screen.height * yalign);
+
+      /* if scroll_dest < screen.y, we move a negative increment (up),
+       * else a positive increment (down)
+       */
+      yvalue = scroll_dest - screen.y + screen_yoffset;
+    }
+  else
+    {
+      /* move minimum to get onscreen */
+      if (rect.y < screen.y)
+        {
+          scroll_dest = rect.y;
+          yvalue = scroll_dest - screen.y - screen_yoffset;
+        }
+      else if ((rect.y + rect.height) > screen_bottom)
+        {
+          scroll_dest = rect.y + rect.height;
+          yvalue = scroll_dest - screen_bottom + screen_yoffset;
+        }
+    }
+  yvalue += current_y_scroll;
+
+  /* Horizontal alignment */
+  scroll_dest = current_x_scroll;
+  if (use_align)
+    {
+      scroll_dest = rect.x + (rect.width * xalign) - (screen.width * xalign);
+
+      /* if scroll_dest < screen.y, we move a negative increment (left),
+       * else a positive increment (right)
+       */
+      xvalue = scroll_dest - screen.x + screen_xoffset;
+    }
+  else
+    {
+      /* move minimum to get onscreen */
+      if (rect.x < screen.x)
+        {
+          scroll_dest = rect.x;
+          xvalue = scroll_dest - screen.x - screen_xoffset;
+        }
+      else if ((rect.x + rect.width) > screen_right)
+        {
+          scroll_dest = rect.x + rect.width;
+          xvalue = scroll_dest - screen_right + screen_xoffset;
+        }
+    }
+  xvalue += current_x_scroll;
+
+  gtk_adjustment_set_value (hadj, xvalue);
+  gtk_adjustment_set_value (vadj, yvalue);
+}


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