focus: Don't consider XWaylandGrab exclusive
This commit is contained in:
parent
4209e61c48
commit
b28f92a6e1
6 changed files with 36 additions and 61 deletions
|
|
@ -344,7 +344,6 @@ fn format_keyboard_focus(focus: Option<KeyboardFocusTarget>) -> String {
|
||||||
Some(Popup(x)) => format!("Popup {}", x.wl_surface().id().protocol_id()),
|
Some(Popup(x)) => format!("Popup {}", x.wl_surface().id().protocol_id()),
|
||||||
Some(Group(_)) => format!("Window Group"),
|
Some(Group(_)) => format!("Window Group"),
|
||||||
Some(LockSurface(x)) => format!("LockSurface {}", x.wl_surface().id().protocol_id()),
|
Some(LockSurface(x)) => format!("LockSurface {}", x.wl_surface().id().protocol_id()),
|
||||||
Some(XWaylandGrab(x)) => format!("XWayland Grab {}", x.id().protocol_id()),
|
|
||||||
None => format!("None"),
|
None => format!("None"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
utils::{float::NextDown, prelude::*, quirks::workspace_overview_is_open},
|
utils::{float::NextDown, prelude::*, quirks::workspace_overview_is_open},
|
||||||
wayland::{
|
wayland::{
|
||||||
handlers::screencopy::SessionHolder,
|
handlers::{screencopy::SessionHolder, xwayland_keyboard_grab::XWaylandGrabSeat},
|
||||||
protocols::screencopy::{BufferConstraints, CursorSessionRef},
|
protocols::screencopy::{BufferConstraints, CursorSessionRef},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -241,12 +241,13 @@ impl State {
|
||||||
let current_focus = seat.get_keyboard().unwrap().current_focus();
|
let current_focus = seat.get_keyboard().unwrap().current_focus();
|
||||||
let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| {
|
let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| {
|
||||||
f.wl_surface()
|
f.wl_surface()
|
||||||
.and_then(|surface| {
|
.map(|surface| {
|
||||||
seat.keyboard_shortcuts_inhibitor_for_surface(&surface)
|
seat.keyboard_shortcuts_inhibitor_for_surface(&surface)
|
||||||
.map(|inhibitor| inhibitor.is_active())
|
.map(|inhibitor| inhibitor.is_active())
|
||||||
|
.unwrap_or(false)
|
||||||
|
|| seat.has_active_xwayland_grab(&surface)
|
||||||
})
|
})
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|| matches!(f, KeyboardFocusTarget::XWaylandGrab(_))
|
|
||||||
});
|
});
|
||||||
let sym = handle.modified_sym();
|
let sym = handle.modified_sym();
|
||||||
|
|
||||||
|
|
@ -686,12 +687,13 @@ impl State {
|
||||||
let current_focus = seat.get_keyboard().unwrap().current_focus();
|
let current_focus = seat.get_keyboard().unwrap().current_focus();
|
||||||
let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| {
|
let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| {
|
||||||
f.wl_surface()
|
f.wl_surface()
|
||||||
.and_then(|surface| {
|
.map(|surface| {
|
||||||
seat.keyboard_shortcuts_inhibitor_for_surface(&surface)
|
seat.keyboard_shortcuts_inhibitor_for_surface(&surface)
|
||||||
.map(|inhibitor| inhibitor.is_active())
|
.map(|inhibitor| inhibitor.is_active())
|
||||||
|
.unwrap_or(false)
|
||||||
|
|| seat.has_active_xwayland_grab(&surface)
|
||||||
})
|
})
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|| matches!(f, KeyboardFocusTarget::XWaylandGrab(_))
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let serial = SERIAL_COUNTER.next_serial();
|
let serial = SERIAL_COUNTER.next_serial();
|
||||||
|
|
@ -1566,12 +1568,13 @@ impl State {
|
||||||
|
|
||||||
let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| {
|
let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| {
|
||||||
f.wl_surface()
|
f.wl_surface()
|
||||||
.and_then(|surface| {
|
.map(|surface| {
|
||||||
seat.keyboard_shortcuts_inhibitor_for_surface(&surface)
|
seat.keyboard_shortcuts_inhibitor_for_surface(&surface)
|
||||||
.map(|inhibitor| inhibitor.is_active())
|
.map(|inhibitor| inhibitor.is_active())
|
||||||
|
.unwrap_or(false)
|
||||||
|
|| seat.has_active_xwayland_grab(&surface)
|
||||||
})
|
})
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|| matches!(f, KeyboardFocusTarget::XWaylandGrab(_))
|
|
||||||
});
|
});
|
||||||
|
|
||||||
self.common.atspi_ei.input(
|
self.common.atspi_ei.input(
|
||||||
|
|
|
||||||
|
|
@ -435,6 +435,14 @@ impl Common {
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for seat in &seats {
|
for seat in &seats {
|
||||||
|
let mut xwayland_grab = seat
|
||||||
|
.user_data()
|
||||||
|
.get_or_insert(XWaylandGrabSeatData::default)
|
||||||
|
.grab
|
||||||
|
.lock()
|
||||||
|
.unwrap();
|
||||||
|
xwayland_grab.take_if(|(surface, g)| !g.grab().is_alive() || !surface.alive());
|
||||||
|
|
||||||
{
|
{
|
||||||
let shell = state.common.shell.read();
|
let shell = state.common.shell.read();
|
||||||
let focused_output = seat.focused_output();
|
let focused_output = seat.focused_output();
|
||||||
|
|
@ -559,18 +567,6 @@ fn focus_target_is_valid(
|
||||||
return matches!(target, KeyboardFocusTarget::LockSurface(_));
|
return matches!(target, KeyboardFocusTarget::LockSurface(_));
|
||||||
}
|
}
|
||||||
|
|
||||||
let xwayland_grab = seat
|
|
||||||
.user_data()
|
|
||||||
.get_or_insert(XWaylandGrabSeatData::default)
|
|
||||||
.grab
|
|
||||||
.lock()
|
|
||||||
.unwrap();
|
|
||||||
if let Some((surface, grab)) = &*xwayland_grab {
|
|
||||||
if grab.grab().is_alive() {
|
|
||||||
return target == KeyboardFocusTarget::XWaylandGrab(surface.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If an exclusive layer shell surface exists (on any output), only exclusive
|
// If an exclusive layer shell surface exists (on any output), only exclusive
|
||||||
// shell surfaces can have focus, on the highest layer with exclusive surfaces.
|
// shell surfaces can have focus, on the highest layer with exclusive surfaces.
|
||||||
if let Some(layer) = exclusive_layer_surface_layer(shell) {
|
if let Some(layer) = exclusive_layer_surface_layer(shell) {
|
||||||
|
|
@ -632,7 +628,6 @@ fn focus_target_is_valid(
|
||||||
}
|
}
|
||||||
KeyboardFocusTarget::Popup(_) => true,
|
KeyboardFocusTarget::Popup(_) => true,
|
||||||
KeyboardFocusTarget::LockSurface(_) => false,
|
KeyboardFocusTarget::LockSurface(_) => false,
|
||||||
KeyboardFocusTarget::XWaylandGrab(_) => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -641,21 +636,12 @@ fn update_focus_target(
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
output: &Output,
|
output: &Output,
|
||||||
) -> Option<KeyboardFocusTarget> {
|
) -> Option<KeyboardFocusTarget> {
|
||||||
let mut xwayland_grab = seat
|
|
||||||
.user_data()
|
|
||||||
.get_or_insert(XWaylandGrabSeatData::default)
|
|
||||||
.grab
|
|
||||||
.lock()
|
|
||||||
.unwrap();
|
|
||||||
xwayland_grab.take_if(|(_, g)| !g.grab().is_alive());
|
|
||||||
if let Some(session_lock) = &shell.session_lock {
|
if let Some(session_lock) = &shell.session_lock {
|
||||||
session_lock
|
session_lock
|
||||||
.surfaces
|
.surfaces
|
||||||
.get(output)
|
.get(output)
|
||||||
.cloned()
|
.cloned()
|
||||||
.map(KeyboardFocusTarget::from)
|
.map(KeyboardFocusTarget::from)
|
||||||
} else if let Some((surface, _)) = &*xwayland_grab {
|
|
||||||
Some(KeyboardFocusTarget::XWaylandGrab(surface.clone()))
|
|
||||||
} else if let Some(layer) = exclusive_layer_surface_layer(shell) {
|
} else if let Some(layer) = exclusive_layer_surface_layer(shell) {
|
||||||
layer_map_for_output(output)
|
layer_map_for_output(output)
|
||||||
.layers()
|
.layers()
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,6 @@ pub enum KeyboardFocusTarget {
|
||||||
LayerSurface(LayerSurface),
|
LayerSurface(LayerSurface),
|
||||||
Popup(PopupKind),
|
Popup(PopupKind),
|
||||||
LockSurface(LockSurface),
|
LockSurface(LockSurface),
|
||||||
XWaylandGrab(WlSurface),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This should be TryFrom, but PopupGrab needs to be able to convert. Fix this in smithay
|
// TODO: This should be TryFrom, but PopupGrab needs to be able to convert. Fix this in smithay
|
||||||
|
|
@ -199,7 +198,6 @@ impl KeyboardFocusTarget {
|
||||||
KeyboardFocusTarget::LayerSurface(l) => Some(l.wl_surface()),
|
KeyboardFocusTarget::LayerSurface(l) => Some(l.wl_surface()),
|
||||||
KeyboardFocusTarget::Popup(p) => Some(p.wl_surface()),
|
KeyboardFocusTarget::Popup(p) => Some(p.wl_surface()),
|
||||||
KeyboardFocusTarget::LockSurface(l) => Some(l.wl_surface()),
|
KeyboardFocusTarget::LockSurface(l) => Some(l.wl_surface()),
|
||||||
KeyboardFocusTarget::XWaylandGrab(g) => Some(g),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,7 +274,6 @@ impl IsAlive for KeyboardFocusTarget {
|
||||||
KeyboardFocusTarget::LayerSurface(l) => l.alive(),
|
KeyboardFocusTarget::LayerSurface(l) => l.alive(),
|
||||||
KeyboardFocusTarget::Popup(p) => p.alive(),
|
KeyboardFocusTarget::Popup(p) => p.alive(),
|
||||||
KeyboardFocusTarget::LockSurface(l) => l.alive(),
|
KeyboardFocusTarget::LockSurface(l) => l.alive(),
|
||||||
KeyboardFocusTarget::XWaylandGrab(g) => g.alive(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -526,7 +523,6 @@ impl WaylandFocus for KeyboardFocusTarget {
|
||||||
KeyboardFocusTarget::LayerSurface(l) => Some(Cow::Borrowed(l.wl_surface())),
|
KeyboardFocusTarget::LayerSurface(l) => Some(Cow::Borrowed(l.wl_surface())),
|
||||||
KeyboardFocusTarget::Popup(p) => Some(Cow::Borrowed(p.wl_surface())),
|
KeyboardFocusTarget::Popup(p) => Some(Cow::Borrowed(p.wl_surface())),
|
||||||
KeyboardFocusTarget::LockSurface(l) => Some(Cow::Borrowed(l.wl_surface())),
|
KeyboardFocusTarget::LockSurface(l) => Some(Cow::Borrowed(l.wl_surface())),
|
||||||
KeyboardFocusTarget::XWaylandGrab(g) => Some(Cow::Borrowed(g)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn same_client_as(&self, object_id: &ObjectId) -> bool {
|
fn same_client_as(&self, object_id: &ObjectId) -> bool {
|
||||||
|
|
@ -537,7 +533,6 @@ impl WaylandFocus for KeyboardFocusTarget {
|
||||||
KeyboardFocusTarget::LayerSurface(l) => l.wl_surface().id().same_client_as(object_id),
|
KeyboardFocusTarget::LayerSurface(l) => l.wl_surface().id().same_client_as(object_id),
|
||||||
KeyboardFocusTarget::Popup(p) => p.wl_surface().id().same_client_as(object_id),
|
KeyboardFocusTarget::Popup(p) => p.wl_surface().id().same_client_as(object_id),
|
||||||
KeyboardFocusTarget::LockSurface(l) => l.wl_surface().id().same_client_as(object_id),
|
KeyboardFocusTarget::LockSurface(l) => l.wl_surface().id().same_client_as(object_id),
|
||||||
KeyboardFocusTarget::XWaylandGrab(g) => g.id().same_client_as(object_id),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1665,30 +1665,6 @@ impl Shell {
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
focus_target = KeyboardFocusTarget::Element(new_target);
|
focus_target = KeyboardFocusTarget::Element(new_target);
|
||||||
} else if let KeyboardFocusTarget::XWaylandGrab(surface) = &focus_target {
|
|
||||||
if let Some(new_target) = self.element_for_surface(surface) {
|
|
||||||
focus_target = KeyboardFocusTarget::Element(new_target.clone());
|
|
||||||
} else if let Some(new_target) = self
|
|
||||||
.workspaces
|
|
||||||
.spaces()
|
|
||||||
.find_map(|w| w.get_fullscreen().filter(|s| *s == surface))
|
|
||||||
{
|
|
||||||
focus_target = KeyboardFocusTarget::Fullscreen(new_target.clone());
|
|
||||||
} else if let Some(or) = self
|
|
||||||
.override_redirect_windows
|
|
||||||
.iter()
|
|
||||||
.find(|w| w.wl_surface().as_ref() == Some(surface))
|
|
||||||
{
|
|
||||||
// Find output the override redirect window overlaps the most with
|
|
||||||
let or_geo = or.geometry().as_global();
|
|
||||||
let (output, _) = self
|
|
||||||
.outputs()
|
|
||||||
.filter_map(|o| Some((o, o.geometry().intersection(or_geo)?)))
|
|
||||||
.max_by_key(|(_, intersection)| intersection.size.w * intersection.size.h)?;
|
|
||||||
return Some(output.clone());
|
|
||||||
} else {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match focus_target {
|
match focus_target {
|
||||||
|
|
@ -1754,7 +1730,6 @@ impl Shell {
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(output, s)| (s == &surface).then_some(output))
|
.find_map(|(output, s)| (s == &surface).then_some(output))
|
||||||
.cloned(),
|
.cloned(),
|
||||||
KeyboardFocusTarget::XWaylandGrab(_) => unreachable!(),
|
|
||||||
KeyboardFocusTarget::Popup(_) => unreachable!(),
|
KeyboardFocusTarget::Popup(_) => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::{shell::focus::target::KeyboardFocusTarget, state::State};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
delegate_xwayland_keyboard_grab,
|
delegate_xwayland_keyboard_grab,
|
||||||
input::Seat,
|
input::Seat,
|
||||||
reexports::wayland_server::protocol::wl_surface::WlSurface,
|
reexports::wayland_server::{protocol::wl_surface::WlSurface, Resource},
|
||||||
wayland::xwayland_keyboard_grab::{XWaylandKeyboardGrab, XWaylandKeyboardGrabHandler},
|
wayland::xwayland_keyboard_grab::{XWaylandKeyboardGrab, XWaylandKeyboardGrabHandler},
|
||||||
};
|
};
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
@ -33,4 +33,21 @@ impl XWaylandKeyboardGrabHandler for State {
|
||||||
Some(KeyboardFocusTarget::Element(element))
|
Some(KeyboardFocusTarget::Element(element))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait XWaylandGrabSeat {
|
||||||
|
fn has_active_xwayland_grab(&self, surface: &WlSurface) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl XWaylandGrabSeat for Seat<State> {
|
||||||
|
fn has_active_xwayland_grab(&self, surface: &WlSurface) -> bool {
|
||||||
|
self.user_data()
|
||||||
|
.get_or_insert(XWaylandGrabSeatData::default)
|
||||||
|
.grab
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|(s, g)| g.grab().is_alive() && s == surface)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delegate_xwayland_keyboard_grab!(State);
|
delegate_xwayland_keyboard_grab!(State);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue