diff --git a/src/apprt/gtk/App.zig b/src/apprt/gtk/App.zig index 8210a448d..80749437f 100644 --- a/src/apprt/gtk/App.zig +++ b/src/apprt/gtk/App.zig @@ -392,10 +392,8 @@ fn loadRuntimeCss(config: *const Config, provider: *c.GtkCssProvider) !void { const fmt = \\widget.unfocused-split {{ \\ opacity: {d:.2}; - \\}} - \\.ghostty-surface>stack {{ \\ background-color: rgb({d},{d},{d}); - \\}}" + \\}} ; // The length required is always less than the length of the pre-formatted string: // -> '{d:.2}' gets replaced with max 4 bytes (0.00) @@ -413,7 +411,7 @@ fn loadRuntimeCss(config: *const Config, provider: *c.GtkCssProvider) !void { }, ); // Clears any previously loaded CSS from this provider - c.gtk_css_provider_load_from_string(provider, css); + c.gtk_css_provider_load_from_data(provider, css, @intCast(css.len)); } /// Called by CoreApp to wake up the event loop. diff --git a/src/apprt/gtk/Surface.zig b/src/apprt/gtk/Surface.zig index d9b60bb39..f370a05a8 100644 --- a/src/apprt/gtk/Surface.zig +++ b/src/apprt/gtk/Surface.zig @@ -325,6 +325,9 @@ gl_area: *c.GtkGLArea, /// If non-null this is the widget on the overlay that shows the URL. url_widget: ?URLWidget = null, +/// If non-null this is the widget on the overlay which dims the surface when it is unfocused +unfocused_widget: ?*c.GtkWidget = null, + /// Any active cursor we may have cursor: ?*c.GdkCursor = null, @@ -590,6 +593,10 @@ pub fn deinit(self: *Surface) void { // Free all our GTK stuff c.g_object_unref(self.im_context); if (self.cursor) |cursor| c.g_object_unref(cursor); + if (self.unfocused_widget) |widget| { + c.gtk_overlay_remove_overlay(self.overlay, widget); + self.unfocused_widget = null; + } } // unref removes the long-held reference to the gl_area and kicks off the @@ -1809,8 +1816,11 @@ fn gtkFocusEnter(_: *c.GtkEventControllerFocus, ud: ?*anyopaque) callconv(.C) vo // Notify our IM context c.gtk_im_context_focus_in(self.im_context); - // Unconditionally remove the unfocused split css class - c.gtk_widget_remove_css_class(@ptrCast(@alignCast(self.gl_area)), "unfocused-split"); + // Remove the unfocused widget overlay, if we have one + if (self.unfocused_widget) |widget| { + c.gtk_overlay_remove_overlay(self.overlay, widget); + self.unfocused_widget = null; + } // Notify our surface self.core_surface.focusCallback(true) catch |err| { @@ -1826,11 +1836,16 @@ fn gtkFocusLeave(_: *c.GtkEventControllerFocus, ud: ?*anyopaque) callconv(.C) vo // Notify our IM context c.gtk_im_context_focus_out(self.im_context); - // We only add the unfocused-split class if we are actually a split + // We only add the unfocused-split widget if we are actually a split switch (self.container) { .split_br, .split_tl, - => c.gtk_widget_add_css_class(@ptrCast(@alignCast(self.gl_area)), "unfocused-split"), + => blk: { + if (self.unfocused_widget != null) break :blk; + self.unfocused_widget = c.gtk_drawing_area_new(); + c.gtk_widget_add_css_class(self.unfocused_widget.?, "unfocused-split"); + c.gtk_overlay_add_overlay(self.overlay, self.unfocused_widget.?); + }, else => {}, }