mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
gtk: switch clipboard confirmation to zig-gobject and blueprints
Note that for Debian 12, the blueprints must be compiled on a distro with a newer version of `blueprint-compiler` and the raw UI XML committed to git. Debian 12 includes `blueprint-compiler` 0.6.0 which doesn't support compiling `adw.MessageDialog` even though the version of `libadwaita` supports it.
This commit is contained in:
@ -4,18 +4,24 @@ const ClipboardConfirmation = @This();
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
const gtk = @import("gtk");
|
||||
const adw = @import("adw");
|
||||
const gobject = @import("gobject");
|
||||
const gio = @import("gio");
|
||||
|
||||
const apprt = @import("../../apprt.zig");
|
||||
const CoreSurface = @import("../../Surface.zig");
|
||||
const App = @import("App.zig");
|
||||
const View = @import("View.zig");
|
||||
const c = @import("c.zig").c;
|
||||
const Builder = @import("Builder.zig");
|
||||
const adwaita = @import("adwaita.zig");
|
||||
|
||||
const log = std.log.scoped(.gtk);
|
||||
|
||||
app: *App,
|
||||
window: *c.GtkWindow,
|
||||
view: PrimaryView,
|
||||
const DialogType = if (adwaita.versionAtLeast(1, 5, 0)) adw.AlertDialog else adw.MessageDialog;
|
||||
|
||||
app: *App,
|
||||
dialog: *DialogType,
|
||||
data: [:0]u8,
|
||||
core_surface: *CoreSurface,
|
||||
pending_req: apprt.ClipboardRequest,
|
||||
@ -57,201 +63,92 @@ fn init(
|
||||
core_surface: *CoreSurface,
|
||||
request: apprt.ClipboardRequest,
|
||||
) !void {
|
||||
// Create the window
|
||||
const window = c.gtk_window_new();
|
||||
const gtk_window: *c.GtkWindow = @ptrCast(window);
|
||||
errdefer c.gtk_window_destroy(gtk_window);
|
||||
c.gtk_window_set_title(gtk_window, titleText(request));
|
||||
c.gtk_window_set_default_size(gtk_window, 550, 275);
|
||||
c.gtk_window_set_resizable(gtk_window, 0);
|
||||
c.gtk_widget_add_css_class(@ptrCast(@alignCast(gtk_window)), "window");
|
||||
c.gtk_widget_add_css_class(@ptrCast(@alignCast(gtk_window)), "clipboard-confirmation-window");
|
||||
_ = c.g_signal_connect_data(
|
||||
window,
|
||||
"destroy",
|
||||
c.G_CALLBACK(>kDestroy),
|
||||
self,
|
||||
null,
|
||||
c.G_CONNECT_DEFAULT,
|
||||
);
|
||||
var builder = switch (DialogType) {
|
||||
adw.AlertDialog => switch (request) {
|
||||
.osc_52_read => Builder.init("ccw-osc-52-write-15", .blp),
|
||||
.osc_52_write => Builder.init("ccw-osc-52-write-15", .blp),
|
||||
.paste => Builder.init("ccw-paste-15", .blp),
|
||||
},
|
||||
adw.MessageDialog => switch (request) {
|
||||
.osc_52_read => Builder.init("ccw-osc-52-write-12", .ui),
|
||||
.osc_52_write => Builder.init("ccw-osc-52-write-12", .ui),
|
||||
.paste => Builder.init("ccw-paste-12", .ui),
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
builder.deinit();
|
||||
|
||||
// Set some state
|
||||
const dialog = builder.getObject(DialogType, "clipboard_confirmation_window").?;
|
||||
|
||||
const copy = try app.core_app.alloc.dupeZ(u8, data);
|
||||
errdefer app.core_app.alloc.free(copy);
|
||||
self.* = .{
|
||||
.app = app,
|
||||
.window = gtk_window,
|
||||
.view = undefined,
|
||||
.data = try app.core_app.alloc.dupeZ(u8, data),
|
||||
.dialog = dialog,
|
||||
.data = copy,
|
||||
.core_surface = core_surface,
|
||||
.pending_req = request,
|
||||
};
|
||||
|
||||
// Show the window
|
||||
const view = try PrimaryView.init(self, data);
|
||||
self.view = view;
|
||||
c.gtk_window_set_child(@ptrCast(window), view.root);
|
||||
_ = c.gtk_widget_grab_focus(view.buttons.cancel_button);
|
||||
const text_view = builder.getObject(gtk.TextView, "text_view").?;
|
||||
|
||||
c.gtk_widget_show(window);
|
||||
const buffer = gtk.TextBuffer.new(null);
|
||||
errdefer buffer.unref();
|
||||
buffer.insertAtCursor(copy.ptr, @intCast(copy.len));
|
||||
text_view.setBuffer(buffer);
|
||||
|
||||
// Block the main window from input.
|
||||
// This will auto-revert when the window is closed.
|
||||
c.gtk_window_set_modal(gtk_window, 1);
|
||||
switch (DialogType) {
|
||||
adw.AlertDialog => {
|
||||
const parent: ?*gtk.Widget = widget: {
|
||||
const window = core_surface.rt_surface.container.window() orelse break :widget null;
|
||||
break :widget @ptrCast(@alignCast(window.window));
|
||||
};
|
||||
|
||||
dialog.choose(parent, null, gtkChoose, self);
|
||||
},
|
||||
adw.MessageDialog => {
|
||||
if (adwaita.versionAtLeast(1, 3, 0)) {
|
||||
dialog.choose(null, gtkChoose, self);
|
||||
} else {
|
||||
_ = adw.MessageDialog.signals.response.connect(
|
||||
dialog,
|
||||
*ClipboardConfirmation,
|
||||
gtkResponse,
|
||||
self,
|
||||
.{},
|
||||
);
|
||||
dialog.as(gtk.Widget).show();
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn gtkDestroy(_: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) void {
|
||||
const self: *ClipboardConfirmation = @ptrCast(@alignCast(ud orelse return));
|
||||
self.destroy();
|
||||
}
|
||||
|
||||
const PrimaryView = struct {
|
||||
root: *c.GtkWidget,
|
||||
text: *c.GtkTextView,
|
||||
buttons: ButtonsView,
|
||||
|
||||
pub fn init(root: *ClipboardConfirmation, data: []const u8) !PrimaryView {
|
||||
// All our widgets
|
||||
const label = c.gtk_label_new(promptText(root.pending_req));
|
||||
const buf = unsafeBuffer(data);
|
||||
defer c.g_object_unref(buf);
|
||||
const buttons = try ButtonsView.init(root);
|
||||
const text_scroll = c.gtk_scrolled_window_new();
|
||||
errdefer c.g_object_unref(text_scroll);
|
||||
const text = c.gtk_text_view_new_with_buffer(buf);
|
||||
errdefer c.g_object_unref(text);
|
||||
c.gtk_scrolled_window_set_child(@ptrCast(text_scroll), text);
|
||||
|
||||
// Create our view
|
||||
const view = try View.init(&.{
|
||||
.{ .name = "label", .widget = label },
|
||||
.{ .name = "text", .widget = text_scroll },
|
||||
.{ .name = "buttons", .widget = buttons.root },
|
||||
}, &vfl);
|
||||
errdefer view.deinit();
|
||||
|
||||
// We can do additional settings once the layout is setup
|
||||
c.gtk_label_set_wrap(@ptrCast(label), 1);
|
||||
c.gtk_text_view_set_editable(@ptrCast(text), 0);
|
||||
c.gtk_text_view_set_cursor_visible(@ptrCast(text), 0);
|
||||
c.gtk_text_view_set_top_margin(@ptrCast(text), 8);
|
||||
c.gtk_text_view_set_bottom_margin(@ptrCast(text), 8);
|
||||
c.gtk_text_view_set_left_margin(@ptrCast(text), 8);
|
||||
c.gtk_text_view_set_right_margin(@ptrCast(text), 8);
|
||||
c.gtk_text_view_set_monospace(@ptrCast(text), 1);
|
||||
|
||||
return .{ .root = view.root, .text = @ptrCast(text), .buttons = buttons };
|
||||
}
|
||||
|
||||
/// Returns the GtkTextBuffer for the data that was unsafe.
|
||||
fn unsafeBuffer(data: []const u8) *c.GtkTextBuffer {
|
||||
const buf = c.gtk_text_buffer_new(null);
|
||||
errdefer c.g_object_unref(buf);
|
||||
|
||||
c.gtk_text_buffer_insert_at_cursor(buf, data.ptr, @intCast(data.len));
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
const vfl = [_][*:0]const u8{
|
||||
"H:|-8-[label]-8-|",
|
||||
"H:|[text]|",
|
||||
"H:|[buttons]|",
|
||||
"V:|[label(<=80)][text(>=100)]-[buttons]-|",
|
||||
};
|
||||
};
|
||||
|
||||
const ButtonsView = struct {
|
||||
root: *c.GtkWidget,
|
||||
confirm_button: *c.GtkWidget,
|
||||
cancel_button: *c.GtkWidget,
|
||||
|
||||
pub fn init(root: *ClipboardConfirmation) !ButtonsView {
|
||||
const cancel_text, const confirm_text = switch (root.pending_req) {
|
||||
.paste => .{ "Cancel", "Paste" },
|
||||
.osc_52_read, .osc_52_write => .{ "Deny", "Allow" },
|
||||
};
|
||||
|
||||
const cancel_button = c.gtk_button_new_with_label(cancel_text);
|
||||
errdefer c.g_object_unref(cancel_button);
|
||||
|
||||
const confirm_button = c.gtk_button_new_with_label(confirm_text);
|
||||
errdefer c.g_object_unref(confirm_button);
|
||||
|
||||
c.gtk_widget_add_css_class(confirm_button, "destructive-action");
|
||||
c.gtk_widget_add_css_class(cancel_button, "suggested-action");
|
||||
|
||||
// Create our view
|
||||
const view = try View.init(&.{
|
||||
.{ .name = "cancel", .widget = cancel_button },
|
||||
.{ .name = "confirm", .widget = confirm_button },
|
||||
}, &vfl);
|
||||
|
||||
// Signals
|
||||
_ = c.g_signal_connect_data(
|
||||
cancel_button,
|
||||
"clicked",
|
||||
c.G_CALLBACK(>kCancelClick),
|
||||
root,
|
||||
null,
|
||||
c.G_CONNECT_DEFAULT,
|
||||
);
|
||||
_ = c.g_signal_connect_data(
|
||||
confirm_button,
|
||||
"clicked",
|
||||
c.G_CALLBACK(>kConfirmClick),
|
||||
root,
|
||||
null,
|
||||
c.G_CONNECT_DEFAULT,
|
||||
);
|
||||
|
||||
return .{ .root = view.root, .confirm_button = confirm_button, .cancel_button = cancel_button };
|
||||
}
|
||||
|
||||
fn gtkCancelClick(_: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) void {
|
||||
const self: *ClipboardConfirmation = @ptrCast(@alignCast(ud));
|
||||
c.gtk_window_destroy(@ptrCast(self.window));
|
||||
}
|
||||
|
||||
fn gtkConfirmClick(_: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) void {
|
||||
// Requeue the paste with force.
|
||||
const self: *ClipboardConfirmation = @ptrCast(@alignCast(ud));
|
||||
fn gtkChoose(dialog_: ?*gobject.Object, result: *gio.AsyncResult, ud: ?*anyopaque) callconv(.C) void {
|
||||
const dialog = gobject.ext.cast(DialogType, dialog_.?).?;
|
||||
const self: *ClipboardConfirmation = @ptrCast(@alignCast(ud.?));
|
||||
const response = dialog.chooseFinish(result);
|
||||
if (std.mem.orderZ(u8, response, "ok") == .eq) {
|
||||
self.core_surface.completeClipboardRequest(
|
||||
self.pending_req,
|
||||
self.data,
|
||||
true,
|
||||
) catch |err| {
|
||||
std.log.err("Failed to requeue clipboard request: {}", .{err});
|
||||
log.err("Failed to requeue clipboard request: {}", .{err});
|
||||
};
|
||||
|
||||
c.gtk_window_destroy(@ptrCast(self.window));
|
||||
}
|
||||
|
||||
const vfl = [_][*:0]const u8{
|
||||
"H:[cancel]-8-[confirm]-8-|",
|
||||
};
|
||||
};
|
||||
|
||||
/// The title of the window, based on the reason the prompt is being shown.
|
||||
fn titleText(req: apprt.ClipboardRequest) [:0]const u8 {
|
||||
return switch (req) {
|
||||
.paste => "Warning: Potentially Unsafe Paste",
|
||||
.osc_52_read, .osc_52_write => "Authorize Clipboard Access",
|
||||
};
|
||||
self.destroy();
|
||||
}
|
||||
|
||||
/// The text to display in the prompt window, based on the reason the prompt
|
||||
/// is being shown.
|
||||
fn promptText(req: apprt.ClipboardRequest) [:0]const u8 {
|
||||
return switch (req) {
|
||||
.paste =>
|
||||
\\Pasting this text into the terminal may be dangerous as it looks like some commands may be executed.
|
||||
,
|
||||
.osc_52_read =>
|
||||
\\An application is attempting to read from the clipboard.
|
||||
\\The current clipboard contents are shown below.
|
||||
,
|
||||
.osc_52_write =>
|
||||
\\An application is attempting to write to the clipboard.
|
||||
\\The content to write is shown below.
|
||||
,
|
||||
};
|
||||
fn gtkResponse(_: *DialogType, response: [*:0]u8, self: *ClipboardConfirmation) callconv(.C) void {
|
||||
if (std.mem.orderZ(u8, response, "ok") == .eq) {
|
||||
self.core_surface.completeClipboardRequest(
|
||||
self.pending_req,
|
||||
self.data,
|
||||
true,
|
||||
) catch |err| {
|
||||
log.err("Failed to requeue clipboard request: {}", .{err});
|
||||
};
|
||||
}
|
||||
self.destroy();
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ const adw = @import("adw");
|
||||
const gtk = @import("gtk");
|
||||
const gio = @import("gio");
|
||||
const gobject = @import("gobject");
|
||||
|
||||
const Allocator = std.mem.Allocator;
|
||||
const build_config = @import("../../build_config.zig");
|
||||
const build_options = @import("build_options");
|
||||
|
@ -53,7 +53,11 @@ const icons = [_]struct {
|
||||
},
|
||||
};
|
||||
|
||||
pub const ui_files = [_][]const u8{};
|
||||
pub const ui_files = [_][]const u8{
|
||||
"ccw-osc-52-read-12",
|
||||
"ccw-osc-52-write-12",
|
||||
"ccw-paste-12",
|
||||
};
|
||||
|
||||
pub const VersionedBlueprint = struct {
|
||||
major: u16,
|
||||
@ -66,6 +70,9 @@ pub const blueprint_files = [_]VersionedBlueprint{
|
||||
.{ .major = 1, .minor = 5, .micro = 0, .name = "prompt-title-dialog" },
|
||||
.{ .major = 1, .minor = 0, .micro = 0, .name = "menu-surface-context_menu" },
|
||||
.{ .major = 1, .minor = 0, .micro = 0, .name = "menu-window-titlebar_menu" },
|
||||
.{ .major = 1, .minor = 5, .micro = 0, .name = "ccw-osc-52-read-15" },
|
||||
.{ .major = 1, .minor = 5, .micro = 0, .name = "ccw-osc-52-write-15" },
|
||||
.{ .major = 1, .minor = 5, .micro = 0, .name = "ccw-paste-15" },
|
||||
};
|
||||
|
||||
pub fn main() !void {
|
||||
|
23
src/apprt/gtk/ui/ccw-osc-52-read-12.blp
Normal file
23
src/apprt/gtk/ui/ccw-osc-52-read-12.blp
Normal file
@ -0,0 +1,23 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
translation-domain "com.mitchellh.ghostty";
|
||||
|
||||
Adw.MessageDialog clipboard_confirmation_window {
|
||||
heading: _("Authorize Clipboard Access");
|
||||
body: _("An application is attempting to read from the clipboard. The current clipboard contents are shown below.");
|
||||
|
||||
responses [
|
||||
cancel: _("Deny") suggested,
|
||||
ok: _("Allow") destructive
|
||||
]
|
||||
|
||||
default-response: "cancel";
|
||||
close-response: "cancel";
|
||||
|
||||
extra-child: ScrolledWindow {
|
||||
width-request: 500;
|
||||
height-request: 250;
|
||||
|
||||
TextView text_view {}
|
||||
};
|
||||
}
|
28
src/apprt/gtk/ui/ccw-osc-52-read-12.ui
Normal file
28
src/apprt/gtk/ui/ccw-osc-52-read-12.ui
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
DO NOT EDIT!
|
||||
This file was @generated by blueprint-compiler. Instead, edit the
|
||||
corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
-->
|
||||
<interface domain="com.mitchellh.ghostty">
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="AdwMessageDialog" id="clipboard_confirmation_window">
|
||||
<property name="heading" translatable="yes">Authorize Clipboard Access</property>
|
||||
<property name="body" translatable="yes">An application is attempting to read from the clipboard. The current clipboard contents are shown below.</property>
|
||||
<responses>
|
||||
<response id="cancel" translatable="yes" appearance="suggested">Deny</response>
|
||||
<response id="ok" translatable="yes" appearance="destructive">Allow</response>
|
||||
</responses>
|
||||
<property name="default-response">cancel</property>
|
||||
<property name="close-response">cancel</property>
|
||||
<property name="extra-child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="width-request">500</property>
|
||||
<property name="height-request">250</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="text_view"></object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</interface>
|
23
src/apprt/gtk/ui/ccw-osc-52-read-15.blp
Normal file
23
src/apprt/gtk/ui/ccw-osc-52-read-15.blp
Normal file
@ -0,0 +1,23 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
translation-domain "com.mitchellh.ghostty";
|
||||
|
||||
Adw.AlertDialog clipboard_confirmation_window {
|
||||
heading: _("Authorize Clipboard Access");
|
||||
body: _("An application is attempting to read from the clipboard. The current clipboard contents are shown below.");
|
||||
|
||||
responses [
|
||||
cancel: _("Deny") suggested,
|
||||
ok: _("Allow") destructive
|
||||
]
|
||||
|
||||
default-response: "cancel";
|
||||
close-response: "cancel";
|
||||
|
||||
extra-child: ScrolledWindow {
|
||||
width-request: 500;
|
||||
height-request: 250;
|
||||
|
||||
TextView text_view {}
|
||||
};
|
||||
}
|
23
src/apprt/gtk/ui/ccw-osc-52-write-12.blp
Normal file
23
src/apprt/gtk/ui/ccw-osc-52-write-12.blp
Normal file
@ -0,0 +1,23 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
translation-domain "com.mitchellh.ghostty";
|
||||
|
||||
Adw.MessageDialog clipboard_confirmation_window {
|
||||
heading: _("Authorize Clipboard Access");
|
||||
body: _("An application is attempting to write to the clipboard. The current clipboard contents are shown below.");
|
||||
|
||||
responses [
|
||||
cancel: _("Deny") suggested,
|
||||
ok: _("Allow") destructive
|
||||
]
|
||||
|
||||
default-response: "cancel";
|
||||
close-response: "cancel";
|
||||
|
||||
extra-child: ScrolledWindow {
|
||||
width-request: 500;
|
||||
height-request: 250;
|
||||
|
||||
TextView text_view {}
|
||||
};
|
||||
}
|
28
src/apprt/gtk/ui/ccw-osc-52-write-12.ui
Normal file
28
src/apprt/gtk/ui/ccw-osc-52-write-12.ui
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
DO NOT EDIT!
|
||||
This file was @generated by blueprint-compiler. Instead, edit the
|
||||
corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
-->
|
||||
<interface domain="com.mitchellh.ghostty">
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="AdwMessageDialog" id="clipboard_confirmation_window">
|
||||
<property name="heading" translatable="yes">Authorize Clipboard Access</property>
|
||||
<property name="body" translatable="yes">An application is attempting to write to the clipboard. The current clipboard contents are shown below.</property>
|
||||
<responses>
|
||||
<response id="cancel" translatable="yes" appearance="suggested">Deny</response>
|
||||
<response id="ok" translatable="yes" appearance="destructive">Allow</response>
|
||||
</responses>
|
||||
<property name="default-response">cancel</property>
|
||||
<property name="close-response">cancel</property>
|
||||
<property name="extra-child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="width-request">500</property>
|
||||
<property name="height-request">250</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="text_view"></object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</interface>
|
23
src/apprt/gtk/ui/ccw-osc-52-write-15.blp
Normal file
23
src/apprt/gtk/ui/ccw-osc-52-write-15.blp
Normal file
@ -0,0 +1,23 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
translation-domain "com.mitchellh.ghostty";
|
||||
|
||||
Adw.AlertDialog clipboard_confirmation_window {
|
||||
heading: _("Authorize Clipboard Access");
|
||||
body: _("An application is attempting to write to the clipboard. The current clipboard contents are shown below.");
|
||||
|
||||
responses [
|
||||
cancel: _("Deny") suggested,
|
||||
ok: _("Allow") destructive
|
||||
]
|
||||
|
||||
default-response: "cancel";
|
||||
close-response: "cancel";
|
||||
|
||||
extra-child: ScrolledWindow {
|
||||
width-request: 500;
|
||||
height-request: 250;
|
||||
|
||||
TextView text_view {}
|
||||
};
|
||||
}
|
23
src/apprt/gtk/ui/ccw-paste-12.blp
Normal file
23
src/apprt/gtk/ui/ccw-paste-12.blp
Normal file
@ -0,0 +1,23 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
translation-domain "com.mitchellh.ghostty";
|
||||
|
||||
Adw.MessageDialog clipboard_confirmation_window {
|
||||
heading: _("Warning: Potentially Unsafe Paste");
|
||||
body: _("Pasting this text into the terminal may be dangerous as it looks like some commands may be executed.");
|
||||
|
||||
responses [
|
||||
cancel: _("Cancel") suggested,
|
||||
ok: _("Paste") destructive
|
||||
]
|
||||
|
||||
default-response: "cancel";
|
||||
close-response: "cancel";
|
||||
|
||||
extra-child: ScrolledWindow {
|
||||
width-request: 500;
|
||||
height-request: 250;
|
||||
|
||||
TextView text_view {}
|
||||
};
|
||||
}
|
28
src/apprt/gtk/ui/ccw-paste-12.ui
Normal file
28
src/apprt/gtk/ui/ccw-paste-12.ui
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
DO NOT EDIT!
|
||||
This file was @generated by blueprint-compiler. Instead, edit the
|
||||
corresponding .blp file and regenerate this file with blueprint-compiler.
|
||||
-->
|
||||
<interface domain="com.mitchellh.ghostty">
|
||||
<requires lib="gtk" version="4.0"/>
|
||||
<object class="AdwMessageDialog" id="clipboard_confirmation_window">
|
||||
<property name="heading" translatable="yes">Warning: Potentially Unsafe Paste</property>
|
||||
<property name="body" translatable="yes">Pasting this text into the terminal may be dangerous as it looks like some commands may be executed.</property>
|
||||
<responses>
|
||||
<response id="cancel" translatable="yes" appearance="suggested">Cancel</response>
|
||||
<response id="ok" translatable="yes" appearance="destructive">Paste</response>
|
||||
</responses>
|
||||
<property name="default-response">cancel</property>
|
||||
<property name="close-response">cancel</property>
|
||||
<property name="extra-child">
|
||||
<object class="GtkScrolledWindow">
|
||||
<property name="width-request">500</property>
|
||||
<property name="height-request">250</property>
|
||||
<child>
|
||||
<object class="GtkTextView" id="text_view"></object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
</interface>
|
23
src/apprt/gtk/ui/ccw-paste-15.blp
Normal file
23
src/apprt/gtk/ui/ccw-paste-15.blp
Normal file
@ -0,0 +1,23 @@
|
||||
using Gtk 4.0;
|
||||
using Adw 1;
|
||||
translation-domain "com.mitchellh.ghostty";
|
||||
|
||||
Adw.AlertDialog clipboard_confirmation_window {
|
||||
heading: _("Warning: Potentially Unsafe Paste");
|
||||
body: _("Pasting this text into the terminal may be dangerous as it looks like some commands may be executed.");
|
||||
|
||||
responses [
|
||||
cancel: _("Cancel") suggested,
|
||||
ok: _("Paste") destructive
|
||||
]
|
||||
|
||||
default-response: "cancel";
|
||||
close-response: "cancel";
|
||||
|
||||
extra-child: ScrolledWindow {
|
||||
width-request: 500;
|
||||
height-request: 250;
|
||||
|
||||
TextView text_view {}
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user