layer_shell: Fix initial keyboard focus

This commit is contained in:
Victoria Brekenfeld 2022-04-21 14:02:44 +02:00
parent 3fe082d648
commit ff844631ea
3 changed files with 42 additions and 28 deletions

View file

@ -17,8 +17,7 @@ use smithay::{
seat::{PointerGrabStartData, Seat}, seat::{PointerGrabStartData, Seat},
shell::{ shell::{
wlr_layer::{ wlr_layer::{
wlr_layer_shell_init, KeyboardInteractivity, Layer, LayerShellRequest, wlr_layer_shell_init, LayerShellRequest, LayerSurfaceAttributes,
LayerSurfaceAttributes, LayerSurfaceCachedState,
}, },
xdg::{ xdg::{
xdg_shell_init, Configure, XdgPopupSurfaceRoleAttributes, XdgRequest, xdg_shell_init, Configure, XdgPopupSurfaceRoleAttributes, XdgRequest,
@ -26,7 +25,6 @@ use smithay::{
}, },
}, },
Serial, Serial,
SERIAL_COUNTER,
}, },
}; };
use std::{cell::Cell, sync::Mutex}; use std::{cell::Cell, sync::Mutex};
@ -236,26 +234,7 @@ pub fn init_shell(config: &Config, display: &mut Display) -> super::Shell {
.as_ref() .as_ref()
.and_then(Output::from_resource) .and_then(Output::from_resource)
.unwrap_or_else(|| active_output(&seat, &*state)); .unwrap_or_else(|| active_output(&seat, &*state));
state.shell.active_space_mut(&output).pending_layer(LayerSurface::new(surface, namespace), &output, &seat);
let focus = surface
.get_surface()
.map(|surface| {
with_states(surface, |states| {
let state = states.cached_state.current::<LayerSurfaceCachedState>();
matches!(state.layer, Layer::Top | Layer::Overlay)
&& state.keyboard_interactivity != KeyboardInteractivity::None
})
.unwrap()
})
.unwrap_or(false);
let mut map = layer_map_for_output(&output);
map.map_layer(&LayerSurface::new(surface.clone(), namespace))
.unwrap();
if focus {
state.set_focus(surface.get_surface(), &seat, Some(SERIAL_COUNTER.next_serial()));
}
} }
_ => {} _ => {}
}, },

View file

@ -6,14 +6,17 @@ use crate::{
state::Common, state::Common,
}; };
pub use smithay::{ pub use smithay::{
desktop::{PopupGrab, PopupManager, PopupUngrabStrategy, Space, Window}, desktop::{PopupGrab, PopupManager, PopupUngrabStrategy, Space, Window, layer_map_for_output},
reexports::wayland_server::protocol::wl_surface::WlSurface, reexports::wayland_server::protocol::wl_surface::WlSurface,
utils::{Logical, Point, Rectangle, Size}, utils::{Logical, Point, Rectangle, Size},
wayland::{ wayland::{
compositor::with_states, compositor::with_states,
output::{Mode as OutputMode, Output, Scale}, output::{Mode as OutputMode, Output, Scale},
seat::Seat, seat::Seat,
shell::xdg::XdgToplevelSurfaceRoleAttributes, shell::{
xdg::XdgToplevelSurfaceRoleAttributes,
wlr_layer::{Layer, KeyboardInteractivity, LayerSurfaceCachedState},
},
Serial, SERIAL_COUNTER, Serial, SERIAL_COUNTER,
}, },
}; };
@ -467,7 +470,33 @@ impl Shell {
} }
workspace.pending_windows.retain(|(w, _)| w != &window); workspace.pending_windows.retain(|(w, _)| w != &window);
} }
workspace.space.commit(surface) if let Some((layer, output, seat)) = workspace
.pending_layers
.iter()
.find(|(l, _, _)| l.get_surface() == Some(surface))
.cloned()
{
let focus = layer
.get_surface()
.map(|surface| {
with_states(surface, |states| {
let state = states.cached_state.current::<LayerSurfaceCachedState>();
matches!(state.layer, Layer::Top | Layer::Overlay)
&& dbg!(state.keyboard_interactivity) != KeyboardInteractivity::None
})
.unwrap()
})
.unwrap_or(false);
let mut map = layer_map_for_output(&output);
map.map_layer(&layer).unwrap();
if focus {
new_focus = Some(seat);
}
workspace.pending_layers.retain(|(l, _, _)| l != &layer);
}
workspace.space.commit(surface);
} }
if let Some(seat) = new_focus { if let Some(seat) = new_focus {
self.set_focus(Some(surface), &seat, seats, None) self.set_focus(Some(surface), &seat, seats, None)

View file

@ -1,7 +1,7 @@
use super::{layout, Layout}; use super::{layout, Layout};
use indexmap::IndexSet; use indexmap::IndexSet;
use smithay::{ use smithay::{
desktop::{Space, Window}, desktop::{LayerSurface, Space, Window},
reexports::wayland_protocols::xdg_shell::server::xdg_toplevel::ResizeEdge, reexports::wayland_protocols::xdg_shell::server::xdg_toplevel::ResizeEdge,
wayland::{ wayland::{
output::Output, output::Output,
@ -52,6 +52,7 @@ pub struct Workspace {
pub space: Space, pub space: Space,
pub(super) layout: Box<dyn Layout>, pub(super) layout: Box<dyn Layout>,
pub(super) pending_windows: Vec<(Window, Seat)>, pub(super) pending_windows: Vec<(Window, Seat)>,
pub(super) pending_layers: Vec<(LayerSurface, Output, Seat)>,
} }
impl Workspace { impl Workspace {
@ -61,6 +62,7 @@ impl Workspace {
space: Space::new(None), space: Space::new(None),
layout: layout::new_default_layout(), layout: layout::new_default_layout(),
pending_windows: Vec::new(), pending_windows: Vec::new(),
pending_layers: Vec::new(),
} }
} }
@ -89,6 +91,10 @@ impl Workspace {
self.pending_windows.push((window, seat.clone())); self.pending_windows.push((window, seat.clone()));
} }
pub fn pending_layer(&mut self, layer: LayerSurface, output: &Output, seat: &Seat) {
self.pending_layers.push((layer, output.clone(), seat.clone()));
}
pub(super) fn map_window(&mut self, window: &Window, seat: &Seat) { pub(super) fn map_window(&mut self, window: &Window, seat: &Seat) {
seat.user_data() seat.user_data()
.insert_if_missing(|| FocusStackData::new((HashMap::new(), IndexSet::new()))); .insert_if_missing(|| FocusStackData::new((HashMap::new(), IndexSet::new())));