From 4ffbd93ab5d657469baab14d72c7ef189cd51ef9 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 20 Jul 2025 14:04:22 -0700 Subject: [PATCH] apprt/gtk-ng: surface mouse visibility --- src/apprt/gtk-ng/class/application.zig | 23 +++++++++- src/apprt/gtk-ng/class/surface.zig | 59 +++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/apprt/gtk-ng/class/application.zig b/src/apprt/gtk-ng/class/application.zig index c4ceeb564..a170afc74 100644 --- a/src/apprt/gtk-ng/class/application.zig +++ b/src/apprt/gtk-ng/class/application.zig @@ -406,6 +406,7 @@ pub const Application = extern struct { ), .mouse_shape => Action.mouseShape(target, value), + .mouse_visibility => Action.mouseVisibility(target, value), .new_window => try Action.newWindow( self, @@ -442,7 +443,6 @@ pub const Application = extern struct { .present_terminal, .initial_size, .size_limit, - .mouse_visibility, .mouse_over_link, .toggle_tab_overview, .toggle_split_zoom, @@ -906,6 +906,27 @@ const Action = struct { } } + pub fn mouseVisibility( + target: apprt.Target, + visibility: apprt.action.MouseVisibility, + ) void { + switch (target) { + .app => log.warn("mouse visibility to app is unexpected", .{}), + .surface => |surface| { + var value = gobject.ext.Value.newFrom(switch (visibility) { + .visible => false, + .hidden => true, + }); + defer value.unset(); + gobject.Object.setProperty( + surface.rt_surface.gobj().as(gobject.Object), + "mouse-hidden", + &value, + ); + }, + } + } + pub fn newWindow( self: *Application, parent: ?*CoreSurface, diff --git a/src/apprt/gtk-ng/class/surface.zig b/src/apprt/gtk-ng/class/surface.zig index 8ab180ae6..92c86cb1a 100644 --- a/src/apprt/gtk-ng/class/surface.zig +++ b/src/apprt/gtk-ng/class/surface.zig @@ -54,6 +54,26 @@ pub const Surface = extern struct { ); }; + pub const @"mouse-hidden" = struct { + pub const name = "mouse-hidden"; + const impl = gobject.ext.defineProperty( + name, + Self, + bool, + .{ + .nick = "Mouse Hidden", + .blurb = "Whether the mouse cursor should be hidden.", + .default = false, + .accessor = gobject.ext.privateFieldAccessor( + Self, + Private, + &Private.offset, + "mouse_hidden", + ), + }, + ); + }; + pub const @"mouse-shape" = struct { pub const name = "mouse-shape"; const impl = gobject.ext.defineProperty( @@ -105,6 +125,9 @@ pub const Surface = extern struct { /// The mouse shape to show for the surface. mouse_shape: terminal.MouseShape = .default, + /// Whether the mouse should be hidden or not as requested externally. + mouse_hidden: bool = false, + /// The GLAarea that renders the actual surface. This is a binding /// to the template so it doesn't have to be unrefed manually. gl_area: *gtk.GLArea = undefined, @@ -742,6 +765,13 @@ pub const Surface = extern struct { ); // Some property signals + _ = gobject.Object.signals.notify.connect( + self, + ?*anyopaque, + &propMouseHidden, + null, + .{ .detail = "mouse-hidden" }, + ); _ = gobject.Object.signals.notify.connect( self, ?*anyopaque, @@ -798,12 +828,35 @@ pub const Surface = extern struct { //--------------------------------------------------------------- // Properties + fn propMouseHidden( + self: *Self, + _: *gobject.ParamSpec, + _: ?*anyopaque, + ) callconv(.c) void { + const priv = self.private(); + + // If we're hidden we set it to "none" + if (priv.mouse_hidden) { + priv.gl_area.as(gtk.Widget).setCursorFromName("none"); + return; + } + + // If we're not hidden we just trigger the mouse shape + // prop notification to handle setting the proper mouse shape. + self.propMouseShape(undefined, null); + } + fn propMouseShape( self: *Self, _: *gobject.ParamSpec, _: ?*anyopaque, ) callconv(.c) void { const priv = self.private(); + + // If our mouse should be hidden currently then we don't + // do anything. + if (priv.mouse_hidden) return; + const name: [:0]const u8 = switch (priv.mouse_shape) { .default => "default", .help => "help", @@ -841,11 +894,6 @@ pub const Surface = extern struct { .zoom_out => "zoom-out", }; - // TODO: mouse visibility - // if (widget.getCursor() != self.app.cursor_none) { - // widget.setCursor(cursor); - // } - // Set our new cursor. priv.gl_area.as(gtk.Widget).setCursorFromName(name.ptr); } @@ -1461,6 +1509,7 @@ pub const Surface = extern struct { gobject.ext.registerProperties(class, &.{ properties.config.impl, properties.@"mouse-shape".impl, + properties.@"mouse-hidden".impl, }); // Signals