From 2409d46600444f0d5001ec1140e7c3055d544549 Mon Sep 17 00:00:00 2001 From: Bryan Lee <38807139+liby@users.noreply.github.com> Date: Sun, 12 Jan 2025 01:15:53 +0800 Subject: [PATCH 1/3] Correct IME position calculation with window padding --- src/Surface.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Surface.zig b/src/Surface.zig index ce00d8237..d018d396d 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -1316,8 +1316,8 @@ pub fn imePoint(self: *const Surface) apprt.IMEPos { 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(cursor.x * self.size.cell.width); + // Simple x * cell width gives the top-left corner, then add padding offset + var x: f64 = @floatFromInt(cursor.x * self.size.cell.width + self.size.padding.left); // We want the midpoint x += @as(f64, @floatFromInt(self.size.cell.width)) / 2; @@ -1329,8 +1329,8 @@ pub fn imePoint(self: *const Surface) apprt.IMEPos { }; const y: f64 = y: { - // Simple x * cell width gives the top-left corner - var y: f64 = @floatFromInt(cursor.y * self.size.cell.height); + // Simple y * cell height gives the top-left corner, then add padding offset + var y: f64 = @floatFromInt(cursor.y * self.size.cell.height + self.size.padding.top); // We want the bottom y += @floatFromInt(self.size.cell.height); From af5e423ea5086b1acb6b265db0870ac79ba5e405 Mon Sep 17 00:00:00 2001 From: Bryan Lee <38807139+liby@users.noreply.github.com> Date: Sun, 12 Jan 2025 01:48:48 +0800 Subject: [PATCH 2/3] Clear selection when IME input starts --- include/ghostty.h | 1 + macos/Sources/Ghostty/SurfaceView_AppKit.swift | 5 +++++ src/apprt/embedded.zig | 5 +++++ 3 files changed, 11 insertions(+) diff --git a/include/ghostty.h b/include/ghostty.h index 29da8f37b..e6e625c4b 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -748,6 +748,7 @@ void ghostty_surface_complete_clipboard_request(ghostty_surface_t, bool); bool ghostty_surface_has_selection(ghostty_surface_t); uintptr_t ghostty_surface_selection(ghostty_surface_t, char*, uintptr_t); +void ghostty_surface_clear_selection(ghostty_surface_t); #ifdef __APPLE__ void ghostty_surface_set_display_id(ghostty_surface_t, uint32_t); diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift index 14143313e..362547e9e 100644 --- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift +++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift @@ -1293,6 +1293,11 @@ extension Ghostty.SurfaceView: NSTextInputClient { } func setMarkedText(_ string: Any, selectedRange: NSRange, replacementRange: NSRange) { + // Clear selection when IME input starts + if let surface = self.surface, ghostty_surface_has_selection(surface) { + ghostty_surface_clear_selection(surface) + } + switch string { case let v as NSAttributedString: self.markedText = NSMutableAttributedString(attributedString: v) diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index 44c4c5f20..441d10f59 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -1550,6 +1550,11 @@ pub const CAPI = struct { return selection.len; } + /// Clear the current selection in the surface. + export fn ghostty_surface_clear_selection(surface: *Surface) void { + surface.core_surface.io.terminal.screen.clearSelection(); + } + /// Tell the surface that it needs to schedule a render export fn ghostty_surface_refresh(surface: *Surface) void { surface.refresh(); From 6c5c5b2ec0bde5db6ae1d3d7f071c97dcb49af98 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 11 Jan 2025 13:59:38 -0800 Subject: [PATCH 3/3] core: clear selection whenever preedit is changed --- include/ghostty.h | 1 - macos/Sources/Ghostty/SurfaceView_AppKit.swift | 5 ----- macos/Sources/Helpers/NSPasteboard+Extension.swift | 1 + src/Surface.zig | 9 +++++++++ src/apprt/embedded.zig | 5 ----- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/include/ghostty.h b/include/ghostty.h index e6e625c4b..29da8f37b 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -748,7 +748,6 @@ void ghostty_surface_complete_clipboard_request(ghostty_surface_t, bool); bool ghostty_surface_has_selection(ghostty_surface_t); uintptr_t ghostty_surface_selection(ghostty_surface_t, char*, uintptr_t); -void ghostty_surface_clear_selection(ghostty_surface_t); #ifdef __APPLE__ void ghostty_surface_set_display_id(ghostty_surface_t, uint32_t); diff --git a/macos/Sources/Ghostty/SurfaceView_AppKit.swift b/macos/Sources/Ghostty/SurfaceView_AppKit.swift index 362547e9e..14143313e 100644 --- a/macos/Sources/Ghostty/SurfaceView_AppKit.swift +++ b/macos/Sources/Ghostty/SurfaceView_AppKit.swift @@ -1293,11 +1293,6 @@ extension Ghostty.SurfaceView: NSTextInputClient { } func setMarkedText(_ string: Any, selectedRange: NSRange, replacementRange: NSRange) { - // Clear selection when IME input starts - if let surface = self.surface, ghostty_surface_has_selection(surface) { - ghostty_surface_clear_selection(surface) - } - switch string { case let v as NSAttributedString: self.markedText = NSMutableAttributedString(attributedString: v) diff --git a/macos/Sources/Helpers/NSPasteboard+Extension.swift b/macos/Sources/Helpers/NSPasteboard+Extension.swift index 7794946f4..c2801da74 100644 --- a/macos/Sources/Helpers/NSPasteboard+Extension.swift +++ b/macos/Sources/Helpers/NSPasteboard+Extension.swift @@ -18,6 +18,7 @@ extension NSPasteboard { return path } } + return self.string(forType: .string) } diff --git a/src/Surface.zig b/src/Surface.zig index d018d396d..4682f4fb5 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -1591,6 +1591,15 @@ pub fn preeditCallback(self: *Surface, preedit_: ?[]const u8) !void { self.renderer_state.mutex.lock(); defer self.renderer_state.mutex.unlock(); + // We clear our selection when ANY OF: + // 1. We have an existing preedit + // 2. We have preedit text + if (self.renderer_state.preedit != null or + preedit_ != null) + { + self.setSelection(null) catch {}; + } + // We always clear our prior preedit if (self.renderer_state.preedit) |p| { self.alloc.free(p.codepoints); diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index 441d10f59..44c4c5f20 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -1550,11 +1550,6 @@ pub const CAPI = struct { return selection.len; } - /// Clear the current selection in the surface. - export fn ghostty_surface_clear_selection(surface: *Surface) void { - surface.core_surface.io.terminal.screen.clearSelection(); - } - /// Tell the surface that it needs to schedule a render export fn ghostty_surface_refresh(surface: *Surface) void { surface.refresh();