macOS: firstRect should return full rect width/height (#8492)
Fixes #2473 This commit changes `ghostty_surface_ime_point` to return a full rect with the width/height calculated for the preedit. The `firstRect` function, which calls `ghostty_surface_ime_point` was previously setting the width/height to zero. macOS didn't like this. We then changed it to just hardcode it to width/height of one cell. This worked but made it so the IME cursor didn't follow the preedit. The result is shown in the video below. Notice the dictation icon follows the text properly: https://github.com/user-attachments/assets/81be8c63-9f0a-49b7-ac30-2db930beb238pull/8462/head
commit
ce94bb9f6a
|
|
@ -964,7 +964,7 @@ void ghostty_surface_mouse_scroll(ghostty_surface_t,
|
|||
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_ime_point(ghostty_surface_t, double*, double*, double*, double*);
|
||||
void ghostty_surface_request_close(ghostty_surface_t);
|
||||
void ghostty_surface_split(ghostty_surface_t, ghostty_action_split_direction_e);
|
||||
void ghostty_surface_split_focus(ghostty_surface_t,
|
||||
|
|
|
|||
|
|
@ -1683,8 +1683,10 @@ extension Ghostty.SurfaceView: NSTextInputClient {
|
|||
}
|
||||
|
||||
// Ghostty will tell us where it thinks an IME keyboard should render.
|
||||
var x: Double = 0;
|
||||
var y: Double = 0;
|
||||
var x: Double = 0
|
||||
var y: Double = 0
|
||||
var width: Double = cellSize.width
|
||||
var height: Double = cellSize.height
|
||||
|
||||
// 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.
|
||||
|
|
@ -1702,15 +1704,19 @@ extension Ghostty.SurfaceView: NSTextInputClient {
|
|||
// Free our text
|
||||
ghostty_surface_free_text(surface, &text)
|
||||
} else {
|
||||
ghostty_surface_ime_point(surface, &x, &y)
|
||||
ghostty_surface_ime_point(surface, &x, &y, &width, &height)
|
||||
}
|
||||
} else {
|
||||
ghostty_surface_ime_point(surface, &x, &y)
|
||||
ghostty_surface_ime_point(surface, &x, &y, &width, &height)
|
||||
}
|
||||
|
||||
// Ghostty coordinates are in top-left (0, 0) so we have to convert to
|
||||
// bottom-left since that is what UIKit expects
|
||||
let viewRect = NSMakeRect(x, frame.size.height - y, cellSize.width, cellSize.height)
|
||||
let viewRect = NSMakeRect(
|
||||
x,
|
||||
frame.size.height - y,
|
||||
max(width, cellSize.width),
|
||||
max(height, cellSize.height))
|
||||
|
||||
// Convert the point to the window coordinates
|
||||
let winRect = self.convert(viewRect, to: nil)
|
||||
|
|
|
|||
|
|
@ -1730,6 +1730,7 @@ pub fn pwd(
|
|||
pub fn imePoint(self: *const Surface) apprt.IMEPos {
|
||||
self.renderer_state.mutex.lock();
|
||||
const cursor = self.renderer_state.terminal.screen.cursor;
|
||||
const preedit_width: usize = if (self.renderer_state.preedit) |preedit| preedit.width() else 0;
|
||||
self.renderer_state.mutex.unlock();
|
||||
|
||||
// TODO: need to handle when scrolling and the cursor is not
|
||||
|
|
@ -1764,7 +1765,38 @@ pub fn imePoint(self: *const Surface) apprt.IMEPos {
|
|||
break :y y;
|
||||
};
|
||||
|
||||
return .{ .x = x, .y = y };
|
||||
// Our height for now is always just the cell height because our preedit
|
||||
// rendering only renders in a single line.
|
||||
const height: f64 = height: {
|
||||
var height: f64 = @floatFromInt(self.size.cell.height);
|
||||
height /= content_scale.y;
|
||||
break :height height;
|
||||
};
|
||||
const width: f64 = width: {
|
||||
var width: f64 = @floatFromInt(preedit_width * self.size.cell.width);
|
||||
|
||||
// Our max width is the remaining screen width after the cursor.
|
||||
// We don't have to deal with wrapping because the preedit doesn't
|
||||
// wrap right now.
|
||||
const screen_width: f64 = @floatFromInt(self.size.terminal().width);
|
||||
const x_offset: f64 = @floatFromInt((cursor.x + 1) * self.size.cell.width);
|
||||
const max = screen_width - x_offset;
|
||||
width = @min(width, max);
|
||||
|
||||
// Note: we don't apply content scale here because it looks like
|
||||
// for some reason in macOS its already scaled. I'm not sure why
|
||||
// that is so I'm going to just leave this comment here so its known
|
||||
// that I left this out on purpose pending more investigation.
|
||||
|
||||
break :width width;
|
||||
};
|
||||
|
||||
return .{
|
||||
.x = x,
|
||||
.y = y,
|
||||
.width = width,
|
||||
.height = height,
|
||||
};
|
||||
}
|
||||
|
||||
fn clipboardWrite(self: *const Surface, data: []const u8, loc: apprt.Clipboard) !void {
|
||||
|
|
|
|||
|
|
@ -1822,10 +1822,18 @@ pub const CAPI = struct {
|
|||
surface.mousePressureCallback(stage, pressure);
|
||||
}
|
||||
|
||||
export fn ghostty_surface_ime_point(surface: *Surface, x: *f64, y: *f64) void {
|
||||
export fn ghostty_surface_ime_point(
|
||||
surface: *Surface,
|
||||
x: *f64,
|
||||
y: *f64,
|
||||
width: *f64,
|
||||
height: *f64,
|
||||
) void {
|
||||
const pos = surface.core_surface.imePoint();
|
||||
x.* = pos.x;
|
||||
y.* = pos.y;
|
||||
width.* = pos.width;
|
||||
height.* = pos.height;
|
||||
}
|
||||
|
||||
/// Request that the surface become closed. This will go through the
|
||||
|
|
|
|||
|
|
@ -24,6 +24,8 @@ pub const CursorPos = struct {
|
|||
pub const IMEPos = struct {
|
||||
x: f64,
|
||||
y: f64,
|
||||
width: f64,
|
||||
height: f64,
|
||||
};
|
||||
|
||||
/// The clipboard type.
|
||||
|
|
|
|||
Loading…
Reference in New Issue