feat: add a mouse idle timer that clears hover state

This commit is contained in:
CJ van den Berg 2024-08-13 22:51:22 +02:00
parent 50d47a73f2
commit f53dc74e9d

View file

@ -53,9 +53,11 @@ no_sleep: bool = false,
final_exit: []const u8 = "normal",
render_pending: bool = false,
keepalive_timer: ?tp.Cancellable = null,
mouse_idle_timer: ?tp.Cancellable = null,
const keepalive = std.time.us_per_day * 365; // one year
const idle_frames = 0;
const mouse_idle_time_milliseconds = 3000;
const init_delay = 1; // ms
@ -149,6 +151,11 @@ fn init_delayed(self: *Self) !void {
}
fn deinit(self: *Self) void {
if (self.mouse_idle_timer) |*t| {
t.cancel() catch {};
t.deinit();
self.mouse_idle_timer = null;
}
if (self.keepalive_timer) |*t| {
t.cancel() catch {};
t.deinit();
@ -174,6 +181,16 @@ fn listen_sigwinch(self: *Self) tp.result {
self.sigwinch_signal = tp.signal.init(std.posix.SIG.WINCH, tp.message.fmt(.{"sigwinch"})) catch |e| return tp.exit_error(e, @errorReturnTrace());
}
fn update_mouse_idle_timer(self: *Self) void {
const delay = std.time.us_per_ms * @as(u64, mouse_idle_time_milliseconds);
if (self.mouse_idle_timer) |*t| {
t.cancel() catch {};
t.deinit();
self.mouse_idle_timer = null;
}
self.mouse_idle_timer = tp.self_pid().delay_send_cancellable(self.a, delay, .{"MOUSE_IDLE"}) catch return;
}
fn receive(self: *Self, from: tp.pid_ref, m: tp.message) tp.result {
const frame = tracy.initZone(@src(), .{ .name = "tui" });
defer frame.deinit();
@ -300,6 +317,11 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void {
if (try m.match(.{ "PRJ", tp.more })) // drop late project manager query responses
return;
if (try m.match(.{"MOUSE_IDLE"})) {
try self.clear_hover_focus();
return;
}
return tp.unexpected(m);
}
@ -380,6 +402,7 @@ fn dispatch_input(ctx: *anyopaque, cbor_msg: []const u8) void {
fn dispatch_mouse(ctx: *anyopaque, y: c_int, x: c_int, cbor_msg: []const u8) void {
const self: *Self = @ptrCast(@alignCast(ctx));
self.update_mouse_idle_timer();
const m: tp.message = .{ .buf = cbor_msg };
const from = tp.self_pid();
self.unrendered_input_events_count += 1;
@ -390,6 +413,7 @@ fn dispatch_mouse(ctx: *anyopaque, y: c_int, x: c_int, cbor_msg: []const u8) voi
fn dispatch_mouse_drag(ctx: *anyopaque, y: c_int, x: c_int, cbor_msg: []const u8) void {
const self: *Self = @ptrCast(@alignCast(ctx));
self.update_mouse_idle_timer();
const m: tp.message = .{ .buf = cbor_msg };
const from = tp.self_pid();
self.unrendered_input_events_count += 1;
@ -492,15 +516,19 @@ fn send_mouse_drag(self: *Self, y: c_int, x: c_int, from: tp.pid_ref, m: tp.mess
_ = try w.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", true }) catch |e| return tp.exit_error(e, @errorReturnTrace()));
}
} else {
if (self.hover_focus) |h| {
var buf: [256]u8 = undefined;
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e, @errorReturnTrace()));
}
self.hover_focus = null;
try self.clear_hover_focus();
}
if (self.drag_source) |w| _ = try w.send(from, m);
}
fn clear_hover_focus(self: *Self) tp.result {
if (self.hover_focus) |h| {
var buf: [256]u8 = undefined;
_ = try h.send(tp.self_pid(), tp.message.fmtbuf(&buf, .{ "H", false }) catch |e| return tp.exit_error(e, @errorReturnTrace()));
}
self.hover_focus = null;
}
pub fn save_config(self: *const Self) !void {
try root.write_config(self.config, self.a);
}