Skip to content

Commit d3f5178

Browse files
committed
gtk: apply initial appearance settings before presenting
Fixes ghostty-org#5934 (only on the GTK side), ghostty-org#5960
1 parent 61f41e5 commit d3f5178

File tree

1 file changed

+45
-30
lines changed

1 file changed

+45
-30
lines changed

src/apprt/gtk/Window.zig

+45-30
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ const configpkg = @import("../../config.zig");
1414
const font = @import("../../font/main.zig");
1515
const input = @import("../../input.zig");
1616
const CoreSurface = @import("../../Surface.zig");
17+
const gtk = @import("gtk");
18+
const gobject = @import("gobject");
1719

1820
const App = @import("App.zig");
1921
const Color = configpkg.Config.Color;
@@ -73,6 +75,7 @@ pub const DerivedConfig = struct {
7375
gtk_wide_tabs: bool,
7476
gtk_toolbar_style: configpkg.Config.GtkToolbarStyle,
7577

78+
title: ?[:0]const u8,
7679
maximize: bool,
7780
fullscreen: bool,
7881
window_decoration: configpkg.Config.WindowDecoration,
@@ -88,6 +91,7 @@ pub const DerivedConfig = struct {
8891
.gtk_wide_tabs = config.@"gtk-wide-tabs",
8992
.gtk_toolbar_style = config.@"gtk-toolbar-style",
9093

94+
.title = config.title,
9195
.maximize = config.maximize,
9296
.fullscreen = config.fullscreen,
9397
.window_decoration = config.@"window-decoration",
@@ -130,17 +134,10 @@ pub fn init(self: *Window, app: *App) !void {
130134

131135
self.window = @ptrCast(@alignCast(gtk_widget));
132136

133-
c.gtk_window_set_title(self.window, "Ghostty");
134-
c.gtk_window_set_default_size(self.window, 1000, 600);
135-
c.gtk_widget_add_css_class(gtk_widget, "window");
136-
c.gtk_widget_add_css_class(gtk_widget, "terminal-window");
137-
138137
// GTK4 grabs F10 input by default to focus the menubar icon. We want
139138
// to disable this so that terminal programs can capture F10 (such as htop)
140139
c.gtk_window_set_handle_menubar_accel(self.window, 0);
141140

142-
c.gtk_window_set_icon_name(self.window, build_config.bundle_id);
143-
144141
// Create our box which will hold our widgets in the main content area.
145142
const box = c.gtk_box_new(c.GTK_ORIENTATION_VERTICAL, 0);
146143

@@ -353,11 +350,7 @@ pub fn init(self: *Window, app: *App) !void {
353350
if (!self.config.gtk_wide_tabs) c.adw_tab_bar_set_expand_tabs(tab_bar, 0);
354351
}
355352

356-
// If we want the window to be maximized, we do that here.
357-
if (self.config.maximize) c.gtk_window_maximize(self.window);
358-
359-
// If we are in fullscreen mode, new windows start fullscreen.
360-
if (self.config.fullscreen) c.gtk_window_fullscreen(self.window);
353+
try self.initAppearance();
361354

362355
// Show the window
363356
c.gtk_widget_show(gtk_widget);
@@ -367,9 +360,13 @@ pub fn updateConfig(
367360
self: *Window,
368361
config: *const configpkg.Config,
369362
) !void {
370-
// avoid multiple reconfigs when we have many surfaces contained in this
371-
// window using the integer value of config as a simple marker to know if
372-
// we've "seen" this particular config before
363+
// HACK:
364+
// Avoid multiple reconfigs when we have many surfaces contained in this
365+
// window using the integer value of the config pointer as a simple marker
366+
// to know if we've "seen" this particular config before.
367+
//
368+
// For the long run we should try to make the flow of config updates saner
369+
// and avoid manual deduplication. See #5947 for more information.
373370
const this_config = @intFromPtr(config);
374371
if (self.last_config == this_config) return;
375372
self.last_config = this_config;
@@ -380,23 +377,47 @@ pub fn updateConfig(
380377
try self.syncAppearance();
381378
}
382379

380+
/// Initializes the appearance of the window.
381+
///
382+
/// Not all appearance changes *should* be applied when a config option is
383+
/// reloaded (for instance, the maximize and fullscreen settings should only
384+
/// apply to new windows), so we apply them here.
385+
pub fn initAppearance(self: *Window) !void {
386+
// FIXME: Remove once self.window has been migrated to use zig-gobject
387+
const window: *gtk.Window = @ptrCast(self.window);
388+
389+
window.setTitle(self.config.title orelse "Ghostty");
390+
window.setDefaultSize(1000, 600);
391+
window.as(gtk.Widget).addCssClass("window");
392+
window.as(gtk.Widget).addCssClass("terminal-window");
393+
window.setIconName(build_config.bundle_id);
394+
395+
if (self.config.maximize) window.maximize();
396+
if (self.config.fullscreen) window.fullscreen();
397+
398+
try self.syncAppearance();
399+
}
400+
383401
/// Updates appearance based on config settings. Will be called once upon window
384402
/// realization, every time the config is reloaded, and every time a window state
385403
/// is toggled (un-/maximized, un-/fullscreened, window decorations toggled, etc.)
386404
///
387405
/// TODO: Many of the initial style settings in `create` could possibly be made
388406
/// reactive by moving them here.
389407
pub fn syncAppearance(self: *Window) !void {
408+
// FIXME: Remove once self.window has been migrated to use zig-gobject
409+
const window: *gtk.Window = @ptrCast(self.window);
410+
390411
const csd_enabled = self.winproto.clientSideDecorationEnabled();
391-
c.gtk_window_set_decorated(self.window, @intFromBool(csd_enabled));
412+
window.setDecorated(@intFromBool(csd_enabled));
392413

393414
// Fix any artifacting that may occur in window corners. The .ssd CSS
394415
// class is defined in the GtkWindow documentation:
395416
// https://docs.gtk.org/gtk4/class.Window.html#css-nodes. A definition
396417
// for .ssd is provided by GTK and Adwaita.
397-
toggleCssClass(@ptrCast(self.window), "csd", csd_enabled);
398-
toggleCssClass(@ptrCast(self.window), "ssd", !csd_enabled);
399-
toggleCssClass(@ptrCast(self.window), "no-border-radius", !csd_enabled);
418+
toggleCssClass(window, "csd", csd_enabled);
419+
toggleCssClass(window, "ssd", !csd_enabled);
420+
toggleCssClass(window, "no-border-radius", !csd_enabled);
400421

401422
self.headerbar.setVisible(visible: {
402423
// Never display the header bar when CSDs are disabled.
@@ -414,7 +435,7 @@ pub fn syncAppearance(self: *Window) !void {
414435
});
415436

416437
toggleCssClass(
417-
@ptrCast(self.window),
438+
window,
418439
"background",
419440
self.config.background_opacity >= 1,
420441
);
@@ -423,7 +444,7 @@ pub fn syncAppearance(self: *Window) !void {
423444
// GTK version is before 4.16. The conditional is because above 4.16
424445
// we use GTK CSS color variables.
425446
toggleCssClass(
426-
@ptrCast(self.window),
447+
window,
427448
"window-theme-ghostty",
428449
!version.atLeast(4, 16, 0) and self.config.window_theme == .ghostty,
429450
);
@@ -451,23 +472,17 @@ pub fn syncAppearance(self: *Window) !void {
451472
self.winproto.syncAppearance() catch |err| {
452473
log.warn("failed to sync winproto appearance error={}", .{err});
453474
};
454-
455-
toggleCssClass(
456-
@ptrCast(self.window),
457-
"background",
458-
self.config.background_opacity >= 1,
459-
);
460475
}
461476

462477
fn toggleCssClass(
463-
widget: *c.GtkWidget,
478+
widget: anytype,
464479
class: [:0]const u8,
465480
v: bool,
466481
) void {
467482
if (v) {
468-
c.gtk_widget_add_css_class(widget, class);
483+
widget.as(gtk.Widget).addCssClass(class);
469484
} else {
470-
c.gtk_widget_remove_css_class(widget, class);
485+
widget.as(gtk.Widget).removeCssClass(class);
471486
}
472487
}
473488

0 commit comments

Comments
 (0)