apprt/gtk: set multiple content types for clipboard ops

This supports the new `setClipboard` parameter that may provide data in
multiple formats, allowing us to copy rich text to/from the clipboard as
well as other types in the future.
pull/9431/head
Mitchell Hashimoto 2025-10-31 10:51:24 -07:00
parent 15bfdcb41e
commit 46db1cfd8f
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
2 changed files with 27 additions and 6 deletions

View File

@ -1962,7 +1962,7 @@ fn copySelectionToClipboards(
) !void {
// Create an arena to simplify memory management here.
var arena = ArenaAllocator.init(self.alloc);
errdefer arena.deinit();
defer arena.deinit();
const alloc = arena.allocator();
// The options we'll use for all formatting. We'll just override the

View File

@ -3340,8 +3340,9 @@ const Clipboard = struct {
) void {
const priv = self.private();
// For GTK, we only support text/plain type to set strings currently.
const val: [:0]const u8 = for (contents) |content| {
// Grab our plaintext content for use in confirmation dialogs
// and signals. We always expect one to exist.
const text: [:0]const u8 = for (contents) |content| {
if (std.mem.eql(u8, content.mime, "text/plain")) {
break content.data;
}
@ -3353,12 +3354,32 @@ const Clipboard = struct {
priv.gl_area.as(gtk.Widget),
clipboard_type,
) orelse return;
clipboard.setText(val);
const alloc = Application.default().allocator();
if (alloc.alloc(*gdk.ContentProvider, contents.len)) |providers| {
// Note: we don't need to unref the individual providers
// because new_union takes ownership of them.
defer alloc.free(providers);
for (contents, 0..) |content, i| {
const bytes = glib.Bytes.new(content.data.ptr, content.data.len);
defer bytes.unref();
const provider = gdk.ContentProvider.newForBytes(content.mime, bytes);
providers[i] = provider;
}
const all = gdk.ContentProvider.newUnion(providers.ptr, providers.len);
defer all.unref();
_ = clipboard.setContent(all);
} else |_| {
// If we fail to alloc, we can at least set the text content.
clipboard.setText(text);
}
Surface.signals.@"clipboard-write".impl.emit(
self,
null,
.{ clipboard_type, val.ptr },
.{ clipboard_type, text.ptr },
null,
);
@ -3368,7 +3389,7 @@ const Clipboard = struct {
showClipboardConfirmation(
self,
.{ .osc_52_write = clipboard_type },
val,
text,
);
}