diff --git a/src/apprt/gtk/Tab.zig b/src/apprt/gtk/Tab.zig index b01212945..d0cce3650 100644 --- a/src/apprt/gtk/Tab.zig +++ b/src/apprt/gtk/Tab.zig @@ -2,7 +2,8 @@ const Tab = @This(); const std = @import("std"); const Allocator = std.mem.Allocator; - +const font = @import("../../font/main.zig"); +const CoreSurface = @import("../../Surface.zig"); const Paned = @import("Paned.zig"); const Surface = @import("Surface.zig"); const Window = @import("Window.zig"); @@ -26,13 +27,13 @@ child: Child, // can easily re-focus that terminal. focus_child: *Surface, -pub fn create(alloc: Allocator, window: *Window) !*Tab { +pub fn create(alloc: Allocator, window: *Window, parent_: ?*CoreSurface) !*Tab { var tab = try alloc.create(Tab); errdefer alloc.destroy(tab); - try tab.init(window); + try tab.init(window, _parent); } -pub fn init(self: *Tab, window: *Window) !void { +pub fn init(self: *Tab, window: *Window, parent_: ?*CoreSurface) !void { self.* = .{ .window = window, .label_text = undefined, @@ -42,6 +43,17 @@ pub fn init(self: *Tab, window: *Window) !void { .focus_child = undefined, }; + // Grab a surface allocation we'll need it later. + var surface = try self.app.core_app.alloc.create(Surface); + errdefer self.app.core_app.alloc.destroy(surface); + + // Inherit the parent's font size if we are configured to. + const font_size: ?font.face.DesiredSize = font_size: { + if (!window.app.config.@"window-inherit-font-size") break :font_size null; + const parent = parent_ orelse break :font_size null; + break :font_size parent.font_size; + }; + // Build the tab label const label_box_widget = c.gtk_box_new(c.GTK_ORIENTATION_HORIZONTAL, 0); const label_box: *c.GtkBox = @ptrCast(label_box_widget); @@ -54,8 +66,60 @@ pub fn init(self: *Tab, window: *Window) !void { c.gtk_button_has_frame(label_close, 0); c.gtk_box_append(label_box, label_close_widget); self.close_button = label_close; + + _ = c.g_signal_connect_data(label_close, "clicked", c.G_CALLBACK(>kTabCloseClick), surface, null, c.G_CONNECT_DEFAULT); + + // Wide style GTK tabs + if (self.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, 1); + c.gtk_widget_set_halign(label_text, c.GTK_ALIGN_FILL); + } + const box_widget = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0); - const box: *c.GtkBox = @ptrCast(box_widget); - self.box = box; - // todo - write the rest of function and initialize a new Surface + c.gtk_widget_set_hexpand(box_widget, 1); + c.gtk_widget_set_vexpand(box_widget, 1); + self.box = ptrCast(box_widget); + + // Initialize the GtkGLArea and attach it to our surface. + // The surface starts in the "unrealized" state because we have to + // wait for the "realize" callback from GTK to know that the OpenGL + // context is ready. See Surface docs for more info. + const gl_area = c.gtk_gl_area_new(); + c.gtk_widget_set_hexpand(gl_area, 1); + c.gtk_widget_set_vexpand(gl_area, 1); + try surface.init(self.app, .{ + .window = self, + .gl_area = @ptrCast(gl_area), + .title_label = @ptrCast(label_text), + .font_size = font_size, + }); + errdefer surface.deinit(); + + c.gtk_box_pack_start(self.box, gl_area); + const page_idx = c.gtk_notebook_append_page(self.notebook, box_widget, label_box_widget); + if (page_idx < 0) { + log.warn("failed to add page to notebook", .{}); + return error.GtkAppendPageFailed; + } + + // Tab settings + c.gtk_notebook_set_tab_reorderable(self.notebook, gl_area, 1); + c.gtk_notebook_set_tab_detachable(self.notebook, gl_area, 1); + + // If we have multiple tabs, show the tab bar. + if (c.gtk_notebook_get_n_pages(self.notebook) > 1) { + c.gtk_notebook_set_show_tabs(self.notebook, 1); + } + + // Set the userdata of the close button so it points to this page. + c.g_object_set_data(@ptrCast(box), GHOSTTY_TAB, self); + + // Switch to the new tab + c.gtk_notebook_set_current_page(self.notebook, page_idx); + + // We need to grab focus after it is added to the window. When + // creating a window we want to always focus on the widget. + _ = c.gtk_widget_grab_focus(box_widget); }