move mouse-hide-after implementation to apprt

pull/9937/head
Elad Kaplan 2025-12-18 12:38:54 +02:00
parent 380e2ab2ba
commit 345a20a740
2 changed files with 18 additions and 38 deletions

View File

@ -243,9 +243,6 @@ const Mouse = struct {
/// True if the mouse is hidden
hidden: bool = false,
/// The last time we observed mouse movement
last_move_time: ?std.time.Instant = null,
/// True if the mouse position is currently over a link.
over_link: bool = false,
@ -301,7 +298,6 @@ const DerivedConfig = struct {
font: font.SharedGridSet.DerivedConfig,
mouse_interval: u64,
mouse_hide_while_typing: bool,
mouse_hide_after: Duration,
mouse_reporting: bool,
mouse_scroll_multiplier: configpkg.MouseScrollMultiplier,
mouse_shift_capture: configpkg.MouseShiftCapture,
@ -377,7 +373,6 @@ const DerivedConfig = struct {
.font = try font.SharedGridSet.DerivedConfig.init(alloc, config),
.mouse_interval = config.@"click-repeat-interval" * 1_000_000, // 500ms
.mouse_hide_while_typing = config.@"mouse-hide-while-typing",
.mouse_hide_after = config.@"mouse-hide-after",
.mouse_reporting = config.@"mouse-reporting",
.mouse_scroll_multiplier = config.@"mouse-scroll-multiplier",
.mouse_shift_capture = config.@"mouse-shift-capture",
@ -1545,23 +1540,6 @@ fn modsChanged(self: *Surface, mods: input.Mods) void {
}
}
/// Hide the mouse if `mouse-hide-after` is configured and the mouse has been
/// idle (no movement) for at least that duration.
pub fn maybeHideMouseAfterIdle(self: *Surface) void {
if (self.config.mouse_hide_after.duration == 0 or self.mouse.hidden) return;
const now = std.time.Instant.now() catch {
return;
};
const last = self.mouse.last_move_time orelse return;
const since = now.since(last);
if (since >= self.config.mouse_hide_after.duration) {
self.hideMouse();
}
}
/// Call this whenever the mouse moves or mods changed. The time
/// at which this is called may matter for the correctness of other
/// mouse events (see cursorPosCallback) but this is shared logic
@ -2607,10 +2585,6 @@ pub fn keyCallback(
crash.sentry.thread_state = self.crashThreadState();
defer crash.sentry.thread_state = null;
// If the mouse has been idle long enough, hide it. Typing does not reset
// the idle timer; we only track mouse movement for this.
self.maybeHideMouseAfterIdle();
// Setup our inspector event if we have an inspector.
var insp_ev: ?inspectorpkg.key.Event = if (self.inspector != null) ev: {
var copy = event;
@ -4430,12 +4404,6 @@ pub fn cursorPosCallback(
// log.debug("cursor pos x={} y={} mods={?}", .{ pos.x, pos.y, mods });
// Any cursor position update is considered mouse movement and resets the
// idle timer used by `mouse-hide-after`.
if (std.time.Instant.now()) |now| {
self.mouse.last_move_time = now;
} else |_| {}
// If the position is negative, it is outside our viewport and
// we need to clear any hover states.
if (pos.x < 0 or pos.y < 0) {

View File

@ -592,6 +592,9 @@ pub const Surface = extern struct {
/// configured idle duration.
mouse_hide_after_timer: ?c_uint = null,
/// The last time we observed mouse movement, used for `mouse-hide-after`.
last_mouse_move_time: ?std.time.Instant = null,
// True while the bell is ringing. This will be set to false (after
// true) under various scenarios, but can also manually be set to
// false by a parent widget.
@ -917,7 +920,7 @@ pub const Surface = extern struct {
}
/// Timer callback for `mouse-hide-after`. Hides the mouse after a period
/// of no mouse movement by delegating to the core surface.
/// of no mouse movement.
fn mouseHideAfterTimer(ud: ?*anyopaque) callconv(.c) c_int {
const self: *Self = @ptrCast(@alignCast(ud orelse
return @intFromBool(glib.SOURCE_REMOVE)));
@ -926,8 +929,9 @@ pub const Surface = extern struct {
// Clear our timer handle first to avoid reusing it.
priv.mouse_hide_after_timer = null;
if (priv.core_surface) |surface| {
surface.maybeHideMouseAfterIdle();
// Hide the mouse cursor directly.
if (!priv.mouse_hidden) {
self.setMouseHidden(true);
}
return @intFromBool(glib.SOURCE_REMOVE);
@ -2670,6 +2674,12 @@ pub const Surface = extern struct {
@abs(priv.cursor_pos.y - pos.y) < 1;
if (is_cursor_still) return;
// If the mouse is currently hidden (for example due to `mouse-hide-after`),
// show it again on real mouse movement.
if (priv.mouse_hidden) {
self.setMouseHidden(false);
}
// If we don't have focus, and we want it, grab it.
if (priv.config) |config| {
const gl_area_widget = priv.gl_area.as(gtk.Widget);
@ -2683,6 +2693,9 @@ pub const Surface = extern struct {
// Our pos changed, update
priv.cursor_pos = pos;
// Track mouse movement time for `mouse-hide-after`.
priv.last_mouse_move_time = std.time.Instant.now() catch null;
// Reset `mouse-hide-after` idle timer if configured.
if (priv.mouse_hide_after_timer) |timer| {
if (glib.Source.remove(timer) == 0) {
@ -2690,9 +2703,8 @@ pub const Surface = extern struct {
}
priv.mouse_hide_after_timer = null;
}
if (priv.config) |config_obj| {
const cfg = config_obj.get();
const ms = cfg.@"mouse-hide-after".asMilliseconds();
if (priv.config) |config| {
const ms = config.get().@"mouse-hide-after".asMilliseconds();
if (ms > 0) {
priv.mouse_hide_after_timer = glib.timeoutAdd(
ms,