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
46
src/focus.rs
46
src/focus.rs
|
@ -1,5 +1,6 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
use keyboard::KeyboardFocusTarget;
|
||||||
use smithay::{desktop::space::SpaceElement, output::Output, utils::SERIAL_COUNTER};
|
use smithay::{desktop::space::SpaceElement, output::Output, utils::SERIAL_COUNTER};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -13,35 +14,38 @@ pub mod pointer;
|
||||||
impl State {
|
impl State {
|
||||||
/// Update the keyboard focus.
|
/// Update the keyboard focus.
|
||||||
pub fn update_keyboard_focus(&mut self, output: &Output) {
|
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 {
|
let current_focused_window = self.pinnacle.focused_window(output);
|
||||||
assert!(!win.is_x11_override_redirect());
|
|
||||||
|
|
||||||
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() {
|
if keyboard_focus_is_same {
|
||||||
win.set_activate(false);
|
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() {
|
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
|
keyboard.set_focus(
|
||||||
.seat
|
self,
|
||||||
.get_keyboard()
|
current_focused_window.map(|win| win.into()),
|
||||||
.expect("no keyboard")
|
SERIAL_COUNTER.next_serial(),
|
||||||
.set_focus(
|
);
|
||||||
self,
|
|
||||||
current_focus.map(|win| win.into()),
|
|
||||||
SERIAL_COUNTER.next_serial(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,7 +62,10 @@ use smithay::{
|
||||||
SelectionHandler, SelectionSource, SelectionTarget,
|
SelectionHandler, SelectionSource, SelectionTarget,
|
||||||
},
|
},
|
||||||
shell::{
|
shell::{
|
||||||
wlr_layer::{self, Layer, LayerSurfaceData, WlrLayerShellHandler, WlrLayerShellState},
|
wlr_layer::{
|
||||||
|
self, Layer, LayerSurfaceCachedState, LayerSurfaceData, WlrLayerShellHandler,
|
||||||
|
WlrLayerShellState,
|
||||||
|
},
|
||||||
xdg::{PopupSurface, XdgPopupSurfaceData, XdgToplevelSurfaceData},
|
xdg::{PopupSurface, XdgPopupSurfaceData, XdgToplevelSurfaceData},
|
||||||
},
|
},
|
||||||
shm::{ShmHandler, ShmState},
|
shm::{ShmHandler, ShmState},
|
||||||
|
@ -680,6 +683,12 @@ impl WlrLayerShellHandler for State {
|
||||||
output = Some(op.clone());
|
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 {
|
if let Some(output) = output {
|
||||||
self.pinnacle.loop_handle.insert_idle(move |state| {
|
self.pinnacle.loop_handle.insert_idle(move |state| {
|
||||||
state.pinnacle.request_layout(&output);
|
state.pinnacle.request_layout(&output);
|
||||||
|
|
115
src/input.rs
115
src/input.rs
|
@ -32,7 +32,7 @@ use smithay::{
|
||||||
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
|
pointer::{AxisFrame, ButtonEvent, MotionEvent, RelativeMotionEvent},
|
||||||
},
|
},
|
||||||
reexports::input::{self, Led},
|
reexports::input::{self, Led},
|
||||||
utils::{IsAlive, Logical, Point, Rectangle, SERIAL_COUNTER},
|
utils::{Logical, Point, Rectangle, SERIAL_COUNTER},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{self, RegionAttributes, SurfaceAttributes},
|
compositor::{self, RegionAttributes, SurfaceAttributes},
|
||||||
pointer_constraints::{with_pointer_constraint, PointerConstraint},
|
pointer_constraints::{with_pointer_constraint, PointerConstraint},
|
||||||
|
@ -118,12 +118,6 @@ pub struct InputState {
|
||||||
/// All libinput devices that have been connected
|
/// All libinput devices that have been connected
|
||||||
pub libinput_devices: Vec<input::Device>,
|
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>>,
|
locked_pointer_position_hint: Option<Point<f64, Logical>>,
|
||||||
|
|
||||||
// Keys that were used in a keybind and should not be released
|
// 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() {
|
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() {
|
for layer in self.pinnacle.layer_shell_state.layer_surfaces().rev() {
|
||||||
let data = compositor::with_states(layer.wl_surface(), |states| {
|
let data = compositor::with_states(layer.wl_surface(), |states| {
|
||||||
*states.cached_state.current::<LayerSurfaceCachedState>()
|
*states.cached_state.current::<LayerSurfaceCachedState>()
|
||||||
|
@ -456,58 +451,21 @@ impl State {
|
||||||
{
|
{
|
||||||
let layer_surface = self.pinnacle.space.outputs().find_map(|op| {
|
let layer_surface = self.pinnacle.space.outputs().find_map(|op| {
|
||||||
let map = layer_map_for_output(op);
|
let map = layer_map_for_output(op);
|
||||||
let cloned = map.layers().find(|l| l.layer_surface() == &layer).cloned();
|
let layer = map.layers().find(|l| l.layer_surface() == &layer).cloned();
|
||||||
cloned
|
layer
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Some(layer_surface) = layer_surface {
|
if let Some(layer_surface) = layer_surface {
|
||||||
match self.pinnacle.input_state.exclusive_layer_focus_stack.last() {
|
exclusive_layers_exist = true;
|
||||||
Some(focus) => {
|
keyboard.set_focus(
|
||||||
let layer_focus = KeyboardFocusTarget::LayerSurface(layer_surface);
|
self,
|
||||||
if &layer_focus != focus {
|
Some(KeyboardFocusTarget::LayerSurface(layer_surface)),
|
||||||
self.pinnacle
|
serial,
|
||||||
.input_state
|
);
|
||||||
.exclusive_layer_focus_stack
|
break;
|
||||||
.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);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// We don't want anything but lock surfaces getting keyboard input when locked
|
// We don't want anything but lock surfaces getting keyboard input when locked
|
||||||
let lock_surface = self
|
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((focus, _)) = self.pinnacle.pointer_focus_target_under(pointer_loc) {
|
||||||
if let Some(window) = focus.window_for(self) {
|
if let Some(window) = focus.window_for(self) {
|
||||||
self.pinnacle.raise_window(window.clone(), true);
|
self.pinnacle.raise_window(window.clone(), true);
|
||||||
if let Some(output) = window.output(&self.pinnacle) {
|
if !window.is_x11_override_redirect() {
|
||||||
output.with_state_mut(|state| state.focus_stack.set_focus(window.clone()));
|
if let Some(output) = window.output(&self.pinnacle) {
|
||||||
}
|
output.with_state_mut(|state| {
|
||||||
}
|
state.focus_stack.set_focus(window.clone())
|
||||||
|
});
|
||||||
if !matches!(
|
self.update_keyboard_focus(&output);
|
||||||
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(focused_op) = self.pinnacle.focused_output() {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
} else if let Some(layer) = focus.layer_for(self) {
|
||||||
|
if layer.can_receive_keyboard_focus() {
|
||||||
|
keyboard.set_focus(
|
||||||
|
self,
|
||||||
|
Some(KeyboardFocusTarget::LayerSurface(layer)),
|
||||||
|
serial,
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
keyboard.set_focus(self, None, serial);
|
} else if let Some(focused_op) = self.pinnacle.focused_output().cloned() {
|
||||||
|
focused_op.with_state_mut(|state| {
|
||||||
|
state.focus_stack.unset_focus();
|
||||||
|
});
|
||||||
|
self.update_keyboard_focus(&focused_op);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue