apprt/macos,gtk: unfocused splits now highlight hovered links

Fixes #1547

The core change to make this work is to make the cursor position
callback support taking updated modifiers. On both macOS and GTK, cursor
position events also provide the pressed modifiers so we can pass those
in.
This commit is contained in:
Mitchell Hashimoto
2024-09-21 15:11:28 -07:00
parent fb6cd7a8fa
commit 261ce00552
6 changed files with 49 additions and 11 deletions

View File

@ -556,7 +556,10 @@ bool ghostty_surface_mouse_button(ghostty_surface_t,
ghostty_input_mouse_state_e,
ghostty_input_mouse_button_e,
ghostty_input_mods_e);
void ghostty_surface_mouse_pos(ghostty_surface_t, double, double);
void ghostty_surface_mouse_pos(ghostty_surface_t,
double,
double,
ghostty_input_mods_e);
void ghostty_surface_mouse_scroll(ghostty_surface_t,
double,
double,

View File

@ -505,7 +505,8 @@ extension Ghostty {
// Convert window position to view position. Note (0, 0) is bottom left.
let pos = self.convert(event.locationInWindow, from: nil)
ghostty_surface_mouse_pos(surface, pos.x, frame.height - pos.y)
let mods = Ghostty.ghosttyMods(event.modifierFlags)
ghostty_surface_mouse_pos(surface, pos.x, frame.height - pos.y, mods)
// If focus follows mouse is enabled then move focus to this surface.
if let window = self.window as? TerminalWindow,

View File

@ -1459,7 +1459,7 @@ pub fn keyCallback(
// mod changes can affect link highlighting.
self.mouse.link_point = null;
const pos = self.rt_surface.getCursorPos() catch break :mouse_mods;
self.cursorPosCallback(pos) catch {};
self.cursorPosCallback(pos, null) catch {};
if (rehide) self.mouse.hidden = true;
}
@ -2421,7 +2421,7 @@ pub fn mouseButtonCallback(
// expensive because it could block all our threads.
if (self.hasSelection()) {
const pos = try self.rt_surface.getCursorPos();
try self.cursorPosCallback(pos);
try self.cursorPosCallback(pos, null);
return true;
}
}
@ -2887,9 +2887,18 @@ pub fn mousePressureCallback(
}
}
/// Cursor position callback.
///
/// The mods parameter is optional because some apprts do not provide
/// modifier information on cursor position events. If mods is null then
/// we'll use the last known mods. This is usually accurate since mod events
/// will trigger key press events but on some platforms we don't get them.
/// For example, on macOS, unfocused surfaces don't receive key events but
/// do receive mouse events so we have to rely on updated mods.
pub fn cursorPosCallback(
self: *Surface,
pos: apprt.CursorPos,
mods: ?input.Mods,
) !void {
// Crash metadata in case we crash in here
crash.sentry.thread_state = self.crashThreadState();
@ -2898,6 +2907,9 @@ pub fn cursorPosCallback(
// Always show the mouse again if it is hidden
if (self.mouse.hidden) self.showMouse();
// Update our modifiers if they changed
if (mods) |v| self.modsChanged(v);
// The mouse position in the viewport
const pos_vp = self.posToViewport(pos.x, pos.y);

View File

@ -763,7 +763,12 @@ pub const Surface = struct {
};
}
pub fn cursorPosCallback(self: *Surface, x: f64, y: f64) void {
pub fn cursorPosCallback(
self: *Surface,
x: f64,
y: f64,
mods: input.Mods,
) void {
// Convert our unscaled x/y to scaled.
self.cursor_pos = self.cursorPosToPixels(.{
.x = @floatCast(x),
@ -776,7 +781,7 @@ pub const Surface = struct {
return;
};
self.core_surface.cursorPosCallback(self.cursor_pos) catch |err| {
self.core_surface.cursorPosCallback(self.cursor_pos, mods) catch |err| {
log.err("error in cursor pos callback err={}", .{err});
return;
};
@ -1716,8 +1721,20 @@ pub const CAPI = struct {
}
/// Update the mouse position within the view.
export fn ghostty_surface_mouse_pos(surface: *Surface, x: f64, y: f64) void {
surface.cursorPosCallback(x, y);
export fn ghostty_surface_mouse_pos(
surface: *Surface,
x: f64,
y: f64,
mods: c_int,
) void {
surface.cursorPosCallback(
x,
y,
@bitCast(@as(
input.Mods.Backing,
@truncate(@as(c_uint, @bitCast(mods))),
)),
);
}
export fn ghostty_surface_mouse_scroll(

View File

@ -1040,7 +1040,7 @@ pub const Surface = struct {
core_win.cursorPosCallback(.{
.x = @floatCast(pos.xpos),
.y = @floatCast(pos.ypos),
}) catch |err| {
}, null) catch |err| {
log.err("error in cursor pos callback err={}", .{err});
return;
};

View File

@ -1386,7 +1386,7 @@ fn gtkMouseUp(
}
fn gtkMouseMotion(
_: *c.GtkEventControllerMotion,
ec: *c.GtkEventControllerMotion,
x: c.gdouble,
y: c.gdouble,
ud: ?*anyopaque,
@ -1415,7 +1415,12 @@ fn gtkMouseMotion(
self.grabFocus();
}
self.core_surface.cursorPosCallback(self.cursor_pos) catch |err| {
// Get our modifiers
const event = c.gtk_event_controller_get_current_event(@ptrCast(ec));
const gtk_mods = c.gdk_event_get_modifier_state(event);
const mods = translateMods(gtk_mods);
self.core_surface.cursorPosCallback(self.cursor_pos, mods) catch |err| {
log.err("error in cursor pos callback err={}", .{err});
return;
};