shell: Rewrite get_focused_output to properly account for groups
This commit is contained in:
parent
0d048b1a8e
commit
b111c9ff48
2 changed files with 94 additions and 12 deletions
|
|
@ -268,6 +268,7 @@ fn update_focus_state(
|
||||||
target.cloned(),
|
target.cloned(),
|
||||||
serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()),
|
serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()),
|
||||||
);
|
);
|
||||||
|
std::mem::drop(keyboard);
|
||||||
|
|
||||||
//update the focused output or set it to the active output
|
//update the focused output or set it to the active output
|
||||||
if target.is_some() {
|
if target.is_some() {
|
||||||
|
|
@ -280,7 +281,8 @@ fn update_focus_state(
|
||||||
.shell
|
.shell
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.get_focused_output(target.unwrap()),
|
.get_output_for_focus(seat)
|
||||||
|
.as_ref(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
seat.set_focused_output(None);
|
seat.set_focused_output(None);
|
||||||
|
|
|
||||||
102
src/shell/mod.rs
102
src/shell/mod.rs
|
|
@ -1,4 +1,5 @@
|
||||||
use calloop::LoopHandle;
|
use calloop::LoopHandle;
|
||||||
|
use focus::target::WindowGroup;
|
||||||
use grabs::SeatMoveGrabState;
|
use grabs::SeatMoveGrabState;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use layout::TilingExceptions;
|
use layout::TilingExceptions;
|
||||||
|
|
@ -1410,11 +1411,93 @@ impl Shell {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get the parent output of the window which has keyboard focus (for a given seat)
|
/// get the parent output of the window which has keyboard focus (for a given seat)
|
||||||
pub fn get_focused_output(&self, focus_target: &KeyboardFocusTarget) -> Option<&Output> {
|
pub fn get_output_for_focus(&self, seat: &Seat<State>) -> Option<Output> {
|
||||||
if let Some(focused_surface) = focus_target.wl_surface() {
|
let mut focus_target = seat.get_keyboard().unwrap().current_focus()?;
|
||||||
self.visible_output_for_surface(&focused_surface)
|
|
||||||
} else {
|
if let KeyboardFocusTarget::Popup(popup) = &focus_target {
|
||||||
None
|
let new_target = match popup {
|
||||||
|
PopupKind::Xdg(popup) => {
|
||||||
|
if let Some(parent) = popup.get_parent_surface() {
|
||||||
|
self.element_for_surface(&parent).cloned()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PopupKind::InputMethod(popup) => {
|
||||||
|
if let Some(parent) = popup.get_parent() {
|
||||||
|
self.element_for_surface(&parent.surface).cloned()
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}?;
|
||||||
|
|
||||||
|
focus_target = KeyboardFocusTarget::Element(new_target);
|
||||||
|
};
|
||||||
|
|
||||||
|
match focus_target {
|
||||||
|
KeyboardFocusTarget::Element(elem) => {
|
||||||
|
if seat
|
||||||
|
.user_data()
|
||||||
|
.get::<SeatMoveGrabState>()
|
||||||
|
.is_some_and(|state| {
|
||||||
|
state
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|state| state.element() == elem)
|
||||||
|
})
|
||||||
|
{
|
||||||
|
return Some(seat.active_output());
|
||||||
|
}
|
||||||
|
|
||||||
|
self.outputs()
|
||||||
|
.find(|output| {
|
||||||
|
let is_sticky = self
|
||||||
|
.workspaces
|
||||||
|
.sets
|
||||||
|
.get(*output)
|
||||||
|
.unwrap()
|
||||||
|
.sticky_layer
|
||||||
|
.mapped()
|
||||||
|
.any(|m| m == &elem);
|
||||||
|
|
||||||
|
let workspace = self.active_space(output);
|
||||||
|
let is_mapped = workspace.mapped().any(|m| m == &elem);
|
||||||
|
|
||||||
|
is_sticky || is_mapped
|
||||||
|
})
|
||||||
|
.cloned()
|
||||||
|
}
|
||||||
|
KeyboardFocusTarget::Fullscreen(elem) => self
|
||||||
|
.outputs()
|
||||||
|
.find(|output| {
|
||||||
|
let workspace = self.active_space(&output);
|
||||||
|
workspace.get_fullscreen() == Some(&elem)
|
||||||
|
})
|
||||||
|
.cloned(),
|
||||||
|
KeyboardFocusTarget::Group(WindowGroup { node, .. }) => self
|
||||||
|
.outputs()
|
||||||
|
.find(|output| {
|
||||||
|
self.workspaces
|
||||||
|
.active(&output)
|
||||||
|
.1
|
||||||
|
.tiling_layer
|
||||||
|
.has_node(&node)
|
||||||
|
})
|
||||||
|
.cloned(),
|
||||||
|
KeyboardFocusTarget::LayerSurface(layer) => self
|
||||||
|
.outputs()
|
||||||
|
.find(|output| layer_map_for_output(output).layers().any(|l| l == &layer))
|
||||||
|
.cloned(),
|
||||||
|
KeyboardFocusTarget::LockSurface(surface) => self
|
||||||
|
.session_lock
|
||||||
|
.as_ref()?
|
||||||
|
.surfaces
|
||||||
|
.iter()
|
||||||
|
.find_map(|(output, s)| (s == &surface).then_some(output))
|
||||||
|
.cloned(),
|
||||||
|
KeyboardFocusTarget::Popup(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2977,12 +3060,9 @@ impl Shell {
|
||||||
direction: Direction,
|
direction: Direction,
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
) -> MoveResult {
|
) -> MoveResult {
|
||||||
let output = seat
|
let Some(output) = seat.focused_output() else {
|
||||||
.get_keyboard()
|
return MoveResult::None;
|
||||||
.unwrap()
|
};
|
||||||
.current_focus()
|
|
||||||
.and_then(|target| self.get_focused_output(&target).cloned())
|
|
||||||
.unwrap();
|
|
||||||
let workspace = self.active_space(&output);
|
let workspace = self.active_space(&output);
|
||||||
let focus_stack = workspace.focus_stack.get(seat);
|
let focus_stack = workspace.focus_stack.get(seat);
|
||||||
let Some(last) = focus_stack.last().cloned() else {
|
let Some(last) = focus_stack.last().cloned() else {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue