diff --git a/include/ghostty.h b/include/ghostty.h index 3697f78d43f..1d249a3a855 100644 --- a/include/ghostty.h +++ b/include/ghostty.h @@ -1180,6 +1180,12 @@ GHOSTTY_API void ghostty_surface_complete_clipboard_request(ghostty_surface_t, GHOSTTY_API bool ghostty_surface_has_selection(ghostty_surface_t); GHOSTTY_API bool ghostty_surface_select_cursor_cell(ghostty_surface_t); GHOSTTY_API bool ghostty_surface_select_cursor_line(ghostty_surface_t); +GHOSTTY_API bool ghostty_surface_set_selection_range(ghostty_surface_t, + uint32_t row_start, + uint32_t col_start, + uint32_t row_end, + uint32_t col_end, + bool is_rectangular); GHOSTTY_API bool ghostty_surface_clear_selection(ghostty_surface_t); GHOSTTY_API bool ghostty_surface_read_selection(ghostty_surface_t, ghostty_text_s*); GHOSTTY_API bool ghostty_surface_read_text(ghostty_surface_t, diff --git a/src/Surface.zig b/src/Surface.zig index a1fd96e7d9b..c373f204403 100644 --- a/src/Surface.zig +++ b/src/Surface.zig @@ -2118,6 +2118,30 @@ pub fn selectCursorLine(self: *Surface) !bool { return true; } +/// Set a selection range from buffer (screen) coordinates (cmux-specific). +pub fn setSelectionRange( + self: *Surface, + row_start: u32, + col_start: u32, + row_end: u32, + col_end: u32, + is_rectangular: bool, +) !bool { + self.renderer_state.mutex.lock(); + defer self.renderer_state.mutex.unlock(); + + const screen: *terminal.Screen = self.io.terminal.screens.active; + const col_start_cell = std.math.cast(terminal.size.CellCountInt, col_start) orelse return false; + const col_end_cell = std.math.cast(terminal.size.CellCountInt, col_end) orelse return false; + const start_pin = screen.pages.pin(.{ .screen = .{ .x = col_start_cell, .y = row_start } }) orelse return false; + const end_pin = screen.pages.pin(.{ .screen = .{ .x = col_end_cell, .y = row_end } }) orelse return false; + + try self.setSelection(terminal.Selection.init(start_pin, end_pin, is_rectangular)); + screen.dirty.selection = true; + try self.queueRender(); + return true; +} + /// Clear the active selection (cmux-specific). pub fn clearSelection(self: *Surface) !bool { self.renderer_state.mutex.lock(); diff --git a/src/apprt/embedded.zig b/src/apprt/embedded.zig index 340fedda58a..0f145487668 100644 --- a/src/apprt/embedded.zig +++ b/src/apprt/embedded.zig @@ -1684,6 +1684,27 @@ pub const CAPI = struct { }; } + /// Set a selection range from buffer (screen) coordinates (cmux-specific). + export fn ghostty_surface_set_selection_range( + surface: *Surface, + row_start: u32, + col_start: u32, + row_end: u32, + col_end: u32, + is_rectangular: bool, + ) bool { + return surface.core_surface.setSelectionRange( + row_start, + col_start, + row_end, + col_end, + is_rectangular, + ) catch |err| { + log.warn("error setting selection range err={}", .{err}); + return false; + }; + } + /// Same as ghostty_surface_read_text but reads from the user selection, /// if any. export fn ghostty_surface_read_selection(