summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Hashimoto <m@mitchellh.com>2025-07-22 13:27:02 -0700
committerMitchell Hashimoto <m@mitchellh.com>2025-07-22 14:36:21 -0700
commit4d39f2728a232144258de907605f22800a0d51b2 (patch)
tree639393d9433f0d24afacf6e48210afc74d12d84c
parent58a5f3f1f8419ce85a3610c3719b2a68d03d99d0 (diff)
apprt/gtk-ng: implement remember
-rw-r--r--src/apprt/gtk-ng/build/gresource.zig3
-rw-r--r--src/apprt/gtk-ng/class/clipboard_confirmation_dialog.zig31
-rw-r--r--src/apprt/gtk-ng/class/surface.zig22
-rw-r--r--src/apprt/gtk-ng/ui/1.0/clipboard-confirmation-dialog.blp74
-rw-r--r--src/apprt/gtk-ng/ui/1.4/clipboard-confirmation-dialog.blp (renamed from src/apprt/gtk-ng/ui/1.2/clipboard-confirmation-dialog.blp)0
5 files changed, 117 insertions, 13 deletions
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
index f1dcf426e..f1dcf426e 100644
--- a/src/apprt/gtk-ng/ui/1.2/clipboard-confirmation-dialog.blp
+++ b/src/apprt/gtk-ng/ui/1.4/clipboard-confirmation-dialog.blp