Force keyboard focus on lock surface, don't trigger keybinds when locked

This commit is contained in:
Ottatop 2024-05-14 20:41:10 -05:00
parent d708fccf58
commit b9c5a88f9f
2 changed files with 97 additions and 52 deletions

View file

@ -155,10 +155,15 @@ impl InputState {
#[derive(Debug)]
enum KeyAction {
/// Call a config callback.
CallCallback(UnboundedSender<Result<SetKeybindResponse, tonic::Status>>),
/// Quit the compositor.
Quit,
/// Switch ttys.
SwitchVt(i32),
/// Reload the config.
ReloadConfig,
/// Prevent the key from being sent to clients.
Suppress,
}
@ -419,68 +424,89 @@ impl State {
device.led_update(leds);
}
for layer in self.pinnacle.layer_shell_state.layer_surfaces().rev() {
let data = compositor::with_states(layer.wl_surface(), |states| {
*states.cached_state.current::<LayerSurfaceCachedState>()
});
if data.keyboard_interactivity == KeyboardInteractivity::Exclusive
&& matches!(
data.layer,
wlr_layer::Layer::Top | wlr_layer::Layer::Overlay
)
{
let layer_surface = self.pinnacle.space.outputs().find_map(|op| {
let map = layer_map_for_output(op);
let cloned = map.layers().find(|l| l.layer_surface() == &layer).cloned();
cloned
if self.pinnacle.lock_state.is_unlocked() {
// Handle exclusive layers
for layer in self.pinnacle.layer_shell_state.layer_surfaces().rev() {
let data = compositor::with_states(layer.wl_surface(), |states| {
*states.cached_state.current::<LayerSurfaceCachedState>()
});
if data.keyboard_interactivity == KeyboardInteractivity::Exclusive
&& matches!(
data.layer,
wlr_layer::Layer::Top | wlr_layer::Layer::Overlay
)
{
let layer_surface = self.pinnacle.space.outputs().find_map(|op| {
let map = layer_map_for_output(op);
let cloned = map.layers().find(|l| l.layer_surface() == &layer).cloned();
cloned
});
if let Some(layer_surface) = layer_surface {
match self.pinnacle.input_state.exclusive_layer_focus_stack.last() {
Some(focus) => {
let layer_focus = KeyboardFocusTarget::LayerSurface(layer_surface);
if &layer_focus != focus {
if let Some(layer_surface) = layer_surface {
match self.pinnacle.input_state.exclusive_layer_focus_stack.last() {
Some(focus) => {
let layer_focus = KeyboardFocusTarget::LayerSurface(layer_surface);
if &layer_focus != focus {
self.pinnacle
.input_state
.exclusive_layer_focus_stack
.push(layer_focus);
}
}
// Push the previous focus on as this is the first exclusive layer surface
// on screen. This lets us restore it when that layer surface goes away.
None => {
self.pinnacle
.input_state
.exclusive_layer_focus_stack
.push(layer_focus);
.extend(keyboard.current_focus());
self.pinnacle
.input_state
.exclusive_layer_focus_stack
.push(KeyboardFocusTarget::LayerSurface(layer_surface));
}
}
// Push the previous focus on as this is the first exclusive layer surface
// on screen. This lets us restore it when that layer surface goes away.
None => {
self.pinnacle
.input_state
.exclusive_layer_focus_stack
.extend(keyboard.current_focus());
self.pinnacle
.input_state
.exclusive_layer_focus_stack
.push(KeyboardFocusTarget::LayerSurface(layer_surface));
}
}
}
}
}
while let Some(last) = self.pinnacle.input_state.exclusive_layer_focus_stack.pop() {
if last.alive() {
// If it's not empty then there's another exclusive layer surface
// underneath. Otherwise `last` is the previous keyboard focus
// and we don't need the stack anymore.
if !self
.pinnacle
.input_state
.exclusive_layer_focus_stack
.is_empty()
{
self.pinnacle
while let Some(last) = self.pinnacle.input_state.exclusive_layer_focus_stack.pop() {
if last.alive() {
// If it's not empty then there's another exclusive layer surface
// underneath. Otherwise `last` is the previous keyboard focus
// and we don't need the stack anymore.
if !self
.pinnacle
.input_state
.exclusive_layer_focus_stack
.push(last.clone());
.is_empty()
{
self.pinnacle
.input_state
.exclusive_layer_focus_stack
.push(last.clone());
}
keyboard.set_focus(self, Some(last), serial);
break;
}
keyboard.set_focus(self, Some(last), serial);
break;
}
} else {
// We don't want anything but lock surfaces getting keyboard input when locked
let lock_surface = self
.pinnacle
.space
.outputs()
.find_map(|op| op.with_state(|state| state.lock_surface.clone()));
if !matches!(
keyboard.current_focus(),
Some(KeyboardFocusTarget::LockSurface(_))
) {
keyboard.set_focus(
self,
lock_surface.map(KeyboardFocusTarget::LockSurface),
serial,
);
}
}
@ -522,15 +548,23 @@ impl State {
})
})
{
return FilterResult::Intercept(KeyAction::CallCallback(sender.clone()));
if state.pinnacle.lock_state.is_unlocked() {
return FilterResult::Intercept(KeyAction::CallCallback(
sender.clone(),
));
}
}
if kill_keybind == Some((mod_mask, mod_sym)) {
return FilterResult::Intercept(KeyAction::Quit);
} else if reload_keybind == Some((mod_mask, mod_sym)) {
}
if reload_keybind == Some((mod_mask, mod_sym)) {
return FilterResult::Intercept(KeyAction::ReloadConfig);
} else if let mut vt @ keysyms::KEY_XF86Switch_VT_1
..=keysyms::KEY_XF86Switch_VT_12 = keysym.modified_sym().raw()
}
if let mut vt @ keysyms::KEY_XF86Switch_VT_1..=keysyms::KEY_XF86Switch_VT_12 =
keysym.modified_sym().raw()
{
vt = vt - keysyms::KEY_XF86Switch_VT_1 + 1;
tracing::info!("Switching to vt {vt}");

View file

@ -128,5 +128,16 @@ impl Pinnacle {
output.set_preferred(mode);
output.with_state_mut(|state| state.modes.push(mode));
}
if let Some(lock_surface) = output.with_state(|state| state.lock_surface.clone()) {
lock_surface.with_pending_state(|state| {
let Some(new_geo) = self.space.output_geometry(output) else {
return;
};
state.size = Some((new_geo.size.w as u32, new_geo.size.h as u32).into());
});
lock_surface.send_configure();
}
}
}