diff --git a/src/apprt/gtk/class/application.zig b/src/apprt/gtk/class/application.zig index 6a07cab84..403f94599 100644 --- a/src/apprt/gtk/class/application.zig +++ b/src/apprt/gtk/class/application.zig @@ -733,6 +733,7 @@ pub const Application = extern struct { .toggle_split_zoom => return Action.toggleSplitZoom(target), .show_on_screen_keyboard => return Action.showOnScreenKeyboard(target), .command_finished => return Action.commandFinished(target, value), + .readonly => return Action.setReadonly(target, value), .start_search => Action.startSearch(target, value), .end_search => Action.endSearch(target), @@ -753,7 +754,6 @@ pub const Application = extern struct { .check_for_updates, .undo, .redo, - .readonly, => { log.warn("unimplemented action={}", .{action}); return false; @@ -2678,6 +2678,15 @@ const Action = struct { } } + pub fn setReadonly(target: apprt.Target, value: apprt.Action.Value(.readonly)) bool { + switch (target) { + .app => return false, + .surface => |surface| { + return surface.rt_surface.gobj().setReadonly(value); + }, + } + } + pub fn keySequence(target: apprt.Target, value: apprt.Action.Value(.key_sequence)) bool { switch (target) { .app => { diff --git a/src/apprt/gtk/class/surface.zig b/src/apprt/gtk/class/surface.zig index 5c3bf18b6..7a1aa4326 100644 --- a/src/apprt/gtk/class/surface.zig +++ b/src/apprt/gtk/class/surface.zig @@ -400,6 +400,25 @@ pub const Surface = extern struct { }, ); }; + + pub const readonly = struct { + pub const name = "readonly"; + const impl = gobject.ext.defineProperty( + name, + Self, + bool, + .{ + .default = false, + .accessor = gobject.ext.typedAccessor( + Self, + bool, + .{ + .getter = getReadonly, + }, + ), + }, + ); + }; }; pub const signals = struct { @@ -1106,6 +1125,20 @@ pub const Surface = extern struct { return true; } + /// Get the readonly state from the core surface. + pub fn getReadonly(self: *Self) bool { + const priv: *Private = self.private(); + const surface = priv.core_surface orelse return false; + return surface.readonly; + } + + /// Notify anyone interested that the readonly status has changed. + pub fn setReadonly(self: *Self, _: apprt.Action.Value(.readonly)) bool { + self.as(gobject.Object).notifyByPspec(properties.readonly.impl.param_spec); + + return true; + } + /// Key press event (press or release). /// /// At a high level, we want to construct an `input.KeyEvent` and @@ -3480,6 +3513,7 @@ pub const Surface = extern struct { properties.@"title-override".impl, properties.zoom.impl, properties.@"is-split".impl, + properties.readonly.impl, // For Gtk.Scrollable properties.hadjustment.impl, diff --git a/src/apprt/gtk/css/style.css b/src/apprt/gtk/css/style.css index f5491b7de..9c0f115f1 100644 --- a/src/apprt/gtk/css/style.css +++ b/src/apprt/gtk/css/style.css @@ -134,6 +134,16 @@ label.resize-overlay { border-style: solid; } +.surface .readonly_overlay { + /* Should be the equivalent of the following SwiftUI color: */ + /* Color(hue: 0.08, saturation: 0.5, brightness: 0.8) */ + color: hsl(25 50 75); + padding: 8px 8px 8px 8px; + margin: 8px 8px 8px 8px; + border-radius: 6px 6px 6px 6px; + outline-style: solid; + outline-width: 1px; +} /* * Command Palette */ diff --git a/src/apprt/gtk/ui/1.2/surface.blp b/src/apprt/gtk/ui/1.2/surface.blp index a594ba98f..dd6ded5de 100644 --- a/src/apprt/gtk/ui/1.2/surface.blp +++ b/src/apprt/gtk/ui/1.2/surface.blp @@ -71,6 +71,39 @@ Overlay terminal_page { } }; + [overlay] + Revealer { + reveal-child: bind template.readonly; + transition-type: crossfade; + transition-duration: 500; + // Revealers take up the full size, we need this to not capture events. + can-focus: false; + can-target: false; + focusable: false; + + Box readonly_overlay { + styles [ + "readonly_overlay", + ] + + // TODO: the tooltip doesn't actually work, but keep it here for now so + // that we can get the tooltip text translated. + has-tooltip: true; + tooltip-text: _("This terminal is in read-only mode. You can still view, select, and scroll through the content, but no input events will be sent to the running application."); + halign: end; + valign: start; + spacing: 6; + + Image { + icon-name: "changes-prevent-symbolic"; + } + + Label { + label: _("Read-only"); + } + } + } + [overlay] ProgressBar progress_bar_overlay { styles [