apprt/gtk-ng: hook up Surface.close

This commit is contained in:
Mitchell Hashimoto
2025-07-19 14:18:50 -07:00
parent 2e9ee16455
commit aadb2c05e5
4 changed files with 74 additions and 8 deletions

View File

@ -26,8 +26,7 @@ pub fn rtApp(self: *Self) *ApprtApp {
}
pub fn close(self: *Self, process_active: bool) void {
_ = self;
_ = process_active;
self.surface.close(process_active);
}
pub fn getTitle(self: *Self) ?[:0]const u8 {

View File

@ -54,6 +54,29 @@ pub const Surface = extern struct {
};
};
pub const signals = struct {
/// Emitted whenever the surface would like to be closed for any
/// reason.
///
/// The surface view does NOT handle its own close confirmation.
/// If there is a process alive then the boolean parameter will
/// specify it and the parent widget should handle this request.
///
/// This signal lets the containing widget decide how closure works.
/// This lets this Surface widget be used as a split, tab, etc.
/// without it having to be aware of its own semantics.
pub const @"close-request" = struct {
pub const name = "close-request";
pub const connect = impl.connect;
const impl = gobject.ext.defineSignal(
name,
Self,
&.{bool},
void,
);
};
};
const Private = struct {
/// The configuration that this surface is using.
config: ?*Config = null,
@ -374,6 +397,15 @@ pub const Surface = extern struct {
//---------------------------------------------------------------
// Libghostty Callbacks
pub fn close(self: *Self, process_active: bool) void {
signals.@"close-request".impl.emit(
self,
null,
.{process_active},
null,
);
}
pub fn getContentScale(self: *Self) apprt.ContentScale {
const priv = self.private();
const gl_area = priv.gl_area;
@ -1341,6 +1373,9 @@ pub const Surface = extern struct {
properties.config.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);

View File

@ -1,4 +1,5 @@
const std = @import("std");
const assert = std.debug.assert;
const adw = @import("adw");
const gobject = @import("gobject");
const gtk = @import("gtk");
@ -23,7 +24,9 @@ pub const Window = extern struct {
});
const Private = struct {
_todo: u8,
/// The surface in the view.
surface: *Surface = undefined,
pub var offset: c_int = 0;
};
@ -33,8 +36,20 @@ pub const Window = extern struct {
fn init(self: *Self, _: *Class) callconv(.C) void {
gtk.Widget.initTemplate(self.as(gtk.Widget));
const surface = self.private().surface;
_ = Surface.signals.@"close-request".connect(
surface,
*Self,
surfaceCloseRequest,
self,
.{},
);
}
//---------------------------------------------------------------
// Virtual methods
fn dispose(self: *Self) callconv(.C) void {
gtk.Widget.disposeTemplate(
self.as(gtk.Widget),
@ -47,6 +62,21 @@ pub const Window = extern struct {
);
}
//---------------------------------------------------------------
// Signal handlers
fn surfaceCloseRequest(
surface: *Surface,
process_active: bool,
self: *Self,
) callconv(.c) void {
// Todo
_ = process_active;
assert(surface == self.private().surface);
self.as(gtk.Window).close();
}
const C = Common(Self, Private);
pub const as = C.as;
pub const ref = C.ref;
@ -60,7 +90,6 @@ pub const Window = extern struct {
fn init(class: *Class) callconv(.C) void {
gobject.ext.ensureType(Surface);
gtk.Widget.Class.setTemplateFromResource(
class.as(gtk.Widget.Class),
comptime gresource.blueprint(.{
@ -70,11 +99,14 @@ pub const Window = extern struct {
}),
);
// Bindings
class.bindTemplateChildPrivate("surface", .{});
// Virtual methods
gobject.Object.virtual_methods.dispose.implement(class, &dispose);
}
pub fn as(class: *Class, comptime T: type) *T {
return gobject.ext.as(T, class);
}
pub const as = C.Class.as;
pub const bindTemplateChildPrivate = C.Class.bindTemplateChildPrivate;
};
};

View File

@ -2,5 +2,5 @@ using Gtk 4.0;
using Adw 1;
template $GhosttyWindow: Adw.ApplicationWindow {
content: $GhosttySurface {};
content: $GhosttySurface surface {};
}