Skip to content

gtk: disable kinetic scrolling for trackpads until 4.20.1 - #11793

Merged
jcollie merged 1 commit into
ghostty-org:mainfrom
viruslobster:disable-trackpad-kinetic-scroll
Mar 29, 2026
Merged

jcollie merged 1 commit into
ghostty-org:mainfrom
viruslobster:disable-trackpad-kinetic-scroll

Conversation

@viruslobster

Copy link
Copy Markdown
Contributor

Until gtk 4.20.1 trackpads have kinetic scrolling behavior regardless of Gtk.ScrolledWindow.kinetic_scrolling. As a workaround, set EventControllerScroll.kinetic to false on all controllers.

observeControllers() has this warning:

Calling this function will enable extra internal bookkeeping to track controllers and emit signals on the returned listmodel. It may slow down operations a lot.
Applications should try hard to avoid calling this function because of the slowdowns.

but judging from the source this is a one time penalty since we free the result immediately afterwards.

Fixes #11460.

AI usage

Zed + Opus 4.5 generated the first pass, but it missed freeing the result of observeControllers() and conveniently binding scrolled_window to the blueprint. Figuring out what was going on also took a lot of human debugging.

@viruslobster
viruslobster requested a review from a team as a code owner March 24, 2026 01:57

@jcollie jcollie left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't really test because I don't have access to a trackpad on a system running an affected version of GTK, so mostly going to have to trust that this doesn't break things for some people. A couple of changes requested though.

// of `Gtk.ScrolledWindow.kinetic_scrolling`. As a workaround, disable
// EventControllerScroll.kinetic
const controllers = self.private().scrolled_window.as(gtk.Widget).observeControllers();
defer controllers.as(gobject.Object).unref();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't have to cast the controller back to a GObject to unref it.
A while loop to iterate over the controllers works better I think.
The objects returned by getObject need to be unref'd.

diff --git a/src/apprt/gtk/class/surface_scrolled_window.zig b/src/apprt/gtk/class/surface_scrolled_window.zig
index 8edada988..dd4f17d11 100644
--- a/src/apprt/gtk/class/surface_scrolled_window.zig
+++ b/src/apprt/gtk/class/surface_scrolled_window.zig
@@ -74,9 +74,10 @@ pub const SurfaceScrolledWindow = extern struct {
         // of `Gtk.ScrolledWindow.kinetic_scrolling`. As a workaround, disable
         // EventControllerScroll.kinetic
         const controllers = self.private().scrolled_window.as(gtk.Widget).observeControllers();
-        defer controllers.as(gobject.Object).unref();
-        for (0..controllers.getNItems()) |i| {
-            const obj = controllers.getObject(@intCast(i)) orelse continue;
+        defer controllers.unref();
+        var i: c_uint = 0;
+        while (controllers.getObject(i)) |obj| : (i += 1) {
+            defer obj.unref();
             const controller = gobject.ext.cast(gtk.EventControllerScroll, obj) orelse continue;
             var flags = controller.getFlags();
             flags.kinetic = false;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jcollie Thanks for the review and good catch with freeing the obj. I assumed that would be a shared reference but the docs do say otherwise.

I just pushed the update.

@ghostty-bot ghostty-bot Bot added the gtk Issues exclusive to GTK which are not OS-specific label Mar 25, 2026
Until gtk 4.20.1 trackpads have kinetic scrolling behavior regardless
of `Gtk.ScrolledWindow.kinetic_scrolling`. As a workaround, set
EventControllerScroll.kinetic to false on all controllers.

`observeControllers()` has this warning:
> Calling this function will enable extra internal bookkeeping to track controllers and emit signals on the returned listmodel. It may slow down operations a lot.
> Applications should try hard to avoid calling this function because of the slowdowns.

but judging from the [source](https://github.com/GNOME/gtk/blob/5301a91f1c74764facb4d60f40ab8621dd7af198/gtk/gtkwidget.c#L12375-L12383)
this is a one time penalty since we free the result immediately afterwards.

Fixes ghostty-org#11460
@viruslobster
viruslobster force-pushed the disable-trackpad-kinetic-scroll branch from 03ae844 to c0a124f Compare March 28, 2026 21:36

@jcollie jcollie left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM pending CI

@jcollie
jcollie merged commit 4903e28 into ghostty-org:main Mar 29, 2026
83 checks passed
@github-actions github-actions Bot added this to the 1.3.2 milestone Mar 29, 2026
@mitchellh mitchellh modified the milestones: 1.3.2, 1.4.0 Oct 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gtk Issues exclusive to GTK which are not OS-specific

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants