mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 16:56:09 +03:00
gtk: add adwaita banner
This commit is contained in:
@ -894,7 +894,7 @@ fn updateTitleLabels(self: *Surface) void {
|
|||||||
|
|
||||||
// If we have a tab and are the focused child, then we have to update the tab
|
// If we have a tab and are the focused child, then we have to update the tab
|
||||||
if (self.container.tab()) |tab| {
|
if (self.container.tab()) |tab| {
|
||||||
if (tab.focus_child == self) tab.setLabelText(title); // c.gtk_label_set_text(tab.label_text, title.ptr);
|
if (tab.focus_child == self) tab.setLabelText(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a window and are focused, then we have to update the window title.
|
// If we have a window and are focused, then we have to update the window title.
|
||||||
|
@ -55,24 +55,6 @@ pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
|
|||||||
.focus_child = undefined,
|
.focus_child = undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
// // Wide style GTK tabs
|
|
||||||
// if (window.app.config.@"gtk-wide-tabs") {
|
|
||||||
// c.gtk_widget_set_hexpand(label_box_widget, 1);
|
|
||||||
// c.gtk_widget_set_halign(label_box_widget, c.GTK_ALIGN_FILL);
|
|
||||||
// c.gtk_widget_set_hexpand(label_text_widget, 1);
|
|
||||||
// c.gtk_widget_set_halign(label_text_widget, c.GTK_ALIGN_FILL);
|
|
||||||
|
|
||||||
// // This ensures that tabs are always equal width. If they're too
|
|
||||||
// // long, they'll be truncated with an ellipsis.
|
|
||||||
// c.gtk_label_set_max_width_chars(label_text, 1);
|
|
||||||
// c.gtk_label_set_ellipsize(label_text, c.PANGO_ELLIPSIZE_END);
|
|
||||||
|
|
||||||
// // We need to set a minimum width so that at a certain point
|
|
||||||
// // the notebook will have an arrow button rather than shrinking tabs
|
|
||||||
// // to an unreadably small size.
|
|
||||||
// c.gtk_widget_set_size_request(label_text_widget, 100, 1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Create a Box in which we'll later keep either Surface or Split.
|
// Create a Box in which we'll later keep either Surface or Split.
|
||||||
// Using a box makes it easier to maintain the tab contents because
|
// Using a box makes it easier to maintain the tab contents because
|
||||||
// we never need to change the root widget of the notebook page (tab).
|
// we never need to change the root widget of the notebook page (tab).
|
||||||
@ -96,34 +78,6 @@ pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void {
|
|||||||
c.g_object_set_data(@ptrCast(box_widget), GHOSTTY_TAB, self);
|
c.g_object_set_data(@ptrCast(box_widget), GHOSTTY_TAB, self);
|
||||||
try window.notebook.addTab(self, "Ghostty");
|
try window.notebook.addTab(self, "Ghostty");
|
||||||
|
|
||||||
// const notebook: *c.GtkNotebook = window.notebook.as_notebook();
|
|
||||||
|
|
||||||
// // Add the notebook page (create tab).
|
|
||||||
// const parent_page_idx = switch (window.app.config.@"window-new-tab-position") {
|
|
||||||
// .current => c.gtk_notebook_get_current_page(notebook) + 1,
|
|
||||||
// .end => c.gtk_notebook_get_n_pages(notebook),
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const page_idx = c.gtk_notebook_insert_page(
|
|
||||||
// notebook,
|
|
||||||
// box_widget,
|
|
||||||
// label_box_widget,
|
|
||||||
// parent_page_idx,
|
|
||||||
// );
|
|
||||||
// if (page_idx < 0) {
|
|
||||||
// log.warn("failed to add page to notebook", .{});
|
|
||||||
// return error.GtkAppendPageFailed;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Tab settings
|
|
||||||
// c.gtk_notebook_set_tab_reorderable(notebook, box_widget, 1);
|
|
||||||
// c.gtk_notebook_set_tab_detachable(notebook, box_widget, 1);
|
|
||||||
|
|
||||||
// // If we have multiple tabs, show the tab bar.
|
|
||||||
// if (c.gtk_notebook_get_n_pages(notebook) > 1) {
|
|
||||||
// c.gtk_notebook_set_show_tabs(notebook, 1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Attach all events
|
// Attach all events
|
||||||
_ = c.g_signal_connect_data(box_widget, "destroy", c.G_CALLBACK(>kDestroy), self, null, c.G_CONNECT_DEFAULT);
|
_ = c.g_signal_connect_data(box_widget, "destroy", c.G_CALLBACK(>kDestroy), self, null, c.G_CONNECT_DEFAULT);
|
||||||
|
|
||||||
@ -171,7 +125,7 @@ pub fn gtkTabCloseClick(_: *c.GtkButton, ud: ?*anyopaque) callconv(.C) void {
|
|||||||
|
|
||||||
fn gtkDestroy(v: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) void {
|
fn gtkDestroy(v: *c.GtkWidget, ud: ?*anyopaque) callconv(.C) void {
|
||||||
_ = v;
|
_ = v;
|
||||||
log.info("tab box destroy", .{});
|
log.debug("tab box destroy", .{});
|
||||||
|
|
||||||
// When our box is destroyed, we want to destroy our tab, too.
|
// When our box is destroyed, we want to destroy our tab, too.
|
||||||
const tab: *Tab = @ptrCast(@alignCast(ud));
|
const tab: *Tab = @ptrCast(@alignCast(ud));
|
||||||
|
@ -124,10 +124,16 @@ pub fn init(self: *Window, app: *App) !void {
|
|||||||
// In debug we show a warning and apply the 'devel' class to the window.
|
// In debug we show a warning and apply the 'devel' class to the window.
|
||||||
// This is a really common issue where people build from source in debug and performance is really bad.
|
// This is a really common issue where people build from source in debug and performance is really bad.
|
||||||
if (comptime std.debug.runtime_safety) {
|
if (comptime std.debug.runtime_safety) {
|
||||||
const warning = c.gtk_label_new("⚠️ You're running a debug build of Ghostty! Performance will be degraded.");
|
const warning_text = "⚠️ You're running a debug build of Ghostty! Performance will be degraded.";
|
||||||
c.gtk_widget_set_margin_top(warning, 10);
|
if (adwaita and c.ADW_MINOR_VERSION >= 3) {
|
||||||
c.gtk_widget_set_margin_bottom(warning, 10);
|
const banner = c.adw_banner_new(warning_text);
|
||||||
c.gtk_box_append(@ptrCast(box), warning);
|
c.gtk_box_append(@ptrCast(box), @ptrCast(banner));
|
||||||
|
} else {
|
||||||
|
const warning = c.gtk_label_new(warning_text);
|
||||||
|
c.gtk_widget_set_margin_top(warning, 10);
|
||||||
|
c.gtk_widget_set_margin_bottom(warning, 10);
|
||||||
|
c.gtk_box_append(@ptrCast(box), warning);
|
||||||
|
}
|
||||||
c.gtk_widget_add_css_class(@ptrCast(gtk_window), "devel");
|
c.gtk_widget_add_css_class(@ptrCast(gtk_window), "devel");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,8 +259,7 @@ pub fn gotoNextTab(self: *Window, surface: *Surface) void {
|
|||||||
/// Go to the next tab for a surface.
|
/// Go to the next tab for a surface.
|
||||||
pub fn gotoLastTab(self: *Window) void {
|
pub fn gotoLastTab(self: *Window) void {
|
||||||
const max = self.notebook.nPages() -| 1;
|
const max = self.notebook.nPages() -| 1;
|
||||||
c.gtk_notebook_set_current_page(self.notebook.gtk_notebook, max);
|
self.gotoTab(@intCast(max));
|
||||||
self.focusCurrentTab();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Go to the specific tab index.
|
/// Go to the specific tab index.
|
||||||
@ -528,6 +533,6 @@ fn actionSurface(self: *Window) ?*CoreSurface {
|
|||||||
return &tab.focus_child.core_surface;
|
return &tab.focus_child.core_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn userdataSelf(ud: *anyopaque) *Window {
|
fn userdataSelf(ud: *anyopaque) *Window {
|
||||||
return @ptrCast(@alignCast(ud));
|
return @ptrCast(@alignCast(ud));
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ const c = @import("c.zig").c;
|
|||||||
const build_options = @import("build_options");
|
const build_options = @import("build_options");
|
||||||
|
|
||||||
const Window = @import("./Window.zig");
|
const Window = @import("./Window.zig");
|
||||||
const userdataSelf = Window.userdataSelf;
|
|
||||||
const Tab = @import("./Tab.zig");
|
const Tab = @import("./Tab.zig");
|
||||||
|
|
||||||
const log = std.log.scoped(.gtk);
|
const log = std.log.scoped(.gtk);
|
||||||
@ -24,7 +23,7 @@ pub const Notebook = union(enum) {
|
|||||||
|
|
||||||
if (!window.app.config.@"gtk-titlebar" or c.ADW_MINOR_VERSION < 4) {
|
if (!window.app.config.@"gtk-titlebar" or c.ADW_MINOR_VERSION < 4) {
|
||||||
const tab_bar = c.adw_tab_bar_new();
|
const tab_bar = c.adw_tab_bar_new();
|
||||||
c.gtk_box_append(@ptrCast(box), @ptrCast(@alignCast(tab_bar)));
|
c.gtk_box_prepend(@ptrCast(box), @ptrCast(@alignCast(tab_bar)));
|
||||||
c.adw_tab_bar_set_view(tab_bar, tab_view);
|
c.adw_tab_bar_set_view(tab_bar, tab_view);
|
||||||
|
|
||||||
if (!window.app.config.@"gtk-wide-tabs")
|
if (!window.app.config.@"gtk-wide-tabs")
|
||||||
@ -310,7 +309,7 @@ fn gtkPageRemoved(
|
|||||||
_: c.guint,
|
_: c.guint,
|
||||||
ud: ?*anyopaque,
|
ud: ?*anyopaque,
|
||||||
) callconv(.C) void {
|
) callconv(.C) void {
|
||||||
const self = userdataSelf(ud.?);
|
const self: *Window = @ptrCast(@alignCast(ud.?));
|
||||||
|
|
||||||
const notebook: *c.GtkNotebook = self.notebook.gtk_notebook;
|
const notebook: *c.GtkNotebook = self.notebook.gtk_notebook;
|
||||||
|
|
||||||
@ -324,7 +323,7 @@ fn gtkPageRemoved(
|
|||||||
fn adwPageAttached(tab_view: *AdwTabView, page: *c.AdwTabPage, position: c_int, ud: ?*anyopaque) callconv(.C) void {
|
fn adwPageAttached(tab_view: *AdwTabView, page: *c.AdwTabPage, position: c_int, ud: ?*anyopaque) callconv(.C) void {
|
||||||
_ = position;
|
_ = position;
|
||||||
_ = tab_view;
|
_ = tab_view;
|
||||||
const self = userdataSelf(ud.?);
|
const self: *Window = @ptrCast(@alignCast(ud.?));
|
||||||
|
|
||||||
const child = c.adw_tab_page_get_child(page);
|
const child = c.adw_tab_page_get_child(page);
|
||||||
const tab: *Tab = @ptrCast(@alignCast(c.g_object_get_data(@ptrCast(child), Tab.GHOSTTY_TAB) orelse return));
|
const tab: *Tab = @ptrCast(@alignCast(c.g_object_get_data(@ptrCast(child), Tab.GHOSTTY_TAB) orelse return));
|
||||||
@ -339,7 +338,7 @@ fn gtkPageAdded(
|
|||||||
page_idx: c.guint,
|
page_idx: c.guint,
|
||||||
ud: ?*anyopaque,
|
ud: ?*anyopaque,
|
||||||
) callconv(.C) void {
|
) callconv(.C) void {
|
||||||
const self = userdataSelf(ud.?);
|
const self: *Window = @ptrCast(@alignCast(ud.?));
|
||||||
|
|
||||||
// The added page can come from another window with drag and drop, thus we migrate the tab
|
// The added page can come from another window with drag and drop, thus we migrate the tab
|
||||||
// window to be self.
|
// window to be self.
|
||||||
@ -358,14 +357,14 @@ fn gtkPageAdded(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn adwSelectPage(_: *c.GObject, _: *c.GParamSpec, ud: ?*anyopaque) void {
|
fn adwSelectPage(_: *c.GObject, _: *c.GParamSpec, ud: ?*anyopaque) void {
|
||||||
const window = userdataSelf(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) 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn gtkSwitchPage(_: *c.GtkNotebook, page: *c.GtkWidget, _: usize, ud: ?*anyopaque) callconv(.C) void {
|
fn gtkSwitchPage(_: *c.GtkNotebook, page: *c.GtkWidget, _: usize, ud: ?*anyopaque) callconv(.C) void {
|
||||||
const window = userdataSelf(ud.?);
|
const window: *Window = @ptrCast(@alignCast(ud.?));
|
||||||
const gtk_label_box = @as(*c.GtkWidget, @ptrCast(c.gtk_notebook_get_tab_label(window.notebook.gtk_notebook, page)));
|
const gtk_label_box = @as(*c.GtkWidget, @ptrCast(c.gtk_notebook_get_tab_label(window.notebook.gtk_notebook, page)));
|
||||||
const gtk_label = @as(*c.GtkLabel, @ptrCast(c.gtk_widget_get_first_child(gtk_label_box)));
|
const gtk_label = @as(*c.GtkLabel, @ptrCast(c.gtk_widget_get_first_child(gtk_label_box)));
|
||||||
const label_text = c.gtk_label_get_text(gtk_label);
|
const label_text = c.gtk_label_get_text(gtk_label);
|
||||||
@ -376,7 +375,7 @@ fn adwTabViewCreateWindow(
|
|||||||
_: *AdwTabView,
|
_: *AdwTabView,
|
||||||
ud: ?*anyopaque,
|
ud: ?*anyopaque,
|
||||||
) callconv(.C) ?*AdwTabView {
|
) callconv(.C) ?*AdwTabView {
|
||||||
const currentWindow = userdataSelf(ud.?);
|
const currentWindow: *Window = @ptrCast(@alignCast(ud.?));
|
||||||
const window = createWindow(currentWindow) catch |err| {
|
const window = createWindow(currentWindow) catch |err| {
|
||||||
log.warn("error creating new window error={}", .{err});
|
log.warn("error creating new window error={}", .{err});
|
||||||
return null;
|
return null;
|
||||||
@ -394,7 +393,7 @@ fn gtkNotebookCreateWindow(
|
|||||||
c.g_object_get_data(@ptrCast(page), Tab.GHOSTTY_TAB) orelse return null,
|
c.g_object_get_data(@ptrCast(page), Tab.GHOSTTY_TAB) orelse return null,
|
||||||
));
|
));
|
||||||
|
|
||||||
const currentWindow = userdataSelf(ud.?);
|
const currentWindow: *Window = @ptrCast(@alignCast(ud.?));
|
||||||
const window = createWindow(currentWindow) catch |err| {
|
const window = createWindow(currentWindow) catch |err| {
|
||||||
log.warn("error creating new window error={}", .{err});
|
log.warn("error creating new window error={}", .{err});
|
||||||
return null;
|
return null;
|
||||||
|
Reference in New Issue
Block a user