1
0
Fork 0
forked from wry/wry

feat: add alternating autotiling

This commit is contained in:
atagen 2026-05-31 17:16:44 +10:00
parent ce14169d6b
commit 5c2f631fdb
17 changed files with 244 additions and 59 deletions

View file

@ -290,6 +290,47 @@ impl ContainerNode {
self.add_child_x(prev, new, |prev, new| self.add_child_after_(prev, new));
}
pub fn add_tiled_child_after(self: &Rc<Self>, prev: &dyn Node, new: Rc<dyn ToplevelNode>) {
if !self.state.theme.autotile_enabled.get()
|| self.mono_child.is_some()
|| self.num_children.get() <= 1
{
self.add_child_after(prev, new);
return;
}
let focused = self
.child_nodes
.borrow()
.get(&prev.node_id())
.map(|n| n.to_ref());
let Some(focused) = focused else {
log::error!(
"Tried to autotile a child into a container but the preceding node is not in the container"
);
return;
};
let focused_node = focused.node.clone();
let focused_active = focused_node.tl_data().active();
let sub = ContainerNode::new(
&self.state,
&self.workspace.get(),
focused_node.clone(),
self.split.get().other(),
);
// Autotile-created groups are structural and collapse once only one
// child remains. Explicit make-group commands control their own
// grouping through the regular manual paths.
sub.ephemeral.set(Ephemeral::On);
sub.append_child(new);
let sub_id = sub.node_id();
self.clone().cnode_replace_child(&*focused_node, sub);
if focused_active
&& let Some(group) = self.child_nodes.borrow().get(&sub_id).map(|n| n.to_ref())
{
self.update_child_active(&group, true, 1);
}
}
pub fn add_child_before(self: &Rc<Self>, prev: &dyn Node, new: Rc<dyn ToplevelNode>) {
self.add_child_x(prev, new, |prev, new| self.add_child_before_(prev, new));
}
@ -1369,42 +1410,6 @@ impl ContainerNode {
}
pub fn insert_child(self: &Rc<Self>, node: Rc<dyn ToplevelNode>, direction: Direction) {
// Autotile: if the container would become too narrow/tall, wrap the
// focused child and new node in a perpendicular sub-container.
if self.state.theme.autotile_enabled.get() && self.mono_child.is_none() {
let (pw, ph) = self.predict_child_body_size();
let opposite = match self.split.get() {
ContainerSplit::Horizontal if pw > 0 && ph > 0 && pw < ph => {
Some(ContainerSplit::Vertical)
}
ContainerSplit::Vertical if pw > 0 && ph > 0 && ph < pw => {
Some(ContainerSplit::Horizontal)
}
_ => None,
};
if let Some(opp_split) = opposite {
if let Some(focused) = self.focus_history.last() {
if self.num_children.get() <= 1 {
// Single child, autotile not applicable.
} else {
let focused_node = focused.node.clone();
let was_ephemeral = self.ephemeral.replace(Ephemeral::Off);
self.clone().cnode_remove_child2(&*focused_node, true);
self.ephemeral.set(was_ephemeral);
let sub = ContainerNode::new(
&self.state,
&self.workspace.get(),
focused_node,
opp_split,
);
sub.ephemeral.set(Ephemeral::On);
sub.append_child(node);
self.append_child(sub);
return;
}
}
}
}
let (split, right) = direction_to_split(direction);
if split != self.split.get() || right {
self.append_child(node);