diff --git a/src/compositor.rs b/src/compositor.rs index 8cb3ae8b..0e333e56 100644 --- a/src/compositor.rs +++ b/src/compositor.rs @@ -728,6 +728,7 @@ fn create_dummy_output(state: &Rc) { bar_rect: Default::default(), bar_rect_rel: Default::default(), bar_rect_with_separator: Default::default(), + bar_separator_rect: Default::default(), bar_separator_rect_rel: Default::default(), non_exclusive_rect: Default::default(), render_data: Default::default(), diff --git a/src/ifs/wl_seat.rs b/src/ifs/wl_seat.rs index 5a96ea29..27ced5da 100644 --- a/src/ifs/wl_seat.rs +++ b/src/ifs/wl_seat.rs @@ -740,7 +740,16 @@ impl WlSeatGlobal { pub fn move_focus(self: &Rc, direction: Direction) { let tl = match self.keyboard_node.get().node_toplevel() { 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() { tl.node_do_focus(self, direction); @@ -762,6 +771,13 @@ impl WlSeatGlobal { pub fn move_focused(self: &Rc, direction: Direction) { let kb_node = self.keyboard_node.get(); 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; }; let data = tl.tl_data(); @@ -995,7 +1011,15 @@ impl WlSeatGlobal { NodeLayer::Layer0 => handle_layer_shell(&output.layers[0]), NodeLayer::Layer1 => handle_layer_shell(&output.layers[1]), 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 .as_ref() .and_then(|w| w.container.get()) diff --git a/src/it/tests/t0007_subsurface/screenshot_1.qoi b/src/it/tests/t0007_subsurface/screenshot_1.qoi index eca5ddef..230c0408 100644 Binary files a/src/it/tests/t0007_subsurface/screenshot_1.qoi and b/src/it/tests/t0007_subsurface/screenshot_1.qoi differ diff --git a/src/it/tests/t0007_subsurface/screenshot_2.qoi b/src/it/tests/t0007_subsurface/screenshot_2.qoi index ea65888d..722271f6 100644 Binary files a/src/it/tests/t0007_subsurface/screenshot_2.qoi and b/src/it/tests/t0007_subsurface/screenshot_2.qoi differ diff --git a/src/it/tests/t0029_double_click_float.rs b/src/it/tests/t0029_double_click_float.rs index dbce7c08..a2c71b92 100644 --- a/src/it/tests/t0029_double_click_float.rs +++ b/src/it/tests/t0029_double_click_float.rs @@ -18,6 +18,7 @@ async fn test(run: Rc) -> TestResult { win1.set_color(255, 0, 0, 255); win1.map2().await?; run.cfg.set_floating(ds.seat.id(), true)?; + client.sync().await; for i in ["1", "2"] { let (x, y) = win1.tl.server.node_absolute_position().position(); diff --git a/src/it/tests/t0029_double_click_float/screenshot_1.qoi b/src/it/tests/t0029_double_click_float/screenshot_1.qoi index f49edd4d..dd974ccf 100644 Binary files a/src/it/tests/t0029_double_click_float/screenshot_1.qoi and b/src/it/tests/t0029_double_click_float/screenshot_1.qoi differ diff --git a/src/it/tests/t0029_double_click_float/screenshot_2.qoi b/src/it/tests/t0029_double_click_float/screenshot_2.qoi index dd974ccf..f49edd4d 100644 Binary files a/src/it/tests/t0029_double_click_float/screenshot_2.qoi and b/src/it/tests/t0029_double_click_float/screenshot_2.qoi differ diff --git a/src/it/tests/t0037_toplevel_drag/screenshot_1.qoi b/src/it/tests/t0037_toplevel_drag/screenshot_1.qoi index 65d5cd35..9ec55fdc 100644 Binary files a/src/it/tests/t0037_toplevel_drag/screenshot_1.qoi and b/src/it/tests/t0037_toplevel_drag/screenshot_1.qoi differ diff --git a/src/renderer.rs b/src/renderer.rs index 6f7efd46..2c94020f 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -85,6 +85,7 @@ impl Renderer<'_> { } else { render_layer!(output.layers[0]); render_layer!(output.layers[1]); + let ws = output.workspace.get(); if self.state.show_bar.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); @@ -109,7 +110,12 @@ impl Renderer<'_> { self.base .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 .fill_boxes2(slice::from_ref(&rd.bar_separator), &c, srgb, x, y); 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 (x, y) = ws_rect.translate_inv(x, y); self.render_workspace(&ws, x, y); diff --git a/src/tasks/connector.rs b/src/tasks/connector.rs index 4b24cba5..85753771 100644 --- a/src/tasks/connector.rs +++ b/src/tasks/connector.rs @@ -235,6 +235,7 @@ impl ConnectorHandler { bar_rect: Default::default(), bar_rect_rel: Default::default(), bar_rect_with_separator: Default::default(), + bar_separator_rect: Default::default(), bar_separator_rect_rel: Default::default(), render_data: Default::default(), state: self.state.clone(), diff --git a/src/tree/output.rs b/src/tree/output.rs index ba78da11..29027687 100644 --- a/src/tree/output.rs +++ b/src/tree/output.rs @@ -96,6 +96,7 @@ pub struct OutputNode { pub bar_rect: Cell, pub bar_rect_rel: Cell, pub bar_rect_with_separator: Cell, + pub bar_separator_rect: Cell, pub bar_separator_rect_rel: Cell, pub render_data: RefCell, pub state: Rc, @@ -774,11 +775,11 @@ impl OutputNode { let mut bar_rect = Rect::default(); let mut bar_rect_rel = 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 workspace_rect = non_exclusive_rect; let mut workspace_rect_rel = non_exclusive_rect_rel; if self.state.show_bar.get() { - let bar_separator_rect; match self.state.theme.bar_position.get() { BarPosition::Bottom => { 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_rel.set(bar_rect_rel); 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.workspace_rect.set(workspace_rect); self.workspace_rect_rel.set(workspace_rect_rel); @@ -1147,20 +1149,13 @@ impl OutputNode { set_layer_visible!(self.layers[3], visible); } - fn button(self: Rc, seat: &Rc, id: PointerType) { + fn bar_button(self: &Rc, seat: &Rc, x: i32, y: i32) -> bool { if !self.state.show_bar.get() { - return; - } - 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)); + return false; } let bar_rect_rel = self.bar_rect_rel.get(); if bar_rect_rel.not_contains(x, y) { - return; + return false; } let (x, _) = bar_rect_rel.translate(x, y); let ws = 'ws: { @@ -1170,9 +1165,25 @@ impl OutputNode { 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, seat: &Rc, 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) { @@ -1489,6 +1500,10 @@ impl OutputNode { if c.node_visible() { c.node_do_focus(seat, direction); } + } else { + if ws.node_visible() { + seat.focus_node(ws); + } } } } diff --git a/src/tree/workspace.rs b/src/tree/workspace.rs index df0e43cf..eb308c08 100644 --- a/src/tree/workspace.rs +++ b/src/tree/workspace.rs @@ -366,17 +366,23 @@ impl Node for WorkspaceNode { seat.focus_node(last); } else if let Some(container) = self.container.get() { container.node_do_focus(seat, direction); - } else if let Some(float) = self + } else if let Some(child) = self .stacked .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( &self, x: i32,