mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2024-12-25 09:59:21 +01:00
parent
0a6984f713
commit
71e4c1f159
3 changed files with 67 additions and 105 deletions
42
src/focus.rs
42
src/focus.rs
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
use keyboard::KeyboardFocusTarget;
|
||||
use smithay::{desktop::space::SpaceElement, output::Output, utils::SERIAL_COUNTER};
|
||||
|
||||
use crate::{
|
||||
|
@ -13,33 +14,36 @@ pub mod pointer;
|
|||
impl State {
|
||||
/// Update the keyboard focus.
|
||||
pub fn update_keyboard_focus(&mut self, output: &Output) {
|
||||
let current_focus = self.pinnacle.focused_window(output);
|
||||
let Some(keyboard) = self.pinnacle.seat.get_keyboard() else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(win) = ¤t_focus {
|
||||
assert!(!win.is_x11_override_redirect());
|
||||
let current_focused_window = self.pinnacle.focused_window(output);
|
||||
|
||||
let wins = output.with_state(|state| state.focus_stack.stack.clone());
|
||||
let keyboard_focus_is_same = keyboard
|
||||
.current_focus()
|
||||
.is_some_and(|foc| {
|
||||
matches!(foc, KeyboardFocusTarget::Window(win) if Some(&win) == current_focused_window.as_ref())
|
||||
});
|
||||
|
||||
for win in wins.iter() {
|
||||
win.set_activate(false);
|
||||
if keyboard_focus_is_same {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(focused_win) = ¤t_focused_window {
|
||||
assert!(!focused_win.is_x11_override_redirect());
|
||||
|
||||
for win in self.pinnacle.windows.iter() {
|
||||
win.set_activate(win == focused_win);
|
||||
if let Some(toplevel) = win.toplevel() {
|
||||
toplevel.send_configure();
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
win.set_activate(true);
|
||||
if let Some(toplevel) = win.toplevel() {
|
||||
toplevel.send_configure();
|
||||
}
|
||||
}
|
||||
|
||||
self.pinnacle
|
||||
.seat
|
||||
.get_keyboard()
|
||||
.expect("no keyboard")
|
||||
.set_focus(
|
||||
keyboard.set_focus(
|
||||
self,
|
||||
current_focus.map(|win| win.into()),
|
||||
current_focused_window.map(|win| win.into()),
|
||||
SERIAL_COUNTER.next_serial(),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,10 @@ use smithay::{
|
|||
SelectionHandler, SelectionSource, SelectionTarget,
|
||||
},
|
||||
shell::{
|
||||
wlr_layer::{self, Layer, LayerSurfaceData, WlrLayerShellHandler, WlrLayerShellState},
|
||||
wlr_layer::{
|
||||
self, Layer, LayerSurfaceCachedState, LayerSurfaceData, WlrLayerShellHandler,
|
||||
WlrLayerShellState,
|
||||
},
|
||||
xdg::{PopupSurface, XdgPopupSurfaceData, XdgToplevelSurfaceData},
|
||||
},
|
||||
shm::{ShmHandler, ShmState},
|
||||
|
@ -680,6 +683,12 @@ impl WlrLayerShellHandler for State {
|
|||
output = Some(op.clone());
|
||||
}
|
||||
|
||||
let focused_output = self.pinnacle.focused_output().cloned();
|
||||
|
||||
if let Some(focused_output) = focused_output {
|
||||
self.update_keyboard_focus(&focused_output);
|
||||
}
|
||||
|
||||
if let Some(output) = output {
|
||||
self.pinnacle.loop_handle.insert_idle(move |state| {
|
||||
state.pinnacle.request_layout(&output);
|
||||
|
|
103
src/input.rs
103
src/input.rs
|
@ -32,7 +32,7 @@ use smithay::{
|
|||
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
|
||||
},
|
||||
reexports::input::{self, Led},
|
||||
utils::{IsAlive, Logical, Point, Rectangle, SERIAL_COUNTER},
|
||||
utils::{Logical, Point, Rectangle, SERIAL_COUNTER},
|
||||
wayland::{
|
||||
compositor::{self, RegionAttributes, SurfaceAttributes},
|
||||
pointer_constraints::{with_pointer_constraint, PointerConstraint},
|
||||
|
@ -118,12 +118,6 @@ pub struct InputState {
|
|||
/// All libinput devices that have been connected
|
||||
pub libinput_devices: Vec<input::Device>,
|
||||
|
||||
/// A keyboard focus target stack that is used when there are exclusive keyboard layer
|
||||
/// surfaces. When used, the first item is the previous focus before there were any
|
||||
/// exclusive layer surfaces.
|
||||
// TODO: make that a type or something
|
||||
exclusive_layer_focus_stack: Vec<KeyboardFocusTarget>,
|
||||
|
||||
locked_pointer_position_hint: Option<Point<f64, Logical>>,
|
||||
|
||||
// Keys that were used in a keybind and should not be released
|
||||
|
@ -443,7 +437,8 @@ impl State {
|
|||
}
|
||||
|
||||
if self.pinnacle.lock_state.is_unlocked() {
|
||||
// Handle exclusive layers
|
||||
// Focus the topmost exclusive layer, if any
|
||||
let mut exclusive_layers_exist = false;
|
||||
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>()
|
||||
|
@ -456,58 +451,21 @@ impl State {
|
|||
{
|
||||
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
|
||||
let layer = map.layers().find(|l| l.layer_surface() == &layer).cloned();
|
||||
layer
|
||||
});
|
||||
|
||||
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
|
||||
.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
|
||||
.input_state
|
||||
.exclusive_layer_focus_stack
|
||||
.push(last.clone());
|
||||
}
|
||||
keyboard.set_focus(self, Some(last), serial);
|
||||
exclusive_layers_exist = true;
|
||||
keyboard.set_focus(
|
||||
self,
|
||||
Some(KeyboardFocusTarget::LayerSurface(layer_surface)),
|
||||
serial,
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We don't want anything but lock surfaces getting keyboard input when locked
|
||||
let lock_surface = self
|
||||
|
@ -670,37 +628,28 @@ impl State {
|
|||
if let Some((focus, _)) = self.pinnacle.pointer_focus_target_under(pointer_loc) {
|
||||
if let Some(window) = focus.window_for(self) {
|
||||
self.pinnacle.raise_window(window.clone(), true);
|
||||
if !window.is_x11_override_redirect() {
|
||||
if let Some(output) = window.output(&self.pinnacle) {
|
||||
output.with_state_mut(|state| state.focus_stack.set_focus(window.clone()));
|
||||
output.with_state_mut(|state| {
|
||||
state.focus_stack.set_focus(window.clone())
|
||||
});
|
||||
self.update_keyboard_focus(&output);
|
||||
}
|
||||
}
|
||||
|
||||
if !matches!(
|
||||
focus.window_for(self),
|
||||
Some(window) if window.is_x11_override_redirect()
|
||||
) && focus.popup_for(self).is_none()
|
||||
{
|
||||
keyboard.set_focus(self, focus.to_keyboard_focus_target(self), serial);
|
||||
}
|
||||
|
||||
for window in self.pinnacle.space.elements() {
|
||||
if let Some(toplevel) = window.toplevel() {
|
||||
toplevel.send_pending_configure();
|
||||
} else if let Some(layer) = focus.layer_for(self) {
|
||||
if layer.can_receive_keyboard_focus() {
|
||||
keyboard.set_focus(
|
||||
self,
|
||||
Some(KeyboardFocusTarget::LayerSurface(layer)),
|
||||
serial,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let Some(focused_op) = self.pinnacle.focused_output() {
|
||||
} else if let Some(focused_op) = self.pinnacle.focused_output().cloned() {
|
||||
focused_op.with_state_mut(|state| {
|
||||
state.focus_stack.unset_focus();
|
||||
for window in state.focus_stack.stack.iter() {
|
||||
window.set_activate(false);
|
||||
if let Some(toplevel) = window.toplevel() {
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
keyboard.set_focus(self, None, serial);
|
||||
self.update_keyboard_focus(&focused_op);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue