1
0
Fork 0
forked from wry/wry

tree: allow focusing workspace nodes

This commit is contained in:
khyperia 2025-12-24 15:53:31 +01:00 committed by Julian Orth
parent dd3f8bad40
commit 5bb19f3ca7
12 changed files with 76 additions and 22 deletions

View file

@ -728,6 +728,7 @@ fn create_dummy_output(state: &Rc<State>) {
bar_rect: Default::default(), bar_rect: Default::default(),
bar_rect_rel: Default::default(), bar_rect_rel: Default::default(),
bar_rect_with_separator: Default::default(), bar_rect_with_separator: Default::default(),
bar_separator_rect: Default::default(),
bar_separator_rect_rel: Default::default(), bar_separator_rect_rel: Default::default(),
non_exclusive_rect: Default::default(), non_exclusive_rect: Default::default(),
render_data: Default::default(), render_data: Default::default(),

View file

@ -740,7 +740,16 @@ impl WlSeatGlobal {
pub fn move_focus(self: &Rc<Self>, direction: Direction) { pub fn move_focus(self: &Rc<Self>, direction: Direction) {
let tl = match self.keyboard_node.get().node_toplevel() { let tl = match self.keyboard_node.get().node_toplevel() {
Some(tl) => tl, Some(tl) => tl,
_ => return, _ => {
if let Some(ws) = self.keyboard_node.get().node_into_workspace()
&& let Some(target) = self
.state
.find_output_in_direction(&ws.output.get(), direction)
{
target.take_keyboard_navigation_focus(self, direction);
}
return;
}
}; };
if direction == Direction::Down && tl.node_is_container() { if direction == Direction::Down && tl.node_is_container() {
tl.node_do_focus(self, direction); tl.node_do_focus(self, direction);
@ -762,6 +771,13 @@ impl WlSeatGlobal {
pub fn move_focused(self: &Rc<Self>, direction: Direction) { pub fn move_focused(self: &Rc<Self>, direction: Direction) {
let kb_node = self.keyboard_node.get(); let kb_node = self.keyboard_node.get();
let Some(tl) = kb_node.node_toplevel() else { let Some(tl) = kb_node.node_toplevel() else {
if let Some(ws) = self.keyboard_node.get().node_into_workspace()
&& let Some(target) = self
.state
.find_output_in_direction(&ws.output.get(), direction)
{
self.state.move_ws_to_output(&ws, &target);
}
return; return;
}; };
let data = tl.tl_data(); let data = tl.tl_data();
@ -995,7 +1011,15 @@ impl WlSeatGlobal {
NodeLayer::Layer0 => handle_layer_shell(&output.layers[0]), NodeLayer::Layer0 => handle_layer_shell(&output.layers[0]),
NodeLayer::Layer1 => handle_layer_shell(&output.layers[1]), NodeLayer::Layer1 => handle_layer_shell(&output.layers[1]),
NodeLayer::Output => None, NodeLayer::Output => None,
NodeLayer::Workspace => None, NodeLayer::Workspace => {
if let Some(ws) = &ws
&& ws.container_visible()
{
self.focus_node(ws.clone());
return;
}
None
}
NodeLayer::Tiled => ws NodeLayer::Tiled => ws
.as_ref() .as_ref()
.and_then(|w| w.container.get()) .and_then(|w| w.container.get())

View file

@ -18,6 +18,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
win1.set_color(255, 0, 0, 255); win1.set_color(255, 0, 0, 255);
win1.map2().await?; win1.map2().await?;
run.cfg.set_floating(ds.seat.id(), true)?; run.cfg.set_floating(ds.seat.id(), true)?;
client.sync().await;
for i in ["1", "2"] { for i in ["1", "2"] {
let (x, y) = win1.tl.server.node_absolute_position().position(); let (x, y) = win1.tl.server.node_absolute_position().position();

View file

@ -85,6 +85,7 @@ impl Renderer<'_> {
} else { } else {
render_layer!(output.layers[0]); render_layer!(output.layers[0]);
render_layer!(output.layers[1]); render_layer!(output.layers[1]);
let ws = output.workspace.get();
if self.state.show_bar.get() { if self.state.show_bar.get() {
let non_exclusive_rect_rel = output.non_exclusive_rect_rel.get(); let non_exclusive_rect_rel = output.non_exclusive_rect_rel.get();
let (mut x, mut y) = non_exclusive_rect_rel.translate_inv(x, y); let (mut x, mut y) = non_exclusive_rect_rel.translate_inv(x, y);
@ -109,7 +110,12 @@ impl Renderer<'_> {
self.base self.base
.fill_boxes2(slice::from_ref(&aw.rect), &c, srgb, x, y); .fill_boxes2(slice::from_ref(&aw.rect), &c, srgb, x, y);
} }
let c = theme.colors.separator.get(); let mut c = theme.colors.separator.get();
if let Some(ws) = &ws
&& ws.seat_state.is_active()
{
c = theme.colors.focused_title_background.get();
}
self.base self.base
.fill_boxes2(slice::from_ref(&rd.bar_separator), &c, srgb, x, y); .fill_boxes2(slice::from_ref(&rd.bar_separator), &c, srgb, x, y);
let c = theme.colors.unfocused_title_background.get(); let c = theme.colors.unfocused_title_background.get();
@ -172,7 +178,7 @@ impl Renderer<'_> {
} }
} }
} }
if let Some(ws) = output.workspace.get() { if let Some(ws) = &ws {
let ws_rect = output.workspace_rect_rel.get(); let ws_rect = output.workspace_rect_rel.get();
let (x, y) = ws_rect.translate_inv(x, y); let (x, y) = ws_rect.translate_inv(x, y);
self.render_workspace(&ws, x, y); self.render_workspace(&ws, x, y);

View file

@ -235,6 +235,7 @@ impl ConnectorHandler {
bar_rect: Default::default(), bar_rect: Default::default(),
bar_rect_rel: Default::default(), bar_rect_rel: Default::default(),
bar_rect_with_separator: Default::default(), bar_rect_with_separator: Default::default(),
bar_separator_rect: Default::default(),
bar_separator_rect_rel: Default::default(), bar_separator_rect_rel: Default::default(),
render_data: Default::default(), render_data: Default::default(),
state: self.state.clone(), state: self.state.clone(),

View file

@ -96,6 +96,7 @@ pub struct OutputNode {
pub bar_rect: Cell<Rect>, pub bar_rect: Cell<Rect>,
pub bar_rect_rel: Cell<Rect>, pub bar_rect_rel: Cell<Rect>,
pub bar_rect_with_separator: Cell<Rect>, pub bar_rect_with_separator: Cell<Rect>,
pub bar_separator_rect: Cell<Rect>,
pub bar_separator_rect_rel: Cell<Rect>, pub bar_separator_rect_rel: Cell<Rect>,
pub render_data: RefCell<OutputRenderData>, pub render_data: RefCell<OutputRenderData>,
pub state: Rc<State>, pub state: Rc<State>,
@ -774,11 +775,11 @@ impl OutputNode {
let mut bar_rect = Rect::default(); let mut bar_rect = Rect::default();
let mut bar_rect_rel = Rect::default(); let mut bar_rect_rel = Rect::default();
let mut bar_rect_with_separator = Rect::default(); let mut bar_rect_with_separator = Rect::default();
let mut bar_separator_rect = Rect::default();
let mut bar_separator_rect_rel = Rect::default(); let mut bar_separator_rect_rel = Rect::default();
let mut workspace_rect = non_exclusive_rect; let mut workspace_rect = non_exclusive_rect;
let mut workspace_rect_rel = non_exclusive_rect_rel; let mut workspace_rect_rel = non_exclusive_rect_rel;
if self.state.show_bar.get() { if self.state.show_bar.get() {
let bar_separator_rect;
match self.state.theme.bar_position.get() { match self.state.theme.bar_position.get() {
BarPosition::Bottom => { BarPosition::Bottom => {
workspace_rect = Rect::new_sized_saturating(x1, y1, width, height - bh - bsw); workspace_rect = Rect::new_sized_saturating(x1, y1, width, height - bh - bsw);
@ -805,6 +806,7 @@ impl OutputNode {
self.bar_rect.set(bar_rect); self.bar_rect.set(bar_rect);
self.bar_rect_rel.set(bar_rect_rel); self.bar_rect_rel.set(bar_rect_rel);
self.bar_rect_with_separator.set(bar_rect_with_separator); self.bar_rect_with_separator.set(bar_rect_with_separator);
self.bar_separator_rect.set(bar_separator_rect);
self.bar_separator_rect_rel.set(bar_separator_rect_rel); self.bar_separator_rect_rel.set(bar_separator_rect_rel);
self.workspace_rect.set(workspace_rect); self.workspace_rect.set(workspace_rect);
self.workspace_rect_rel.set(workspace_rect_rel); self.workspace_rect_rel.set(workspace_rect_rel);
@ -1147,20 +1149,13 @@ impl OutputNode {
set_layer_visible!(self.layers[3], visible); set_layer_visible!(self.layers[3], visible);
} }
fn button(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, id: PointerType) { fn bar_button(self: &Rc<Self>, seat: &Rc<WlSeatGlobal>, x: i32, y: i32) -> bool {
if !self.state.show_bar.get() { if !self.state.show_bar.get() {
return; return false;
}
let (x, y) = match self.pointer_positions.get(&id) {
Some(p) => p,
_ => return,
};
if let PointerType::Seat(s) = id {
self.pointer_down.set(s, (x, y));
} }
let bar_rect_rel = self.bar_rect_rel.get(); let bar_rect_rel = self.bar_rect_rel.get();
if bar_rect_rel.not_contains(x, y) { if bar_rect_rel.not_contains(x, y) {
return; return false;
} }
let (x, _) = bar_rect_rel.translate(x, y); let (x, _) = bar_rect_rel.translate(x, y);
let ws = 'ws: { let ws = 'ws: {
@ -1170,9 +1165,25 @@ impl OutputNode {
break 'ws title.ws.clone(); break 'ws title.ws.clone();
} }
} }
return; return true;
}; };
self.state.show_workspace2(Some(seat), &self, &ws); self.state.show_workspace2(Some(seat), self, &ws);
true
}
fn button(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, id: PointerType) {
let (x, y) = match self.pointer_positions.get(&id) {
Some(p) => p,
_ => return,
};
if let PointerType::Seat(s) = id {
self.pointer_down.set(s, (x, y));
}
if self.bar_button(seat, x, y) {
return;
}
let ws = self.ensure_workspace();
seat.focus_node(ws);
} }
pub fn update_presentation_type(&self) { pub fn update_presentation_type(&self) {
@ -1489,6 +1500,10 @@ impl OutputNode {
if c.node_visible() { if c.node_visible() {
c.node_do_focus(seat, direction); c.node_do_focus(seat, direction);
} }
} else {
if ws.node_visible() {
seat.focus_node(ws);
}
} }
} }
} }

View file

@ -366,17 +366,23 @@ impl Node for WorkspaceNode {
seat.focus_node(last); seat.focus_node(last);
} else if let Some(container) = self.container.get() { } else if let Some(container) = self.container.get() {
container.node_do_focus(seat, direction); container.node_do_focus(seat, direction);
} else if let Some(float) = self } else if let Some(child) = self
.stacked .stacked
.rev_iter() .rev_iter()
.find_map(|node| (*node).clone().node_into_float()) .filter_map(|node| (*node).clone().node_into_float())
.find_map(|float| float.child.get())
{ {
if let Some(child) = float.child.get() { child.node_do_focus(seat, direction);
child.node_do_focus(seat, direction); } else {
} seat.focus_node(self);
} }
} }
fn node_active_changed(&self, _active: bool) {
let output = self.output.get();
self.state.damage(output.bar_separator_rect.get());
}
fn node_find_tree_at( fn node_find_tree_at(
&self, &self,
x: i32, x: i32,