mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
core: mouse pressure state and callbacks
This commit is contained in:
@ -535,6 +535,7 @@ void ghostty_surface_mouse_scroll(ghostty_surface_t,
|
||||
double,
|
||||
double,
|
||||
ghostty_input_scroll_mods_t);
|
||||
void ghostty_surface_mouse_pressure(ghostty_surface_t, uint32_t, double);
|
||||
void ghostty_surface_ime_point(ghostty_surface_t, double*, double*);
|
||||
void ghostty_surface_request_close(ghostty_surface_t);
|
||||
void ghostty_surface_split(ghostty_surface_t, ghostty_split_direction_e);
|
||||
|
@ -578,6 +578,13 @@ extension Ghostty {
|
||||
}
|
||||
|
||||
override func pressureChange(with event: NSEvent) {
|
||||
guard let surface = self.surface else { return }
|
||||
|
||||
// Notify Ghostty first. We do this because this will let Ghostty handle
|
||||
// state setup that we'll need for later pressure handling (such as
|
||||
// QuickLook)
|
||||
ghostty_surface_mouse_pressure(surface, UInt32(event.stage), Double(event.pressure))
|
||||
|
||||
// Pressure stage 2 is force click. We only want to execute this on the
|
||||
// initial transition to stage 2, and not for any repeated events.
|
||||
guard self.prevPressureStage < 2 else { return }
|
||||
|
@ -173,6 +173,10 @@ const Mouse = struct {
|
||||
/// The last x/y sent for mouse reports.
|
||||
event_point: ?terminal.point.Coordinate = null,
|
||||
|
||||
/// The pressure stage for the mouse. This should always be none if
|
||||
/// the mouse is not pressed.
|
||||
pressure_stage: input.MousePressureStage = .none,
|
||||
|
||||
/// Pending scroll amounts for high-precision scrolls
|
||||
pending_scroll_x: f64 = 0,
|
||||
pending_scroll_y: f64 = 0,
|
||||
@ -2492,6 +2496,41 @@ fn processLinks(self: *Surface, pos: apprt.CursorPos) !bool {
|
||||
return true;
|
||||
}
|
||||
|
||||
pub fn mousePressureCallback(
|
||||
self: *Surface,
|
||||
stage: input.MousePressureStage,
|
||||
pressure: f64,
|
||||
) !void {
|
||||
// We don't currently use the pressure value for anything. In the
|
||||
// future, we could report this to applications using new mouse
|
||||
// events or utilize it for some custom UI.
|
||||
_ = pressure;
|
||||
|
||||
// If the pressure stage is the same as what we already have do nothing
|
||||
if (self.mouse.pressure_stage == stage) return;
|
||||
|
||||
// Update our pressure stage.
|
||||
self.mouse.pressure_stage = stage;
|
||||
|
||||
// If our left mouse button is pressed and we're entering a deep
|
||||
// click then we want to start a selection. We treat this as a
|
||||
// word selection since that is typical macOS behavior.
|
||||
const left_idx = @intFromEnum(input.MouseButton.left);
|
||||
if (self.mouse.click_state[left_idx] == .press and
|
||||
stage == .deep)
|
||||
select: {
|
||||
self.renderer_state.mutex.lock();
|
||||
defer self.renderer_state.mutex.unlock();
|
||||
|
||||
// This should always be set in this state but we don't want
|
||||
// to handle state inconsistency here.
|
||||
const pin = self.mouse.left_click_pin orelse break :select;
|
||||
const sel = self.io.terminal.screen.selectWord(pin.*) orelse break :select;
|
||||
try self.setSelection(sel);
|
||||
try self.queueRender();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cursorPosCallback(
|
||||
self: *Surface,
|
||||
pos: apprt.CursorPos,
|
||||
|
@ -716,6 +716,17 @@ pub const Surface = struct {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn mousePressureCallback(
|
||||
self: *Surface,
|
||||
stage: input.MousePressureStage,
|
||||
pressure: f64,
|
||||
) void {
|
||||
self.core_surface.mousePressureCallback(stage, pressure) catch |err| {
|
||||
log.err("error in mouse pressure callback err={}", .{err});
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
pub fn scrollCallback(
|
||||
self: *Surface,
|
||||
xoff: f64,
|
||||
@ -1648,6 +1659,25 @@ pub const CAPI = struct {
|
||||
);
|
||||
}
|
||||
|
||||
export fn ghostty_surface_mouse_pressure(
|
||||
surface: *Surface,
|
||||
stage_raw: u32,
|
||||
pressure: f64,
|
||||
) void {
|
||||
const stage = std.meta.intToEnum(
|
||||
input.MousePressureStage,
|
||||
stage_raw,
|
||||
) catch {
|
||||
log.warn(
|
||||
"invalid mouse pressure stage value={}",
|
||||
.{stage_raw},
|
||||
);
|
||||
return;
|
||||
};
|
||||
|
||||
surface.mousePressureCallback(stage, pressure);
|
||||
}
|
||||
|
||||
export fn ghostty_surface_ime_point(surface: *Surface, x: *f64, y: *f64) void {
|
||||
const pos = surface.core_surface.imePoint();
|
||||
x.* = pos.x;
|
||||
|
@ -63,6 +63,22 @@ pub const MouseMomentum = enum(u3) {
|
||||
may_begin = 6,
|
||||
};
|
||||
|
||||
/// The pressure stage of a pressure-sensitive input device.
|
||||
///
|
||||
/// This currently only supports the stages that macOS supports.
|
||||
pub const MousePressureStage = enum(u2) {
|
||||
/// The input device is unpressed.
|
||||
none = 0,
|
||||
|
||||
/// The input device is pressed a normal amount. On macOS trackpads,
|
||||
/// this is after a "click".
|
||||
normal = 1,
|
||||
|
||||
/// The input device is pressed a deep amount. On macOS trackpads,
|
||||
/// this is after a "force click".
|
||||
deep = 2,
|
||||
};
|
||||
|
||||
/// The bitmask for mods for scroll events.
|
||||
pub const ScrollMods = packed struct(u8) {
|
||||
/// True if this is a high-precision scroll event. For example, Apple
|
||||
|
Reference in New Issue
Block a user