mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
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:
@ -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);
|
||||||
|
@ -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
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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,
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -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")
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -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,
|
|
||||||
|
|
||||||
_,
|
|
||||||
};
|
|
||||||
|
Reference in New Issue
Block a user