diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index afe1dc31..9421faeb 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -189,9 +189,10 @@ impl WlSeatGlobal { self.pointer_stack.borrow().last().cloned() } - pub fn last_tiled_keyboard_toplevel(&self) -> Option> { + pub fn last_tiled_keyboard_toplevel(&self, new: &dyn Node) -> Option> { + let is_container = new.is_container(); for tl in self.toplevel_focus_history.rev_iter() { - if !tl.parent_is_float() { + if !tl.parent_is_float() && (!is_container || !tl.is_contained_in(new.id())) { return Some(tl.deref().clone()); } } diff --git a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs index b9ab648c..6e417d1f 100644 --- a/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs +++ b/src/ifs/wl_surface/xdg_surface/xdg_toplevel.rs @@ -417,6 +417,16 @@ impl Node for XdgToplevel { visitor.visit_surface(&self.xdg.surface); } + fn is_contained_in(&self, other: NodeId) -> bool { + if let Some(parent) = self.parent_node.get() { + if parent.id() == other { + return true; + } + return parent.is_contained_in(other); + } + false + } + fn do_focus(self: Rc, seat: &Rc, _direction: Direction) { seat.focus_toplevel(&self); } diff --git a/src/state.rs b/src/state.rs index d1938060..c3feada2 100644 --- a/src/state.rs +++ b/src/state.rs @@ -116,7 +116,7 @@ impl State { pub fn map_tiled(self: &Rc, node: Rc) { let seat = self.seat_queue.last(); if let Some(seat) = seat { - if let Some(prev) = seat.last_tiled_keyboard_toplevel() { + if let Some(prev) = seat.last_tiled_keyboard_toplevel(&*node) { if let Some(container) = prev.parent_node.get() { if let Some(container) = container.into_container() { container.add_child_after(&*prev, node); diff --git a/src/tree/container.rs b/src/tree/container.rs index 0ffa5357..ba745710 100644 --- a/src/tree/container.rs +++ b/src/tree/container.rs @@ -589,6 +589,14 @@ impl Node for ContainerNode { } } + fn is_contained_in(&self, other: NodeId) -> bool { + let parent = self.parent.get(); + if parent.id() == other { + return true; + } + parent.is_contained_in(other) + } + fn child_title_changed(self: Rc, child: &dyn Node, title: &str) { let child = match self.child_nodes.borrow_mut().get(&child.id()) { Some(cn) => cn.to_ref(), @@ -621,6 +629,18 @@ impl Node for ContainerNode { seat.focus_node(self); } + fn do_focus(self: Rc, seat: &Rc, direction: Direction) { + let node = match direction { + Direction::Left => self.children.last(), + Direction::Down => self.children.first(), + Direction::Up => self.children.last(), + Direction::Right => self.children.first(), + }; + if let Some(node) = node { + node.node.clone().do_focus(seat, direction); + } + } + fn move_focus(self: Rc, seat: &Rc, direction: Direction) { if direction == Direction::Down { self.do_focus(seat, direction); @@ -635,18 +655,6 @@ impl Node for ContainerNode { self.parent.get().move_child(self, direction); } - fn do_focus(self: Rc, seat: &Rc, direction: Direction) { - let node = match direction { - Direction::Left => self.children.last(), - Direction::Down => self.children.first(), - Direction::Up => self.children.last(), - Direction::Right => self.children.first(), - }; - if let Some(node) = node { - node.node.clone().do_focus(seat, direction); - } - } - fn move_focus_from_child( &self, seat: &Rc, diff --git a/src/tree/mod.rs b/src/tree/mod.rs index a7e2c8cd..518f8b95 100644 --- a/src/tree/mod.rs +++ b/src/tree/mod.rs @@ -73,6 +73,11 @@ pub trait Node { fn visit(self: Rc, visitor: &mut dyn NodeVisitor); fn visit_children(&self, visitor: &mut dyn NodeVisitor); + fn is_contained_in(&self, other: NodeId) -> bool { + let _ = other; + false + } + fn child_title_changed(self: Rc, child: &dyn Node, title: &str) { let _ = child; let _ = title;