fix: restore focus after backend visibility resumes
This commit is contained in:
parent
f777b4c521
commit
5db14936e7
2 changed files with 58 additions and 5 deletions
|
|
@ -2,7 +2,7 @@ use {
|
||||||
crate::{
|
crate::{
|
||||||
ifs::wl_surface::xdg_surface::xdg_toplevel::STATE_SUSPENDED,
|
ifs::wl_surface::xdg_surface::xdg_toplevel::STATE_SUSPENDED,
|
||||||
it::{
|
it::{
|
||||||
test_error::TestResult,
|
test_error::{TestErrorExt, TestResult},
|
||||||
test_utils::{
|
test_utils::{
|
||||||
test_ouput_node_ext::TestOutputNodeExt, test_toplevel_node_ext::TestToplevelNodeExt,
|
test_ouput_node_ext::TestOutputNodeExt, test_toplevel_node_ext::TestToplevelNodeExt,
|
||||||
},
|
},
|
||||||
|
|
@ -10,7 +10,7 @@ use {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
isnt::std_1::collections::IsntHashSetExt,
|
isnt::std_1::collections::IsntHashSetExt,
|
||||||
std::rc::Rc,
|
std::{rc::Rc, time::Duration},
|
||||||
};
|
};
|
||||||
|
|
||||||
testcase!();
|
testcase!();
|
||||||
|
|
@ -19,6 +19,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
let ds = run.create_default_setup().await?;
|
let ds = run.create_default_setup().await?;
|
||||||
|
|
||||||
let client = run.create_client().await?;
|
let client = run.create_client().await?;
|
||||||
|
let default_seat = client.get_default_seat().await?;
|
||||||
|
|
||||||
let win1 = client.create_window().await?;
|
let win1 = client.create_window().await?;
|
||||||
win1.set_color(255, 0, 0, 255);
|
win1.set_color(255, 0, 0, 255);
|
||||||
|
|
@ -44,5 +45,23 @@ async fn test(run: Rc<TestRun>) -> TestResult {
|
||||||
client.sync().await;
|
client.sync().await;
|
||||||
tassert!(win2.tl.core.states.borrow().not_contains(&STATE_SUSPENDED));
|
tassert!(win2.tl.core.states.borrow().not_contains(&STATE_SUSPENDED));
|
||||||
|
|
||||||
|
let leaves = default_seat.kb.leave.expect()?;
|
||||||
|
let enters = default_seat.kb.enter.expect()?;
|
||||||
|
|
||||||
|
run.cfg.set_idle(Duration::from_micros(100))?;
|
||||||
|
run.cfg.set_idle_grace_period(Duration::from_secs(0))?;
|
||||||
|
run.state.wheel.timeout(3).await?;
|
||||||
|
|
||||||
|
client.sync().await;
|
||||||
|
tassert!(win2.tl.core.states.borrow().contains(&STATE_SUSPENDED));
|
||||||
|
let leave = leaves.next().with_context(|| "no leave on suspend")?;
|
||||||
|
tassert_eq!(leave.surface, win2.surface.id);
|
||||||
|
|
||||||
|
ds.mouse.rel(1.0, 1.0);
|
||||||
|
client.sync().await;
|
||||||
|
tassert!(win2.tl.core.states.borrow().not_contains(&STATE_SUSPENDED));
|
||||||
|
let enter = enters.next().with_context(|| "no enter on restore")?;
|
||||||
|
tassert_eq!(enter.surface, win2.surface.id);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,18 +8,25 @@ use {
|
||||||
renderer::Renderer,
|
renderer::Renderer,
|
||||||
state::State,
|
state::State,
|
||||||
tree::{
|
tree::{
|
||||||
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation,
|
Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink,
|
||||||
OutputNode, StackedNode, TileDragDestination, WorkspaceDragDestination,
|
NodeLocation, OutputNode, StackedNode, TileDragDestination, WorkspaceDragDestination,
|
||||||
WorkspaceNodeId, walker::NodeVisitor,
|
WorkspaceNodeId, walker::NodeVisitor,
|
||||||
},
|
},
|
||||||
utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList},
|
utils::{copyhashmap::CopyHashMap, linkedlist::LinkedList},
|
||||||
},
|
},
|
||||||
std::{cell::Cell, ops::Deref, rc::Rc},
|
std::{
|
||||||
|
cell::{Cell, RefCell},
|
||||||
|
mem,
|
||||||
|
ops::Deref,
|
||||||
|
rc::{Rc, Weak},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct DisplayNode {
|
pub struct DisplayNode {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
pub extents: Cell<Rect>,
|
pub extents: Cell<Rect>,
|
||||||
|
visible: Cell<bool>,
|
||||||
|
suspend_restore_kb_foci: RefCell<Vec<(Rc<WlSeatGlobal>, Weak<dyn Node>)>>,
|
||||||
pub outputs: CopyHashMap<ConnectorId, Rc<OutputNode>>,
|
pub outputs: CopyHashMap<ConnectorId, Rc<OutputNode>>,
|
||||||
pub stacked: Rc<LinkedList<Rc<dyn StackedNode>>>,
|
pub stacked: Rc<LinkedList<Rc<dyn StackedNode>>>,
|
||||||
pub stacked_above_layers: Rc<LinkedList<Rc<dyn StackedNode>>>,
|
pub stacked_above_layers: Rc<LinkedList<Rc<dyn StackedNode>>>,
|
||||||
|
|
@ -31,6 +38,8 @@ impl DisplayNode {
|
||||||
let slf = Self {
|
let slf = Self {
|
||||||
id,
|
id,
|
||||||
extents: Default::default(),
|
extents: Default::default(),
|
||||||
|
visible: Default::default(),
|
||||||
|
suspend_restore_kb_foci: Default::default(),
|
||||||
outputs: Default::default(),
|
outputs: Default::default(),
|
||||||
stacked: Default::default(),
|
stacked: Default::default(),
|
||||||
stacked_above_layers: Default::default(),
|
stacked_above_layers: Default::default(),
|
||||||
|
|
@ -71,6 +80,17 @@ impl DisplayNode {
|
||||||
|
|
||||||
pub fn update_visible(&self, state: &State) {
|
pub fn update_visible(&self, state: &State) {
|
||||||
let visible = state.root_visible();
|
let visible = state.root_visible();
|
||||||
|
let was_visible = self.visible.replace(visible);
|
||||||
|
if !visible && was_visible {
|
||||||
|
let mut foci = self.suspend_restore_kb_foci.borrow_mut();
|
||||||
|
foci.clear();
|
||||||
|
for seat in state.globals.seats.lock().values() {
|
||||||
|
let node = seat.get_keyboard_node();
|
||||||
|
if node.node_id() != self.id {
|
||||||
|
foci.push((seat.clone(), Rc::downgrade(&node)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for output in self.outputs.lock().values() {
|
for output in self.outputs.lock().values() {
|
||||||
output.update_visible();
|
output.update_visible();
|
||||||
}
|
}
|
||||||
|
|
@ -82,6 +102,20 @@ impl DisplayNode {
|
||||||
for seat in state.globals.seats.lock().values() {
|
for seat in state.globals.seats.lock().values() {
|
||||||
seat.set_visible(visible);
|
seat.set_visible(visible);
|
||||||
}
|
}
|
||||||
|
if visible && !was_visible {
|
||||||
|
for (seat, node) in mem::take(&mut *self.suspend_restore_kb_foci.borrow_mut()) {
|
||||||
|
if seat.get_keyboard_node().node_id() == self.id {
|
||||||
|
if let Some(node) = node.upgrade()
|
||||||
|
&& node.node_visible()
|
||||||
|
{
|
||||||
|
seat.focus_node(node);
|
||||||
|
} else {
|
||||||
|
seat.get_fallback_output()
|
||||||
|
.take_keyboard_navigation_focus(&seat, Direction::Unspecified);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if visible {
|
if visible {
|
||||||
state.damage(self.extents.get());
|
state.damage(self.extents.get());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue