[vte/wip/issue-335: 2/3] widget: Add API to make scrolling pixel-based




commit 5ff99e6bfed5c8bfbc1d44b2b30171a5aa366d19
Author: Christian Persch <chpe src gnome org>
Date:   Wed Mar 3 18:56:08 2021 +0100

    widget: Add API to make scrolling pixel-based
    
    TODO: Update adjustment value and properties when the cell height
    changes (font size, font zoom, DPI change, cell scale change).
    
    https://gitlab.gnome.org/GNOME/vte/-/issues/335
    https://gitlab.gnome.org/GNOME/gtk/-/issues/3707

 doc/reference/vte-sections.txt.in |  2 ++
 src/app/app.cc                    |  4 +++
 src/vte/vteterminal.h             |  6 ++++
 src/vtegtk.cc                     | 68 +++++++++++++++++++++++++++++++++++++++
 src/vtegtk.hh                     |  1 +
 src/widget.cc                     | 27 +++++++++++++---
 src/widget.hh                     | 11 +++++++
 7 files changed, 115 insertions(+), 4 deletions(-)
---
diff --git a/doc/reference/vte-sections.txt.in b/doc/reference/vte-sections.txt.in
index 53079292..f078b0ae 100644
--- a/doc/reference/vte-sections.txt.in
+++ b/doc/reference/vte-sections.txt.in
@@ -35,6 +35,8 @@ vte_terminal_set_scroll_on_output
 vte_terminal_get_scroll_on_output
 vte_terminal_set_scroll_on_keystroke
 vte_terminal_get_scroll_on_keystroke
+vte_terminal_set_scroll_unit_pixels
+vte_terminal_get_scroll_unit_pixels
 vte_terminal_set_cell_height_scale
 vte_terminal_get_cell_height_scale
 vte_terminal_set_cell_width_scale
diff --git a/src/app/app.cc b/src/app/app.cc
index e7a20c87..bee48a1a 100644
--- a/src/app/app.cc
+++ b/src/app/app.cc
@@ -81,6 +81,7 @@ public:
         gboolean object_notifications{false};
         gboolean require_systemd_scope{false};
         gboolean reverse{false};
+        gboolean scroll_unit_pixels{false};
         gboolean test_mode{false};
         gboolean track_clipboard_targets{false};
         gboolean use_theme_colors{false};
@@ -622,6 +623,8 @@ public:
                           "Reverse foreground/background colors", nullptr },
                         { "require-systemd-scope", 0, 0, G_OPTION_ARG_NONE, &require_systemd_scope,
                           "Require use of a systemd user scope", nullptr },
+                        { "scroll-unit-pixels", 0, 0, G_OPTION_ARG_NONE, &scroll_unit_pixels,
+                          "Use pixels as scroll unit", nullptr },
                         { "scrollback-lines", 'n', 0, G_OPTION_ARG_INT, &scrollback_lines,
                           "Specify the number of scrollback-lines (-1 for infinite)", nullptr },
                         { "sixel", 0, G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &no_sixel,
@@ -2528,6 +2531,7 @@ vteapp_window_constructed(GObject *object)
         vte_terminal_set_rewrap_on_resize(window->terminal, !options.no_rewrap);
         vte_terminal_set_scroll_on_output(window->terminal, false);
         vte_terminal_set_scroll_on_keystroke(window->terminal, true);
+        vte_terminal_set_scroll_unit_pixels(window->terminal, options.scroll_unit_pixels);
         vte_terminal_set_scrollback_lines(window->terminal, options.scrollback_lines);
         vte_terminal_set_text_blink_mode(window->terminal, options.text_blink_mode);
 
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index 346523ad..95472450 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -270,6 +270,12 @@ void vte_terminal_set_enable_fallback_scrolling(VteTerminal *terminal,
 _VTE_PUBLIC
 gboolean vte_terminal_get_enable_fallback_scrolling(VteTerminal *terminal)  _VTE_CXX_NOEXCEPT 
_VTE_GNUC_NONNULL(1);
 
+_VTE_PUBLIC
+void vte_terminal_set_scroll_unit_pixels(VteTerminal *terminal,
+                                         gboolean enable) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
+_VTE_PUBLIC
+gboolean vte_terminal_get_scroll_unit_pixels(VteTerminal *terminal)  _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
+
 /* Set the color scheme. */
 _VTE_PUBLIC
 void vte_terminal_set_color_bold(VteTerminal *terminal,
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 1f35e749..01aff289 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -1001,6 +1001,9 @@ try
                 case PROP_SCROLL_ON_OUTPUT:
                         g_value_set_boolean (value, vte_terminal_get_scroll_on_output(terminal));
                         break;
+                case PROP_SCROLL_UNIT_PIXELS:
+                        g_value_set_boolean (value, vte_terminal_get_scroll_unit_pixels(terminal));
+                        break;
                 case PROP_TEXT_BLINK_MODE:
                         g_value_set_enum (value, vte_terminal_get_text_blink_mode (terminal));
                         break;
@@ -1119,6 +1122,9 @@ try
                 case PROP_SCROLL_ON_OUTPUT:
                         vte_terminal_set_scroll_on_output (terminal, g_value_get_boolean (value));
                         break;
+                case PROP_SCROLL_UNIT_PIXELS:
+                        vte_terminal_set_scroll_unit_pixels(terminal, g_value_get_boolean(value));
+                        break;
                 case PROP_TEXT_BLINK_MODE:
                         vte_terminal_set_text_blink_mode (terminal, (VteTextBlinkMode)g_value_get_enum 
(value));
                         break;
@@ -2239,6 +2245,20 @@ vte_terminal_class_init(VteTerminalClass *klass)
                                       true,
                                       GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | 
G_PARAM_EXPLICIT_NOTIFY));
 
+        /**
+         * VteTerminal:scroll-unit-pixels:
+         *
+         * Controls whether the terminal's GtkAdjustment values unit is lines
+         * or pixels. This can be enabled when the terminal is the child of a
+         * GtkScrolledWindow to fix some bugs with its kinetic scrolling.
+         *
+         * Since: 0.66
+         */
+        pspecs[PROP_SCROLL_UNIT_PIXELS] =
+                g_param_spec_boolean ("scroll-unit-pixels", nullptr, nullptr,
+                                      false,
+                                      GParamFlags(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | 
G_PARAM_EXPLICIT_NOTIFY));
+
         /**
          * VteTerminal:text-blink-mode:
          *
@@ -5854,6 +5874,54 @@ catch (...)
         return true;
 }
 
+/**
+ * vte_terminal_set_scroll_unit_pixels:
+ * @terminal: a #VteTerminal
+ * @enable: whether to use pixels as scroll unit
+ *
+ * Controls whether the terminal's scroll unit is lines or pixels.
+ *
+ * This function is rarely useful, except when the terminal is added to a
+ * #GtkScrolledWindow.
+ *
+ * Since: 0.66
+ */
+void
+vte_terminal_set_scroll_unit_pixels(VteTerminal *terminal,
+                                    gboolean enable) noexcept
+try
+{
+        g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
+        if (WIDGET(terminal)->set_scroll_unit_pixels(enable != false))
+                g_object_notify_by_pspec(G_OBJECT(terminal), pspecs[PROP_SCROLL_UNIT_PIXELS]);
+}
+catch (...)
+{
+        vte::log_exception();
+}
+
+/**
+ * vte_terminal_get_scroll_unit_pixels:
+ * @terminal: a #VteTerminal
+ *
+ * Returns: %TRUE if the scroll unit is pixels; or %FALSE if the unit is lines
+ *
+ * Since: 0.66
+ */
+gboolean
+vte_terminal_get_scroll_unit_pixels(VteTerminal *terminal) noexcept
+try
+{
+    g_return_val_if_fail(VTE_IS_TERMINAL(terminal), false);
+    return WIDGET(terminal)->scroll_unit_pixels();
+}
+catch (...)
+{
+        vte::log_exception();
+        return false;
+}
+
 /**
  * vte_terminal_get_window_title:
  * @terminal: a #VteTerminal
diff --git a/src/vtegtk.hh b/src/vtegtk.hh
index e56314ad..e46d3ca5 100644
--- a/src/vtegtk.hh
+++ b/src/vtegtk.hh
@@ -88,6 +88,7 @@ enum {
         PROP_SCROLLBACK_LINES,
         PROP_SCROLL_ON_KEYSTROKE,
         PROP_SCROLL_ON_OUTPUT,
+        PROP_SCROLL_UNIT_PIXELS,
         PROP_TEXT_BLINK_MODE,
         PROP_WINDOW_TITLE,
         PROP_WORD_CHAR_EXCEPTIONS,
diff --git a/src/widget.cc b/src/widget.cc
index b9265750..1a675b03 100644
--- a/src/widget.cc
+++ b/src/widget.cc
@@ -151,6 +151,7 @@ catch (...)
 
 Widget::Widget(VteTerminal* t)
         : m_widget{&t->widget},
+          m_scroll_unit_pixels{false},
           m_hscroll_policy{GTK_SCROLL_NATURAL},
           m_vscroll_policy{GTK_SCROLL_NATURAL}
 {
@@ -745,8 +746,16 @@ Widget::notify_scroll_bounds_changed(long lower,
         auto const freezer = vte::glib::FreezeObjectNotify{m_vadjustment.get()};
         auto changed = false;
 
-        auto const dlower = double(lower);
-        auto const dupper = double(upper);
+        auto dlower = double(lower);
+        auto dupper = double(upper);
+        auto dline = 1.;
+        if (scroll_unit_pixels()) [[unlikely]] {
+                auto const factor = m_terminal->get_cell_height();
+                dlower *= factor;
+                dupper *= factor;
+                dline *= factor;
+                row_count *= factor;
+        }
 
         auto current = gtk_adjustment_get_lower(m_vadjustment.get());
         if (!_vte_double_equal(current, dlower)) {
@@ -768,7 +777,7 @@ Widget::notify_scroll_bounds_changed(long lower,
 
         /* The step increment should always be one. */
         auto v = gtk_adjustment_get_step_increment(m_vadjustment.get());
-        if (!_vte_double_equal(v, 1.)) {
+        if (!_vte_double_equal(v, dline)) {
                 _vte_debug_print(VTE_DEBUG_ADJ,
                                  "Changing step increment from %.0lf to 1.0\n", v);
                 gtk_adjustment_set_step_increment(m_vadjustment.get(), 1.);
@@ -805,6 +814,11 @@ Widget::notify_scroll_bounds_changed(long lower,
 void
 Widget::notify_scroll_value_changed(double value)
 {
+        if (scroll_unit_pixels()) [[unlikely]] {
+                auto const factor = m_terminal->get_cell_height();
+                value *= factor;
+        }
+
         auto const v = gtk_adjustment_get_value(m_vadjustment.get());
         if (!_vte_double_equal(v, value)) {
                 /* Note that this will generate a 'value-changed' signal */
@@ -1384,7 +1398,12 @@ Widget::vadjustment_value_changed()
         if (!m_terminal)
                 return;
 
-        auto const adj = gtk_adjustment_get_value(m_vadjustment.get());
+        auto adj = gtk_adjustment_get_value(m_vadjustment.get());
+        if (scroll_unit_pixels()) [[unlikely]] {
+                auto const factor = m_terminal->get_cell_height();
+                adj /= factor;
+        }
+
         m_terminal->set_scroll_value(adj);
 }
 
diff --git a/src/widget.hh b/src/widget.hh
index 5e9b5a59..3f475ac5 100644
--- a/src/widget.hh
+++ b/src/widget.hh
@@ -350,6 +350,16 @@ public:
         void set_vscroll_policy(GtkScrollablePolicy policy);
         auto hscroll_policy() const noexcept { return m_hscroll_policy; }
         auto vscroll_policy() const noexcept { return m_vscroll_policy; }
+
+        constexpr bool set_scroll_unit_pixels(bool enable) noexcept
+        {
+                auto const rv = m_scroll_unit_pixels != enable;
+                m_scroll_unit_pixels = enable;
+                return rv;
+        }
+
+        constexpr auto scroll_unit_pixels() const noexcept { return m_scroll_unit_pixels; }
+
         auto padding() const noexcept { return terminal()->padding(); }
 
         bool set_cursor_blink_mode(VteCursorBlinkMode mode) { return 
terminal()->set_cursor_blink_mode(vte::terminal::Terminal::CursorBlinkMode(mode)); }
@@ -522,6 +532,7 @@ private:
         vte::glib::RefPtr<GtkAdjustment> m_vadjustment{};
         vte::glib::RefPtr<GtkAdjustment> m_hadjustment{};
 
+        uint32_t m_scroll_unit_pixels : 1;
         uint32_t m_hscroll_policy : 1;
         uint32_t m_vscroll_policy : 1;
 };


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