diff --git a/src/Window.zig b/src/Window.zig index 9a7e3a4f7..11e8bb715 100644 --- a/src/Window.zig +++ b/src/Window.zig @@ -839,17 +839,26 @@ fn mouseReport( // Get the code we'll actually write const button_code: u8 = code: { - var acc: u8 = if (action == .release or button == null) - 3 - else - @as(u8, switch (button.?) { + var acc: u8 = 0; + + // Determine our initial button value + if (button == null) { + // Null button means motion without a button pressed + acc = 3; + } else if (action == .release and self.terminal.modes.mouse_format != .sgr) { + // Release is 3. It is NOT 3 in SGR mode because SGR can tell + // the application what button was released. + acc = 3; + } else { + acc = switch (button.?) { .left => 0, .right => 1, .middle => 2, .four => 64, .five => 65, else => return, // unsupported - }); + }; + } // X10 doesn't have modifiers if (self.terminal.modes.mouse_event != .x10) { @@ -897,6 +906,20 @@ fn mouseReport( try self.queueWrite(buf[0..i]); }, + .sgr => { + // Response always is at least 4 chars, so this leaves the + // remainder for numbers which are very large... + var buf: [32]u8 = undefined; + const resp = try std.fmt.bufPrint(&buf, "\x1B[<{d};{d};{d}{c}", .{ + button_code, + viewport_point.x + 1, + viewport_point.y + 1, + @as(u8, if (action == .release) 'm' else 'M'), + }); + + try self.queueWrite(resp); + }, + else => @panic("TODO"), } } @@ -1475,6 +1498,7 @@ pub fn setMode(self: *Window, mode: terminal.Mode, enabled: bool) !void { .mouse_event_any => self.terminal.modes.mouse_event = if (enabled) .any else .none, .mouse_format_utf8 => self.terminal.modes.mouse_format = if (enabled) .utf8 else .x10, + .mouse_format_sgr => self.terminal.modes.mouse_format = if (enabled) .sgr else .x10, else => if (enabled) log.warn("unimplemented mode: {}", .{mode}), } diff --git a/src/terminal/Terminal.zig b/src/terminal/Terminal.zig index 093033b2c..63f692dc5 100644 --- a/src/terminal/Terminal.zig +++ b/src/terminal/Terminal.zig @@ -94,9 +94,9 @@ pub const MouseEvents = enum(u3) { pub const MouseFormat = enum(u3) { x10 = 0, utf8 = 1, // 1005 + sgr = 2, // 1006 // TODO: - sgr = 2, // 1006 urxvt = 3, // 1015 sgr_pixels = 4, // 1016 }; diff --git a/src/terminal/ansi.zig b/src/terminal/ansi.zig index 025de8ecc..cd1c58385 100644 --- a/src/terminal/ansi.zig +++ b/src/terminal/ansi.zig @@ -83,6 +83,9 @@ pub const Mode = enum(u16) { /// Report mouse position in the utf8 format to support larger screens. mouse_format_utf8 = 1005, + /// Report mouse position in the SGR format. + mouse_format_sgr = 1006, + /// Alternate screen mode with save cursor and clear on enter. alt_screen_save_cursor_clear_enter = 1049,