tree: activate workspace on click
This commit is contained in:
parent
70cc24107b
commit
858e777f5a
7 changed files with 127 additions and 13 deletions
|
|
@ -373,6 +373,7 @@ fn create_dummy_output(state: &Rc<State>) {
|
||||||
is_dummy: true,
|
is_dummy: true,
|
||||||
status: Default::default(),
|
status: Default::default(),
|
||||||
scroll: Default::default(),
|
scroll: Default::default(),
|
||||||
|
pointer_positions: Default::default(),
|
||||||
});
|
});
|
||||||
let dummy_workspace = Rc::new(WorkspaceNode {
|
let dummy_workspace = Rc::new(WorkspaceNode {
|
||||||
id: state.node_ids.next(),
|
id: state.node_ids.next(),
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ mod t0014_container_scroll_focus;
|
||||||
mod t0015_scroll_partial;
|
mod t0015_scroll_partial;
|
||||||
mod t0016_scroll_ws;
|
mod t0016_scroll_ws;
|
||||||
mod t0017_remove_unused_ws;
|
mod t0017_remove_unused_ws;
|
||||||
|
mod t0018_click_to_active_ws;
|
||||||
|
|
||||||
pub trait TestCase: Sync {
|
pub trait TestCase: Sync {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
|
@ -78,5 +79,6 @@ pub fn tests() -> Vec<&'static dyn TestCase> {
|
||||||
t0015_scroll_partial,
|
t0015_scroll_partial,
|
||||||
t0016_scroll_ws,
|
t0016_scroll_ws,
|
||||||
t0017_remove_unused_ws,
|
t0017_remove_unused_ws,
|
||||||
|
t0018_click_to_active_ws,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
46
src/it/tests/t0018_click_to_active_ws.rs
Normal file
46
src/it/tests/t0018_click_to_active_ws.rs
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
use {
|
||||||
|
crate::{
|
||||||
|
ifs::wl_seat::BTN_LEFT,
|
||||||
|
it::{test_error::TestResult, testrun::TestRun},
|
||||||
|
},
|
||||||
|
std::rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
testcase!();
|
||||||
|
|
||||||
|
async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
|
let ds = run.create_default_setup().await?;
|
||||||
|
run.cfg.show_workspace(ds.seat.id(), "1")?;
|
||||||
|
|
||||||
|
let client = run.create_client().await?;
|
||||||
|
|
||||||
|
let win1 = client.create_window().await?;
|
||||||
|
win1.map().await?;
|
||||||
|
|
||||||
|
run.cfg.show_workspace(ds.seat.id(), "2")?;
|
||||||
|
|
||||||
|
let win2 = client.create_window().await?;
|
||||||
|
win2.map().await?;
|
||||||
|
|
||||||
|
ds.mouse.abs(&ds.connector, 0.0, 0.0);
|
||||||
|
ds.mouse.click(BTN_LEFT);
|
||||||
|
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
let name = ds.output.workspace.get().map(|ws| ws.name.clone());
|
||||||
|
tassert_eq!(name.as_deref(), Some("1"));
|
||||||
|
|
||||||
|
let pos = {
|
||||||
|
let rd = ds.output.render_data.borrow_mut();
|
||||||
|
rd.titles.last().map(|t| t.x1).unwrap_or(0)
|
||||||
|
};
|
||||||
|
ds.mouse.abs(&ds.connector, pos as _, 0.0);
|
||||||
|
ds.mouse.click(BTN_LEFT);
|
||||||
|
|
||||||
|
client.sync().await;
|
||||||
|
|
||||||
|
let name = ds.output.workspace.get().map(|ws| ws.name.clone());
|
||||||
|
tassert_eq!(name.as_deref(), Some("2"));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
@ -114,10 +114,10 @@ impl Renderer<'_> {
|
||||||
let c = theme.colors.unfocused_title_background.get();
|
let c = theme.colors.unfocused_title_background.get();
|
||||||
self.fill_boxes2(&rd.inactive_workspaces, &c, x, y);
|
self.fill_boxes2(&rd.inactive_workspaces, &c, x, y);
|
||||||
for title in &rd.titles {
|
for title in &rd.titles {
|
||||||
self.render_texture(&title.tex, x + title.x, y + title.y, ARGB8888);
|
self.render_texture(&title.tex, x + title.tex_x, y + title.tex_y, ARGB8888);
|
||||||
}
|
}
|
||||||
if let Some(status) = &rd.status {
|
if let Some(status) = &rd.status {
|
||||||
self.render_texture(&status.tex, x + status.x, y + status.y, ARGB8888);
|
self.render_texture(&status.tex, x + status.tex_x, y + status.tex_y, ARGB8888);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ws) = output.workspace.get() {
|
if let Some(ws) = output.workspace.get() {
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ impl ConnectorHandler {
|
||||||
is_dummy: false,
|
is_dummy: false,
|
||||||
status: self.state.status.clone(),
|
status: self.state.status.clone(),
|
||||||
scroll: Default::default(),
|
scroll: Default::default(),
|
||||||
|
pointer_positions: Default::default(),
|
||||||
});
|
});
|
||||||
let mode = info.initial_mode;
|
let mode = info.initial_mode;
|
||||||
let output_data = Rc::new(OutputData {
|
let output_data = Rc::new(OutputData {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,14 @@
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
backend::Mode,
|
backend::{KeyState, Mode},
|
||||||
cursor::KnownCursor,
|
cursor::KnownCursor,
|
||||||
|
fixed::Fixed,
|
||||||
ifs::{
|
ifs::{
|
||||||
wl_output::WlOutputGlobal,
|
wl_output::WlOutputGlobal,
|
||||||
wl_seat::{collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, WlSeatGlobal},
|
wl_seat::{
|
||||||
|
collect_kb_foci2, wl_pointer::PendingScroll, NodeSeatState, SeatId, WlSeatGlobal,
|
||||||
|
BTN_LEFT,
|
||||||
|
},
|
||||||
wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
wl_surface::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1,
|
||||||
zwlr_layer_shell_v1::{BACKGROUND, BOTTOM, OVERLAY, TOP},
|
zwlr_layer_shell_v1::{BACKGROUND, BOTTOM, OVERLAY, TOP},
|
||||||
},
|
},
|
||||||
|
|
@ -16,7 +20,8 @@ use {
|
||||||
walker::NodeVisitor, Direction, FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode,
|
walker::NodeVisitor, Direction, FindTreeResult, FoundNode, Node, NodeId, WorkspaceNode,
|
||||||
},
|
},
|
||||||
utils::{
|
utils::{
|
||||||
clonecell::CloneCell, errorfmt::ErrorFmt, linkedlist::LinkedList, scroller::Scroller,
|
clonecell::CloneCell, copyhashmap::CopyHashMap, errorfmt::ErrorFmt,
|
||||||
|
linkedlist::LinkedList, scroller::Scroller,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
smallvec::SmallVec,
|
smallvec::SmallVec,
|
||||||
|
|
@ -41,6 +46,7 @@ pub struct OutputNode {
|
||||||
pub is_dummy: bool,
|
pub is_dummy: bool,
|
||||||
pub status: CloneCell<Rc<String>>,
|
pub status: CloneCell<Rc<String>>,
|
||||||
pub scroll: Scroller,
|
pub scroll: Scroller,
|
||||||
|
pub pointer_positions: CopyHashMap<SeatId, (i32, i32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OutputNode {
|
impl OutputNode {
|
||||||
|
|
@ -98,9 +104,12 @@ impl OutputNode {
|
||||||
x = pos + (title_width - title.width()) / 2;
|
x = pos + (title_width - title.width()) / 2;
|
||||||
}
|
}
|
||||||
rd.titles.push(OutputTitle {
|
rd.titles.push(OutputTitle {
|
||||||
x,
|
x1: pos,
|
||||||
y: 0,
|
x2: pos + title_width,
|
||||||
|
tex_x: x,
|
||||||
|
tex_y: 0,
|
||||||
tex: title,
|
tex: title,
|
||||||
|
ws: ws.deref().clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -130,9 +139,9 @@ impl OutputNode {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let pos = width - title.width() - 1;
|
let pos = width - title.width() - 1;
|
||||||
rd.status = Some(OutputTitle {
|
rd.status = Some(OutputStatus {
|
||||||
x: pos,
|
tex_x: pos,
|
||||||
y: 0,
|
tex_y: 0,
|
||||||
tex: title,
|
tex: title,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -295,11 +304,24 @@ impl OutputNode {
|
||||||
self.status.set(status.clone());
|
self.status.set(status.clone());
|
||||||
self.update_render_data();
|
self.update_render_data();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn pointer_move(self: &Rc<Self>, seat: &Rc<WlSeatGlobal>, x: i32, y: i32) {
|
||||||
|
self.pointer_positions.set(seat.id(), (x, y));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct OutputTitle {
|
pub struct OutputTitle {
|
||||||
pub x: i32,
|
pub x1: i32,
|
||||||
pub y: i32,
|
pub x2: i32,
|
||||||
|
pub tex_x: i32,
|
||||||
|
pub tex_y: i32,
|
||||||
|
pub tex: Rc<Texture>,
|
||||||
|
pub ws: Rc<WorkspaceNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct OutputStatus {
|
||||||
|
pub tex_x: i32,
|
||||||
|
pub tex_y: i32,
|
||||||
pub tex: Rc<Texture>,
|
pub tex: Rc<Texture>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -309,7 +331,7 @@ pub struct OutputRenderData {
|
||||||
pub underline: Rect,
|
pub underline: Rect,
|
||||||
pub inactive_workspaces: Vec<Rect>,
|
pub inactive_workspaces: Vec<Rect>,
|
||||||
pub titles: Vec<OutputTitle>,
|
pub titles: Vec<OutputTitle>,
|
||||||
pub status: Option<OutputTitle>,
|
pub status: Option<OutputStatus>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Debug for OutputNode {
|
impl Debug for OutputNode {
|
||||||
|
|
@ -423,6 +445,37 @@ impl Node for OutputNode {
|
||||||
renderer.render_output(self, x, y);
|
renderer.render_output(self, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_on_button(
|
||||||
|
self: Rc<Self>,
|
||||||
|
seat: &Rc<WlSeatGlobal>,
|
||||||
|
button: u32,
|
||||||
|
state: KeyState,
|
||||||
|
_serial: u32,
|
||||||
|
) {
|
||||||
|
if state != KeyState::Pressed || button != BTN_LEFT {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let (x, y) = match self.pointer_positions.get(&seat.id()) {
|
||||||
|
Some(p) => p,
|
||||||
|
_ => return,
|
||||||
|
};
|
||||||
|
if y >= self.state.theme.sizes.title_height.get() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let ws = 'ws: {
|
||||||
|
let rd = self.render_data.borrow_mut();
|
||||||
|
for title in &rd.titles {
|
||||||
|
if x >= title.x1 && x < title.x2 {
|
||||||
|
break 'ws title.ws.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
self.show_workspace(&ws);
|
||||||
|
self.update_render_data();
|
||||||
|
self.state.tree_changed();
|
||||||
|
}
|
||||||
|
|
||||||
fn node_on_axis_event(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, event: &PendingScroll) {
|
fn node_on_axis_event(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, event: &PendingScroll) {
|
||||||
let steps = match self.scroll.handle(event) {
|
let steps = match self.scroll.handle(event) {
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
|
|
@ -460,11 +513,19 @@ impl Node for OutputNode {
|
||||||
self.state.tree_changed();
|
self.state.tree_changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_on_pointer_enter(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||||
|
self.pointer_move(seat, x.round_down(), y.round_down());
|
||||||
|
}
|
||||||
|
|
||||||
fn node_on_pointer_focus(&self, seat: &Rc<WlSeatGlobal>) {
|
fn node_on_pointer_focus(&self, seat: &Rc<WlSeatGlobal>) {
|
||||||
// log::info!("output focus");
|
// log::info!("output focus");
|
||||||
seat.set_known_cursor(KnownCursor::Default);
|
seat.set_known_cursor(KnownCursor::Default);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn node_on_pointer_motion(self: Rc<Self>, seat: &Rc<WlSeatGlobal>, x: Fixed, y: Fixed) {
|
||||||
|
self.pointer_move(seat, x.round_down(), y.round_down());
|
||||||
|
}
|
||||||
|
|
||||||
fn node_into_output(self: Rc<Self>) -> Option<Rc<OutputNode>> {
|
fn node_into_output(self: Rc<Self>) -> Option<Rc<OutputNode>> {
|
||||||
Some(self.clone())
|
Some(self.clone())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,5 +76,8 @@ unsafe impl<T> UnsafeCellCloneSafe for NodeRef<T> {}
|
||||||
|
|
||||||
unsafe impl UnsafeCellCloneSafe for () {}
|
unsafe impl UnsafeCellCloneSafe for () {}
|
||||||
unsafe impl UnsafeCellCloneSafe for u64 {}
|
unsafe impl UnsafeCellCloneSafe for u64 {}
|
||||||
|
unsafe impl UnsafeCellCloneSafe for i32 {}
|
||||||
|
|
||||||
|
unsafe impl<A: UnsafeCellCloneSafe, B: UnsafeCellCloneSafe> UnsafeCellCloneSafe for (A, B) {}
|
||||||
|
|
||||||
unsafe impl UnsafeCellCloneSafe for Modifiers {}
|
unsafe impl UnsafeCellCloneSafe for Modifiers {}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue