mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-08-02 14:57:31 +03:00
adw tab headers should have their own menu
This commit is contained in:
@ -42,8 +42,7 @@ header: ?*c.GtkWidget,
|
|||||||
tab_overview: ?*c.GtkWidget,
|
tab_overview: ?*c.GtkWidget,
|
||||||
|
|
||||||
/// The notebook (tab grouping) for this window.
|
/// The notebook (tab grouping) for this window.
|
||||||
/// can be either c.GtkNotebook or c.AdwTabView.
|
notebook: *Notebook,
|
||||||
notebook: Notebook,
|
|
||||||
|
|
||||||
context_menu: *c.GtkWidget,
|
context_menu: *c.GtkWidget,
|
||||||
|
|
||||||
@ -54,7 +53,7 @@ toast_overlay: ?*c.GtkWidget,
|
|||||||
/// See adwTabOverviewOpen for why we have this.
|
/// See adwTabOverviewOpen for why we have this.
|
||||||
adw_tab_overview_focus_timer: ?c.guint = null,
|
adw_tab_overview_focus_timer: ?c.guint = null,
|
||||||
|
|
||||||
pub fn create(alloc: Allocator, app: *App) !*Window {
|
pub fn create(alloc: Allocator, app: *App) std.mem.Allocator.Error!*Window {
|
||||||
// Allocate a fixed pointer for our window. We try to minimize
|
// Allocate a fixed pointer for our window. We try to minimize
|
||||||
// allocations but windows and other GUI requirements are so minimal
|
// allocations but windows and other GUI requirements are so minimal
|
||||||
// compared to the steady-state terminal operation so we use heap
|
// compared to the steady-state terminal operation so we use heap
|
||||||
@ -64,11 +63,11 @@ pub fn create(alloc: Allocator, app: *App) !*Window {
|
|||||||
// freed when the window is closed.
|
// freed when the window is closed.
|
||||||
var window = try alloc.create(Window);
|
var window = try alloc.create(Window);
|
||||||
errdefer alloc.destroy(window);
|
errdefer alloc.destroy(window);
|
||||||
try window.init(app);
|
try window.init(alloc, app);
|
||||||
return window;
|
return window;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init(self: *Window, app: *App) !void {
|
pub fn init(self: *Window, alloc: Allocator, app: *App) std.mem.Allocator.Error!void {
|
||||||
// Set up our own state
|
// Set up our own state
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.app = app,
|
.app = app,
|
||||||
@ -226,7 +225,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup our notebook
|
// Setup our notebook
|
||||||
self.notebook = Notebook.create(self);
|
self.notebook = try Notebook.create(alloc, self);
|
||||||
|
|
||||||
// Setup our toast overlay if we have one
|
// Setup our toast overlay if we have one
|
||||||
self.toast_overlay = if (adwaita.enabled(&self.app.config)) toast: {
|
self.toast_overlay = if (adwaita.enabled(&self.app.config)) toast: {
|
||||||
@ -245,8 +244,8 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
// If we have a tab overview then we can set it on our notebook.
|
// If we have a tab overview then we can set it on our notebook.
|
||||||
if (self.tab_overview) |tab_overview| {
|
if (self.tab_overview) |tab_overview| {
|
||||||
if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable;
|
if (comptime !adwaita.versionAtLeast(1, 4, 0)) unreachable;
|
||||||
assert(self.notebook == .adw_tab_view);
|
assert(self.notebook.* == .adw_tab_view);
|
||||||
c.adw_tab_overview_set_view(@ptrCast(tab_overview), self.notebook.adw_tab_view);
|
c.adw_tab_overview_set_view(@ptrCast(tab_overview), self.notebook.adw_tab_view.tab_view);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.context_menu = c.gtk_popover_menu_new_from_model(@ptrCast(@alignCast(self.app.context_menu)));
|
self.context_menu = c.gtk_popover_menu_new_from_model(@ptrCast(@alignCast(self.app.context_menu)));
|
||||||
@ -280,7 +279,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
const header_widget: *c.GtkWidget = @ptrCast(@alignCast(self.header.?));
|
const header_widget: *c.GtkWidget = @ptrCast(@alignCast(self.header.?));
|
||||||
c.adw_toolbar_view_add_top_bar(toolbar_view, header_widget);
|
c.adw_toolbar_view_add_top_bar(toolbar_view, header_widget);
|
||||||
const tab_bar = c.adw_tab_bar_new();
|
const tab_bar = c.adw_tab_bar_new();
|
||||||
c.adw_tab_bar_set_view(tab_bar, self.notebook.adw_tab_view);
|
c.adw_tab_bar_set_view(tab_bar, self.notebook.adw_tab_view.tab_view);
|
||||||
|
|
||||||
if (!app.config.@"gtk-wide-tabs") c.adw_tab_bar_set_expand_tabs(tab_bar, 0);
|
if (!app.config.@"gtk-wide-tabs") c.adw_tab_bar_set_expand_tabs(tab_bar, 0);
|
||||||
|
|
||||||
@ -323,7 +322,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (self.notebook) {
|
switch (self.notebook.*) {
|
||||||
.adw_tab_view => |tab_view| if (comptime adwaita.versionAtLeast(0, 0, 0)) {
|
.adw_tab_view => |tab_view| if (comptime adwaita.versionAtLeast(0, 0, 0)) {
|
||||||
// In earlier adwaita versions, we need to add the tabbar manually since we do not use
|
// In earlier adwaita versions, we need to add the tabbar manually since we do not use
|
||||||
// an AdwToolbarView.
|
// an AdwToolbarView.
|
||||||
@ -344,7 +343,7 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
@ptrCast(@alignCast(tab_bar)),
|
@ptrCast(@alignCast(tab_bar)),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
c.adw_tab_bar_set_view(tab_bar, tab_view);
|
c.adw_tab_bar_set_view(tab_bar, tab_view.tab_view);
|
||||||
|
|
||||||
if (!app.config.@"gtk-wide-tabs") {
|
if (!app.config.@"gtk-wide-tabs") {
|
||||||
c.adw_tab_bar_set_expand_tabs(tab_bar, 0);
|
c.adw_tab_bar_set_expand_tabs(tab_bar, 0);
|
||||||
@ -403,6 +402,8 @@ pub fn deinit(self: *Window) void {
|
|||||||
if (self.adw_tab_overview_focus_timer) |timer| {
|
if (self.adw_tab_overview_focus_timer) |timer| {
|
||||||
_ = c.g_source_remove(timer);
|
_ = c.g_source_remove(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.app.core_app.alloc.destroy(self.notebook);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this window should use an Adwaita window.
|
/// Returns true if this window should use an Adwaita window.
|
||||||
@ -552,14 +553,14 @@ fn gtkNewTabFromOverview(_: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) ?*c.AdwT
|
|||||||
const alloc = self.app.core_app.alloc;
|
const alloc = self.app.core_app.alloc;
|
||||||
const surface = self.actionSurface();
|
const surface = self.actionSurface();
|
||||||
const tab = Tab.create(alloc, self, surface) catch return null;
|
const tab = Tab.create(alloc, self, surface) catch return null;
|
||||||
return c.adw_tab_view_get_page(self.notebook.adw_tab_view, @ptrCast(@alignCast(tab.box)));
|
return c.adw_tab_view_get_page(self.notebook.adw_tab_view.tab_view, @ptrCast(@alignCast(tab.box)));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adwTabOverviewOpen(
|
fn adwTabOverviewOpen(
|
||||||
object: *c.GObject,
|
object: *c.GObject,
|
||||||
_: *c.GParamSpec,
|
_: *c.GParamSpec,
|
||||||
ud: ?*anyopaque,
|
ud: ?*anyopaque,
|
||||||
) void {
|
) callconv(.C) void {
|
||||||
const tab_overview: *c.AdwTabOverview = @ptrCast(@alignCast(object));
|
const tab_overview: *c.AdwTabOverview = @ptrCast(@alignCast(object));
|
||||||
|
|
||||||
// We only care about when the tab overview is closed.
|
// We only care about when the tab overview is closed.
|
||||||
|
@ -14,16 +14,36 @@ const AdwTabPage = if (adwaita.versionAtLeast(0, 0, 0)) c.AdwTabPage else anyopa
|
|||||||
/// An abstraction over the GTK notebook and Adwaita tab view to manage
|
/// An abstraction over the GTK notebook and Adwaita tab view to manage
|
||||||
/// all the terminal tabs in a window.
|
/// all the terminal tabs in a window.
|
||||||
pub const Notebook = union(enum) {
|
pub const Notebook = union(enum) {
|
||||||
adw_tab_view: *AdwTabView,
|
adw_tab_view: struct {
|
||||||
|
/// the tab view
|
||||||
|
tab_view: *AdwTabView,
|
||||||
|
|
||||||
|
/// the last tab to have the context menu shown
|
||||||
|
last_tab: ?*Tab,
|
||||||
|
},
|
||||||
|
|
||||||
gtk_notebook: *c.GtkNotebook,
|
gtk_notebook: *c.GtkNotebook,
|
||||||
|
|
||||||
pub fn create(window: *Window) Notebook {
|
pub fn create(alloc: std.mem.Allocator, window: *Window) std.mem.Allocator.Error!*Notebook {
|
||||||
|
// Allocate a fixed pointer for our notebook. We try to minimize
|
||||||
|
// allocations but windows and other GUI requirements are so minimal
|
||||||
|
// compared to the steady-state terminal operation so we use heap
|
||||||
|
// allocation for this.
|
||||||
|
//
|
||||||
|
// The allocation is owned by the GtkWindow created. It will be
|
||||||
|
// freed when the window is closed.
|
||||||
|
var notebook = try alloc.create(Notebook);
|
||||||
|
errdefer alloc.destroy(notebook);
|
||||||
const app = window.app;
|
const app = window.app;
|
||||||
if (adwaita.enabled(&app.config)) return initAdw(window);
|
if (adwaita.enabled(&app.config)) {
|
||||||
return initGtk(window);
|
notebook.initAdw(window);
|
||||||
|
return notebook;
|
||||||
|
}
|
||||||
|
notebook.initGtk(window);
|
||||||
|
return notebook;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initGtk(window: *Window) Notebook {
|
fn initGtk(self: *Notebook, window: *Window) void {
|
||||||
const app = window.app;
|
const app = window.app;
|
||||||
|
|
||||||
// Create a notebook to hold our tabs.
|
// Create a notebook to hold our tabs.
|
||||||
@ -58,10 +78,10 @@ pub const Notebook = union(enum) {
|
|||||||
_ = c.g_signal_connect_data(notebook, "switch-page", c.G_CALLBACK(>kSwitchPage), window, null, c.G_CONNECT_DEFAULT);
|
_ = c.g_signal_connect_data(notebook, "switch-page", c.G_CALLBACK(>kSwitchPage), window, null, c.G_CONNECT_DEFAULT);
|
||||||
_ = c.g_signal_connect_data(notebook, "create-window", c.G_CALLBACK(>kNotebookCreateWindow), window, null, c.G_CONNECT_DEFAULT);
|
_ = c.g_signal_connect_data(notebook, "create-window", c.G_CALLBACK(>kNotebookCreateWindow), window, null, c.G_CONNECT_DEFAULT);
|
||||||
|
|
||||||
return .{ .gtk_notebook = notebook };
|
self.* = .{ .gtk_notebook = notebook };
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initAdw(window: *Window) Notebook {
|
fn initAdw(self: *Notebook, window: *Window) void {
|
||||||
const app = window.app;
|
const app = window.app;
|
||||||
assert(adwaita.enabled(&app.config));
|
assert(adwaita.enabled(&app.config));
|
||||||
|
|
||||||
@ -73,19 +93,24 @@ pub const Notebook = union(enum) {
|
|||||||
c.adw_tab_view_remove_shortcuts(tab_view, c.ADW_TAB_VIEW_SHORTCUT_ALL_SHORTCUTS);
|
c.adw_tab_view_remove_shortcuts(tab_view, c.ADW_TAB_VIEW_SHORTCUT_ALL_SHORTCUTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
c.adw_tab_view_set_menu_model(tab_view, @ptrCast(@alignCast(app.context_menu)));
|
self.* = .{
|
||||||
|
.adw_tab_view = .{
|
||||||
|
.tab_view = tab_view,
|
||||||
|
.last_tab = null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
self.initContextMenu(window);
|
||||||
|
|
||||||
_ = c.g_signal_connect_data(tab_view, "page-attached", c.G_CALLBACK(&adwPageAttached), window, null, c.G_CONNECT_DEFAULT);
|
_ = c.g_signal_connect_data(tab_view, "page-attached", c.G_CALLBACK(&adwPageAttached), window, null, c.G_CONNECT_DEFAULT);
|
||||||
_ = c.g_signal_connect_data(tab_view, "create-window", c.G_CALLBACK(&adwTabViewCreateWindow), window, null, c.G_CONNECT_DEFAULT);
|
_ = c.g_signal_connect_data(tab_view, "create-window", c.G_CALLBACK(&adwTabViewCreateWindow), window, null, c.G_CONNECT_DEFAULT);
|
||||||
_ = c.g_signal_connect_data(tab_view, "setup-menu", c.G_CALLBACK(&adwTabViewSetupMenu), window, null, c.G_CONNECT_DEFAULT);
|
|
||||||
_ = c.g_signal_connect_data(tab_view, "notify::selected-page", c.G_CALLBACK(&adwSelectPage), window, null, c.G_CONNECT_DEFAULT);
|
_ = c.g_signal_connect_data(tab_view, "notify::selected-page", c.G_CALLBACK(&adwSelectPage), window, null, c.G_CONNECT_DEFAULT);
|
||||||
|
_ = c.g_signal_connect_data(tab_view, "setup-menu", c.G_CALLBACK(&adwTabViewSetupMenu), self, null, c.G_CONNECT_DEFAULT);
|
||||||
return .{ .adw_tab_view = tab_view };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn asWidget(self: Notebook) *c.GtkWidget {
|
pub fn asWidget(self: Notebook) *c.GtkWidget {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
.adw_tab_view => |tab_view| @ptrCast(@alignCast(tab_view)),
|
.adw_tab_view => |tab_view| @ptrCast(@alignCast(tab_view.tab_view)),
|
||||||
.gtk_notebook => |notebook| @ptrCast(@alignCast(notebook)),
|
.gtk_notebook => |notebook| @ptrCast(@alignCast(notebook)),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -94,7 +119,7 @@ pub const Notebook = union(enum) {
|
|||||||
return switch (self) {
|
return switch (self) {
|
||||||
.gtk_notebook => |notebook| c.gtk_notebook_get_n_pages(notebook),
|
.gtk_notebook => |notebook| c.gtk_notebook_get_n_pages(notebook),
|
||||||
.adw_tab_view => |tab_view| if (comptime adwaita.versionAtLeast(0, 0, 0))
|
.adw_tab_view => |tab_view| if (comptime adwaita.versionAtLeast(0, 0, 0))
|
||||||
c.adw_tab_view_get_n_pages(tab_view)
|
c.adw_tab_view_get_n_pages(tab_view.tab_view)
|
||||||
else
|
else
|
||||||
unreachable,
|
unreachable,
|
||||||
};
|
};
|
||||||
@ -106,8 +131,8 @@ pub const Notebook = union(enum) {
|
|||||||
switch (self) {
|
switch (self) {
|
||||||
.adw_tab_view => |tab_view| {
|
.adw_tab_view => |tab_view| {
|
||||||
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
||||||
const page = c.adw_tab_view_get_selected_page(tab_view) orelse return null;
|
const page = c.adw_tab_view_get_selected_page(tab_view.tab_view) orelse return null;
|
||||||
return c.adw_tab_view_get_page_position(tab_view, page);
|
return c.adw_tab_view_get_page_position(tab_view.tab_view, page);
|
||||||
},
|
},
|
||||||
|
|
||||||
.gtk_notebook => |notebook| {
|
.gtk_notebook => |notebook| {
|
||||||
@ -122,7 +147,7 @@ pub const Notebook = union(enum) {
|
|||||||
const child = switch (self) {
|
const child = switch (self) {
|
||||||
.adw_tab_view => |tab_view| child: {
|
.adw_tab_view => |tab_view| child: {
|
||||||
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
||||||
const page = c.adw_tab_view_get_selected_page(tab_view) orelse return null;
|
const page = c.adw_tab_view_get_selected_page(tab_view.tab_view) orelse return null;
|
||||||
const child = c.adw_tab_page_get_child(page);
|
const child = c.adw_tab_page_get_child(page);
|
||||||
break :child child;
|
break :child child;
|
||||||
},
|
},
|
||||||
@ -141,8 +166,8 @@ pub const Notebook = union(enum) {
|
|||||||
switch (self) {
|
switch (self) {
|
||||||
.adw_tab_view => |tab_view| {
|
.adw_tab_view => |tab_view| {
|
||||||
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
||||||
const page_to_select = c.adw_tab_view_get_nth_page(tab_view, position);
|
const page_to_select = c.adw_tab_view_get_nth_page(tab_view.tab_view, position);
|
||||||
c.adw_tab_view_set_selected_page(tab_view, page_to_select);
|
c.adw_tab_view_set_selected_page(tab_view.tab_view, page_to_select);
|
||||||
},
|
},
|
||||||
.gtk_notebook => |notebook| c.gtk_notebook_set_current_page(notebook, position),
|
.gtk_notebook => |notebook| c.gtk_notebook_set_current_page(notebook, position),
|
||||||
}
|
}
|
||||||
@ -152,8 +177,8 @@ pub const Notebook = union(enum) {
|
|||||||
return switch (self) {
|
return switch (self) {
|
||||||
.adw_tab_view => |tab_view| page_idx: {
|
.adw_tab_view => |tab_view| page_idx: {
|
||||||
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
||||||
const page = c.adw_tab_view_get_page(tab_view, @ptrCast(tab.box)) orelse return null;
|
const page = c.adw_tab_view_get_page(tab_view.tab_view, @ptrCast(tab.box)) orelse return null;
|
||||||
break :page_idx c.adw_tab_view_get_page_position(tab_view, page);
|
break :page_idx c.adw_tab_view_get_page_position(tab_view.tab_view, page);
|
||||||
},
|
},
|
||||||
.gtk_notebook => |notebook| page_idx: {
|
.gtk_notebook => |notebook| page_idx: {
|
||||||
const page = c.gtk_notebook_get_page(notebook, @ptrCast(tab.box)) orelse return null;
|
const page = c.gtk_notebook_get_page(notebook, @ptrCast(tab.box)) orelse return null;
|
||||||
@ -210,8 +235,8 @@ pub const Notebook = union(enum) {
|
|||||||
},
|
},
|
||||||
.adw_tab_view => |tab_view| {
|
.adw_tab_view => |tab_view| {
|
||||||
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
||||||
const page = c.adw_tab_view_get_page(tab_view, @ptrCast(tab.box));
|
const page = c.adw_tab_view_get_page(tab_view.tab_view, @ptrCast(tab.box));
|
||||||
_ = c.adw_tab_view_reorder_page(tab_view, page, position);
|
_ = c.adw_tab_view_reorder_page(tab_view.tab_view, page, position);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -220,7 +245,7 @@ pub const Notebook = union(enum) {
|
|||||||
switch (self) {
|
switch (self) {
|
||||||
.adw_tab_view => |tab_view| {
|
.adw_tab_view => |tab_view| {
|
||||||
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
||||||
const page = c.adw_tab_view_get_page(tab_view, @ptrCast(tab.box));
|
const page = c.adw_tab_view_get_page(tab_view.tab_view, @ptrCast(tab.box));
|
||||||
c.adw_tab_page_set_title(page, title.ptr);
|
c.adw_tab_page_set_title(page, title.ptr);
|
||||||
},
|
},
|
||||||
.gtk_notebook => c.gtk_label_set_text(tab.label_text, title.ptr),
|
.gtk_notebook => c.gtk_label_set_text(tab.label_text, title.ptr),
|
||||||
@ -253,11 +278,11 @@ pub const Notebook = union(enum) {
|
|||||||
.adw_tab_view => |tab_view| {
|
.adw_tab_view => |tab_view| {
|
||||||
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
||||||
|
|
||||||
const page = c.adw_tab_view_insert(tab_view, box_widget, self.newTabInsertPosition(tab));
|
const page = c.adw_tab_view_insert(tab_view.tab_view, box_widget, self.newTabInsertPosition(tab));
|
||||||
c.adw_tab_page_set_title(page, title.ptr);
|
c.adw_tab_page_set_title(page, title.ptr);
|
||||||
|
|
||||||
// Switch to the new tab
|
// Switch to the new tab
|
||||||
c.adw_tab_view_set_selected_page(tab_view, page);
|
c.adw_tab_view_set_selected_page(tab_view.tab_view, page);
|
||||||
},
|
},
|
||||||
.gtk_notebook => |notebook| {
|
.gtk_notebook => |notebook| {
|
||||||
// Build the tab label
|
// Build the tab label
|
||||||
@ -327,8 +352,8 @@ pub const Notebook = union(enum) {
|
|||||||
.adw_tab_view => |tab_view| {
|
.adw_tab_view => |tab_view| {
|
||||||
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
if (comptime !adwaita.versionAtLeast(0, 0, 0)) unreachable;
|
||||||
|
|
||||||
const page = c.adw_tab_view_get_page(tab_view, @ptrCast(tab.box)) orelse return;
|
const page = c.adw_tab_view_get_page(tab_view.tab_view, @ptrCast(tab.box)) orelse return;
|
||||||
c.adw_tab_view_close_page(tab_view, page);
|
c.adw_tab_view_close_page(tab_view.tab_view, page);
|
||||||
|
|
||||||
// If we have no more tabs we close the window
|
// If we have no more tabs we close the window
|
||||||
if (self.nPages() == 0) {
|
if (self.nPages() == 0) {
|
||||||
@ -385,6 +410,53 @@ pub const Notebook = union(enum) {
|
|||||||
|
|
||||||
return c.g_value_get_int(&value);
|
return c.g_value_get_int(&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn initContextMenu(self: *Notebook, window: *Window) void {
|
||||||
|
switch (self.*) {
|
||||||
|
.adw_tab_view => |tab_view| {
|
||||||
|
{
|
||||||
|
var buf: [32]u8 = undefined;
|
||||||
|
const action_name = std.fmt.bufPrintZ(
|
||||||
|
&buf,
|
||||||
|
"close-tab-{x:8>0}",
|
||||||
|
.{@intFromPtr(self)},
|
||||||
|
) catch unreachable;
|
||||||
|
|
||||||
|
const action = c.g_simple_action_new(action_name, null);
|
||||||
|
defer c.g_object_unref(action);
|
||||||
|
_ = c.g_signal_connect_data(
|
||||||
|
action,
|
||||||
|
"activate",
|
||||||
|
c.G_CALLBACK(&adwTabViewCloseTab),
|
||||||
|
self,
|
||||||
|
null,
|
||||||
|
c.G_CONNECT_DEFAULT,
|
||||||
|
);
|
||||||
|
c.g_action_map_add_action(@ptrCast(window.window), @ptrCast(action));
|
||||||
|
}
|
||||||
|
|
||||||
|
const menu = c.g_menu_new();
|
||||||
|
errdefer c.g_object_unref(menu);
|
||||||
|
|
||||||
|
{
|
||||||
|
var buf: [32]u8 = undefined;
|
||||||
|
const action_name = std.fmt.bufPrintZ(
|
||||||
|
&buf,
|
||||||
|
"win.close-tab-{x:8>0}",
|
||||||
|
.{@intFromPtr(self)},
|
||||||
|
) catch unreachable;
|
||||||
|
|
||||||
|
const section = c.g_menu_new();
|
||||||
|
defer c.g_object_unref(section);
|
||||||
|
c.g_menu_append_section(menu, null, @ptrCast(@alignCast(section)));
|
||||||
|
c.g_menu_append(section, "Close Tab", action_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
c.adw_tab_view_set_menu_model(tab_view.tab_view, @ptrCast(@alignCast(menu)));
|
||||||
|
},
|
||||||
|
.gtk_notebook => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
fn gtkPageRemoved(
|
fn gtkPageRemoved(
|
||||||
@ -442,7 +514,7 @@ fn gtkPageAdded(
|
|||||||
|
|
||||||
fn adwSelectPage(_: *c.GObject, _: *c.GParamSpec, ud: ?*anyopaque) void {
|
fn adwSelectPage(_: *c.GObject, _: *c.GParamSpec, ud: ?*anyopaque) void {
|
||||||
const window: *Window = @ptrCast(@alignCast(ud.?));
|
const window: *Window = @ptrCast(@alignCast(ud.?));
|
||||||
const page = c.adw_tab_view_get_selected_page(window.notebook.adw_tab_view) orelse return;
|
const page = c.adw_tab_view_get_selected_page(window.notebook.adw_tab_view.tab_view) orelse return;
|
||||||
const title = c.adw_tab_page_get_title(page);
|
const title = c.adw_tab_page_get_title(page);
|
||||||
c.gtk_window_set_title(window.window, title);
|
c.gtk_window_set_title(window.window, title);
|
||||||
}
|
}
|
||||||
@ -464,7 +536,7 @@ fn adwTabViewCreateWindow(
|
|||||||
log.warn("error creating new window error={}", .{err});
|
log.warn("error creating new window error={}", .{err});
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
return window.notebook.adw_tab_view;
|
return window.notebook.adw_tab_view.tab_view;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gtkNotebookCreateWindow(
|
fn gtkNotebookCreateWindow(
|
||||||
@ -497,14 +569,19 @@ fn createWindow(currentWindow: *Window) !*Window {
|
|||||||
return Window.create(alloc, app);
|
return Window.create(alloc, app);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn adwTabViewSetupMenu(tab_view: *AdwTabView, page: *AdwTabPage, ud: ?*anyopaque) callconv(.C) void {
|
fn adwTabViewSetupMenu(_: *AdwTabView, page: *AdwTabPage, ud: ?*anyopaque) callconv(.C) void {
|
||||||
const window: *Window = @ptrCast(@alignCast(ud.?));
|
const self: *Notebook = @ptrCast(@alignCast(ud.?));
|
||||||
|
self.adw_tab_view.last_tab = null;
|
||||||
|
|
||||||
const child = c.adw_tab_page_get_child(page);
|
const child = c.adw_tab_page_get_child(page);
|
||||||
const tab: *Tab = @ptrCast(@alignCast(
|
const tab: *Tab = @ptrCast(@alignCast(
|
||||||
c.g_object_get_data(@ptrCast(child), Tab.GHOSTTY_TAB) orelse return,
|
c.g_object_get_data(@ptrCast(child), Tab.GHOSTTY_TAB) orelse return,
|
||||||
));
|
));
|
||||||
window.app.refreshContextMenu(window.window, if (tab.focus_child) |focus_child| focus_child.core_surface.hasSelection() else false);
|
|
||||||
|
|
||||||
c.adw_tab_view_set_menu_model(tab_view, @ptrCast(@alignCast(window.app.context_menu)));
|
self.adw_tab_view.last_tab = tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn adwTabViewCloseTab(_: *c.GSimpleAction, _: *c.GVariant, ud: ?*anyopaque) callconv(.C) void {
|
||||||
|
const self: *Notebook = @ptrCast(@alignCast(ud.?));
|
||||||
|
self.closeTab(self.adw_tab_view.last_tab orelse return);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user