mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
normal event (motion) mouse tracking
This commit is contained in:
103
src/Window.zig
103
src/Window.zig
@ -154,9 +154,8 @@ const Mouse = struct {
|
|||||||
left_click_xpos: f64 = 0,
|
left_click_xpos: f64 = 0,
|
||||||
left_click_ypos: f64 = 0,
|
left_click_ypos: f64 = 0,
|
||||||
|
|
||||||
// /// The last
|
/// The last x/y sent for mouse reports.
|
||||||
// event_cx: usize = 0,
|
event_point: terminal.point.Viewport = .{},
|
||||||
// event_cy: usize = 0,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Create a new window. This allocates and returns a pointer because we
|
/// Create a new window. This allocates and returns a pointer because we
|
||||||
@ -788,10 +787,13 @@ fn scrollCallback(window: glfw.Window, xoff: f64, yoff: f64) void {
|
|||||||
win.render_timer.schedule() catch unreachable;
|
win.render_timer.schedule() catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The type of action to report for a mouse event.
|
||||||
|
const MouseReportAction = enum { press, release, motion };
|
||||||
|
|
||||||
fn mouseReport(
|
fn mouseReport(
|
||||||
self: *Window,
|
self: *Window,
|
||||||
button: input.MouseButton,
|
button: input.MouseButton,
|
||||||
action: input.MouseButtonState,
|
action: MouseReportAction,
|
||||||
mods: input.Mods,
|
mods: input.Mods,
|
||||||
unscaled_pos: glfw.Window.CursorPos,
|
unscaled_pos: glfw.Window.CursorPos,
|
||||||
) !void {
|
) !void {
|
||||||
@ -809,34 +811,17 @@ fn mouseReport(
|
|||||||
button == .right or
|
button == .right or
|
||||||
button == .middle)) return,
|
button == .middle)) return,
|
||||||
|
|
||||||
// Everything
|
// Doesn't report motion
|
||||||
.normal => {},
|
.normal => if (action == .motion) return,
|
||||||
|
|
||||||
else => {},
|
// Everything
|
||||||
|
.button => {},
|
||||||
|
|
||||||
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (self.terminal.modes.mouse_format) {
|
switch (self.terminal.modes.mouse_format) {
|
||||||
.x10 => {
|
.x10 => {
|
||||||
const button_code: u8 = code: {
|
|
||||||
var acc: u8 = if (action == .press) @as(u8, switch (button) {
|
|
||||||
.left => 0,
|
|
||||||
.right => 1,
|
|
||||||
.middle => 2,
|
|
||||||
.four => 64,
|
|
||||||
.five => 65,
|
|
||||||
else => return, // unsupported
|
|
||||||
}) else 3; // release is always 3
|
|
||||||
|
|
||||||
// Normal mode adds in modifiers
|
|
||||||
if (self.terminal.modes.mouse_event == .normal) {
|
|
||||||
if (mods.shift) acc += 4;
|
|
||||||
if (mods.super) acc += 8;
|
|
||||||
if (mods.ctrl) acc += 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
break :code acc;
|
|
||||||
};
|
|
||||||
|
|
||||||
// This format reports X/Y
|
// This format reports X/Y
|
||||||
const pos = self.cursorPosToPixels(unscaled_pos);
|
const pos = self.cursorPosToPixels(unscaled_pos);
|
||||||
const viewport_point = self.posToViewport(pos.xpos, pos.ypos);
|
const viewport_point = self.posToViewport(pos.xpos, pos.ypos);
|
||||||
@ -845,6 +830,38 @@ fn mouseReport(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For button events, we only report if we moved cells
|
||||||
|
if (self.terminal.modes.mouse_event == .button) {
|
||||||
|
if (self.mouse.event_point.x == viewport_point.x and
|
||||||
|
self.mouse.event_point.y == viewport_point.y) return;
|
||||||
|
|
||||||
|
// Record our new point
|
||||||
|
self.mouse.event_point = viewport_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
const button_code: u8 = code: {
|
||||||
|
var acc: u8 = if (action == .release) 3 else @as(u8, 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) {
|
||||||
|
if (mods.shift) acc += 4;
|
||||||
|
if (mods.super) acc += 8;
|
||||||
|
if (mods.ctrl) acc += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Motion adds another bit
|
||||||
|
if (action == .motion) acc += 32;
|
||||||
|
|
||||||
|
break :code acc;
|
||||||
|
};
|
||||||
|
|
||||||
// + 1 below is because our x/y is 0-indexed and proto wants 1
|
// + 1 below is because our x/y is 0-indexed and proto wants 1
|
||||||
var buf = [_]u8{ '\x1b', '[', 'M', 0, 0, 0 };
|
var buf = [_]u8{ '\x1b', '[', 'M', 0, 0, 0 };
|
||||||
buf[3] = 32 + button_code;
|
buf[3] = 32 + button_code;
|
||||||
@ -898,9 +915,14 @@ fn mouseButtonCallback(
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const report_action: MouseReportAction = switch (action) {
|
||||||
|
.press => .press,
|
||||||
|
.release => .release,
|
||||||
|
};
|
||||||
|
|
||||||
win.mouseReport(
|
win.mouseReport(
|
||||||
button,
|
button,
|
||||||
action,
|
report_action,
|
||||||
win.mouse.mods,
|
win.mouse.mods,
|
||||||
pos,
|
pos,
|
||||||
) catch |err| {
|
) catch |err| {
|
||||||
@ -942,6 +964,31 @@ fn cursorPosCallback(
|
|||||||
|
|
||||||
const win = window.getUserPointer(Window) orelse return;
|
const win = window.getUserPointer(Window) orelse return;
|
||||||
|
|
||||||
|
// Do a mouse report
|
||||||
|
if (win.terminal.modes.mouse_event == .button) {
|
||||||
|
// We use the first mouse button we find pressed in order to report
|
||||||
|
// since the spec (afaict) does not say...
|
||||||
|
const button_: ?input.MouseButton = button: for (win.mouse.click_state) |state, i| {
|
||||||
|
if (state == .press)
|
||||||
|
break :button @intToEnum(input.MouseButton, i);
|
||||||
|
} else null;
|
||||||
|
|
||||||
|
// A button must be pressed.
|
||||||
|
if (button_) |button| {
|
||||||
|
win.mouseReport(button, .motion, win.mouse.mods, .{
|
||||||
|
.xpos = unscaled_xpos,
|
||||||
|
.ypos = unscaled_ypos,
|
||||||
|
}) catch |err| {
|
||||||
|
log.err("error reporting mouse event: {}", .{err});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're doing mouse motion tracking, we do not support text
|
||||||
|
// selection.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If the cursor isn't clicked currently, it doesn't matter
|
// If the cursor isn't clicked currently, it doesn't matter
|
||||||
if (win.mouse.click_state[@enumToInt(input.MouseButton.left)] != .press) return;
|
if (win.mouse.click_state[@enumToInt(input.MouseButton.left)] != .press) return;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user