apprt/gtk: gotoSplit, has some bugs

This commit is contained in:
Mitchell Hashimoto
2023-12-01 09:58:57 -08:00
parent dc2cee1c78
commit f811ac6b18
2 changed files with 107 additions and 0 deletions

View File

@ -182,6 +182,102 @@ fn updateChildren(self: *const Split) void {
);
}
/// A mapping of direction to the element (if any) in that direction.
pub const DirectionMap = std.EnumMap(
input.SplitFocusDirection,
?*Surface,
);
pub const Side = enum { top_left, bottom_right };
/// Returns the map that can be used to determine elements in various
/// directions (primarily for gotoSplit).
pub fn directionMap(self: *const Split, from: Side) DirectionMap {
return switch (from) {
.top_left => self.directionMapFromTopLeft(),
.bottom_right => self.directionMapFromBottomRight(),
};
}
fn directionMapFromTopLeft(self: *const Split) DirectionMap {
var result = DirectionMap.initFull(null);
if (self.container.split()) |parent_split| {
const deepest_br = parent_split.deepestSurface(.bottom_right);
result.put(.previous, deepest_br);
// This behavior matches the behavior of macOS at the time of writing
// this. There is an open issue (#524) to make this depend on the
// actual physical location of the current split.
result.put(.top, deepest_br);
result.put(.left, deepest_br);
}
switch (self.bottom_right) {
.surface => |s| {
result.put(.next, s);
result.put(.bottom, s);
result.put(.right, s);
},
.split => |s| {
const deepest_tl = s.deepestSurface(.top_left);
result.put(.next, deepest_tl);
result.put(.bottom, deepest_tl);
result.put(.right, deepest_tl);
},
}
return result;
}
fn directionMapFromBottomRight(self: *const Split) DirectionMap {
var result = DirectionMap.initFull(null);
if (self.container.split()) |parent_split| {
const deepest_tl = parent_split.deepestSurface(.top_left);
result.put(.next, deepest_tl);
// This behavior matches the behavior of macOS at the time of writing
// this. There is an open issue (#524) to make this depend on the
// actual physical location of the current split.
result.put(.top, deepest_tl);
result.put(.left, deepest_tl);
}
switch (self.top_left) {
.surface => |s| {
result.put(.previous, s);
result.put(.bottom, s);
result.put(.right, s);
},
.split => |s| {
const deepest_br = s.deepestSurface(.bottom_right);
result.put(.previous, deepest_br);
result.put(.bottom, deepest_br);
result.put(.right, deepest_br);
},
}
return result;
}
/// Get the most deeply nested surface for a given side.
fn deepestSurface(self: *const Split, side: Side) *Surface {
return switch (side) {
.bottom_right => switch (self.bottom_right) {
.surface => |s| s,
.split => |s| s.deepestSurface(.bottom_right),
},
.top_left => switch (self.top_left) {
.surface => |s| s,
.split => |s| s.deepestSurface(.top_left),
},
};
}
fn removeChildren(self: *const Split) void {
c.gtk_paned_set_start_child(@ptrCast(self.paned), null);
c.gtk_paned_set_end_child(@ptrCast(self.paned), null);

View File

@ -524,6 +524,17 @@ pub fn newSplit(self: *Surface, direction: input.SplitDirection) !void {
_ = try Split.create(alloc, self, direction);
}
pub fn gotoSplit(self: *const Surface, direction: input.SplitFocusDirection) void {
const s = self.container.split() orelse return;
const map = s.directionMap(switch (self.container) {
.split_tl => .top_left,
.split_br => .bottom_right,
.none, .tab_ => unreachable,
});
const surface_ = map.get(direction) orelse return;
if (surface_) |surface| surface.grabFocus();
}
pub fn newTab(self: *Surface) !void {
const window = self.container.window() orelse {
log.info("surface cannot create new tab when not attached to a window", .{});