diff --git a/src/Surface.zig b/src/Surface.zig index 2839f908c..fb267b50c 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -1308,7 +1308,10 @@ pub fn keyCallback( } // If this input event has text, then we hide the mouse if configured. + // We only do this on pressed events to avoid hiding the mouse when we + // change focus due to a keybinding (i.e. switching tabs). if (self.config.mouse_hide_while_typing and + event.action == .press and !self.mouse.hidden and event.utf8.len > 0) { @@ -1319,9 +1322,12 @@ pub fn keyCallback( // This handles the scenario where URL highlighting should be // toggled for example. if (!self.mouse.mods.equal(event.mods)) mouse_mods: { - // Usually moving the cursor unhides the mouse so we need - // to hide it again if it was hidden. + // This is a hacky way to prevent cursorPosCallback from + // showing our hidden mouse: we just pretend the mouse isn't hidden. + // We used to re-call `self.hideMouse()` but this causes flickering + // in some cases in GTK. const rehide = self.mouse.hidden; + self.mouse.hidden = false; // Update our modifiers, this will update mouse mods too self.modsChanged(event.mods); @@ -1331,7 +1337,7 @@ pub fn keyCallback( self.mouse.link_point = null; const pos = self.rt_surface.getCursorPos() catch break :mouse_mods; self.cursorPosCallback(pos) catch {}; - if (rehide) self.hideMouse(); + if (rehide) self.mouse.hidden = true; } // Process the cursor state logic. This will update the cursor shape if diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index 6e2d4d035..794e2eaf4 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -741,7 +741,14 @@ fn updateTitleLabels(self: *Surface) void { // If we have a window and are focused, then we have to update the window title. if (self.container.window()) |window| { const widget = @as(*c.GtkWidget, @ptrCast(self.gl_area)); - if (c.gtk_widget_is_focus(widget) == 1) c.gtk_window_set_title(window.window, title.ptr); + if (c.gtk_widget_is_focus(widget) == 1) { + // Changing the title somehow unhides our cursor. + // https://github.com/ghostty-org/ghostty/issues/1419 + // I don't know a way around this yet. I've tried re-hiding the + // cursor after setting the title but it doesn't work, I think + // due to some gtk event loop things... + c.gtk_window_set_title(window.window, title.ptr); + } } } @@ -803,8 +810,12 @@ pub fn setMouseShape( }; errdefer c.g_object_unref(cursor); - // Set our new cursor - c.gtk_widget_set_cursor(@ptrCast(self.gl_area), cursor); + // Set our new cursor. We only do this if the cursor we currently + // have is NOT set to "none" because setting the cursor causes it + // to become visible again. + if (c.gtk_widget_get_cursor(@ptrCast(self.gl_area)) != self.app.cursor_none) { + c.gtk_widget_set_cursor(@ptrCast(self.gl_area), cursor); + } // Free our existing cursor if (self.cursor) |old| c.g_object_unref(old);