mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
gtk: menubar update
1. "top menu" => "menubar" 2. Slimmed down context menu. 3. More robust compile time checks of GTK builder UI files.
This commit is contained in:
@ -571,7 +571,7 @@ typedef enum {
|
|||||||
GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS,
|
GHOSTTY_ACTION_TOGGLE_WINDOW_DECORATIONS,
|
||||||
GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL,
|
GHOSTTY_ACTION_TOGGLE_QUICK_TERMINAL,
|
||||||
GHOSTTY_ACTION_TOGGLE_VISIBILITY,
|
GHOSTTY_ACTION_TOGGLE_VISIBILITY,
|
||||||
GHOSTTY_ACTION_TOGGLE_TOP_MENU,
|
GHOSTTY_ACTION_TOGGLE_MENUBAR,
|
||||||
GHOSTTY_ACTION_MOVE_TAB,
|
GHOSTTY_ACTION_MOVE_TAB,
|
||||||
GHOSTTY_ACTION_GOTO_TAB,
|
GHOSTTY_ACTION_GOTO_TAB,
|
||||||
GHOSTTY_ACTION_GOTO_SPLIT,
|
GHOSTTY_ACTION_GOTO_SPLIT,
|
||||||
|
@ -4213,9 +4213,9 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
|||||||
.toggle,
|
.toggle,
|
||||||
),
|
),
|
||||||
|
|
||||||
.toggle_top_menu => try self.rt_app.performAction(
|
.toggle_menubar => try self.rt_app.performAction(
|
||||||
.{ .surface = self },
|
.{ .surface = self },
|
||||||
.toggle_top_menu,
|
.toggle_menubar,
|
||||||
{},
|
{},
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@ -110,8 +110,8 @@ pub const Action = union(Key) {
|
|||||||
/// Toggle the visibility of all Ghostty terminal windows.
|
/// Toggle the visibility of all Ghostty terminal windows.
|
||||||
toggle_visibility,
|
toggle_visibility,
|
||||||
|
|
||||||
/// Toggle whether the top menu is shown.
|
/// Toggle whether the window menubar is shown.
|
||||||
toggle_top_menu,
|
toggle_menubar,
|
||||||
|
|
||||||
/// Moves a tab by a relative offset.
|
/// Moves a tab by a relative offset.
|
||||||
///
|
///
|
||||||
@ -243,7 +243,7 @@ pub const Action = union(Key) {
|
|||||||
toggle_window_decorations,
|
toggle_window_decorations,
|
||||||
toggle_quick_terminal,
|
toggle_quick_terminal,
|
||||||
toggle_visibility,
|
toggle_visibility,
|
||||||
toggle_top_menu,
|
toggle_menubar,
|
||||||
move_tab,
|
move_tab,
|
||||||
goto_tab,
|
goto_tab,
|
||||||
goto_split,
|
goto_split,
|
||||||
|
@ -223,7 +223,7 @@ pub const App = struct {
|
|||||||
.toggle_window_decorations,
|
.toggle_window_decorations,
|
||||||
.toggle_quick_terminal,
|
.toggle_quick_terminal,
|
||||||
.toggle_visibility,
|
.toggle_visibility,
|
||||||
.toggle_top_menu,
|
.toggle_menubar,
|
||||||
.goto_tab,
|
.goto_tab,
|
||||||
.move_tab,
|
.move_tab,
|
||||||
.inspector,
|
.inspector,
|
||||||
|
@ -506,7 +506,7 @@ pub fn performAction(
|
|||||||
}),
|
}),
|
||||||
.toggle_maximize => self.toggleMaximize(target),
|
.toggle_maximize => self.toggleMaximize(target),
|
||||||
.toggle_fullscreen => self.toggleFullscreen(target, value),
|
.toggle_fullscreen => self.toggleFullscreen(target, value),
|
||||||
.toggle_top_menu => self.toggleTopMenu(target),
|
.toggle_menubar => self.toggleMenubar(target),
|
||||||
|
|
||||||
.new_tab => try self.newTab(target),
|
.new_tab => try self.newTab(target),
|
||||||
.close_tab => try self.closeTab(target),
|
.close_tab => try self.closeTab(target),
|
||||||
@ -789,18 +789,18 @@ fn toggleWindowDecorations(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggleTopMenu(_: *App, target: apprt.Target) void {
|
fn toggleMenubar(_: *App, target: apprt.Target) void {
|
||||||
switch (target) {
|
switch (target) {
|
||||||
.app => {},
|
.app => {},
|
||||||
.surface => |v| {
|
.surface => |v| {
|
||||||
const window = v.rt_surface.container.window() orelse {
|
const window = v.rt_surface.container.window() orelse {
|
||||||
log.info(
|
log.info(
|
||||||
"toggleTopMenu invalid for container={s}",
|
"toggleMenubar invalid for container={s}",
|
||||||
.{@tagName(v.rt_surface.container)},
|
.{@tagName(v.rt_surface.container)},
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
window.toggleTopMenu();
|
window.toggleMenubar();
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -380,7 +380,7 @@ im_len: u7 = 0,
|
|||||||
cgroup_path: ?[]const u8 = null,
|
cgroup_path: ?[]const u8 = null,
|
||||||
|
|
||||||
/// Our context menu.
|
/// Our context menu.
|
||||||
context_menu: Menu(Surface, .context, .popover_menu),
|
context_menu: Menu(Surface, "context_menu", .popover_menu),
|
||||||
|
|
||||||
/// Configuration used for initializing the surface. We have to copy some
|
/// Configuration used for initializing the surface. We have to copy some
|
||||||
/// data since initialization is delayed with GTK (on realize).
|
/// data since initialization is delayed with GTK (on realize).
|
||||||
|
@ -48,14 +48,14 @@ tab_overview: ?*c.GtkWidget,
|
|||||||
/// can be either c.GtkNotebook or c.AdwTabView.
|
/// can be either c.GtkNotebook or c.AdwTabView.
|
||||||
notebook: Notebook,
|
notebook: Notebook,
|
||||||
|
|
||||||
/// The "top" menu that appears at the top of a window.
|
/// Menu that appears at the top of a window inbetween the titlebar and tabbar.
|
||||||
top_menu: Menu(Window, .top, .popover_menu_bar),
|
menubar: Menu(Window, "menubar", .popover_menu_bar),
|
||||||
|
|
||||||
/// Revealer for showing/hiding top menu.
|
/// Revealer for showing/hiding top menu.
|
||||||
top_menu_revealer: *c.GtkRevealer,
|
menubar_revealer: *c.GtkRevealer,
|
||||||
|
|
||||||
/// The "main" menu that is attached to a button in the headerbar.
|
/// The "main" menu that is attached to a button in the headerbar.
|
||||||
titlebar_menu: Menu(Window, .titlebar, .popover_menu),
|
titlebar_menu: Menu(Window, "titlebar_menu", .popover_menu),
|
||||||
|
|
||||||
/// The libadwaita widget for receiving toast send requests. If libadwaita is
|
/// The libadwaita widget for receiving toast send requests. If libadwaita is
|
||||||
/// not used, this is null and unused.
|
/// not used, this is null and unused.
|
||||||
@ -104,8 +104,8 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
.tab_overview = null,
|
.tab_overview = null,
|
||||||
.toast_overlay = null,
|
.toast_overlay = null,
|
||||||
.notebook = undefined,
|
.notebook = undefined,
|
||||||
.top_menu = undefined,
|
.menubar = undefined,
|
||||||
.top_menu_revealer = undefined,
|
.menubar_revealer = undefined,
|
||||||
.titlebar_menu = undefined,
|
.titlebar_menu = undefined,
|
||||||
.winproto = .none,
|
.winproto = .none,
|
||||||
};
|
};
|
||||||
@ -149,12 +149,12 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
const box = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0);
|
const box = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0);
|
||||||
|
|
||||||
// Set up the menus
|
// Set up the menus
|
||||||
self.top_menu.init();
|
self.menubar.init();
|
||||||
self.titlebar_menu.init();
|
self.titlebar_menu.init();
|
||||||
|
|
||||||
self.top_menu_revealer = @ptrCast(@alignCast(c.gtk_revealer_new()));
|
self.menubar_revealer = @ptrCast(@alignCast(c.gtk_revealer_new()));
|
||||||
c.gtk_revealer_set_child(self.top_menu_revealer, self.top_menu.asWidget());
|
c.gtk_revealer_set_child(self.menubar_revealer, self.menubar.asWidget());
|
||||||
c.gtk_revealer_set_transition_type(self.top_menu_revealer, c.GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN);
|
c.gtk_revealer_set_transition_type(self.menubar_revealer, c.GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN);
|
||||||
|
|
||||||
// Setup our notebook
|
// Setup our notebook
|
||||||
self.notebook.init();
|
self.notebook.init();
|
||||||
@ -200,7 +200,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
_ = c.g_signal_connect_data(
|
_ = c.g_signal_connect_data(
|
||||||
btn,
|
btn,
|
||||||
"notify::active",
|
"notify::active",
|
||||||
c.G_CALLBACK(>kMenuActivate),
|
c.G_CALLBACK(>kTitlebarMenuActivate),
|
||||||
self,
|
self,
|
||||||
null,
|
null,
|
||||||
c.G_CONNECT_DEFAULT,
|
c.G_CONNECT_DEFAULT,
|
||||||
@ -258,11 +258,11 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
.adw140 => {},
|
.adw140 => {},
|
||||||
.adw, .adw130 => {
|
.adw, .adw130 => {
|
||||||
c.gtk_box_append(@ptrCast(box), self.headerbar.asWidget());
|
c.gtk_box_append(@ptrCast(box), self.headerbar.asWidget());
|
||||||
c.gtk_box_append(@ptrCast(box), @ptrCast(@alignCast(self.top_menu_revealer)));
|
c.gtk_box_append(@ptrCast(box), @ptrCast(@alignCast(self.menubar_revealer)));
|
||||||
},
|
},
|
||||||
.gtk => {
|
.gtk => {
|
||||||
c.gtk_window_set_titlebar(gtk_window, self.headerbar.asWidget());
|
c.gtk_window_set_titlebar(gtk_window, self.headerbar.asWidget());
|
||||||
c.gtk_box_append(@ptrCast(box), @ptrCast(@alignCast(self.top_menu_revealer)));
|
c.gtk_box_append(@ptrCast(box), @ptrCast(@alignCast(self.menubar_revealer)));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,7 +344,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
|
|
||||||
const top_box = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0);
|
const top_box = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0);
|
||||||
c.gtk_box_append(@ptrCast(top_box), self.headerbar.asWidget());
|
c.gtk_box_append(@ptrCast(top_box), self.headerbar.asWidget());
|
||||||
c.gtk_box_append(@ptrCast(top_box), @ptrCast(@alignCast(self.top_menu_revealer)));
|
c.gtk_box_append(@ptrCast(top_box), @ptrCast(@alignCast(self.menubar_revealer)));
|
||||||
|
|
||||||
c.adw_toolbar_view_add_top_bar(toolbar_view, top_box);
|
c.adw_toolbar_view_add_top_bar(toolbar_view, top_box);
|
||||||
|
|
||||||
@ -644,9 +644,9 @@ pub fn toggleWindowDecorations(self: *Window) void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Toggle top menu.
|
/// Toggle top menu.
|
||||||
pub fn toggleTopMenu(self: *Window) void {
|
pub fn toggleMenubar(self: *Window) void {
|
||||||
const is_revealed = c.gtk_revealer_get_reveal_child(self.top_menu_revealer) != 0;
|
const is_revealed = c.gtk_revealer_get_reveal_child(self.menubar_revealer) != 0;
|
||||||
c.gtk_revealer_set_reveal_child(self.top_menu_revealer, @intFromBool(!is_revealed));
|
c.gtk_revealer_set_reveal_child(self.menubar_revealer, @intFromBool(!is_revealed));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Grabs focus on the currently selected tab.
|
/// Grabs focus on the currently selected tab.
|
||||||
@ -1149,7 +1149,7 @@ fn userdataSelf(ud: *anyopaque) *Window {
|
|||||||
return @ptrCast(@alignCast(ud));
|
return @ptrCast(@alignCast(ud));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gtkMenuActivate(
|
fn gtkTitlebarMenuActivate(
|
||||||
btn: *c.GtkMenuButton,
|
btn: *c.GtkMenuButton,
|
||||||
_: *c.GParamSpec,
|
_: *c.GParamSpec,
|
||||||
ud: ?*anyopaque,
|
ud: ?*anyopaque,
|
||||||
|
24
src/apprt/gtk/builder_check.zig
Normal file
24
src/apprt/gtk/builder_check.zig
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const c = @cImport({
|
||||||
|
@cInclude("gtk/gtk.h");
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn main() !void {
|
||||||
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
|
const filename = filename: {
|
||||||
|
var it = try std.process.argsWithAllocator(alloc);
|
||||||
|
defer it.deinit();
|
||||||
|
|
||||||
|
_ = it.next() orelse return error.NoFilename;
|
||||||
|
break :filename try alloc.dupeZ(u8, it.next() orelse return error.NoFilename);
|
||||||
|
};
|
||||||
|
defer alloc.free(filename);
|
||||||
|
|
||||||
|
c.gtk_init();
|
||||||
|
|
||||||
|
const builder = c.gtk_builder_new_from_file(filename.ptr);
|
||||||
|
defer c.g_object_unref(builder);
|
||||||
|
}
|
@ -53,6 +53,12 @@ const icons = [_]struct {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ui_files = [_][]const u8{
|
||||||
|
"menu-surface-context_menu",
|
||||||
|
"menu-window-menubar",
|
||||||
|
"menu-window-titlebar_menu",
|
||||||
|
};
|
||||||
|
|
||||||
pub const gresource_xml = comptimeGenerateGResourceXML();
|
pub const gresource_xml = comptimeGenerateGResourceXML();
|
||||||
|
|
||||||
fn comptimeGenerateGResourceXML() []const u8 {
|
fn comptimeGenerateGResourceXML() []const u8 {
|
||||||
@ -93,6 +99,17 @@ fn writeGResourceXML(writer: anytype) !void {
|
|||||||
.{ icon.alias, icon.source },
|
.{ icon.alias, icon.source },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
try writer.writeAll(
|
||||||
|
\\ </gresource>
|
||||||
|
\\ <gresource prefix="/com/mitchellh/ghostty/ui">
|
||||||
|
\\
|
||||||
|
);
|
||||||
|
for (ui_files) |ui_file| {
|
||||||
|
try writer.print(
|
||||||
|
" <file alias=\"{0s}.ui\">src/apprt/gtk/ui/{0s}.ui</file>\n",
|
||||||
|
.{ui_file},
|
||||||
|
);
|
||||||
|
}
|
||||||
try writer.writeAll(
|
try writer.writeAll(
|
||||||
\\ </gresource>
|
\\ </gresource>
|
||||||
\\</gresources>
|
\\</gresources>
|
||||||
@ -101,7 +118,7 @@ fn writeGResourceXML(writer: anytype) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const dependencies = deps: {
|
pub const dependencies = deps: {
|
||||||
const total = css_files.len + icons.len;
|
const total = css_files.len + icons.len + ui_files.len;
|
||||||
var deps: [total][]const u8 = undefined;
|
var deps: [total][]const u8 = undefined;
|
||||||
var index: usize = 0;
|
var index: usize = 0;
|
||||||
for (css_files) |css_file| {
|
for (css_files) |css_file| {
|
||||||
@ -112,5 +129,9 @@ pub const dependencies = deps: {
|
|||||||
deps[index] = std.fmt.comptimePrint("images/icons/icon_{s}.png", .{icon.source});
|
deps[index] = std.fmt.comptimePrint("images/icons/icon_{s}.png", .{icon.source});
|
||||||
index += 1;
|
index += 1;
|
||||||
}
|
}
|
||||||
|
for (ui_files) |ui_file| {
|
||||||
|
deps[index] = std.fmt.comptimePrint("src/apprt/gtk/ui/{s}.ui", .{ui_file});
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
break :deps deps;
|
break :deps deps;
|
||||||
};
|
};
|
||||||
|
@ -10,7 +10,7 @@ const log = std.log.scoped(.gtk_menu);
|
|||||||
|
|
||||||
pub fn Menu(
|
pub fn Menu(
|
||||||
comptime T: type,
|
comptime T: type,
|
||||||
comptime variant: enum { top, titlebar, context },
|
comptime variant: []const u8,
|
||||||
comptime style: enum { popover_menu, popover_menu_bar },
|
comptime style: enum { popover_menu, popover_menu_bar },
|
||||||
) type {
|
) type {
|
||||||
return struct {
|
return struct {
|
||||||
@ -29,12 +29,27 @@ pub fn Menu(
|
|||||||
Surface => "surface",
|
Surface => "surface",
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
const parent: *T = @alignCast(@fieldParentPtr(@tagName(variant) ++ "_menu", self));
|
const parent: *T = @alignCast(@fieldParentPtr(variant, self));
|
||||||
|
|
||||||
// embed the menu data using Zig @embedFile rather than as a GTK resource so that we get
|
const path = "ui/menu-" ++ name ++ "-" ++ variant ++ ".ui";
|
||||||
// compile-time errors if we try and embed a file that doesn't exist
|
|
||||||
const data = @embedFile("ui/menu-" ++ name ++ "-" ++ @tagName(variant) ++ ".ui");
|
comptime {
|
||||||
const builder = c.gtk_builder_new_from_string(data.ptr, @intCast(data.len));
|
// Use @embedFile to make sure that the file exists at compile
|
||||||
|
// time. Zig _should_ discard the data so that it doesn't end up
|
||||||
|
// in the final executable. At runtime we will load the data from
|
||||||
|
// a GResource.
|
||||||
|
_ = @embedFile(path);
|
||||||
|
|
||||||
|
// Check to make sure that our file is listed as a `ui_file` in
|
||||||
|
// `gresource.zig`. If it isn't Ghostty could crash at runtime
|
||||||
|
// when we try and load a nonexistent GResource.
|
||||||
|
const gresource = @import("gresource.zig");
|
||||||
|
for (gresource.ui_files) |ui_file| {
|
||||||
|
if (std.mem.eql(u8, ui_file, "menu-" ++ name ++ "-" ++ variant)) break;
|
||||||
|
} else @compileError("missing 'menu-" ++ name ++ "-" ++ variant ++ "' in gresource.zig");
|
||||||
|
}
|
||||||
|
|
||||||
|
const builder = c.gtk_builder_new_from_resource("/com/mitchellh/ghostty/" ++ path);
|
||||||
defer c.g_object_unref(@ptrCast(builder));
|
defer c.g_object_unref(@ptrCast(builder));
|
||||||
|
|
||||||
const menu_model: *c.GMenuModel = @ptrCast(@alignCast(c.gtk_builder_get_object(builder, "menu")));
|
const menu_model: *c.GMenuModel = @ptrCast(@alignCast(c.gtk_builder_get_object(builder, "menu")));
|
||||||
|
@ -14,22 +14,12 @@
|
|||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label" translatable="yes">New Window</attribute>
|
<attribute name="label" translatable="yes">Clear</attribute>
|
||||||
<attribute name="action">win.new-window</attribute>
|
<attribute name="action">win.clear</attribute>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<attribute name="label" translatable="yes">Close Window</attribute>
|
<attribute name="label" translatable="yes">Reset</attribute>
|
||||||
<attribute name="action">win.close</attribute>
|
<attribute name="action">win.reset</attribute>
|
||||||
</item>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<item>
|
|
||||||
<attribute name="label" translatable="yes">New Tab</attribute>
|
|
||||||
<attribute name="action">win.new-tab</attribute>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<attribute name="label" translatable="yes">Close Tab</attribute>
|
|
||||||
<attribute name="action">win.close-tab</attribute>
|
|
||||||
</item>
|
</item>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
@ -54,40 +44,47 @@
|
|||||||
</item>
|
</item>
|
||||||
</section>
|
</section>
|
||||||
</submenu>
|
</submenu>
|
||||||
|
<submenu>
|
||||||
|
<attribute name="label">Tab</attribute>
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">New Tab</attribute>
|
||||||
|
<attribute name="action">win.new-tab</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Close Tab</attribute>
|
||||||
|
<attribute name="action">win.close-tab</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</submenu>
|
||||||
|
<submenu>
|
||||||
|
<attribute name="label">Window</attribute>
|
||||||
|
<section>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">New Window</attribute>
|
||||||
|
<attribute name="action">win.new-window</attribute>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<attribute name="label" translatable="yes">Close Window</attribute>
|
||||||
|
<attribute name="action">win.close</attribute>
|
||||||
|
</item>
|
||||||
|
</section>
|
||||||
|
</submenu>
|
||||||
</section>
|
</section>
|
||||||
<section>
|
<section>
|
||||||
<item>
|
<submenu>
|
||||||
<attribute name="label" translatable="yes">Clear</attribute>
|
<attribute name="label">Config</attribute>
|
||||||
<attribute name="action">win.clear</attribute>
|
<section>
|
||||||
</item>
|
<item>
|
||||||
<item>
|
<attribute name="label" translatable="yes">Open Configuration</attribute>
|
||||||
<attribute name="label" translatable="yes">Reset</attribute>
|
<attribute name="action">app.open-config</attribute>
|
||||||
<attribute name="action">win.reset</attribute>
|
</item>
|
||||||
</item>
|
<item>
|
||||||
</section>
|
<attribute name="label" translatable="yes">Reload Configuration</attribute>
|
||||||
<section>
|
<attribute name="action">app.reload-config</attribute>
|
||||||
<item>
|
</item>
|
||||||
<attribute name="label" translatable="yes">Terminal Inspector</attribute>
|
</section>
|
||||||
<attribute name="action">win.toggle-inspector</attribute>
|
</submenu>
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<attribute name="label" translatable="yes">Open Configuration</attribute>
|
|
||||||
<attribute name="action">app.open-config</attribute>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<attribute name="label" translatable="yes">Reload Configuration</attribute>
|
|
||||||
<attribute name="action">app.reload-config</attribute>
|
|
||||||
</item>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<item>
|
|
||||||
<attribute name="label" translatable="yes">About Ghostty</attribute>
|
|
||||||
<attribute name="action">win.about</attribute>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<attribute name="label" translatable="yes">Quit</attribute>
|
|
||||||
<attribute name="action">app.quit</attribute>
|
|
||||||
</item>
|
|
||||||
</section>
|
</section>
|
||||||
</menu>
|
</menu>
|
||||||
</interface>
|
</interface>
|
@ -469,6 +469,24 @@ pub fn add(
|
|||||||
const wf = b.addWriteFiles();
|
const wf = b.addWriteFiles();
|
||||||
const gresource_xml = wf.add("gresource.xml", gresource.gresource_xml);
|
const gresource_xml = wf.add("gresource.xml", gresource.gresource_xml);
|
||||||
|
|
||||||
|
{
|
||||||
|
const builder_check = b.addExecutable(.{
|
||||||
|
.name = "builder_check",
|
||||||
|
.root_source_file = b.path("src/apprt/gtk/builder_check.zig"),
|
||||||
|
.target = b.host,
|
||||||
|
});
|
||||||
|
builder_check.linkSystemLibrary2("gtk4", dynamic_link_opts);
|
||||||
|
builder_check.linkLibC();
|
||||||
|
|
||||||
|
for (gresource.dependencies) |pathname| {
|
||||||
|
const extension = std.fs.path.extension(pathname);
|
||||||
|
if (!std.mem.eql(u8, extension, ".ui")) continue;
|
||||||
|
const check = b.addRunArtifact(builder_check);
|
||||||
|
check.addFileArg(b.path(pathname));
|
||||||
|
step.step.dependOn(&check.step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const generate_resources_c = b.addSystemCommand(&.{
|
const generate_resources_c = b.addSystemCommand(&.{
|
||||||
"glib-compile-resources",
|
"glib-compile-resources",
|
||||||
"--c-name",
|
"--c-name",
|
||||||
|
@ -473,9 +473,9 @@ pub const Action = union(enum) {
|
|||||||
/// This currently only works on macOS.
|
/// This currently only works on macOS.
|
||||||
toggle_visibility: void,
|
toggle_visibility: void,
|
||||||
|
|
||||||
/// Show/hide the application menu that appears below the titlebar and above
|
/// Show/hide the window menu that appears below the titlebar and above the
|
||||||
/// the tab bar.
|
/// tab bar.
|
||||||
toggle_top_menu: void,
|
toggle_menubar: void,
|
||||||
|
|
||||||
/// Quit ghostty.
|
/// Quit ghostty.
|
||||||
quit: void,
|
quit: void,
|
||||||
@ -784,7 +784,7 @@ pub const Action = union(enum) {
|
|||||||
.goto_tab,
|
.goto_tab,
|
||||||
.move_tab,
|
.move_tab,
|
||||||
.toggle_tab_overview,
|
.toggle_tab_overview,
|
||||||
.toggle_top_menu,
|
.toggle_menubar,
|
||||||
.new_split,
|
.new_split,
|
||||||
.goto_split,
|
.goto_split,
|
||||||
.toggle_split_zoom,
|
.toggle_split_zoom,
|
||||||
|
Reference in New Issue
Block a user