apprt/gtk-ng: action accelerators, clean up explicit error sets (#8146)
Not a lot here, ported the action accelerators which was small. Besides that, cleaned up a bunch of explicit error sets which allowed us to remove some forwarded errors because they're so unlikely, and could unify others.pull/8148/head
commit
37bac094c7
|
|
@ -15,6 +15,7 @@ const apprt = @import("../../../apprt.zig");
|
||||||
const cgroup = @import("../cgroup.zig");
|
const cgroup = @import("../cgroup.zig");
|
||||||
const CoreApp = @import("../../../App.zig");
|
const CoreApp = @import("../../../App.zig");
|
||||||
const configpkg = @import("../../../config.zig");
|
const configpkg = @import("../../../config.zig");
|
||||||
|
const input = @import("../../../input.zig");
|
||||||
const internal_os = @import("../../../os/main.zig");
|
const internal_os = @import("../../../os/main.zig");
|
||||||
const systemd = @import("../../../os/systemd.zig");
|
const systemd = @import("../../../os/systemd.zig");
|
||||||
const terminal = @import("../../../terminal/main.zig");
|
const terminal = @import("../../../terminal/main.zig");
|
||||||
|
|
@ -24,6 +25,7 @@ const CoreConfig = configpkg.Config;
|
||||||
const CoreSurface = @import("../../../Surface.zig");
|
const CoreSurface = @import("../../../Surface.zig");
|
||||||
|
|
||||||
const ext = @import("../ext.zig");
|
const ext = @import("../ext.zig");
|
||||||
|
const key = @import("../key.zig");
|
||||||
const adw_version = @import("../adw_version.zig");
|
const adw_version = @import("../adw_version.zig");
|
||||||
const gtk_version = @import("../gtk_version.zig");
|
const gtk_version = @import("../gtk_version.zig");
|
||||||
const winprotopkg = @import("../winproto.zig");
|
const winprotopkg = @import("../winproto.zig");
|
||||||
|
|
@ -861,6 +863,61 @@ pub const Application = extern struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn syncActionAccelerators(self: *Self) void {
|
||||||
|
self.syncActionAccelerator("app.quit", .{ .quit = {} });
|
||||||
|
self.syncActionAccelerator("app.open-config", .{ .open_config = {} });
|
||||||
|
self.syncActionAccelerator("app.reload-config", .{ .reload_config = {} });
|
||||||
|
self.syncActionAccelerator("win.toggle-inspector", .{ .inspector = .toggle });
|
||||||
|
self.syncActionAccelerator("app.show-gtk-inspector", .show_gtk_inspector);
|
||||||
|
self.syncActionAccelerator("win.toggle-command-palette", .toggle_command_palette);
|
||||||
|
self.syncActionAccelerator("win.close", .{ .close_window = {} });
|
||||||
|
self.syncActionAccelerator("win.new-window", .{ .new_window = {} });
|
||||||
|
self.syncActionAccelerator("win.new-tab", .{ .new_tab = {} });
|
||||||
|
self.syncActionAccelerator("win.close-tab", .{ .close_tab = {} });
|
||||||
|
self.syncActionAccelerator("win.split-right", .{ .new_split = .right });
|
||||||
|
self.syncActionAccelerator("win.split-down", .{ .new_split = .down });
|
||||||
|
self.syncActionAccelerator("win.split-left", .{ .new_split = .left });
|
||||||
|
self.syncActionAccelerator("win.split-up", .{ .new_split = .up });
|
||||||
|
self.syncActionAccelerator("win.copy", .{ .copy_to_clipboard = {} });
|
||||||
|
self.syncActionAccelerator("win.paste", .{ .paste_from_clipboard = {} });
|
||||||
|
self.syncActionAccelerator("win.reset", .{ .reset = {} });
|
||||||
|
self.syncActionAccelerator("win.clear", .{ .clear_screen = {} });
|
||||||
|
self.syncActionAccelerator("win.prompt-title", .{ .prompt_surface_title = {} });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn syncActionAccelerator(
|
||||||
|
self: *Self,
|
||||||
|
gtk_action: [:0]const u8,
|
||||||
|
action: input.Binding.Action,
|
||||||
|
) void {
|
||||||
|
const gtk_app = self.as(gtk.Application);
|
||||||
|
|
||||||
|
// Reset it initially
|
||||||
|
const zero = [_:null]?[*:0]const u8{};
|
||||||
|
gtk_app.setAccelsForAction(gtk_action, &zero);
|
||||||
|
|
||||||
|
const config = self.private().config.get();
|
||||||
|
const trigger = config.keybind.set.getTrigger(action) orelse return;
|
||||||
|
var buf: [1024]u8 = undefined;
|
||||||
|
const accel = if (key.accelFromTrigger(
|
||||||
|
&buf,
|
||||||
|
trigger,
|
||||||
|
)) |accel_|
|
||||||
|
accel_ orelse return
|
||||||
|
else |err| switch (err) {
|
||||||
|
// This should really never, never happen. Its not critical enough
|
||||||
|
// to actually crash, but this is a bug somewhere. An accelerator
|
||||||
|
// for a trigger can't possibly be more than 1024 bytes.
|
||||||
|
error.NoSpaceLeft => {
|
||||||
|
log.warn("accelerator somehow longer than 1024 bytes: {}", .{trigger});
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const accels = [_:null]?[*:0]const u8{accel};
|
||||||
|
|
||||||
|
gtk_app.setAccelsForAction(gtk_action, &accels);
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Properties
|
// Properties
|
||||||
|
|
||||||
|
|
@ -891,6 +948,9 @@ pub const Application = extern struct {
|
||||||
_: *gobject.ParamSpec,
|
_: *gobject.ParamSpec,
|
||||||
self: *Self,
|
self: *Self,
|
||||||
) callconv(.c) void {
|
) callconv(.c) void {
|
||||||
|
// Sync our accelerators for menu items.
|
||||||
|
self.syncActionAccelerators();
|
||||||
|
|
||||||
// Load our runtime and custom CSS. If this fails then our window is
|
// Load our runtime and custom CSS. If this fails then our window is
|
||||||
// just stuck with the old CSS but we don't want to fail the entire
|
// just stuck with the old CSS but we don't want to fail the entire
|
||||||
// config change operation.
|
// config change operation.
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ pub const GlobalShortcuts = extern struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refresh(self: *Self) !void {
|
fn refresh(self: *Self) Allocator.Error!void {
|
||||||
// Always close our previous state first.
|
// Always close our previous state first.
|
||||||
self.close();
|
self.close();
|
||||||
|
|
||||||
|
|
@ -173,7 +173,7 @@ pub const GlobalShortcuts = extern struct {
|
||||||
errdefer priv.map = .{};
|
errdefer priv.map = .{};
|
||||||
|
|
||||||
// Update map
|
// Update map
|
||||||
var trigger_buf: [256]u8 = undefined;
|
var trigger_buf: [1024]u8 = undefined;
|
||||||
var it = config.keybind.set.bindings.iterator();
|
var it = config.keybind.set.bindings.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
const leaf = switch (entry.value_ptr.*) {
|
const leaf = switch (entry.value_ptr.*) {
|
||||||
|
|
@ -183,10 +183,23 @@ pub const GlobalShortcuts = extern struct {
|
||||||
};
|
};
|
||||||
if (!leaf.flags.global) continue;
|
if (!leaf.flags.global) continue;
|
||||||
|
|
||||||
const trigger = try key.xdgShortcutFromTrigger(
|
const trigger = if (key.xdgShortcutFromTrigger(
|
||||||
&trigger_buf,
|
&trigger_buf,
|
||||||
entry.key_ptr.*,
|
entry.key_ptr.*,
|
||||||
) orelse continue;
|
)) |shortcut_|
|
||||||
|
shortcut_ orelse continue
|
||||||
|
else |err| switch (err) {
|
||||||
|
// If there isn't space to translate the trigger, then our
|
||||||
|
// buffer might be too small (but 1024 is insane!). In any case
|
||||||
|
// we don't want to stop registering globals.
|
||||||
|
error.NoSpaceLeft => {
|
||||||
|
log.warn(
|
||||||
|
"buffer too small to translate trigger, ignoring={}",
|
||||||
|
.{entry.key_ptr.*},
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
try priv.map.put(
|
try priv.map.put(
|
||||||
alloc,
|
alloc,
|
||||||
|
|
|
||||||
|
|
@ -117,23 +117,6 @@ pub const Window = extern struct {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const @"background-opaque" = struct {
|
|
||||||
pub const name = "background-opaque";
|
|
||||||
const impl = gobject.ext.defineProperty(
|
|
||||||
name,
|
|
||||||
Self,
|
|
||||||
bool,
|
|
||||||
.{
|
|
||||||
.nick = "Background Opaque",
|
|
||||||
.blurb = "True if the background should be opaque.",
|
|
||||||
.default = true,
|
|
||||||
.accessor = gobject.ext.typedAccessor(Self, bool, .{
|
|
||||||
.getter = Self.getBackgroundOpaque,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const @"quick-terminal" = struct {
|
pub const @"quick-terminal" = struct {
|
||||||
pub const name = "quick-terminal";
|
pub const name = "quick-terminal";
|
||||||
const impl = gobject.ext.defineProperty(
|
const impl = gobject.ext.defineProperty(
|
||||||
|
|
@ -553,7 +536,6 @@ pub const Window = extern struct {
|
||||||
|
|
||||||
// Trigger all our dynamic properties that depend on the config.
|
// Trigger all our dynamic properties that depend on the config.
|
||||||
inline for (&.{
|
inline for (&.{
|
||||||
"background-opaque",
|
|
||||||
"headerbar-visible",
|
"headerbar-visible",
|
||||||
"tabs-autohide",
|
"tabs-autohide",
|
||||||
"tabs-visible",
|
"tabs-visible",
|
||||||
|
|
@ -568,6 +550,12 @@ pub const Window = extern struct {
|
||||||
// Remainder uses the config
|
// Remainder uses the config
|
||||||
const config = if (priv.config) |v| v.get() else return;
|
const config = if (priv.config) |v| v.get() else return;
|
||||||
|
|
||||||
|
// Only add a solid background if we're opaque.
|
||||||
|
self.toggleCssClass(
|
||||||
|
"background",
|
||||||
|
config.@"background-opacity" >= 1,
|
||||||
|
);
|
||||||
|
|
||||||
// Apply class to color headerbar if window-theme is set to `ghostty` and
|
// Apply class to color headerbar if window-theme is set to `ghostty` and
|
||||||
// GTK version is before 4.16. The conditional is because above 4.16
|
// GTK version is before 4.16. The conditional is because above 4.16
|
||||||
// we use GTK CSS color variables.
|
// we use GTK CSS color variables.
|
||||||
|
|
@ -751,12 +739,6 @@ pub const Window = extern struct {
|
||||||
return config.@"gtk-titlebar";
|
return config.@"gtk-titlebar";
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getBackgroundOpaque(self: *Self) bool {
|
|
||||||
const priv = self.private();
|
|
||||||
const config = (priv.config orelse return true).get();
|
|
||||||
return config.@"background-opacity" >= 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn getTabsAutohide(self: *Self) bool {
|
fn getTabsAutohide(self: *Self) bool {
|
||||||
const priv = self.private();
|
const priv = self.private();
|
||||||
const config = if (priv.config) |v| v.get() else return true;
|
const config = if (priv.config) |v| v.get() else return true;
|
||||||
|
|
@ -889,16 +871,6 @@ pub const Window = extern struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add or remove "background" CSS class depending on if the background
|
|
||||||
/// should be opaque.
|
|
||||||
fn propBackgroundOpaque(
|
|
||||||
_: *adw.ApplicationWindow,
|
|
||||||
_: *gobject.ParamSpec,
|
|
||||||
self: *Self,
|
|
||||||
) callconv(.c) void {
|
|
||||||
self.toggleCssClass("background", self.getBackgroundOpaque());
|
|
||||||
}
|
|
||||||
|
|
||||||
fn propScaleFactor(
|
fn propScaleFactor(
|
||||||
_: *adw.ApplicationWindow,
|
_: *adw.ApplicationWindow,
|
||||||
_: *gobject.ParamSpec,
|
_: *gobject.ParamSpec,
|
||||||
|
|
@ -1604,7 +1576,6 @@ pub const Window = extern struct {
|
||||||
// Properties
|
// Properties
|
||||||
gobject.ext.registerProperties(class, &.{
|
gobject.ext.registerProperties(class, &.{
|
||||||
properties.@"active-surface".impl,
|
properties.@"active-surface".impl,
|
||||||
properties.@"background-opaque".impl,
|
|
||||||
properties.config.impl,
|
properties.config.impl,
|
||||||
properties.debug.impl,
|
properties.debug.impl,
|
||||||
properties.@"headerbar-visible".impl,
|
properties.@"headerbar-visible".impl,
|
||||||
|
|
@ -1634,7 +1605,6 @@ pub const Window = extern struct {
|
||||||
class.bindTemplateCallback("tab_create_window", &tabViewCreateWindow);
|
class.bindTemplateCallback("tab_create_window", &tabViewCreateWindow);
|
||||||
class.bindTemplateCallback("notify_n_pages", &tabViewNPages);
|
class.bindTemplateCallback("notify_n_pages", &tabViewNPages);
|
||||||
class.bindTemplateCallback("notify_selected_page", &tabViewSelectedPage);
|
class.bindTemplateCallback("notify_selected_page", &tabViewSelectedPage);
|
||||||
class.bindTemplateCallback("notify_background_opaque", &propBackgroundOpaque);
|
|
||||||
class.bindTemplateCallback("notify_config", &propConfig);
|
class.bindTemplateCallback("notify_config", &propConfig);
|
||||||
class.bindTemplateCallback("notify_fullscreened", &propFullscreened);
|
class.bindTemplateCallback("notify_fullscreened", &propFullscreened);
|
||||||
class.bindTemplateCallback("notify_maximized", &propMaximized);
|
class.bindTemplateCallback("notify_maximized", &propMaximized);
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,10 @@ const input = @import("../../input.zig");
|
||||||
const winproto = @import("winproto.zig");
|
const winproto = @import("winproto.zig");
|
||||||
|
|
||||||
/// Returns a GTK accelerator string from a trigger.
|
/// Returns a GTK accelerator string from a trigger.
|
||||||
pub fn accelFromTrigger(buf: []u8, trigger: input.Binding.Trigger) !?[:0]const u8 {
|
pub fn accelFromTrigger(
|
||||||
|
buf: []u8,
|
||||||
|
trigger: input.Binding.Trigger,
|
||||||
|
) error{NoSpaceLeft}!?[:0]const u8 {
|
||||||
var buf_stream = std.io.fixedBufferStream(buf);
|
var buf_stream = std.io.fixedBufferStream(buf);
|
||||||
const writer = buf_stream.writer();
|
const writer = buf_stream.writer();
|
||||||
|
|
||||||
|
|
@ -30,7 +33,10 @@ pub fn accelFromTrigger(buf: []u8, trigger: input.Binding.Trigger) !?[:0]const u
|
||||||
|
|
||||||
/// Returns a XDG-compliant shortcuts string from a trigger.
|
/// Returns a XDG-compliant shortcuts string from a trigger.
|
||||||
/// Spec: https://specifications.freedesktop.org/shortcuts-spec/latest/
|
/// Spec: https://specifications.freedesktop.org/shortcuts-spec/latest/
|
||||||
pub fn xdgShortcutFromTrigger(buf: []u8, trigger: input.Binding.Trigger) !?[:0]const u8 {
|
pub fn xdgShortcutFromTrigger(
|
||||||
|
buf: []u8,
|
||||||
|
trigger: input.Binding.Trigger,
|
||||||
|
) error{NoSpaceLeft}!?[:0]const u8 {
|
||||||
var buf_stream = std.io.fixedBufferStream(buf);
|
var buf_stream = std.io.fixedBufferStream(buf);
|
||||||
const writer = buf_stream.writer();
|
const writer = buf_stream.writer();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ template $GhosttyWindow: Adw.ApplicationWindow {
|
||||||
|
|
||||||
close-request => $close_request();
|
close-request => $close_request();
|
||||||
realize => $realize();
|
realize => $realize();
|
||||||
notify::background-opaque => $notify_background_opaque();
|
|
||||||
notify::config => $notify_config();
|
notify::config => $notify_config();
|
||||||
notify::fullscreened => $notify_fullscreened();
|
notify::fullscreened => $notify_fullscreened();
|
||||||
notify::maximized => $notify_maximized();
|
notify::maximized => $notify_maximized();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue