apprt/gtk-ng: hook up all the syncAppearance calls for winproto
parent
c7eee9ee7a
commit
084a20c865
|
|
@ -503,7 +503,17 @@ pub const Window = extern struct {
|
|||
/// happens that might affect how the window appears (config change,
|
||||
/// fullscreen, etc.).
|
||||
fn syncAppearance(self: *Self) void {
|
||||
// TODO: CSD/SSD
|
||||
const priv = self.private();
|
||||
const csd_enabled = priv.winproto.clientSideDecorationEnabled();
|
||||
self.as(gtk.Window).setDecorated(@intFromBool(csd_enabled));
|
||||
|
||||
// Fix any artifacting that may occur in window corners. The .ssd CSS
|
||||
// class is defined in the GtkWindow documentation:
|
||||
// https://docs.gtk.org/gtk4/class.Window.html#css-nodes. A definition
|
||||
// for .ssd is provided by GTK and Adwaita.
|
||||
self.toggleCssClass("csd", csd_enabled);
|
||||
self.toggleCssClass("ssd", !csd_enabled);
|
||||
self.toggleCssClass("no-border-radius", !csd_enabled);
|
||||
|
||||
// Trigger all our dynamic properties that depend on the config.
|
||||
inline for (&.{
|
||||
|
|
@ -520,15 +530,28 @@ pub const Window = extern struct {
|
|||
}
|
||||
|
||||
// Remainder uses the config
|
||||
const priv = self.private();
|
||||
const config = if (priv.config) |v| v.get() else return;
|
||||
|
||||
// Apply class to color headerbar if window-theme is set to `ghostty` and
|
||||
// GTK version is before 4.16. The conditional is because above 4.16
|
||||
// we use GTK CSS color variables.
|
||||
self.toggleCssClass(
|
||||
"window-theme-ghostty",
|
||||
!gtk_version.atLeast(4, 16, 0) and
|
||||
config.@"window-theme" == .ghostty,
|
||||
);
|
||||
|
||||
// Move the tab bar to the proper location.
|
||||
priv.toolbar.remove(priv.tab_bar.as(gtk.Widget));
|
||||
switch (config.@"gtk-tabs-location") {
|
||||
.top => priv.toolbar.addTopBar(priv.tab_bar.as(gtk.Widget)),
|
||||
.bottom => priv.toolbar.addBottomBar(priv.tab_bar.as(gtk.Widget)),
|
||||
}
|
||||
|
||||
// Do our window-protocol specific appearance sync.
|
||||
priv.winproto.syncAppearance() catch |err| {
|
||||
log.warn("failed to sync winproto appearance error={}", .{err});
|
||||
};
|
||||
}
|
||||
|
||||
fn toggleCssClass(self: *Self, class: [:0]const u8, value: bool) void {
|
||||
|
|
@ -614,8 +637,14 @@ pub const Window = extern struct {
|
|||
}
|
||||
|
||||
fn getHeaderbarVisible(self: *Self) bool {
|
||||
// TODO: CSD/SSD
|
||||
// TODO: QuickTerminal
|
||||
const priv = self.private();
|
||||
|
||||
// Never display the header bar when CSDs are disabled.
|
||||
const csd_enabled = priv.winproto.clientSideDecorationEnabled();
|
||||
if (!csd_enabled) return false;
|
||||
|
||||
// Never display the header bar as a quick terminal.
|
||||
if (priv.quick_terminal) return false;
|
||||
|
||||
// If we're fullscreen we never show the header bar.
|
||||
if (self.as(gtk.Window).isFullscreen() != 0) return false;
|
||||
|
|
@ -749,6 +778,24 @@ pub const Window = extern struct {
|
|||
self.toggleCssClass("background", self.getBackgroundOpaque());
|
||||
}
|
||||
|
||||
fn propScaleFactor(
|
||||
_: *adw.ApplicationWindow,
|
||||
_: *gobject.ParamSpec,
|
||||
self: *Self,
|
||||
) callconv(.c) void {
|
||||
// On some platforms (namely X11) we need to refresh our appearance when
|
||||
// the scale factor changes. In theory this could be more fine-grained as
|
||||
// a full refresh could be expensive, but a) this *should* be rare, and
|
||||
// b) quite noticeable visual bugs would occur if this is not present.
|
||||
self.private().winproto.syncAppearance() catch |err| {
|
||||
log.warn(
|
||||
"failed to sync appearance after scale factor has been updated={}",
|
||||
.{err},
|
||||
);
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Virtual methods
|
||||
|
||||
|
|
@ -1451,11 +1498,12 @@ pub const Window = extern struct {
|
|||
class.bindTemplateCallback("tab_create_window", &tabViewCreateWindow);
|
||||
class.bindTemplateCallback("notify_n_pages", &tabViewNPages);
|
||||
class.bindTemplateCallback("notify_selected_page", &tabViewSelectedPage);
|
||||
class.bindTemplateCallback("notify_background_opaque", &propBackgroundOpaque);
|
||||
class.bindTemplateCallback("notify_config", &propConfig);
|
||||
class.bindTemplateCallback("notify_fullscreened", &propFullscreened);
|
||||
class.bindTemplateCallback("notify_maximized", &propMaximized);
|
||||
class.bindTemplateCallback("notify_menu_active", &propMenuActive);
|
||||
class.bindTemplateCallback("notify_background_opaque", &propBackgroundOpaque);
|
||||
class.bindTemplateCallback("notify_scale_factor", &propScaleFactor);
|
||||
|
||||
// Virtual methods
|
||||
gobject.Object.virtual_methods.dispose.implement(class, &dispose);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,14 @@
|
|||
* https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1.3/styles-and-appearance.html#custom-styles
|
||||
*/
|
||||
|
||||
window.ssd.no-border-radius {
|
||||
/* Without clearing the border radius, at least on Mutter with
|
||||
* gtk-titlebar=true and gtk-adwaita=false, there is some window artifacting
|
||||
* that this will mitigate.
|
||||
*/
|
||||
border-radius: 0 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* GhosttySurface URL overlay
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@ template $GhosttyWindow: Adw.ApplicationWindow {
|
|||
|
||||
close-request => $close_request();
|
||||
realize => $realize();
|
||||
notify::background-opaque => $notify_background_opaque();
|
||||
notify::config => $notify_config();
|
||||
notify::fullscreened => $notify_fullscreened();
|
||||
notify::maximized => $notify_maximized();
|
||||
notify::background-opaque => $notify_background_opaque();
|
||||
notify::scale-factor => $notify_scale_factor();
|
||||
default-width: 800;
|
||||
default-height: 600;
|
||||
// GTK4 grabs F10 input by default to focus the menubar icon. We want
|
||||
|
|
@ -21,8 +22,13 @@ template $GhosttyWindow: Adw.ApplicationWindow {
|
|||
content: Adw.TabOverview tab_overview {
|
||||
create-tab => $overview_create_tab();
|
||||
notify::open => $overview_notify_open();
|
||||
enable-new-tab: true;
|
||||
view: tab_view;
|
||||
enable-new-tab: true;
|
||||
// Disable the title buttons (close, maximize, minimize, ...)
|
||||
// *inside* the tab overview if CSDs are disabled.
|
||||
// We do spare the search button, though.
|
||||
show-start-title-buttons: bind template.decorated;
|
||||
show-end-title-buttons: bind template.decorated;
|
||||
|
||||
Adw.ToolbarView toolbar {
|
||||
top-bar-style: bind template.toolbar-style;
|
||||
|
|
|
|||
|
|
@ -364,7 +364,11 @@ pub const Window = struct {
|
|||
/// Update the blur state of the window.
|
||||
fn syncBlur(self: *Window) !void {
|
||||
const manager = self.app_context.kde_blur_manager orelse return;
|
||||
const blur = self.apprt_window.config.background_blur;
|
||||
const config = if (self.apprt_window.getConfig()) |v|
|
||||
v.get()
|
||||
else
|
||||
return;
|
||||
const blur = config.@"background-blur";
|
||||
|
||||
if (self.blur_token) |tok| {
|
||||
// Only release token when transitioning from blurred -> not blurred
|
||||
|
|
@ -392,7 +396,12 @@ pub const Window = struct {
|
|||
}
|
||||
|
||||
fn getDecorationMode(self: Window) org.KdeKwinServerDecorationManager.Mode {
|
||||
return switch (self.apprt_window.config.window_decoration) {
|
||||
const config = if (self.apprt_window.getConfig()) |v|
|
||||
v.get()
|
||||
else
|
||||
return .Client;
|
||||
|
||||
return switch (config.@"window-decoration") {
|
||||
.auto => self.app_context.default_deco_mode orelse .Client,
|
||||
.client => .Client,
|
||||
.server => .Server,
|
||||
|
|
@ -401,12 +410,15 @@ pub const Window = struct {
|
|||
}
|
||||
|
||||
fn syncQuickTerminal(self: *Window) !void {
|
||||
const window = self.apprt_window.window.as(gtk.Window);
|
||||
const config = &self.apprt_window.config;
|
||||
const window = self.apprt_window.as(gtk.Window);
|
||||
const config = if (self.apprt_window.getConfig()) |v|
|
||||
v.get()
|
||||
else
|
||||
return;
|
||||
|
||||
layer_shell.setKeyboardMode(
|
||||
window,
|
||||
switch (config.quick_terminal_keyboard_interactivity) {
|
||||
switch (config.@"quick-terminal-keyboard-interactivity") {
|
||||
.none => .none,
|
||||
.@"on-demand" => on_demand: {
|
||||
if (layer_shell.getProtocolVersion() < 4) {
|
||||
|
|
@ -419,7 +431,7 @@ pub const Window = struct {
|
|||
},
|
||||
);
|
||||
|
||||
const anchored_edge: ?layer_shell.ShellEdge = switch (config.quick_terminal_position) {
|
||||
const anchored_edge: ?layer_shell.ShellEdge = switch (config.@"quick-terminal-position") {
|
||||
.left => .left,
|
||||
.right => .right,
|
||||
.top => .top,
|
||||
|
|
|
|||
|
|
@ -239,7 +239,12 @@ pub const Window = struct {
|
|||
}
|
||||
|
||||
pub fn clientSideDecorationEnabled(self: Window) bool {
|
||||
return switch (self.config.window_decoration) {
|
||||
const config = if (self.apprt_window.getConfig()) |v|
|
||||
v.get()
|
||||
else
|
||||
return true;
|
||||
|
||||
return switch (config.@"window-decoration") {
|
||||
.auto, .client => true,
|
||||
.server, .none => false,
|
||||
};
|
||||
|
|
@ -255,13 +260,14 @@ pub const Window = struct {
|
|||
// (Wayland also has this visual artifact anyway...)
|
||||
|
||||
const gtk_widget = self.apprt_window.as(gtk.Widget);
|
||||
const config = if (self.apprt_window.getConfig()) |v| v.get() else return;
|
||||
|
||||
// Transform surface coordinates to device coordinates.
|
||||
const scale = self.apprt_window.as(gtk.Widget).getScaleFactor();
|
||||
const scale = gtk_widget.getScaleFactor();
|
||||
self.blur_region.width = gtk_widget.getWidth() * scale;
|
||||
self.blur_region.height = gtk_widget.getHeight() * scale;
|
||||
|
||||
const blur = self.config.background_blur;
|
||||
const blur = config.@"background-blur";
|
||||
log.debug("set blur={}, window xid={}, region={}", .{
|
||||
blur,
|
||||
self.x11_surface.getXid(),
|
||||
|
|
@ -283,6 +289,11 @@ pub const Window = struct {
|
|||
}
|
||||
|
||||
fn syncDecorations(self: *Window) !void {
|
||||
const config = if (self.apprt_window.getConfig()) |v|
|
||||
v.get()
|
||||
else
|
||||
return;
|
||||
|
||||
var hints: MotifWMHints = .{};
|
||||
|
||||
self.getWindowProperty(
|
||||
|
|
@ -303,7 +314,7 @@ pub const Window = struct {
|
|||
};
|
||||
|
||||
hints.flags.decorations = true;
|
||||
hints.decorations.all = switch (self.config.window_decoration) {
|
||||
hints.decorations.all = switch (config.@"window-decoration") {
|
||||
.server => true,
|
||||
.auto, .client, .none => false,
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue