mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-17 09:16:11 +03:00
macos: add API to get selection top-left for quicklook
This commit is contained in:
@ -558,6 +558,7 @@ uintptr_t ghostty_surface_selection(ghostty_surface_t, char*, uintptr_t);
|
||||
void ghostty_surface_set_display_id(ghostty_surface_t, uint32_t);
|
||||
void* ghostty_surface_quicklook_font(ghostty_surface_t);
|
||||
void ghostty_surface_selection_range(ghostty_surface_t, uint32_t*, uint32_t*);
|
||||
void ghostty_surface_selection_point(ghostty_surface_t, double*, double*);
|
||||
#endif
|
||||
|
||||
ghostty_inspector_t ghostty_surface_inspector(ghostty_surface_t);
|
||||
|
@ -1010,7 +1010,17 @@ extension Ghostty.SurfaceView: NSTextInputClient {
|
||||
// Ghostty will tell us where it thinks an IME keyboard should render.
|
||||
var x: Double = 0;
|
||||
var y: Double = 0;
|
||||
ghostty_surface_ime_point(surface, &x, &y)
|
||||
|
||||
// QuickLook never gives us a matching range to our selection so if we detect
|
||||
// this then we return the top-left selection point rather than the cursor point.
|
||||
// This is hacky but I can't think of a better way to get the right IME vs. QuickLook
|
||||
// point right now. I'm sure I'm missing something fundamental...
|
||||
if range.length > 0 && range != self.selectedRange() {
|
||||
// QuickLook
|
||||
ghostty_surface_selection_point(surface, &x, &y)
|
||||
} else {
|
||||
ghostty_surface_ime_point(surface, &x, &y)
|
||||
}
|
||||
|
||||
// Ghostty coordinates are in top-left (0, 0) so we have to convert to
|
||||
// bottom-left since that is what UIKit expects
|
||||
|
@ -933,6 +933,53 @@ pub fn imePoint(self: *const Surface) apprt.IMEPos {
|
||||
return .{ .x = x, .y = y };
|
||||
}
|
||||
|
||||
/// Returns the x/y coordinate of where the selection top-left is. This is
|
||||
/// used currently only by macOS to render the QuickLook highlight in the
|
||||
/// proper location.
|
||||
pub fn selectionPoint(self: *const Surface) ?apprt.IMEPos {
|
||||
self.renderer_state.mutex.lock();
|
||||
defer self.renderer_state.mutex.unlock();
|
||||
|
||||
// Get the top-left coordinate of the selection in the viewport.
|
||||
const sel = self.io.terminal.screen.selection orelse return null;
|
||||
const tl_pt = self.io.terminal.screen.pages.pointFromPin(
|
||||
.viewport,
|
||||
sel.topLeft(&self.io.terminal.screen),
|
||||
) orelse return null;
|
||||
const tl_coord = tl_pt.coord();
|
||||
|
||||
// Our sizes are all scaled so we need to send the unscaled values back.
|
||||
const content_scale = self.rt_surface.getContentScale() catch .{ .x = 1, .y = 1 };
|
||||
|
||||
const x: f64 = x: {
|
||||
// Simple x * cell width gives the top-left corner
|
||||
var x: f64 = @floatFromInt(tl_coord.x * self.cell_size.width);
|
||||
|
||||
// We want the midpoint
|
||||
x += @as(f64, @floatFromInt(self.cell_size.width)) / 2;
|
||||
|
||||
// And scale it
|
||||
x /= content_scale.x;
|
||||
|
||||
break :x x;
|
||||
};
|
||||
|
||||
const y: f64 = y: {
|
||||
// Simple x * cell width gives the top-left corner
|
||||
var y: f64 = @floatFromInt(tl_coord.y * self.cell_size.height);
|
||||
|
||||
// We want the bottom
|
||||
y += @floatFromInt(self.cell_size.height);
|
||||
|
||||
// And scale it
|
||||
y /= content_scale.y;
|
||||
|
||||
break :y y;
|
||||
};
|
||||
|
||||
return .{ .x = x, .y = y };
|
||||
}
|
||||
|
||||
fn clipboardWrite(self: *const Surface, data: []const u8, loc: apprt.Clipboard) !void {
|
||||
if (self.config.clipboard_write == .deny) {
|
||||
log.info("application attempted to write clipboard, but 'clipboard-write' is set to deny", .{});
|
||||
|
@ -1823,6 +1823,16 @@ pub const CAPI = struct {
|
||||
len.* = range.len;
|
||||
}
|
||||
|
||||
export fn ghostty_surface_selection_point(
|
||||
ptr: *Surface,
|
||||
x: *f64,
|
||||
y: *f64,
|
||||
) void {
|
||||
const point = ptr.core_surface.selectionPoint() orelse return;
|
||||
x.* = point.x;
|
||||
y.* = point.y;
|
||||
}
|
||||
|
||||
export fn ghostty_inspector_metal_init(ptr: *Inspector, device: objc.c.id) bool {
|
||||
return ptr.initMetal(objc.Object.fromId(device));
|
||||
}
|
||||
|
Reference in New Issue
Block a user