mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 16:26:08 +03:00
apprt/gtk: gotoSplit gets proper previous/next direction
This commit is contained in:
@ -193,89 +193,68 @@ 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);
|
||||
if (self.directionPrevious(from)) |prev| {
|
||||
result.put(.previous, prev);
|
||||
|
||||
// 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);
|
||||
result.put(.top, prev);
|
||||
result.put(.left, prev);
|
||||
}
|
||||
|
||||
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);
|
||||
},
|
||||
if (self.directionNext(from)) |next| {
|
||||
result.put(.next, next);
|
||||
result.put(.bottom, next);
|
||||
result.put(.right, next);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn directionMapFromBottomRight(self: *const Split) DirectionMap {
|
||||
var result = DirectionMap.initFull(null);
|
||||
fn directionPrevious(self: *const Split, from: Side) ?*Surface {
|
||||
switch (from) {
|
||||
// From the bottom right, our previous is the deepest surface
|
||||
// in the top-left of our own split.
|
||||
.bottom_right => return self.top_left.deepestSurface(.bottom_right),
|
||||
|
||||
if (self.container.split()) |parent_split| {
|
||||
const deepest_tl = parent_split.deepestSurface(.top_left);
|
||||
result.put(.next, deepest_tl);
|
||||
// From the top left its more complicated. It is the de
|
||||
.top_left => {
|
||||
// If we have no parent split then there can be no previous.
|
||||
const parent = self.container.split() orelse return null;
|
||||
const side = self.container.splitSide() orelse return null;
|
||||
|
||||
// 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 {
|
||||
// The previous value is the previous of the side that we are.
|
||||
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),
|
||||
},
|
||||
.top_left => parent.directionPrevious(.top_left),
|
||||
.bottom_right => parent.directionPrevious(.bottom_right),
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn directionNext(self: *const Split, from: Side) ?*Surface {
|
||||
switch (from) {
|
||||
// From the top left, our next is the earliest surface in the
|
||||
// top-left direction of the bottom-right side of our split. Fun!
|
||||
.top_left => return self.bottom_right.deepestSurface(.top_left),
|
||||
|
||||
// From the bottom right is more compliated. It is the deepest
|
||||
// (last) surface in the
|
||||
.bottom_right => {
|
||||
// If we have no parent split then there can be no next.
|
||||
const parent = self.container.split() orelse return null;
|
||||
const side = self.container.splitSide() orelse return null;
|
||||
|
||||
// The previous value is the previous of the side that we are.
|
||||
return switch (side) {
|
||||
.top_left => parent.directionNext(.bottom_right),
|
||||
.bottom_right => parent.directionNext(.bottom_right),
|
||||
};
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn removeChildren(self: *const Split) void {
|
||||
|
@ -48,6 +48,9 @@ pub const Container = union(enum) {
|
||||
split_tl: *Elem,
|
||||
split_br: *Elem,
|
||||
|
||||
/// The side of the split.
|
||||
pub const SplitSide = enum { top_left, bottom_right };
|
||||
|
||||
/// Elem is the possible element of any container. A container can
|
||||
/// hold both a surface and a split. Any valid container should
|
||||
/// have an Elem value so that it can be properly used with
|
||||
@ -92,6 +95,18 @@ pub const Container = union(enum) {
|
||||
.split => |s| s.grabFocus(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The last surface in this container in the direction specified.
|
||||
/// Direction must be "top_left" or "bottom_right".
|
||||
pub fn deepestSurface(self: Elem, side: SplitSide) ?*Surface {
|
||||
return switch (self) {
|
||||
.surface => |s| s,
|
||||
.split => |s| (switch (side) {
|
||||
.top_left => s.top_left,
|
||||
.bottom_right => s.bottom_right,
|
||||
}).deepestSurface(side),
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
/// Returns the window that this surface is attached to.
|
||||
@ -127,6 +142,15 @@ pub const Container = union(enum) {
|
||||
};
|
||||
}
|
||||
|
||||
/// The side that we are in the split.
|
||||
pub fn splitSide(self: Container) ?SplitSide {
|
||||
return switch (self) {
|
||||
.none, .tab_ => null,
|
||||
.split_tl => .top_left,
|
||||
.split_br => .bottom_right,
|
||||
};
|
||||
}
|
||||
|
||||
/// Replace the container's element with this element. This is
|
||||
/// used by children to modify their parents to for example change
|
||||
/// from a surface to a split or a split back to a surface or
|
||||
|
Reference in New Issue
Block a user