mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
apprt/embedded: support selection clipboard
This commit is contained in:
@ -29,6 +29,11 @@ typedef void *ghostty_config_t;
|
|||||||
typedef void *ghostty_surface_t;
|
typedef void *ghostty_surface_t;
|
||||||
|
|
||||||
// Enums are up top so we can reference them later.
|
// Enums are up top so we can reference them later.
|
||||||
|
typedef enum {
|
||||||
|
GHOSTTY_CLIPBOARD_STANDARD,
|
||||||
|
GHOSTTY_CLIPBOARD_SELECTION,
|
||||||
|
} ghostty_clipboard_e;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
GHOSTTY_SPLIT_RIGHT,
|
GHOSTTY_SPLIT_RIGHT,
|
||||||
GHOSTTY_SPLIT_DOWN
|
GHOSTTY_SPLIT_DOWN
|
||||||
@ -238,8 +243,8 @@ typedef struct {
|
|||||||
typedef void (*ghostty_runtime_wakeup_cb)(void *);
|
typedef void (*ghostty_runtime_wakeup_cb)(void *);
|
||||||
typedef const ghostty_config_t (*ghostty_runtime_reload_config_cb)(void *);
|
typedef const ghostty_config_t (*ghostty_runtime_reload_config_cb)(void *);
|
||||||
typedef void (*ghostty_runtime_set_title_cb)(void *, const char *);
|
typedef void (*ghostty_runtime_set_title_cb)(void *, const char *);
|
||||||
typedef const char* (*ghostty_runtime_read_clipboard_cb)(void *);
|
typedef const char* (*ghostty_runtime_read_clipboard_cb)(void *, ghostty_clipboard_e);
|
||||||
typedef void (*ghostty_runtime_write_clipboard_cb)(void *, const char *);
|
typedef void (*ghostty_runtime_write_clipboard_cb)(void *, const char *, ghostty_clipboard_e);
|
||||||
typedef void (*ghostty_runtime_new_split_cb)(void *, ghostty_split_direction_e);
|
typedef void (*ghostty_runtime_new_split_cb)(void *, ghostty_split_direction_e);
|
||||||
typedef void (*ghostty_runtime_close_surface_cb)(void *, bool);
|
typedef void (*ghostty_runtime_close_surface_cb)(void *, bool);
|
||||||
typedef void (*ghostty_runtime_focus_split_cb)(void *, ghostty_split_focus_direction_e);
|
typedef void (*ghostty_runtime_focus_split_cb)(void *, ghostty_split_focus_direction_e);
|
||||||
|
@ -57,8 +57,8 @@ extension Ghostty {
|
|||||||
wakeup_cb: { userdata in AppState.wakeup(userdata) },
|
wakeup_cb: { userdata in AppState.wakeup(userdata) },
|
||||||
reload_config_cb: { userdata in AppState.reloadConfig(userdata) },
|
reload_config_cb: { userdata in AppState.reloadConfig(userdata) },
|
||||||
set_title_cb: { userdata, title in AppState.setTitle(userdata, title: title) },
|
set_title_cb: { userdata, title in AppState.setTitle(userdata, title: title) },
|
||||||
read_clipboard_cb: { userdata in AppState.readClipboard(userdata) },
|
read_clipboard_cb: { userdata, loc in AppState.readClipboard(userdata, location: loc) },
|
||||||
write_clipboard_cb: { userdata, str in AppState.writeClipboard(userdata, string: str) },
|
write_clipboard_cb: { userdata, str, loc in AppState.writeClipboard(userdata, string: str, location: loc) },
|
||||||
new_split_cb: { userdata, direction in AppState.newSplit(userdata, direction: direction) },
|
new_split_cb: { userdata, direction in AppState.newSplit(userdata, direction: direction) },
|
||||||
close_surface_cb: { userdata, processAlive in AppState.closeSurface(userdata, processAlive: processAlive) },
|
close_surface_cb: { userdata, processAlive in AppState.closeSurface(userdata, processAlive: processAlive) },
|
||||||
focus_split_cb: { userdata, direction in AppState.focusSplit(userdata, direction: direction) },
|
focus_split_cb: { userdata, direction in AppState.focusSplit(userdata, direction: direction) },
|
||||||
@ -170,7 +170,10 @@ extension Ghostty {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func readClipboard(_ userdata: UnsafeMutableRawPointer?) -> UnsafePointer<CChar>? {
|
static func readClipboard(_ userdata: UnsafeMutableRawPointer?, location: ghostty_clipboard_e) -> UnsafePointer<CChar>? {
|
||||||
|
// We only support the standard clipboard
|
||||||
|
if (location != GHOSTTY_CLIPBOARD_STANDARD) { return nil }
|
||||||
|
|
||||||
guard let appState = self.appState(fromSurface: userdata) else { return nil }
|
guard let appState = self.appState(fromSurface: userdata) else { return nil }
|
||||||
guard let str = NSPasteboard.general.string(forType: .string) else { return nil }
|
guard let str = NSPasteboard.general.string(forType: .string) else { return nil }
|
||||||
|
|
||||||
@ -180,7 +183,10 @@ extension Ghostty {
|
|||||||
return (str as NSString).utf8String
|
return (str as NSString).utf8String
|
||||||
}
|
}
|
||||||
|
|
||||||
static func writeClipboard(_ userdata: UnsafeMutableRawPointer?, string: UnsafePointer<CChar>?) {
|
static func writeClipboard(_ userdata: UnsafeMutableRawPointer?, string: UnsafePointer<CChar>?, location: ghostty_clipboard_e) {
|
||||||
|
// We only support the standard clipboard
|
||||||
|
if (location != GHOSTTY_CLIPBOARD_STANDARD) { return }
|
||||||
|
|
||||||
guard let valueStr = String(cString: string!, encoding: .utf8) else { return }
|
guard let valueStr = String(cString: string!, encoding: .utf8) else { return }
|
||||||
let pb = NSPasteboard.general
|
let pb = NSPasteboard.general
|
||||||
pb.declareTypes([.string], owner: nil)
|
pb.declareTypes([.string], owner: nil)
|
||||||
|
@ -47,10 +47,10 @@ pub const App = struct {
|
|||||||
/// Read the clipboard value. The return value must be preserved
|
/// Read the clipboard value. The return value must be preserved
|
||||||
/// by the host until the next call. If there is no valid clipboard
|
/// by the host until the next call. If there is no valid clipboard
|
||||||
/// value then this should return null.
|
/// value then this should return null.
|
||||||
read_clipboard: *const fn (SurfaceUD) callconv(.C) ?[*:0]const u8,
|
read_clipboard: *const fn (SurfaceUD, c_int) callconv(.C) ?[*:0]const u8,
|
||||||
|
|
||||||
/// Write the clipboard value.
|
/// Write the clipboard value.
|
||||||
write_clipboard: *const fn (SurfaceUD, [*:0]const u8) callconv(.C) void,
|
write_clipboard: *const fn (SurfaceUD, [*:0]const u8, c_int) callconv(.C) void,
|
||||||
|
|
||||||
/// Create a new split view. If the embedder doesn't support split
|
/// Create a new split view. If the embedder doesn't support split
|
||||||
/// views then this can be null.
|
/// views then this can be null.
|
||||||
@ -239,13 +239,27 @@ pub const Surface = struct {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getClipboardString(self: *const Surface) ![:0]const u8 {
|
pub fn getClipboardString(
|
||||||
const ptr = self.app.opts.read_clipboard(self.opts.userdata) orelse return "";
|
self: *const Surface,
|
||||||
|
clipboard_type: apprt.Clipboard,
|
||||||
|
) ![:0]const u8 {
|
||||||
|
const ptr = self.app.opts.read_clipboard(
|
||||||
|
self.opts.userdata,
|
||||||
|
@intCast(@intFromEnum(clipboard_type)),
|
||||||
|
) orelse return "";
|
||||||
return std.mem.sliceTo(ptr, 0);
|
return std.mem.sliceTo(ptr, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setClipboardString(self: *const Surface, val: [:0]const u8) !void {
|
pub fn setClipboardString(
|
||||||
self.app.opts.write_clipboard(self.opts.userdata, val.ptr);
|
self: *const Surface,
|
||||||
|
val: [:0]const u8,
|
||||||
|
clipboard_type: apprt.Clipboard,
|
||||||
|
) !void {
|
||||||
|
self.app.opts.write_clipboard(
|
||||||
|
self.opts.userdata,
|
||||||
|
val.ptr,
|
||||||
|
@intCast(@intFromEnum(clipboard_type)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setShouldClose(self: *Surface) void {
|
pub fn setShouldClose(self: *Surface) void {
|
||||||
|
@ -526,7 +526,7 @@ pub const Surface = struct {
|
|||||||
.standard => glfw.setClipboardString(val),
|
.standard => glfw.setClipboardString(val),
|
||||||
.selection => {
|
.selection => {
|
||||||
// Not supported except on Linux
|
// Not supported except on Linux
|
||||||
if (comptime builtin.os.tag != .linux) return "";
|
if (comptime builtin.os.tag != .linux) return;
|
||||||
glfwNative.setX11SelectionString(val.ptr);
|
glfwNative.setX11SelectionString(val.ptr);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user