mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +03:00
gtk: use GtkDrawingArea to dim unfocused split
Refactor the GTK unfocused split code to use a GtkDrawingArea widget to dim the unfocused split. The GtkDrawingArea is added to the overlay and a CSS style is used to give it a background color and opacity. This aligns with the macOS design of drawing on top of the surface. In GTK, we don't need to actually draw a rectangle because we can apply CSS directly to the widget.
This commit is contained in:
@ -392,10 +392,8 @@ fn loadRuntimeCss(config: *const Config, provider: *c.GtkCssProvider) !void {
|
|||||||
const fmt =
|
const fmt =
|
||||||
\\widget.unfocused-split {{
|
\\widget.unfocused-split {{
|
||||||
\\ opacity: {d:.2};
|
\\ opacity: {d:.2};
|
||||||
\\}}
|
|
||||||
\\.ghostty-surface>stack {{
|
|
||||||
\\ background-color: rgb({d},{d},{d});
|
\\ background-color: rgb({d},{d},{d});
|
||||||
\\}}"
|
\\}}
|
||||||
;
|
;
|
||||||
// The length required is always less than the length of the pre-formatted string:
|
// The length required is always less than the length of the pre-formatted string:
|
||||||
// -> '{d:.2}' gets replaced with max 4 bytes (0.00)
|
// -> '{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
|
// 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.
|
/// Called by CoreApp to wake up the event loop.
|
||||||
|
@ -325,6 +325,9 @@ gl_area: *c.GtkGLArea,
|
|||||||
/// If non-null this is the widget on the overlay that shows the URL.
|
/// If non-null this is the widget on the overlay that shows the URL.
|
||||||
url_widget: ?URLWidget = null,
|
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
|
/// Any active cursor we may have
|
||||||
cursor: ?*c.GdkCursor = null,
|
cursor: ?*c.GdkCursor = null,
|
||||||
|
|
||||||
@ -590,6 +593,10 @@ pub fn deinit(self: *Surface) void {
|
|||||||
// Free all our GTK stuff
|
// Free all our GTK stuff
|
||||||
c.g_object_unref(self.im_context);
|
c.g_object_unref(self.im_context);
|
||||||
if (self.cursor) |cursor| c.g_object_unref(cursor);
|
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
|
// 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
|
// Notify our IM context
|
||||||
c.gtk_im_context_focus_in(self.im_context);
|
c.gtk_im_context_focus_in(self.im_context);
|
||||||
|
|
||||||
// Unconditionally remove the unfocused split css class
|
// Remove the unfocused widget overlay, if we have one
|
||||||
c.gtk_widget_remove_css_class(@ptrCast(@alignCast(self.gl_area)), "unfocused-split");
|
if (self.unfocused_widget) |widget| {
|
||||||
|
c.gtk_overlay_remove_overlay(self.overlay, widget);
|
||||||
|
self.unfocused_widget = null;
|
||||||
|
}
|
||||||
|
|
||||||
// Notify our surface
|
// Notify our surface
|
||||||
self.core_surface.focusCallback(true) catch |err| {
|
self.core_surface.focusCallback(true) catch |err| {
|
||||||
@ -1826,11 +1836,16 @@ fn gtkFocusLeave(_: *c.GtkEventControllerFocus, ud: ?*anyopaque) callconv(.C) vo
|
|||||||
// Notify our IM context
|
// Notify our IM context
|
||||||
c.gtk_im_context_focus_out(self.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) {
|
switch (self.container) {
|
||||||
.split_br,
|
.split_br,
|
||||||
.split_tl,
|
.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 => {},
|
else => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user