mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-25 13:16:11 +03:00
apprt/gtk-ng: child exited overlay (#8044)
This ports the child exited overlay. We're able to use Zig comptime and Blueprint templates to use the same Surface blueprint for this even if libadwaita is too old to support banners (< 1.3) by inheriting from `gtk.Widget` instead and not instantiating the blueprint. Its a bit noisy to maintain the `noop` version but we should be able to test that compilation in CI (we do via Debian 12).
This commit is contained in:
@ -39,6 +39,7 @@ pub const blueprints: []const Blueprint = &.{
|
|||||||
.{ .major = 1, .minor = 2, .name = "config-errors-dialog" },
|
.{ .major = 1, .minor = 2, .name = "config-errors-dialog" },
|
||||||
.{ .major = 1, .minor = 2, .name = "resize-overlay" },
|
.{ .major = 1, .minor = 2, .name = "resize-overlay" },
|
||||||
.{ .major = 1, .minor = 2, .name = "surface" },
|
.{ .major = 1, .minor = 2, .name = "surface" },
|
||||||
|
.{ .major = 1, .minor = 3, .name = "surface-child-exited" },
|
||||||
.{ .major = 1, .minor = 5, .name = "window" },
|
.{ .major = 1, .minor = 5, .name = "window" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -485,6 +485,8 @@ pub const Application = extern struct {
|
|||||||
|
|
||||||
.set_title => Action.setTitle(target, value),
|
.set_title => Action.setTitle(target, value),
|
||||||
|
|
||||||
|
.show_child_exited => return Action.showChildExited(target, value),
|
||||||
|
|
||||||
.show_gtk_inspector => Action.showGtkInspector(),
|
.show_gtk_inspector => Action.showGtkInspector(),
|
||||||
|
|
||||||
// Unimplemented but todo on gtk-ng branch
|
// Unimplemented but todo on gtk-ng branch
|
||||||
@ -514,7 +516,6 @@ pub const Application = extern struct {
|
|||||||
.ring_bell,
|
.ring_bell,
|
||||||
.toggle_command_palette,
|
.toggle_command_palette,
|
||||||
.open_url,
|
.open_url,
|
||||||
.show_child_exited,
|
|
||||||
.close_all_windows,
|
.close_all_windows,
|
||||||
.float_window,
|
.float_window,
|
||||||
.toggle_visibility,
|
.toggle_visibility,
|
||||||
@ -1141,6 +1142,16 @@ const Action = struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn showChildExited(
|
||||||
|
target: apprt.Target,
|
||||||
|
value: apprt.surface.Message.ChildExited,
|
||||||
|
) bool {
|
||||||
|
return switch (target) {
|
||||||
|
.app => false,
|
||||||
|
.surface => |v| v.rt_surface.surface.childExited(value),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn showGtkInspector() void {
|
pub fn showGtkInspector() void {
|
||||||
gtk.Window.setInteractiveDebugging(@intFromBool(true));
|
gtk.Window.setInteractiveDebugging(@intFromBool(true));
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ const Common = @import("../class.zig").Common;
|
|||||||
const Application = @import("application.zig").Application;
|
const Application = @import("application.zig").Application;
|
||||||
const Config = @import("config.zig").Config;
|
const Config = @import("config.zig").Config;
|
||||||
const ResizeOverlay = @import("resize_overlay.zig").ResizeOverlay;
|
const ResizeOverlay = @import("resize_overlay.zig").ResizeOverlay;
|
||||||
|
const ChildExited = @import("surface_child_exited.zig").SurfaceChildExited;
|
||||||
const ClipboardConfirmationDialog = @import("clipboard_confirmation_dialog.zig").ClipboardConfirmationDialog;
|
const ClipboardConfirmationDialog = @import("clipboard_confirmation_dialog.zig").ClipboardConfirmationDialog;
|
||||||
|
|
||||||
const log = std.log.scoped(.gtk_ghostty_surface);
|
const log = std.log.scoped(.gtk_ghostty_surface);
|
||||||
@ -57,6 +58,26 @@ pub const Surface = extern struct {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const @"child-exited" = struct {
|
||||||
|
pub const name = "child-exited";
|
||||||
|
const impl = gobject.ext.defineProperty(
|
||||||
|
name,
|
||||||
|
Self,
|
||||||
|
bool,
|
||||||
|
.{
|
||||||
|
.nick = "Child Exited",
|
||||||
|
.blurb = "True when the child process has exited.",
|
||||||
|
.default = false,
|
||||||
|
.accessor = gobject.ext.privateFieldAccessor(
|
||||||
|
Self,
|
||||||
|
Private,
|
||||||
|
&Private.offset,
|
||||||
|
"child_exited",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
pub const focused = struct {
|
pub const focused = struct {
|
||||||
pub const name = "focused";
|
pub const name = "focused";
|
||||||
const impl = gobject.ext.defineProperty(
|
const impl = gobject.ext.defineProperty(
|
||||||
@ -284,7 +305,11 @@ pub const Surface = extern struct {
|
|||||||
/// True when we have a precision scroll in progress
|
/// True when we have a precision scroll in progress
|
||||||
precision_scroll: bool = false,
|
precision_scroll: bool = false,
|
||||||
|
|
||||||
|
/// True when the child has exited.
|
||||||
|
child_exited: bool = false,
|
||||||
|
|
||||||
// Template binds
|
// Template binds
|
||||||
|
child_exited_overlay: *ChildExited,
|
||||||
drop_target: *gtk.DropTarget,
|
drop_target: *gtk.DropTarget,
|
||||||
|
|
||||||
pub var offset: c_int = 0;
|
pub var offset: c_int = 0;
|
||||||
@ -634,6 +659,26 @@ pub const Surface = extern struct {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn childExited(
|
||||||
|
self: *Self,
|
||||||
|
data: apprt.surface.Message.ChildExited,
|
||||||
|
) bool {
|
||||||
|
// If we have the noop child exited overlay then we don't do anything
|
||||||
|
// for child exited. The false return will force libghostty to show
|
||||||
|
// the normal text-based message.
|
||||||
|
if (comptime @hasDecl(ChildExited, "noop")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const priv = self.private();
|
||||||
|
priv.child_exited = true;
|
||||||
|
priv.child_exited_overlay.setData(&data);
|
||||||
|
self.as(gobject.Object).notifyByPspec(
|
||||||
|
properties.@"child-exited".impl.param_spec,
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cgroupPath(self: *Self) ?[]const u8 {
|
pub fn cgroupPath(self: *Self) ?[]const u8 {
|
||||||
return self.private().cgroup_path;
|
return self.private().cgroup_path;
|
||||||
}
|
}
|
||||||
@ -1015,6 +1060,14 @@ pub const Surface = extern struct {
|
|||||||
//---------------------------------------------------------------
|
//---------------------------------------------------------------
|
||||||
// Signal Handlers
|
// Signal Handlers
|
||||||
|
|
||||||
|
fn childExitedClose(
|
||||||
|
_: *ChildExited,
|
||||||
|
self: *Self,
|
||||||
|
) callconv(.c) void {
|
||||||
|
// This closes the surface with no confirmation.
|
||||||
|
self.close(false);
|
||||||
|
}
|
||||||
|
|
||||||
fn dtDrop(
|
fn dtDrop(
|
||||||
_: *gtk.DropTarget,
|
_: *gtk.DropTarget,
|
||||||
value: *gobject.Value,
|
value: *gobject.Value,
|
||||||
@ -1762,6 +1815,7 @@ pub const Surface = extern struct {
|
|||||||
|
|
||||||
fn init(class: *Class) callconv(.C) void {
|
fn init(class: *Class) callconv(.C) void {
|
||||||
gobject.ext.ensureType(ResizeOverlay);
|
gobject.ext.ensureType(ResizeOverlay);
|
||||||
|
gobject.ext.ensureType(ChildExited);
|
||||||
gtk.Widget.Class.setTemplateFromResource(
|
gtk.Widget.Class.setTemplateFromResource(
|
||||||
class.as(gtk.Widget.Class),
|
class.as(gtk.Widget.Class),
|
||||||
comptime gresource.blueprint(.{
|
comptime gresource.blueprint(.{
|
||||||
@ -1775,6 +1829,7 @@ pub const Surface = extern struct {
|
|||||||
class.bindTemplateChildPrivate("gl_area", .{});
|
class.bindTemplateChildPrivate("gl_area", .{});
|
||||||
class.bindTemplateChildPrivate("url_left", .{});
|
class.bindTemplateChildPrivate("url_left", .{});
|
||||||
class.bindTemplateChildPrivate("url_right", .{});
|
class.bindTemplateChildPrivate("url_right", .{});
|
||||||
|
class.bindTemplateChildPrivate("child_exited_overlay", .{});
|
||||||
class.bindTemplateChildPrivate("resize_overlay", .{});
|
class.bindTemplateChildPrivate("resize_overlay", .{});
|
||||||
class.bindTemplateChildPrivate("drop_target", .{});
|
class.bindTemplateChildPrivate("drop_target", .{});
|
||||||
class.bindTemplateChildPrivate("im_context", .{});
|
class.bindTemplateChildPrivate("im_context", .{});
|
||||||
@ -1802,6 +1857,7 @@ pub const Surface = extern struct {
|
|||||||
class.bindTemplateCallback("im_commit", &imCommit);
|
class.bindTemplateCallback("im_commit", &imCommit);
|
||||||
class.bindTemplateCallback("url_mouse_enter", &ecUrlMouseEnter);
|
class.bindTemplateCallback("url_mouse_enter", &ecUrlMouseEnter);
|
||||||
class.bindTemplateCallback("url_mouse_leave", &ecUrlMouseLeave);
|
class.bindTemplateCallback("url_mouse_leave", &ecUrlMouseLeave);
|
||||||
|
class.bindTemplateCallback("child_exited_close", &childExitedClose);
|
||||||
class.bindTemplateCallback("notify_config", &propConfig);
|
class.bindTemplateCallback("notify_config", &propConfig);
|
||||||
class.bindTemplateCallback("notify_mouse_hover_url", &propMouseHoverUrl);
|
class.bindTemplateCallback("notify_mouse_hover_url", &propMouseHoverUrl);
|
||||||
class.bindTemplateCallback("notify_mouse_hidden", &propMouseHidden);
|
class.bindTemplateCallback("notify_mouse_hidden", &propMouseHidden);
|
||||||
@ -1810,6 +1866,7 @@ pub const Surface = extern struct {
|
|||||||
// Properties
|
// Properties
|
||||||
gobject.ext.registerProperties(class, &.{
|
gobject.ext.registerProperties(class, &.{
|
||||||
properties.config.impl,
|
properties.config.impl,
|
||||||
|
properties.@"child-exited".impl,
|
||||||
properties.focused.impl,
|
properties.focused.impl,
|
||||||
properties.@"mouse-shape".impl,
|
properties.@"mouse-shape".impl,
|
||||||
properties.@"mouse-hidden".impl,
|
properties.@"mouse-hidden".impl,
|
||||||
|
272
src/apprt/gtk-ng/class/surface_child_exited.zig
Normal file
272
src/apprt/gtk-ng/class/surface_child_exited.zig
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const assert = std.debug.assert;
|
||||||
|
const adw = @import("adw");
|
||||||
|
const glib = @import("glib");
|
||||||
|
const gobject = @import("gobject");
|
||||||
|
const gtk = @import("gtk");
|
||||||
|
|
||||||
|
const adw_version = @import("../adw_version.zig");
|
||||||
|
const apprt = @import("../../../apprt.zig");
|
||||||
|
const gresource = @import("../build/gresource.zig");
|
||||||
|
const i18n = @import("../../../os/main.zig").i18n;
|
||||||
|
const Common = @import("../class.zig").Common;
|
||||||
|
|
||||||
|
const log = std.log.scoped(.gtk_ghostty_surface_child_exited);
|
||||||
|
|
||||||
|
pub const SurfaceChildExited = if (adw_version.supportsBanner())
|
||||||
|
SurfaceChildExitedBanner
|
||||||
|
else
|
||||||
|
SurfaceChildExitedNoop;
|
||||||
|
|
||||||
|
/// Child exited overlay based on adw.Banner introduced in
|
||||||
|
/// Adwaita 1.3.
|
||||||
|
const SurfaceChildExitedBanner = extern struct {
|
||||||
|
const Self = @This();
|
||||||
|
parent_instance: Parent,
|
||||||
|
pub const Parent = adw.Bin;
|
||||||
|
pub const getGObjectType = gobject.ext.defineClass(Self, .{
|
||||||
|
.name = "GhosttySurfaceChildExited",
|
||||||
|
.instanceInit = &init,
|
||||||
|
.classInit = &Class.init,
|
||||||
|
.parent_class = &Class.parent,
|
||||||
|
.private = .{ .Type = Private, .offset = &Private.offset },
|
||||||
|
});
|
||||||
|
|
||||||
|
pub const properties = struct {
|
||||||
|
pub const data = struct {
|
||||||
|
pub const name = "data";
|
||||||
|
const impl = gobject.ext.defineProperty(
|
||||||
|
name,
|
||||||
|
Self,
|
||||||
|
?*apprt.surface.Message.ChildExited,
|
||||||
|
.{
|
||||||
|
.nick = "Data",
|
||||||
|
.blurb = "The child exit data.",
|
||||||
|
.accessor = gobject.ext.privateFieldAccessor(
|
||||||
|
Self,
|
||||||
|
Private,
|
||||||
|
&Private.offset,
|
||||||
|
"data",
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const signals = struct {
|
||||||
|
/// Emitted when the banner would like to be closed.
|
||||||
|
pub const @"close-request" = struct {
|
||||||
|
pub const name = "close-request";
|
||||||
|
pub const connect = impl.connect;
|
||||||
|
const impl = gobject.ext.defineSignal(
|
||||||
|
name,
|
||||||
|
Self,
|
||||||
|
&.{},
|
||||||
|
void,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const Private = struct {
|
||||||
|
/// The child exited data sent by the apprt.
|
||||||
|
data: ?*apprt.surface.Message.ChildExited = null,
|
||||||
|
|
||||||
|
// Template bindings
|
||||||
|
banner: *adw.Banner,
|
||||||
|
|
||||||
|
pub var offset: c_int = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
fn init(self: *Self, _: *Class) callconv(.C) void {
|
||||||
|
gtk.Widget.initTemplate(self.as(gtk.Widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setData(
|
||||||
|
self: *Self,
|
||||||
|
data_: ?*const apprt.surface.Message.ChildExited,
|
||||||
|
) void {
|
||||||
|
const priv = self.private();
|
||||||
|
if (priv.data) |v| glib.ext.destroy(v);
|
||||||
|
const data = data_ orelse {
|
||||||
|
priv.data = null;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ptr = glib.ext.create(apprt.surface.Message.ChildExited);
|
||||||
|
ptr.* = data.*;
|
||||||
|
priv.data = ptr;
|
||||||
|
self.as(gobject.Object).notifyByPspec(properties.data.impl.param_spec);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Signal handlers
|
||||||
|
|
||||||
|
fn propData(
|
||||||
|
self: *Self,
|
||||||
|
_: *gobject.ParamSpec,
|
||||||
|
_: ?*anyopaque,
|
||||||
|
) callconv(.c) void {
|
||||||
|
const priv = self.private();
|
||||||
|
const banner = priv.banner;
|
||||||
|
const data = priv.data orelse {
|
||||||
|
// Not localized on purpose.
|
||||||
|
banner.as(adw.Banner).setTitle("This is a bug in Ghostty. Please report it.");
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
if (data.exit_code == 0) {
|
||||||
|
banner.as(adw.Banner).setTitle(i18n._("Command succeeded"));
|
||||||
|
self.as(gtk.Widget).addCssClass("normal");
|
||||||
|
self.as(gtk.Widget).removeCssClass("abnormal");
|
||||||
|
} else {
|
||||||
|
banner.as(adw.Banner).setTitle(i18n._("Command failed"));
|
||||||
|
self.as(gtk.Widget).removeCssClass("normal");
|
||||||
|
self.as(gtk.Widget).addCssClass("abnormal");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn closeButtonClicked(
|
||||||
|
_: *adw.Banner,
|
||||||
|
self: *Self,
|
||||||
|
) callconv(.c) void {
|
||||||
|
signals.@"close-request".impl.emit(
|
||||||
|
self,
|
||||||
|
null,
|
||||||
|
.{},
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------
|
||||||
|
// Virtual methods
|
||||||
|
|
||||||
|
fn dispose(self: *Self) callconv(.C) void {
|
||||||
|
gtk.Widget.disposeTemplate(
|
||||||
|
self.as(gtk.Widget),
|
||||||
|
getGObjectType(),
|
||||||
|
);
|
||||||
|
|
||||||
|
gobject.Object.virtual_methods.dispose.call(
|
||||||
|
Class.parent,
|
||||||
|
self.as(Parent),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finalize(self: *Self) callconv(.C) void {
|
||||||
|
const priv = self.private();
|
||||||
|
if (priv.data) |v| {
|
||||||
|
glib.ext.destroy(v);
|
||||||
|
priv.data = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
gobject.Object.virtual_methods.finalize.call(
|
||||||
|
Class.parent,
|
||||||
|
self.as(Parent),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const C = Common(Self, Private);
|
||||||
|
pub const as = C.as;
|
||||||
|
pub const ref = C.ref;
|
||||||
|
pub const unref = C.unref;
|
||||||
|
const private = C.private;
|
||||||
|
|
||||||
|
pub const Class = extern struct {
|
||||||
|
parent_class: Parent.Class,
|
||||||
|
var parent: *Parent.Class = undefined;
|
||||||
|
pub const Instance = Self;
|
||||||
|
|
||||||
|
fn init(class: *Class) callconv(.C) void {
|
||||||
|
gtk.Widget.Class.setTemplateFromResource(
|
||||||
|
class.as(gtk.Widget.Class),
|
||||||
|
comptime gresource.blueprint(.{
|
||||||
|
.major = 1,
|
||||||
|
.minor = 3,
|
||||||
|
.name = "surface-child-exited",
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Template bindings
|
||||||
|
class.bindTemplateChildPrivate("banner", .{});
|
||||||
|
class.bindTemplateCallback("clicked", &closeButtonClicked);
|
||||||
|
class.bindTemplateCallback("notify_data", &propData);
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
gobject.ext.registerProperties(class, &.{
|
||||||
|
properties.data.impl,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Signals
|
||||||
|
signals.@"close-request".impl.register(.{});
|
||||||
|
|
||||||
|
// Virtual methods
|
||||||
|
gobject.Object.virtual_methods.dispose.implement(class, &dispose);
|
||||||
|
gobject.Object.virtual_methods.finalize.implement(class, &finalize);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const as = C.Class.as;
|
||||||
|
pub const bindTemplateChildPrivate = C.Class.bindTemplateChildPrivate;
|
||||||
|
pub const bindTemplateCallback = C.Class.bindTemplateCallback;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Empty widget that does nothing if we don't have a new enough
|
||||||
|
/// Adwaita version to support the child exited banner.
|
||||||
|
const SurfaceChildExitedNoop = extern struct {
|
||||||
|
/// Can be detected at comptime
|
||||||
|
pub const noop = true;
|
||||||
|
|
||||||
|
const Self = @This();
|
||||||
|
parent_instance: Parent,
|
||||||
|
pub const Parent = gtk.Widget;
|
||||||
|
pub const getGObjectType = gobject.ext.defineClass(Self, .{
|
||||||
|
.name = "GhosttySurfaceChildExited",
|
||||||
|
.classInit = &Class.init,
|
||||||
|
.parent_class = &Class.parent,
|
||||||
|
});
|
||||||
|
|
||||||
|
pub const signals = struct {
|
||||||
|
pub const @"close-request" = struct {
|
||||||
|
pub const name = "close-request";
|
||||||
|
pub const connect = impl.connect;
|
||||||
|
const impl = gobject.ext.defineSignal(
|
||||||
|
name,
|
||||||
|
Self,
|
||||||
|
&.{},
|
||||||
|
void,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn setData(
|
||||||
|
self: *Self,
|
||||||
|
_: ?*const apprt.surface.Message.ChildExited,
|
||||||
|
) void {
|
||||||
|
signals.@"close-request".impl.emit(
|
||||||
|
self,
|
||||||
|
null,
|
||||||
|
.{},
|
||||||
|
null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const C = Common(Self, null);
|
||||||
|
pub const as = C.as;
|
||||||
|
pub const ref = C.ref;
|
||||||
|
pub const unref = C.unref;
|
||||||
|
const private = C.private;
|
||||||
|
|
||||||
|
pub const Class = extern struct {
|
||||||
|
parent_class: Parent.Class,
|
||||||
|
var parent: *Parent.Class = undefined;
|
||||||
|
pub const Instance = Self;
|
||||||
|
|
||||||
|
fn init(class: *Class) callconv(.C) void {
|
||||||
|
_ = class;
|
||||||
|
signals.@"close-request".impl.register(.{});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const as = C.Class.as;
|
||||||
|
pub const bindTemplateChildPrivate = C.Class.bindTemplateChildPrivate;
|
||||||
|
pub const bindTemplateCallback = C.Class.bindTemplateCallback;
|
||||||
|
};
|
||||||
|
};
|
@ -69,3 +69,18 @@ label.url-overlay.right {
|
|||||||
.clipboard-confirmation-dialog .clipboard-contents.blurred {
|
.clipboard-confirmation-dialog .clipboard-contents.blurred {
|
||||||
filter: blur(5px);
|
filter: blur(5px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Child Exited Overlay
|
||||||
|
*/
|
||||||
|
.child-exited.normal revealer widget {
|
||||||
|
background-color: rgba(38, 162, 105, 0.5);
|
||||||
|
/* after GTK 4.16 is a requirement, switch to the following:
|
||||||
|
/* background-color: color-mix(in srgb, var(--success-bg-color), transparent 50%); */
|
||||||
|
}
|
||||||
|
|
||||||
|
.child-exited.abnormal revealer widget {
|
||||||
|
background-color: rgba(192, 28, 40, 0.5);
|
||||||
|
/* after GTK 4.16 is a requirement, switch to the following:
|
||||||
|
/* background-color: color-mix(in srgb, var(--error-bg-color), transparent 50%); */
|
||||||
|
}
|
||||||
|
@ -25,6 +25,12 @@ template $GhosttySurface: Adw.Bin {
|
|||||||
use-es: false;
|
use-es: false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[overlay]
|
||||||
|
$GhosttySurfaceChildExited child_exited_overlay {
|
||||||
|
visible: bind template.child-exited;
|
||||||
|
close-request => $child_exited_close();
|
||||||
|
}
|
||||||
|
|
||||||
[overlay]
|
[overlay]
|
||||||
$GhosttyResizeOverlay resize_overlay {
|
$GhosttyResizeOverlay resize_overlay {
|
||||||
styles [
|
styles [
|
||||||
|
22
src/apprt/gtk-ng/ui/1.3/surface-child-exited.blp
Normal file
22
src/apprt/gtk-ng/ui/1.3/surface-child-exited.blp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
using Gtk 4.0;
|
||||||
|
using Adw 1;
|
||||||
|
|
||||||
|
template $GhosttySurfaceChildExited: Adw.Bin {
|
||||||
|
styles [
|
||||||
|
"child-exited",
|
||||||
|
]
|
||||||
|
|
||||||
|
notify::data => $notify_data();
|
||||||
|
|
||||||
|
Adw.Bin {
|
||||||
|
Adw.Banner banner {
|
||||||
|
button-clicked => $clicked();
|
||||||
|
revealed: true;
|
||||||
|
// Not localized on purpose because it should never be seen.
|
||||||
|
title: "This is a bug in Ghostty. Please report it.";
|
||||||
|
button-label: _("Close");
|
||||||
|
halign: fill;
|
||||||
|
valign: end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ const std = @import("std");
|
|||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const apprt = @import("../apprt.zig");
|
const apprt = @import("../apprt.zig");
|
||||||
|
const build_config = @import("../build_config.zig");
|
||||||
const App = @import("../App.zig");
|
const App = @import("../App.zig");
|
||||||
const Surface = @import("../Surface.zig");
|
const Surface = @import("../Surface.zig");
|
||||||
const renderer = @import("../renderer.zig");
|
const renderer = @import("../renderer.zig");
|
||||||
@ -107,6 +108,18 @@ pub const Message = union(enum) {
|
|||||||
pub const ChildExited = extern struct {
|
pub const ChildExited = extern struct {
|
||||||
exit_code: u32,
|
exit_code: u32,
|
||||||
runtime_ms: u64,
|
runtime_ms: u64,
|
||||||
|
|
||||||
|
/// Make this a valid gobject if we're in a GTK environment.
|
||||||
|
pub const getGObjectType = switch (build_config.app_runtime) {
|
||||||
|
.gtk,
|
||||||
|
.@"gtk-ng",
|
||||||
|
=> @import("gobject").ext.defineBoxed(
|
||||||
|
ChildExited,
|
||||||
|
.{ .name = "GhosttyApprtChildExited" },
|
||||||
|
),
|
||||||
|
|
||||||
|
.none => void,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,6 +82,18 @@
|
|||||||
fun:main
|
fun:main
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
VMware Graphics Driver
|
||||||
|
Memcheck:Leak
|
||||||
|
match-leak-kinds: possible
|
||||||
|
...
|
||||||
|
fun:vmw_fence_create
|
||||||
|
fun:vmw_ioctl_command
|
||||||
|
fun:vmw_swc_flush
|
||||||
|
fun:svga_context_flush
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
GSK Renderer GPU Stuff
|
GSK Renderer GPU Stuff
|
||||||
Memcheck:Leak
|
Memcheck:Leak
|
||||||
|
Reference in New Issue
Block a user