apprt/gtk-ng: surface close in split tree

This commit is contained in:
Mitchell Hashimoto
2025-08-09 12:36:24 -07:00
parent a28d673467
commit 8232cf33b4
3 changed files with 62 additions and 30 deletions

View File

@@ -272,6 +272,13 @@ pub const SplitTree = extern struct {
var it = tree.iterator();
while (it.next()) |entry| {
const surface = entry.view;
_ = Surface.signals.@"close-request".connect(
surface,
*Self,
surfaceCloseRequest,
self,
.{},
);
_ = gobject.Object.signals.notify.connect(
surface,
*Self,
@@ -461,6 +468,45 @@ pub const SplitTree = extern struct {
};
}
fn surfaceCloseRequest(
surface: *Surface,
scope: *const Surface.CloseScope,
self: *Self,
) callconv(.c) void {
switch (scope.*) {
// Handled upstream... this will probably go away for widget
// actions eventually.
.window, .tab => return,
// Remove the surface from the tree.
.surface => {
// TODO: close confirmation
// Find the surface in the tree.
const tree = self.getTree() orelse return;
const handle: Surface.Tree.Node.Handle = handle: {
var it = tree.iterator();
while (it.next()) |entry| {
if (entry.view == surface) break :handle entry.handle;
}
return;
};
// Remove it from the tree.
var new_tree = tree.remove(
Application.default().allocator(),
handle,
) catch |err| {
log.warn("unable to remove surface from tree: {}", .{err});
return;
};
defer new_tree.deinit();
self.setTree(&new_tree);
},
}
}
fn propSurfaceFocused(
surface: *Surface,
_: *gobject.ParamSpec,

View File

@@ -182,13 +182,6 @@ pub const Tab = extern struct {
var it = tree.iterator();
while (it.next()) |entry| {
const surface = entry.view;
_ = Surface.signals.@"close-request".connect(
surface,
*Self,
surfaceCloseRequest,
self,
.{},
);
_ = gobject.Object.signals.notify.connect(
surface,
*Self,
@@ -285,27 +278,6 @@ pub const Tab = extern struct {
//---------------------------------------------------------------
// Signal handlers
fn surfaceCloseRequest(
_: *Surface,
scope: *const Surface.CloseScope,
self: *Self,
) callconv(.c) void {
switch (scope.*) {
// Handled upstream... we don't control our window close.
.window => return,
// Presently both the same, results in the tab closing.
.surface, .tab => {
signals.@"close-request".impl.emit(
self,
null,
.{},
null,
);
},
}
}
fn splitTreeChanged(
_: *SplitTree,
old_tree: ?*const Surface.Tree,
@@ -316,9 +288,20 @@ pub const Tab = extern struct {
self.disconnectSurfaceHandlers(tree);
}
if (new_tree) |tree| {
self.connectSurfaceHandlers(tree);
// If our tree is empty we close the tab.
const tree: *const Surface.Tree = new_tree orelse &.empty;
if (tree.isEmpty()) {
signals.@"close-request".impl.emit(
self,
null,
.{},
null,
);
return;
}
// Non-empty tree, connect handlers we care about.
self.connectSurfaceHandlers(tree);
}
fn propSplitTree(

View File

@@ -119,6 +119,9 @@ pub fn SplitTree(comptime V: type) type {
/// Clone this tree, returning a new tree with the same nodes.
pub fn clone(self: *const Self, gpa: Allocator) Allocator.Error!Self {
// If we're empty then return an empty tree.
if (self.isEmpty()) return .empty;
// Create a new arena allocator for the clone.
var arena = ArenaAllocator.init(gpa);
errdefer arena.deinit();