diff --git a/src/apprt/gtk-ng/build/gresource.zig b/src/apprt/gtk-ng/build/gresource.zig index 4e608278c..3e192ebbd 100644 --- a/src/apprt/gtk-ng/build/gresource.zig +++ b/src/apprt/gtk-ng/build/gresource.zig @@ -33,7 +33,8 @@ pub const icon_sizes: []const comptime_int = &.{ 16, 32, 128, 256, 512, 1024 }; /// /// These will be asserted to exist at runtime. pub const blueprints: []const Blueprint = &.{ - .{ .major = 1, .minor = 2, .name = "clipboard-confirmation-dialog" }, + .{ .major = 1, .minor = 0, .name = "clipboard-confirmation-dialog" }, + .{ .major = 1, .minor = 4, .name = "clipboard-confirmation-dialog" }, .{ .major = 1, .minor = 2, .name = "close-confirmation-dialog" }, .{ .major = 1, .minor = 2, .name = "config-errors-dialog" }, .{ .major = 1, .minor = 2, .name = "resize-overlay" }, diff --git a/src/apprt/gtk-ng/class/clipboard_confirmation_dialog.zig b/src/apprt/gtk-ng/class/clipboard_confirmation_dialog.zig index c56309df9..065521228 100644 --- a/src/apprt/gtk-ng/class/clipboard_confirmation_dialog.zig +++ b/src/apprt/gtk-ng/class/clipboard_confirmation_dialog.zig @@ -8,11 +8,15 @@ const gtk = @import("gtk"); const apprt = @import("../../../apprt.zig"); const gresource = @import("../build/gresource.zig"); const i18n = @import("../../../os/main.zig").i18n; +const adw_version = @import("../adw_version.zig"); const Common = @import("../class.zig").Common; const Dialog = @import("dialog.zig").Dialog; const log = std.log.scoped(.gtk_ghostty_clipboard_confirmation); +/// Whether we're able to have the remember switch +const can_remember = adw_version.supportsSwitchRow(); + pub const ClipboardConfirmationDialog = extern struct { const Self = @This(); parent_instance: Parent, @@ -147,6 +151,7 @@ pub const ClipboardConfirmationDialog = extern struct { text_view: *gtk.TextView, reveal_button: *gtk.Button, hide_button: *gtk.Button, + remember_choice: if (can_remember) *adw.SwitchRow else void, pub var offset: c_int = 0; }; @@ -279,8 +284,10 @@ pub const ClipboardConfirmationDialog = extern struct { self: *Self, response_id: [*:0]const u8, ) callconv(.C) void { - // TODO: remember - const remember = false; + const remember: bool = if (comptime can_remember) remember: { + const priv = self.private(); + break :remember priv.remember_choice.getActive() != 0; + } else false; if (std.mem.orderZ(u8, response_id, "cancel") == .eq) { signals.deny.impl.emit( @@ -344,11 +351,18 @@ pub const ClipboardConfirmationDialog = extern struct { fn init(class: *Class) callconv(.C) void { gtk.Widget.Class.setTemplateFromResource( class.as(gtk.Widget.Class), - comptime gresource.blueprint(.{ - .major = 1, - .minor = 2, - .name = "clipboard-confirmation-dialog", - }), + if (comptime adw_version.atLeast(1, 4, 0)) + comptime gresource.blueprint(.{ + .major = 1, + .minor = 4, + .name = "clipboard-confirmation-dialog", + }) + else + comptime gresource.blueprint(.{ + .major = 1, + .minor = 0, + .name = "clipboard-confirmation-dialog", + }), ); // Bindings @@ -356,6 +370,9 @@ pub const ClipboardConfirmationDialog = extern struct { class.bindTemplateChildPrivate("text_view", .{}); class.bindTemplateChildPrivate("hide_button", .{}); class.bindTemplateChildPrivate("reveal_button", .{}); + if (comptime can_remember) { + class.bindTemplateChildPrivate("remember_choice", .{}); + } // Properties gobject.ext.registerProperties(class, &.{ diff --git a/src/apprt/gtk-ng/class/surface.zig b/src/apprt/gtk-ng/class/surface.zig index 11c5e7ac2..45fa6182f 100644 --- a/src/apprt/gtk-ng/class/surface.zig +++ b/src/apprt/gtk-ng/class/surface.zig @@ -2119,12 +2119,17 @@ const Clipboard = struct { remember: bool, self: *Surface, ) callconv(.c) void { - _ = remember; - const priv = self.private(); const surface = priv.core_surface orelse return; const req = dialog.getRequest() orelse return; + // Handle remember + if (remember) switch (req.*) { + .osc_52_read => surface.config.clipboard_read = .allow, + .osc_52_write => surface.config.clipboard_write = .allow, + .paste => {}, + }; + // Get our text const text_buf = dialog.getClipboardContents() orelse return; var text_val = gobject.ext.Value.new(?[:0]const u8); @@ -2153,9 +2158,16 @@ const Clipboard = struct { remember: bool, self: *Surface, ) callconv(.c) void { - _ = dialog; - _ = remember; - _ = self; + const priv = self.private(); + const surface = priv.core_surface orelse return; + const req = dialog.getRequest() orelse return; + + // Handle remember + if (remember) switch (req.*) { + .osc_52_read => surface.config.clipboard_read = .deny, + .osc_52_write => surface.config.clipboard_write = .deny, + .paste => {}, + }; } fn clipboardReadText( diff --git a/src/apprt/gtk-ng/ui/1.0/clipboard-confirmation-dialog.blp b/src/apprt/gtk-ng/ui/1.0/clipboard-confirmation-dialog.blp new file mode 100644 index 000000000..38fc8706b --- /dev/null +++ b/src/apprt/gtk-ng/ui/1.0/clipboard-confirmation-dialog.blp @@ -0,0 +1,74 @@ +using Gtk 4.0; +// This is unused but if we remove it we get a blueprint-compiler error. +using Adw 1; + +template $GhosttyClipboardConfirmationDialog: $GhosttyDialog { + styles [ + "clipboard-confirmation-dialog", + ] + + heading: _("Authorize Clipboard Access"); + // Not localized because this is a placeholder users never see. + body: "If you see this text, there is a bug in Ghostty. Please report it."; + + responses [ + cancel: _("Deny") suggested, + ok: _("Allow") destructive, + ] + + default-response: "cancel"; + close-response: "cancel"; + + extra-child: ListBox { + selection-mode: none; + + Overlay { + styles [ + "osd", + "clipboard-overlay", + ] + + ScrolledWindow text_view_scroll { + width-request: 500; + height-request: 200; + + TextView text_view { + styles [ + "clipboard-contents", + ] + + cursor-visible: false; + editable: false; + monospace: true; + top-margin: 8; + left-margin: 8; + bottom-margin: 8; + right-margin: 8; + buffer: bind template.clipboard-contents; + } + } + + [overlay] + Button reveal_button { + visible: false; + halign: end; + valign: start; + margin-end: 12; + margin-top: 12; + + Image { + icon-name: "view-reveal-symbolic"; + } + } + + [overlay] + Button hide_button { + visible: false; + halign: end; + valign: start; + margin-end: 12; + margin-top: 12; + } + } + }; +} diff --git a/src/apprt/gtk-ng/ui/1.2/clipboard-confirmation-dialog.blp b/src/apprt/gtk-ng/ui/1.4/clipboard-confirmation-dialog.blp similarity index 100% rename from src/apprt/gtk-ng/ui/1.2/clipboard-confirmation-dialog.blp rename to src/apprt/gtk-ng/ui/1.4/clipboard-confirmation-dialog.blp