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::{
|
||||
ifs::wl_surface::xdg_surface::xdg_toplevel::STATE_SUSPENDED,
|
||||
it::{
|
||||
test_error::TestResult,
|
||||
test_error::{TestErrorExt, TestResult},
|
||||
test_utils::{
|
||||
test_ouput_node_ext::TestOutputNodeExt, test_toplevel_node_ext::TestToplevelNodeExt,
|
||||
},
|
||||
|
|
@ -10,7 +10,7 @@ use {
|
|||
},
|
||||
},
|
||||
isnt::std_1::collections::IsntHashSetExt,
|
||||
std::rc::Rc,
|
||||
std::{rc::Rc, time::Duration},
|
||||
};
|
||||
|
||||
testcase!();
|
||||
|
|
@ -19,6 +19,7 @@ async fn test(run: Rc<TestRun>) -> TestResult {
|
|||
let ds = run.create_default_setup().await?;
|
||||
|
||||
let client = run.create_client().await?;
|
||||
let default_seat = client.get_default_seat().await?;
|
||||
|
||||
let win1 = client.create_window().await?;
|
||||
win1.set_color(255, 0, 0, 255);
|
||||
|
|
@ -44,5 +45,23 @@ async fn test(run: Rc<TestRun>) -> TestResult {
|
|||
client.sync().await;
|
||||
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(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,18 +8,25 @@ use {
|
|||
renderer::Renderer,
|
||||
state::State,
|
||||
tree::{
|
||||
FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink, NodeLocation,
|
||||
OutputNode, StackedNode, TileDragDestination, WorkspaceDragDestination,
|
||||
Direction, FindTreeResult, FindTreeUsecase, FoundNode, Node, NodeId, NodeLayerLink,
|
||||
NodeLocation, OutputNode, StackedNode, TileDragDestination, WorkspaceDragDestination,
|
||||
WorkspaceNodeId, walker::NodeVisitor,
|
||||
},
|
||||
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 id: NodeId,
|
||||
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 stacked: Rc<LinkedList<Rc<dyn StackedNode>>>,
|
||||
pub stacked_above_layers: Rc<LinkedList<Rc<dyn StackedNode>>>,
|
||||
|
|
@ -31,6 +38,8 @@ impl DisplayNode {
|
|||
let slf = Self {
|
||||
id,
|
||||
extents: Default::default(),
|
||||
visible: Default::default(),
|
||||
suspend_restore_kb_foci: Default::default(),
|
||||
outputs: Default::default(),
|
||||
stacked: Default::default(),
|
||||
stacked_above_layers: Default::default(),
|
||||
|
|
@ -71,6 +80,17 @@ impl DisplayNode {
|
|||
|
||||
pub fn update_visible(&self, state: &State) {
|
||||
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() {
|
||||
output.update_visible();
|
||||
}
|
||||
|
|
@ -82,6 +102,20 @@ impl DisplayNode {
|
|||
for seat in state.globals.seats.lock().values() {
|
||||
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 {
|
||||
state.damage(self.extents.get());
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue