mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 00:36:07 +03:00
X10 click-only mouse reporting
This commit is contained in:
@ -769,6 +769,57 @@ fn scrollCallback(window: glfw.Window, xoff: f64, yoff: f64) void {
|
|||||||
win.render_timer.schedule() catch unreachable;
|
win.render_timer.schedule() catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mouseReport(
|
||||||
|
self: *Window,
|
||||||
|
button: glfw.MouseButton,
|
||||||
|
action: glfw.Action,
|
||||||
|
mods: glfw.Mods,
|
||||||
|
unscaled_pos: glfw.Window.CursorPos,
|
||||||
|
) !void {
|
||||||
|
// TODO: posToViewport currently clamps to the window boundary,
|
||||||
|
// do we want to not report mouse events at all outside the window?
|
||||||
|
|
||||||
|
assert(self.terminal.modes.mouse_event != .none);
|
||||||
|
|
||||||
|
_ = mods;
|
||||||
|
|
||||||
|
// Depending on the event, we may do nothing at all.
|
||||||
|
switch (self.terminal.modes.mouse_event) {
|
||||||
|
// X10 only reports clicks with mouse button 1, 2, 3. We verify
|
||||||
|
// the button later.
|
||||||
|
.x10 => if (action != .press) return,
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (self.terminal.modes.mouse_format) {
|
||||||
|
.x10 => {
|
||||||
|
const button_code: u8 = switch (button) {
|
||||||
|
.left => 0,
|
||||||
|
.right => 1,
|
||||||
|
.middle => 2,
|
||||||
|
else => return, // unsupported with X10
|
||||||
|
};
|
||||||
|
|
||||||
|
// This format reports X/Y
|
||||||
|
const pos = self.cursorPosToPixels(unscaled_pos);
|
||||||
|
const viewport_point = self.posToViewport(pos.xpos, pos.ypos);
|
||||||
|
if (viewport_point.x > 222 or viewport_point.y > 222) {
|
||||||
|
log.info("X10 mouse format can only encode X/Y up to 223", .{});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// + 1 below is because our x/y is 0-indexed and proto wants 1
|
||||||
|
var buf = [_]u8{ '\x1b', '[', 'M', 0, 0, 0 };
|
||||||
|
buf[3] = 32 + button_code;
|
||||||
|
buf[4] = 32 + @intCast(u8, viewport_point.x) + 1;
|
||||||
|
buf[5] = 32 + @intCast(u8, viewport_point.y) + 1;
|
||||||
|
try self.queueWrite(&buf);
|
||||||
|
},
|
||||||
|
|
||||||
|
else => @panic("TODO"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn mouseButtonCallback(
|
fn mouseButtonCallback(
|
||||||
window: glfw.Window,
|
window: glfw.Window,
|
||||||
button: glfw.MouseButton,
|
button: glfw.MouseButton,
|
||||||
@ -780,10 +831,24 @@ fn mouseButtonCallback(
|
|||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
|
||||||
|
const win = window.getUserPointer(Window) orelse return;
|
||||||
|
|
||||||
|
// Report mouse events if enabled
|
||||||
|
if (win.terminal.modes.mouse_event != .none) {
|
||||||
|
const pos = window.getCursorPos() catch |err| {
|
||||||
|
log.err("error reading cursor position: {}", .{err});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
win.mouseReport(button, action, mods, pos) catch |err| {
|
||||||
|
log.err("error reporting mouse event: {}", .{err});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (button == .left) {
|
if (button == .left) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
.press => {
|
.press => {
|
||||||
const win = window.getUserPointer(Window) orelse return;
|
|
||||||
const pos = win.cursorPosToPixels(window.getCursorPos() catch |err| {
|
const pos = win.cursorPosToPixels(window.getCursorPos() catch |err| {
|
||||||
log.err("error reading cursor position: {}", .{err});
|
log.err("error reading cursor position: {}", .{err});
|
||||||
return;
|
return;
|
||||||
@ -810,7 +875,6 @@ fn mouseButtonCallback(
|
|||||||
},
|
},
|
||||||
|
|
||||||
.release => {
|
.release => {
|
||||||
const win = window.getUserPointer(Window) orelse return;
|
|
||||||
win.mouse.click_state = .none;
|
win.mouse.click_state = .none;
|
||||||
log.debug("click end", .{});
|
log.debug("click end", .{});
|
||||||
},
|
},
|
||||||
@ -1284,6 +1348,8 @@ pub fn setMode(self: *Window, mode: terminal.Mode, enabled: bool) !void {
|
|||||||
if (enabled) .@"132_cols" else .@"80_cols",
|
if (enabled) .@"132_cols" else .@"80_cols",
|
||||||
),
|
),
|
||||||
|
|
||||||
|
.mouse_event_x10 => self.terminal.modes.mouse_event = .x10,
|
||||||
|
|
||||||
else => if (enabled) log.warn("unimplemented mode: {}", .{mode}),
|
else => if (enabled) log.warn("unimplemented mode: {}", .{mode}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,9 @@ pub const Mode = enum(u16) {
|
|||||||
/// Enable or disable automatic line wrapping.
|
/// Enable or disable automatic line wrapping.
|
||||||
autowrap = 7,
|
autowrap = 7,
|
||||||
|
|
||||||
|
/// Click-only (press) mouse reporting.
|
||||||
|
mouse_event_x10 = 9,
|
||||||
|
|
||||||
/// Set whether the cursor is visible or not.
|
/// Set whether the cursor is visible or not.
|
||||||
cursor_visible = 25,
|
cursor_visible = 25,
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user