fix(macOS): filter phantom mouse events that defeat mouse-hide-while-typing

On macOS, TUI apps like Zellij that frequently update the window title
cause phantom mouse-move events to be generated at the same coordinates.
These phantom events reach cursorPosCallback in the core, which calls
showMouse() and explicitly unhides the cursor via
NSCursor.setHiddenUntilMouseMoves(false), defeating the
mouse-hide-while-typing feature.

This ports the same position-equality check already present in the GTK
runtime (added in PR #4973 for issue #3345) to the embedded runtime used
by macOS. If the cursor position hasn't changed by more than 1px, the
event is discarded.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
linustalacko
2026-02-27 09:08:13 -08:00
parent 99311e8c27
commit 2a41401463

View File

@@ -848,7 +848,7 @@ pub const Surface = struct {
mods: input.Mods,
) void {
// Convert our unscaled x/y to scaled.
self.cursor_pos = self.cursorPosToPixels(.{
const pos = self.cursorPosToPixels(.{
.x = @floatCast(x),
.y = @floatCast(y),
}) catch |err| {
@@ -859,6 +859,19 @@ pub const Surface = struct {
return;
};
// There are cases where the platform reports a mouse motion event
// without the cursor actually moving. For example, on macOS, updating
// the window title can trigger a phantom mouse-move event at the same
// coordinates. This can cause the mouse to incorrectly unhide when
// mouse-hide-while-typing is enabled (commonly seen with TUI apps
// like Zellij that frequently update the title). To prevent incorrect
// behavior, we only continue with callback logic if the cursor has
// actually moved.
if (@abs(self.cursor_pos.x - pos.x) < 1 and
@abs(self.cursor_pos.y - pos.y) < 1) return;
self.cursor_pos = pos;
self.core_surface.cursorPosCallback(self.cursor_pos, mods) catch |err| {
log.err("error in cursor pos callback err={}", .{err});
return;