From ab4acf0d008ff3f57e176502dc74d563f8fd96a5 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sun, 17 Sep 2023 11:45:53 -0700 Subject: [PATCH] core: send mouse motion events if motion tracking and button pressed --- src/Surface.zig | 34 +++++++++++++++++++++++----------- src/terminal/Terminal.zig | 5 +++++ 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index b0c2d3c51..97890b828 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -1283,12 +1283,6 @@ fn mouseReport( mods: input.Mods, pos: apprt.CursorPos, ) !void { - // The maximum pos values so we can determine if we're outside the window. - // If we're outside the window, we do not report mouse events. - const max_x: f32 = @floatFromInt(self.screen_size.width); - const max_y: f32 = @floatFromInt(self.screen_size.height); - if (pos.x < 0 or pos.y < 0 or pos.x > max_x or pos.y > max_y) return; - // Depending on the event, we may do nothing at all. switch (self.io.terminal.flags.mouse_event) { .none => return, @@ -1311,6 +1305,27 @@ fn mouseReport( .any => {}, } + // The maximum pos values so we can determine if we're outside the window. + // If we're outside the window, we do not report mouse events. + const pos_out_viewport = pos_out_viewport: { + const max_x: f32 = @floatFromInt(self.screen_size.width); + const max_y: f32 = @floatFromInt(self.screen_size.height); + break :pos_out_viewport pos.x < 0 or pos.y < 0 or + pos.x > max_x or pos.y > max_y; + }; + if (pos_out_viewport) outside_viewport: { + // If we don't have a motion-tracking event mode, do nothing. + if (!self.io.terminal.flags.mouse_event.motion()) return; + + // If any button is pressed, we still do the report. Otherwise, + // we do not do the report. + for (self.mouse.click_state) |state| { + if (state != .release) break :outside_viewport; + } + + return; + } + // This format reports X/Y const viewport_point = self.posToViewport(pos.x, pos.y); @@ -1450,9 +1465,6 @@ fn mouseReport( }, .sgr_pixels => { - assert(pos.x >= 0); - assert(pos.y >= 0); - // Final character to send in the CSI const final: u8 = if (action == .release) 'm' else 'M'; @@ -1461,8 +1473,8 @@ fn mouseReport( var data: termio.Message.WriteReq.Small.Array = undefined; const resp = try std.fmt.bufPrint(&data, "\x1B[<{d};{d};{d}{c}", .{ button_code, - @as(u32, @intFromFloat(@round(pos.x))), - @as(u32, @intFromFloat(@round(pos.y))), + @as(i32, @intFromFloat(@round(pos.x))), + @as(i32, @intFromFloat(@round(pos.y))), final, }); diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index bd32dbb83..ba53ffbfe 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -132,6 +132,11 @@ pub const MouseEvents = enum(u3) { normal = 2, // 1000 button = 3, // 1002 any = 4, // 1003 + + /// Returns true if this event sends motion events. + pub fn motion(self: MouseEvents) bool { + return self == .button or self == .any; + } }; /// The format of mouse events when enabled.