core: use ClipboardRequestType instead of ClipboardPromptReason

Instead of making a separate enum that must be translated from the
ClipboardRequest type, simply re-use ClipboardRequest to determine the
clipboard confirmation reason.
This commit is contained in:
Gregory Anders
2023-11-10 18:06:53 -06:00
parent 2a64180ebd
commit 98b43007a0
9 changed files with 94 additions and 136 deletions

View File

@ -36,10 +36,10 @@ typedef enum {
} ghostty_clipboard_e; } ghostty_clipboard_e;
typedef enum { typedef enum {
GHOSTTY_CLIPBOARD_PROMPT_UNSAFE = 1, GHOSTTY_CLIPBOARD_REQUEST_PASTE,
GHOSTTY_CLIPBOARD_PROMPT_READ = 2, GHOSTTY_CLIPBOARD_REQUEST_OSC_52_READ,
GHOSTTY_CLIPBOARD_PROMPT_WRITE = 3, GHOSTTY_CLIPBOARD_REQUEST_OSC_52_WRITE,
} ghostty_clipboard_prompt_reason_e; } ghostty_clipboard_request_e;
typedef enum { typedef enum {
GHOSTTY_SPLIT_RIGHT, GHOSTTY_SPLIT_RIGHT,
@ -346,7 +346,7 @@ typedef void (*ghostty_runtime_set_title_cb)(void *, const char *);
typedef void (*ghostty_runtime_set_mouse_shape_cb)(void *, ghostty_mouse_shape_e); typedef void (*ghostty_runtime_set_mouse_shape_cb)(void *, ghostty_mouse_shape_e);
typedef void (*ghostty_runtime_set_mouse_visibility_cb)(void *, bool); typedef void (*ghostty_runtime_set_mouse_visibility_cb)(void *, bool);
typedef void (*ghostty_runtime_read_clipboard_cb)(void *, ghostty_clipboard_e, void *); typedef void (*ghostty_runtime_read_clipboard_cb)(void *, ghostty_clipboard_e, void *);
typedef void (*ghostty_runtime_confirm_read_clipboard_cb)(void *, const char*, void *, ghostty_clipboard_prompt_reason_e); typedef void (*ghostty_runtime_confirm_read_clipboard_cb)(void *, const char*, void *, ghostty_clipboard_request_e);
typedef void (*ghostty_runtime_write_clipboard_cb)(void *, const char *, ghostty_clipboard_e, bool); typedef void (*ghostty_runtime_write_clipboard_cb)(void *, const char *, ghostty_clipboard_e, bool);
typedef void (*ghostty_runtime_new_split_cb)(void *, ghostty_split_direction_e, ghostty_surface_config_s); typedef void (*ghostty_runtime_new_split_cb)(void *, ghostty_split_direction_e, ghostty_surface_config_s);
typedef void (*ghostty_runtime_new_tab_cb)(void *, ghostty_surface_config_s); typedef void (*ghostty_runtime_new_tab_cb)(void *, ghostty_surface_config_s);

View File

@ -11,14 +11,14 @@ class ClipboardConfirmationController: NSWindowController {
let surface: ghostty_surface_t let surface: ghostty_surface_t
let contents: String let contents: String
let reason: Ghostty.ClipboardPromptReason let request: Ghostty.ClipboardRequest
let state: UnsafeMutableRawPointer? let state: UnsafeMutableRawPointer?
weak private var delegate: ClipboardConfirmationViewDelegate? = nil weak private var delegate: ClipboardConfirmationViewDelegate? = nil
init(surface: ghostty_surface_t, contents: String, reason: Ghostty.ClipboardPromptReason, state: UnsafeMutableRawPointer?, delegate: ClipboardConfirmationViewDelegate) { init(surface: ghostty_surface_t, contents: String, request: Ghostty.ClipboardRequest, state: UnsafeMutableRawPointer?, delegate: ClipboardConfirmationViewDelegate) {
self.surface = surface self.surface = surface
self.contents = contents self.contents = contents
self.reason = reason self.request = request
self.state = state self.state = state
self.delegate = delegate self.delegate = delegate
super.init(window: nil) super.init(window: nil)
@ -33,16 +33,16 @@ class ClipboardConfirmationController: NSWindowController {
override func windowDidLoad() { override func windowDidLoad() {
guard let window = window else { return } guard let window = window else { return }
switch (reason) { switch (request) {
case .unsafe: case .paste:
window.title = "Warning: Potentially Unsafe Paste" window.title = "Warning: Potentially Unsafe Paste"
case .read, .write: case .osc_52_read, .osc_52_write:
window.title = "Authorize Clipboard Access" window.title = "Authorize Clipboard Access"
} }
window.contentView = NSHostingView(rootView: ClipboardConfirmationView( window.contentView = NSHostingView(rootView: ClipboardConfirmationView(
contents: contents, contents: contents,
reason: reason, request: request,
delegate: delegate delegate: delegate
)) ))
} }

View File

@ -2,7 +2,7 @@ import SwiftUI
/// This delegate is notified of the completion result of the clipboard confirmation dialog. /// This delegate is notified of the completion result of the clipboard confirmation dialog.
protocol ClipboardConfirmationViewDelegate: AnyObject { protocol ClipboardConfirmationViewDelegate: AnyObject {
func clipboardConfirmationComplete(_ action: ClipboardConfirmationView.Action, _ reason: Ghostty.ClipboardPromptReason) func clipboardConfirmationComplete(_ action: ClipboardConfirmationView.Action, _ request: Ghostty.ClipboardRequest)
} }
/// The SwiftUI view for showing a clipboard confirmation dialog. /// The SwiftUI view for showing a clipboard confirmation dialog.
@ -11,18 +11,16 @@ struct ClipboardConfirmationView: View {
case cancel case cancel
case confirm case confirm
static func text(_ action: Action, _ reason: Ghostty.ClipboardPromptReason) -> String { static func text(_ action: Action, _ reason: Ghostty.ClipboardRequest) -> String {
switch (action) { switch (action, reason) {
case .cancel: case (.cancel, .paste):
switch (reason) { return "Cancel"
case .unsafe: return "Cancel" case (.cancel, .osc_52_read), (.cancel, .osc_52_write):
case .read, .write: return "Deny" return "Deny"
} case (.confirm, .paste):
case .confirm: return "Paste"
switch (reason) { case (.confirm, .osc_52_read), (.confirm, .osc_52_write):
case .unsafe: return "Paste" return "Allow"
case .read, .write: return "Allow"
}
} }
} }
} }
@ -30,8 +28,8 @@ struct ClipboardConfirmationView: View {
/// The contents of the paste. /// The contents of the paste.
let contents: String let contents: String
/// The reason for displaying the view /// The type of the clipboard request
let reason: Ghostty.ClipboardPromptReason let request: Ghostty.ClipboardRequest
/// Optional delegate to get results. If this is nil, then this view will never close on its own. /// Optional delegate to get results. If this is nil, then this view will never close on its own.
weak var delegate: ClipboardConfirmationViewDelegate? = nil weak var delegate: ClipboardConfirmationViewDelegate? = nil
@ -45,7 +43,7 @@ struct ClipboardConfirmationView: View {
.padding() .padding()
.frame(alignment: .center) .frame(alignment: .center)
Text(reason.text()) Text(request.text())
.frame(maxWidth: .infinity, alignment: .leading) .frame(maxWidth: .infinity, alignment: .leading)
.padding() .padding()
} }
@ -57,9 +55,9 @@ struct ClipboardConfirmationView: View {
HStack { HStack {
Spacer() Spacer()
Button(Action.text(.cancel, reason)) { onCancel() } Button(Action.text(.cancel, request)) { onCancel() }
.keyboardShortcut(.cancelAction) .keyboardShortcut(.cancelAction)
Button(Action.text(.confirm, reason)) { onPaste() } Button(Action.text(.confirm, request)) { onPaste() }
.keyboardShortcut(.defaultAction) .keyboardShortcut(.defaultAction)
Spacer() Spacer()
} }
@ -68,10 +66,10 @@ struct ClipboardConfirmationView: View {
} }
private func onCancel() { private func onCancel() {
delegate?.clipboardConfirmationComplete(.cancel, reason) delegate?.clipboardConfirmationComplete(.cancel, request)
} }
private func onPaste() { private func onPaste() {
delegate?.clipboardConfirmationComplete(.confirm, reason) delegate?.clipboardConfirmationComplete(.confirm, request)
} }
} }

View File

@ -348,7 +348,7 @@ class TerminalController: NSWindowController, NSWindowDelegate,
//MARK: - Clipboard Confirmation //MARK: - Clipboard Confirmation
func clipboardConfirmationComplete(_ action: ClipboardConfirmationView.Action, _ reason: Ghostty.ClipboardPromptReason) { func clipboardConfirmationComplete(_ action: ClipboardConfirmationView.Action, _ request: Ghostty.ClipboardRequest) {
// End our clipboard confirmation no matter what // End our clipboard confirmation no matter what
guard let cc = self.clipboardConfirmation else { return } guard let cc = self.clipboardConfirmation else { return }
self.clipboardConfirmation = nil self.clipboardConfirmation = nil
@ -358,13 +358,13 @@ class TerminalController: NSWindowController, NSWindowDelegate,
window?.endSheet(ccWindow) window?.endSheet(ccWindow)
} }
switch (reason) { switch (request) {
case .write: case .osc_52_write:
guard case .confirm = action else { break } guard case .confirm = action else { break }
let pb = NSPasteboard.general let pb = NSPasteboard.general
pb.declareTypes([.string], owner: nil) pb.declareTypes([.string], owner: nil)
pb.setString(cc.contents, forType: .string) pb.setString(cc.contents, forType: .string)
case .read, .unsafe: case .osc_52_read, .paste:
let str: String let str: String
switch (action) { switch (action) {
case .cancel: case .cancel:
@ -448,7 +448,7 @@ class TerminalController: NSWindowController, NSWindowDelegate,
// Check whether we use non-native fullscreen // Check whether we use non-native fullscreen
guard let str = notification.userInfo?[Ghostty.Notification.ConfirmClipboardStrKey] as? String else { return } guard let str = notification.userInfo?[Ghostty.Notification.ConfirmClipboardStrKey] as? String else { return }
guard let state = notification.userInfo?[Ghostty.Notification.ConfirmClipboardStateKey] as? UnsafeMutableRawPointer? else { return } guard let state = notification.userInfo?[Ghostty.Notification.ConfirmClipboardStateKey] as? UnsafeMutableRawPointer? else { return }
guard let reason = notification.userInfo?[Ghostty.Notification.ConfirmClipboardReasonKey] as? Ghostty.ClipboardPromptReason else { return } guard let request = notification.userInfo?[Ghostty.Notification.ConfirmClipboardRequestKey] as? Ghostty.ClipboardRequest else { return }
// If we already have a clipboard confirmation view up, we ignore this request. // If we already have a clipboard confirmation view up, we ignore this request.
// This shouldn't be possible... // This shouldn't be possible...
@ -461,7 +461,7 @@ class TerminalController: NSWindowController, NSWindowDelegate,
self.clipboardConfirmation = ClipboardConfirmationController( self.clipboardConfirmation = ClipboardConfirmationController(
surface: surface, surface: surface,
contents: str, contents: str,
reason: reason, request: request,
state: state, state: state,
delegate: self delegate: self
) )

View File

@ -150,7 +150,7 @@ extension Ghostty {
set_mouse_shape_cb: { userdata, shape in AppState.setMouseShape(userdata, shape: shape) }, set_mouse_shape_cb: { userdata, shape in AppState.setMouseShape(userdata, shape: shape) },
set_mouse_visibility_cb: { userdata, visible in AppState.setMouseVisibility(userdata, visible: visible) }, set_mouse_visibility_cb: { userdata, visible in AppState.setMouseVisibility(userdata, visible: visible) },
read_clipboard_cb: { userdata, loc, state in AppState.readClipboard(userdata, location: loc, state: state) }, read_clipboard_cb: { userdata, loc, state in AppState.readClipboard(userdata, location: loc, state: state) },
confirm_read_clipboard_cb: { userdata, str, state, reason in AppState.confirmReadClipboard(userdata, string: str, state: state, reason: reason ) }, confirm_read_clipboard_cb: { userdata, str, state, request in AppState.confirmReadClipboard(userdata, string: str, state: state, request: request ) },
write_clipboard_cb: { userdata, str, loc, confirm in AppState.writeClipboard(userdata, string: str, location: loc, confirm: confirm) }, write_clipboard_cb: { userdata, str, loc, confirm in AppState.writeClipboard(userdata, string: str, location: loc, confirm: confirm) },
new_split_cb: { userdata, direction, surfaceConfig in AppState.newSplit(userdata, direction: direction, config: surfaceConfig) }, new_split_cb: { userdata, direction, surfaceConfig in AppState.newSplit(userdata, direction: direction, config: surfaceConfig) },
new_tab_cb: { userdata, surfaceConfig in AppState.newTab(userdata, config: surfaceConfig) }, new_tab_cb: { userdata, surfaceConfig in AppState.newTab(userdata, config: surfaceConfig) },
@ -434,18 +434,18 @@ extension Ghostty {
_ userdata: UnsafeMutableRawPointer?, _ userdata: UnsafeMutableRawPointer?,
string: UnsafePointer<CChar>?, string: UnsafePointer<CChar>?,
state: UnsafeMutableRawPointer?, state: UnsafeMutableRawPointer?,
reason: ghostty_clipboard_prompt_reason_e request: ghostty_clipboard_request_e
) { ) {
guard let surface = self.surfaceUserdata(from: userdata) else { return } guard let surface = self.surfaceUserdata(from: userdata) else { return }
guard let valueStr = String(cString: string!, encoding: .utf8) else { return } guard let valueStr = String(cString: string!, encoding: .utf8) else { return }
guard let reason = Ghostty.ClipboardPromptReason.from(reason: reason) else { return } guard let request = Ghostty.ClipboardRequest.from(request: request) else { return }
NotificationCenter.default.post( NotificationCenter.default.post(
name: Notification.confirmClipboard, name: Notification.confirmClipboard,
object: surface, object: surface,
userInfo: [ userInfo: [
Notification.ConfirmClipboardStrKey: valueStr, Notification.ConfirmClipboardStrKey: valueStr,
Notification.ConfirmClipboardStateKey: state as Any, Notification.ConfirmClipboardStateKey: state as Any,
Notification.ConfirmClipboardReasonKey: reason, Notification.ConfirmClipboardRequestKey: request,
] ]
) )
} }
@ -478,7 +478,7 @@ extension Ghostty {
object: surface, object: surface,
userInfo: [ userInfo: [
Notification.ConfirmClipboardStrKey: valueStr, Notification.ConfirmClipboardStrKey: valueStr,
Notification.ConfirmClipboardReasonKey: Ghostty.ClipboardPromptReason.write, Notification.ConfirmClipboardRequestKey: Ghostty.ClipboardRequest.osc_52_write,
] ]
) )
} }

View File

@ -95,29 +95,30 @@ extension Ghostty {
} }
} }
/// The reason a clipboard prompt is shown to the user /// The type of a clipboard request
enum ClipboardPromptReason { enum ClipboardRequest {
/// An unsafe paste may cause commands to be executed /// A direct paste of clipboard contents
case unsafe case paste
/// An application is attempting to read from the clipboard /// An application is attempting to read from the clipboard using OSC 52
case read case osc_52_read
/// An applciation is attempting to write to the clipboard /// An applciation is attempting to write to the clipboard using OSC 52
case write case osc_52_write
/// The text to show in the clipboard confirmation prompt for a given request type
func text() -> String { func text() -> String {
switch (self) { switch (self) {
case .unsafe: case .paste:
return """ return """
Pasting this text to the terminal may be dangerous as it looks like some commands may be executed. Pasting this text to the terminal may be dangerous as it looks like some commands may be executed.
""" """
case .read: case .osc_52_read:
return """ return """
An application is attempting to read from the clipboard. An application is attempting to read from the clipboard.
The current clipboard contents are shown below. The current clipboard contents are shown below.
""" """
case .write: case .osc_52_write:
return """ return """
An application is attempting to write to the clipboard. An application is attempting to write to the clipboard.
The content to write is shown below. The content to write is shown below.
@ -125,29 +126,18 @@ extension Ghostty {
} }
} }
static func from(reason: ghostty_clipboard_prompt_reason_e) -> ClipboardPromptReason? { static func from(request: ghostty_clipboard_request_e) -> ClipboardRequest? {
switch (reason) { switch (request) {
case GHOSTTY_CLIPBOARD_PROMPT_UNSAFE: case GHOSTTY_CLIPBOARD_REQUEST_PASTE:
return .unsafe return .paste
case GHOSTTY_CLIPBOARD_PROMPT_READ: case GHOSTTY_CLIPBOARD_REQUEST_OSC_52_READ:
return .read return .osc_52_read
case GHOSTTY_CLIPBOARD_PROMPT_WRITE: case GHOSTTY_CLIPBOARD_REQUEST_OSC_52_WRITE:
return .write return .osc_52_write
default: default:
return nil return nil
} }
} }
func toNative() -> ghostty_clipboard_prompt_reason_e {
switch (self) {
case .unsafe:
return GHOSTTY_CLIPBOARD_PROMPT_UNSAFE
case .read:
return GHOSTTY_CLIPBOARD_PROMPT_READ
case .write:
return GHOSTTY_CLIPBOARD_PROMPT_WRITE
}
}
} }
} }
@ -200,7 +190,7 @@ extension Ghostty.Notification {
static let confirmClipboard = Notification.Name("com.mitchellh.ghostty.confirmClipboard") static let confirmClipboard = Notification.Name("com.mitchellh.ghostty.confirmClipboard")
static let ConfirmClipboardStrKey = confirmClipboard.rawValue + ".str" static let ConfirmClipboardStrKey = confirmClipboard.rawValue + ".str"
static let ConfirmClipboardStateKey = confirmClipboard.rawValue + ".state" static let ConfirmClipboardStateKey = confirmClipboard.rawValue + ".state"
static let ConfirmClipboardReasonKey = confirmClipboard.rawValue + ".reason" static let ConfirmClipboardRequestKey = confirmClipboard.rawValue + ".request"
/// Notification sent to the active split view to resize the split. /// Notification sent to the active split view to resize the split.
static let didResizeSplit = Notification.Name("com.mitchellh.ghostty.didResizeSplit") static let didResizeSplit = Notification.Name("com.mitchellh.ghostty.didResizeSplit")

View File

@ -17,7 +17,6 @@ const CoreInspector = @import("../inspector/main.zig").Inspector;
const CoreSurface = @import("../Surface.zig"); const CoreSurface = @import("../Surface.zig");
const configpkg = @import("../config.zig"); const configpkg = @import("../config.zig");
const Config = configpkg.Config; const Config = configpkg.Config;
const ClipboardPromptReason = @import("../apprt/structs.zig").ClipboardPromptReason;
const log = std.log.scoped(.embedded_window); const log = std.log.scoped(.embedded_window);
@ -69,7 +68,7 @@ pub const App = struct {
SurfaceUD, SurfaceUD,
[*:0]const u8, [*:0]const u8,
*apprt.ClipboardRequest, *apprt.ClipboardRequest,
ClipboardPromptReason, apprt.ClipboardRequestType,
) callconv(.C) void, ) callconv(.C) void,
/// Write the clipboard value. /// Write the clipboard value.
@ -508,6 +507,8 @@ pub const Surface = struct {
) void { ) void {
const alloc = self.app.core_app.alloc; const alloc = self.app.core_app.alloc;
const request_type = @as(apprt.ClipboardRequestType, state.*);
// Attempt to complete the request, but we may request // Attempt to complete the request, but we may request
// confirmation. // confirmation.
self.core_surface.completeClipboardRequest( self.core_surface.completeClipboardRequest(
@ -515,22 +516,14 @@ pub const Surface = struct {
str, str,
confirmed, confirmed,
) catch |err| switch (err) { ) catch |err| switch (err) {
error.UnsafePaste => { error.UnsafePaste,
error.UnauthorizedPaste,
=> {
self.app.opts.confirm_read_clipboard( self.app.opts.confirm_read_clipboard(
self.opts.userdata, self.opts.userdata,
str.ptr, str.ptr,
state, state,
.unsafe, request_type,
);
return;
},
error.UnauthorizedPaste => {
self.app.opts.confirm_read_clipboard(
self.opts.userdata,
str.ptr,
state,
.read,
); );
return; return;

View File

@ -4,9 +4,8 @@ const ClipboardConfirmation = @This();
const std = @import("std"); const std = @import("std");
const Allocator = std.mem.Allocator; const Allocator = std.mem.Allocator;
const apprt = @import("../../apprt.zig");
const CoreSurface = @import("../../Surface.zig"); const CoreSurface = @import("../../Surface.zig");
const ClipboardRequest = @import("../structs.zig").ClipboardRequest;
const ClipboardPromptReason = @import("../structs.zig").ClipboardPromptReason;
const App = @import("App.zig"); const App = @import("App.zig");
const View = @import("View.zig"); const View = @import("View.zig");
const c = @import("c.zig"); const c = @import("c.zig");
@ -19,14 +18,13 @@ view: PrimaryView,
data: [:0]u8, data: [:0]u8,
core_surface: CoreSurface, core_surface: CoreSurface,
pending_req: ClipboardRequest, pending_req: apprt.ClipboardRequest,
reason: ClipboardPromptReason,
pub fn create( pub fn create(
app: *App, app: *App,
data: []const u8, data: []const u8,
core_surface: CoreSurface, core_surface: CoreSurface,
request: ClipboardRequest, request: apprt.ClipboardRequest,
) !void { ) !void {
if (app.clipboard_confirmation_window != null) return error.WindowAlreadyExists; if (app.clipboard_confirmation_window != null) return error.WindowAlreadyExists;
@ -34,18 +32,11 @@ pub fn create(
const self = try alloc.create(ClipboardConfirmation); const self = try alloc.create(ClipboardConfirmation);
errdefer alloc.destroy(self); errdefer alloc.destroy(self);
const reason: ClipboardPromptReason = switch (request) {
.paste => .unsafe,
.osc_52_read => .read,
.osc_52_write => .write,
};
try self.init( try self.init(
app, app,
data, data,
core_surface, core_surface,
request, request,
reason,
); );
app.clipboard_confirmation_window = self; app.clipboard_confirmation_window = self;
@ -64,14 +55,13 @@ fn init(
app: *App, app: *App,
data: []const u8, data: []const u8,
core_surface: CoreSurface, core_surface: CoreSurface,
request: ClipboardRequest, request: apprt.ClipboardRequest,
reason: ClipboardPromptReason,
) !void { ) !void {
// Create the window // Create the window
const window = c.gtk_window_new(); const window = c.gtk_window_new();
const gtk_window: *c.GtkWindow = @ptrCast(window); const gtk_window: *c.GtkWindow = @ptrCast(window);
errdefer c.gtk_window_destroy(gtk_window); errdefer c.gtk_window_destroy(gtk_window);
c.gtk_window_set_title(gtk_window, titleText(reason)); c.gtk_window_set_title(gtk_window, titleText(request));
c.gtk_window_set_default_size(gtk_window, 550, 275); c.gtk_window_set_default_size(gtk_window, 550, 275);
c.gtk_window_set_resizable(gtk_window, 0); c.gtk_window_set_resizable(gtk_window, 0);
_ = c.g_signal_connect_data( _ = c.g_signal_connect_data(
@ -91,7 +81,6 @@ fn init(
.data = try app.core_app.alloc.dupeZ(u8, data), .data = try app.core_app.alloc.dupeZ(u8, data),
.core_surface = core_surface, .core_surface = core_surface,
.pending_req = request, .pending_req = request,
.reason = reason,
}; };
// Show the window // Show the window
@ -116,7 +105,7 @@ const PrimaryView = struct {
pub fn init(root: *ClipboardConfirmation, data: []const u8) !PrimaryView { pub fn init(root: *ClipboardConfirmation, data: []const u8) !PrimaryView {
// All our widgets // All our widgets
const label = c.gtk_label_new(promptText(root.reason)); const label = c.gtk_label_new(promptText(root.pending_req));
const buf = unsafeBuffer(data); const buf = unsafeBuffer(data);
defer c.g_object_unref(buf); defer c.g_object_unref(buf);
const buttons = try ButtonsView.init(root); const buttons = try ButtonsView.init(root);
@ -168,10 +157,9 @@ const ButtonsView = struct {
root: *c.GtkWidget, root: *c.GtkWidget,
pub fn init(root: *ClipboardConfirmation) !ButtonsView { pub fn init(root: *ClipboardConfirmation) !ButtonsView {
const cancel_text, const confirm_text = switch (root.reason) { const cancel_text, const confirm_text = switch (root.pending_req) {
.unsafe => .{ "Cancel", "Paste" }, .paste => .{ "Cancel", "Paste" },
.read, .write => .{ "Deny", "Allow" }, .osc_52_read, .osc_52_write => .{ "Deny", "Allow" },
_ => unreachable,
}; };
const cancel_button = c.gtk_button_new_with_label(cancel_text); const cancel_button = c.gtk_button_new_with_label(cancel_text);
@ -235,29 +223,27 @@ const ButtonsView = struct {
}; };
/// The title of the window, based on the reason the prompt is being shown. /// The title of the window, based on the reason the prompt is being shown.
fn titleText(reason: ClipboardPromptReason) [:0]const u8 { fn titleText(req: apprt.ClipboardRequest) [:0]const u8 {
return switch (reason) { return switch (req) {
.unsafe => "Warning: Potentially Unsafe Paste", .paste => "Warning: Potentially Unsafe Paste",
.read, .write => "Authorize Clipboard Access", .osc_52_read, .osc_52_write => "Authorize Clipboard Access",
_ => unreachable,
}; };
} }
/// The text to display in the prompt window, based on the reason the prompt /// The text to display in the prompt window, based on the reason the prompt
/// is being shown. /// is being shown.
fn promptText(reason: ClipboardPromptReason) [:0]const u8 { fn promptText(req: apprt.ClipboardRequest) [:0]const u8 {
return switch (reason) { return switch (req) {
.unsafe => .paste =>
\\Pasting this text into the terminal may be dangerous as it looks like some commands may be executed. \\Pasting this text into the terminal may be dangerous as it looks like some commands may be executed.
, ,
.read => .osc_52_read =>
\\An appliclication is attempting to read from the clipboard. \\An appliclication is attempting to read from the clipboard.
\\The current clipboard contents are shown below. \\The current clipboard contents are shown below.
, ,
.write => .osc_52_write =>
\\An application is attempting to write to the clipboard. \\An application is attempting to write to the clipboard.
\\The content to write is shown below. \\The content to write is shown below.
, ,
_ => unreachable,
}; };
} }

View File

@ -32,9 +32,15 @@ pub const Clipboard = enum(u1) {
selection = 1, // also known as the "primary" clipboard selection = 1, // also known as the "primary" clipboard
}; };
pub const ClipboardRequestType = enum(u8) {
paste,
osc_52_read,
osc_52_write,
};
/// Clipboard request. This is used to request clipboard contents and must /// Clipboard request. This is used to request clipboard contents and must
/// be sent as a response to a ClipboardRequest event. /// be sent as a response to a ClipboardRequest event.
pub const ClipboardRequest = union(enum) { pub const ClipboardRequest = union(ClipboardRequestType) {
/// A direct paste of clipboard contents. /// A direct paste of clipboard contents.
paste: void, paste: void,
@ -44,18 +50,3 @@ pub const ClipboardRequest = union(enum) {
/// A request to write clipboard contents via OSC 52. /// A request to write clipboard contents via OSC 52.
osc_52_write: Clipboard, osc_52_write: Clipboard,
}; };
/// The reason for displaying a clipboard prompt to the user
pub const ClipboardPromptReason = enum(i32) {
/// For pasting data only. Pasted data contains potentially unsafe
/// characters
unsafe = 1,
/// The user must authorize the application to read from the clipboard
read = 2,
/// The user must authorize the application to write to the clipboard
write = 3,
_,
};