Fix shell focus, launcher touch dismissal, and sandbox clipboard access
This commit is contained in:
1 parent
c8dfb3074d
commit
a62f1367bd
8 files changed
+126
-79
No files matched your search
@@ -6,6 +6,7 @@ use smithay::reexports::wayland_server::{Resource, backend::ClientId};
|
||||
use smithay::utils::Serial;
|
||||
|
||||
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
|
||||
#[cfg(test)]
|
||||
use smithay::utils::SERIAL_COUNTER;
|
||||
use smithay::wayland::xdg_activation::{
|
||||
XdgActivationHandler, XdgActivationState, XdgActivationToken, XdgActivationTokenData,
|
||||
@@ -110,34 +111,10 @@ impl XdgActivationHandler for Ferese {
|
||||
return;
|
||||
}
|
||||
|
||||
let Some(window) = self
|
||||
.space
|
||||
.elements()
|
||||
.find(|window| {
|
||||
window
|
||||
.toplevel()
|
||||
.is_some_and(|toplevel| toplevel.wl_surface() == &surface)
|
||||
})
|
||||
.cloned()
|
||||
else {
|
||||
let Some(id) = self.windows.id_for_surface(&surface) else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.focused_window = self.windows.ids().get(&window).copied();
|
||||
if let Some(focused) = self.focused_window
|
||||
&& let Err(error) = self.workspaces.focus_window(focused)
|
||||
{
|
||||
tracing::error!(%error, ?focused, "failed to update workspace focus");
|
||||
return;
|
||||
}
|
||||
self.raise_window(&window, true);
|
||||
let keyboard = self.seat.get_keyboard().expect("seat has a keyboard");
|
||||
keyboard.set_focus(self, Some(surface), SERIAL_COUNTER.next_serial());
|
||||
self.space.elements().for_each(|window| {
|
||||
if let Some(toplevel) = window.toplevel() {
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
});
|
||||
self.activate_managed_window(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,8 +229,7 @@ mod tests {
|
||||
assert_ne!(approved.client_id, Some(recipient.id()));
|
||||
assert!(approved.user_data.get::<ApprovedInteraction>().unwrap().0.elapsed() < TOKEN_MAX_AGE);
|
||||
|
||||
// Exercise the production handler with a real recipient toplevel.
|
||||
// Creating the window needs no GPU or client buffer.
|
||||
// A valid handoff must not focus a recipient before its first buffer.
|
||||
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_wm_base::XdgWmBase;
|
||||
use smithay::reexports::wayland_server::protocol::wl_compositor::WlCompositor;
|
||||
use smithay::wayland::shell::xdg::XdgWmBaseUserData;
|
||||
@@ -279,7 +255,7 @@ mod tests {
|
||||
})
|
||||
.expect("recipient's toplevel");
|
||||
state.request_activation(token, approved, target.clone());
|
||||
assert_eq!(state.seat.get_keyboard().unwrap().current_focus(), Some(target));
|
||||
assert_eq!(state.seat.get_keyboard().unwrap().current_focus(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -195,11 +195,14 @@ pub fn handle_commit(state: &mut Ferese, surface: &WlSurface) {
|
||||
}
|
||||
|
||||
impl Ferese {
|
||||
pub(crate) fn layer_keyboard_eligible(&self, layer: &DesktopLayerSurface) -> bool {
|
||||
layer.can_receive_keyboard_focus() && self.layer_mapped_and_visible(layer)
|
||||
}
|
||||
|
||||
/// Layer-map membership tracks the role and output, not buffer mapping.
|
||||
/// Use the renderer state updated by on_commit_buffer_handler, as for windows.
|
||||
pub(crate) fn layer_keyboard_eligible(&self, layer: &DesktopLayerSurface) -> bool {
|
||||
fn layer_mapped_and_visible(&self, layer: &DesktopLayerSurface) -> bool {
|
||||
layer.layer_surface().alive()
|
||||
&& layer.can_receive_keyboard_focus()
|
||||
&& smithay::backend::renderer::utils::with_renderer_surface_state(layer.wl_surface(), |state| {
|
||||
state.buffer().is_some()
|
||||
})
|
||||
@@ -262,10 +265,16 @@ impl Ferese {
|
||||
return;
|
||||
}
|
||||
let keyboard = self.seat.get_keyboard().expect("seat has a keyboard");
|
||||
if let Some(root) = self.keyboard_layer_root().filter(|_| {
|
||||
!self
|
||||
.keyboard_focused_layer()
|
||||
.is_some_and(|layer| self.layer_keyboard_eligible(&layer))
|
||||
if let Some(root) = self.keyboard_layer_root().filter(|root| {
|
||||
!self.keyboard_focused_layer().is_some_and(|layer| {
|
||||
// A popup owns its keyboard focus independently of the bar's
|
||||
// interactivity policy, but still needs a visible, mapped parent.
|
||||
if keyboard.current_focus().as_ref() != Some(root) {
|
||||
self.layer_mapped_and_visible(&layer)
|
||||
} else {
|
||||
self.layer_keyboard_eligible(&layer)
|
||||
}
|
||||
})
|
||||
}) {
|
||||
// A popup grab cannot keep an ineligible layer alive as input owner.
|
||||
for (popup, _) in smithay::desktop::PopupManager::popups_for_surface(&root) {
|
||||
|
||||
@@ -6,6 +6,7 @@ mod layer_shell;
|
||||
pub(crate) mod screencopy;
|
||||
pub(crate) mod screenshot;
|
||||
pub(crate) mod screenshot_worker;
|
||||
pub(crate) mod security_context;
|
||||
pub(crate) mod window_capture;
|
||||
mod xdg_shell;
|
||||
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use smithay::reexports::wayland_server::Client;
|
||||
use smithay::wayland::security_context::{SecurityContext, SecurityContextHandler, SecurityContextListenerSource};
|
||||
|
||||
use crate::Ferese;
|
||||
use crate::state::ClientState;
|
||||
|
||||
pub(crate) fn unrestricted_client(client: &Client) -> bool {
|
||||
client
|
||||
.get_data::<ClientState>()
|
||||
.is_some_and(|state| state.security_context.is_none())
|
||||
}
|
||||
|
||||
impl SecurityContextHandler for Ferese {
|
||||
fn context_created(&mut self, source: SecurityContextListenerSource, context: SecurityContext) {
|
||||
if let Err(error) = self.loop_handle.insert_source(source, move |stream, _, state| {
|
||||
let data = ClientState {
|
||||
security_context: Some(context.clone()),
|
||||
..Default::default()
|
||||
};
|
||||
if let Err(error) = state.display_handle.insert_client(stream, Arc::new(data)) {
|
||||
tracing::warn!(%error, "failed to register sandboxed Wayland client");
|
||||
}
|
||||
}) {
|
||||
tracing::warn!(%error, "failed to register security context listener");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
smithay::delegate_security_context!(Ferese);
|
||||
Reference in new issue
Block a user