diff --git a/cosmic-panel-bin/src/iced/elements/target.rs b/cosmic-panel-bin/src/iced/elements/target.rs index 0111ffe7..8ffb1986 100644 --- a/cosmic-panel-bin/src/iced/elements/target.rs +++ b/cosmic-panel-bin/src/iced/elements/target.rs @@ -3,18 +3,16 @@ use super::{CosmicMappedInternal, PopupMappedInternal}; use crate::xdg_shell_wrapper::shared_state::GlobalState; use anyhow::bail; -use smithay::{ - input::{ - Seat, - dnd::{self, DndFocus}, - keyboard::KeyboardTarget, - pointer::PointerTarget, - touch::TouchTarget, - }, - reexports::wayland_server::{DisplayHandle, protocol::wl_surface::WlSurface}, - utils::IsAlive, - wayland::{seat::WaylandFocus, selection::data_device::WlOfferData}, -}; +use smithay::input::Seat; +use smithay::input::dnd::{self, DndFocus}; +use smithay::input::keyboard::KeyboardTarget; +use smithay::input::pointer::PointerTarget; +use smithay::input::touch::TouchTarget; +use smithay::reexports::wayland_server::DisplayHandle; +use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; +use smithay::utils::IsAlive; +use smithay::wayland::seat::WaylandFocus; +use smithay::wayland::selection::data_device::WlOfferData; use std::sync::Arc; #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/cosmic-panel-bin/src/space/render.rs b/cosmic-panel-bin/src/space/render.rs index 3897e1a1..ad35b689 100644 --- a/cosmic-panel-bin/src/space/render.rs +++ b/cosmic-panel-bin/src/space/render.rs @@ -21,7 +21,8 @@ use smithay::backend::renderer::element::{AsRenderElements, RenderElement, Under use smithay::backend::renderer::gles::{GlesError, GlesFrame, GlesRenderer}; use smithay::backend::renderer::{Bind, Color32F, Frame, Renderer}; use smithay::reexports::wayland_server::Resource; -use smithay::utils::{Buffer, IsAlive, Physical, Point, Rectangle, user_data::UserDataMap}; +use smithay::utils::user_data::UserDataMap; +use smithay::utils::{Buffer, IsAlive, Physical, Point, Rectangle}; use smithay::wayland::seat::WaylandFocus; pub(crate) enum PanelRenderElement { @@ -134,10 +135,10 @@ impl PanelSpace { anyhow::bail!("Failed to clear panel."); }; - _ = frame.clear( - Color32F::new(0.0, 0.0, 0.0, 0.0), - &[Rectangle::new((0, 0).into(), dim)], - ); + _ = frame.clear(Color32F::new(0.0, 0.0, 0.0, 0.0), &[Rectangle::new( + (0, 0).into(), + dim, + )]); if let Ok(sync_point) = frame.finish() { if let Err(err) = sync_point.wait() { tracing::error!("Error waiting for sync point: {:?}", err); diff --git a/cosmic-panel-bin/src/space/wrapper_space.rs b/cosmic-panel-bin/src/space/wrapper_space.rs index 6829a7e5..f782c672 100644 --- a/cosmic-panel-bin/src/space/wrapper_space.rs +++ b/cosmic-panel-bin/src/space/wrapper_space.rs @@ -176,8 +176,6 @@ impl WrapperSpace for PanelSpace { s_surface: PopupSurface, positioner: sctk::shell::xdg::XdgPositioner, positioner_state: PositionerState, - latest_seat: &wl_seat::WlSeat, - latest_serial: u32, ) -> anyhow::Result<()> { self.apply_positioner_state(&positioner, positioner_state, &s_surface); let c_wl_surface = compositor_state.create_surface(qh); @@ -270,14 +268,7 @@ impl WrapperSpace for PanelSpace { area = area.saturating_add(r.1.size.w.saturating_mul(r.1.size.h)); input_region.add(0, 0, r.1.size.w, r.1.size.h); } - // must take a grab on all popups to avoid being closed automatically by focus - // follows cursor... - if area > 1 { - c_popup.xdg_popup().grab(latest_seat, latest_serial); - } c_wl_surface.set_input_region(Some(input_region.wl_region())); - } else { - c_popup.xdg_popup().grab(latest_seat, latest_serial); } let fractional_scale = fractional_scale_manager.map(|f| f.fractional_scaling(&c_wl_surface, qh)); @@ -334,6 +325,18 @@ impl WrapperSpace for PanelSpace { Ok(()) } + fn grab_popup( + &mut self, + popup: PopupSurface, + seat: wl_seat::WlSeat, + serial: u32, + ) -> anyhow::Result<()> { + if let Some(p) = self.popups.iter().find(|wp| wp.s_surface == popup) { + p.popup.c_popup.xdg_popup().grab(&seat, serial); + } + Ok(()) + } + fn reposition_popup( &mut self, popup: PopupSurface, @@ -710,13 +713,10 @@ impl WrapperSpace for PanelSpace { return; }; if let Err(err) = pman - .update_process_env( - &key, - vec![( - "COSMIC_NOTIFICATIONS".to_string(), - fd.as_raw_fd().to_string(), - )], - ) + .update_process_env(&key, vec![( + "COSMIC_NOTIFICATIONS".to_string(), + fd.as_raw_fd().to_string(), + )]) .await { error!("Failed to update process env: {}", err); @@ -1370,16 +1370,29 @@ impl WrapperSpace for PanelSpace { } fn keyboard_leave(&mut self, seat_name: &str, f: Option) { - // if not a leaf, return early - if let Some(surface) = f.as_ref() - && self.popups.iter().any(|p| p.popup.parent == *surface) - { - return; - } - if self.layer.as_ref().zip(f).is_some_and(|l| l.0.wl_surface() == &l.1) - && (self.popups.iter().any(|p| p.popup.grab) || self.overflow_popup.is_some()) - { - return; + if let Some(surface) = f.as_ref() { + // if not a leaf, return early + if self.popups.iter().any(|p| p.popup.parent == *surface) { + return; + } + + if self.layer.as_ref().is_some_and(|l| l.wl_surface() == surface) + && (self.popups.iter().any(|p| p.popup.grab) || self.overflow_popup.is_some()) + { + return; + } + + // Ignore event for wl_surface that isn't our layer or popup (i.e. a different + // panel) + if !self.layer.as_ref().is_some_and(|l| l.wl_surface() == surface) + && !self + .overflow_popup + .as_ref() + .is_some_and(|(p, _)| p.c_popup.wl_surface() == surface) + && !self.popups.iter().any(|p| p.popup.c_popup.wl_surface() == surface) + { + return; + } } self.s_focused_surface.retain(|(_, name)| name != seat_name); diff --git a/cosmic-panel-bin/src/space_container/mod.rs b/cosmic-panel-bin/src/space_container/mod.rs index 723a1803..db17cd9c 100644 --- a/cosmic-panel-bin/src/space_container/mod.rs +++ b/cosmic-panel-bin/src/space_container/mod.rs @@ -2,9 +2,27 @@ //! separate panel space container implements the WrapperSpace abstraction, //! calling handle events and other methods of its PanelSpaces as necessary +use crate::space::PanelSpace; + mod space_container; pub(crate) mod toplevel; pub(crate) mod workspace; mod wrapper_space; pub use space_container::*; + +fn space_for_client_mut( + space_list: &mut [PanelSpace], + client: Option, +) -> Option<&mut PanelSpace> { + space_list.iter_mut().find(|space| { + space + .clients_center + .lock() + .unwrap() + .iter() + .chain(space.clients_left.lock().unwrap().iter()) + .chain(space.clients_right.lock().unwrap().iter()) + .any(|c| c.client.as_ref().zip(client.as_ref()).is_some_and(|c| c.0.id() == *c.1)) + }) +} diff --git a/cosmic-panel-bin/src/space_container/space_container.rs b/cosmic-panel-bin/src/space_container/space_container.rs index 965ae7e4..fbfd0ce3 100644 --- a/cosmic-panel-bin/src/space_container/space_container.rs +++ b/cosmic-panel-bin/src/space_container/space_container.rs @@ -40,6 +40,8 @@ use tokio::sync::mpsc; use tracing::{error, info}; use wayland_server::Resource; +use super::space_for_client_mut; + pub struct SpaceContainer { pub(crate) connection: Option, pub(crate) config: CosmicPanelContainerConfig, @@ -572,16 +574,7 @@ impl SpaceContainer { // add window to the space with a client that matches the window let s_client = wlsurface.client().map(|c| c.id()); - if let Some(space) = self.space_list.iter_mut().find(|space| { - space - .clients_center - .lock() - .unwrap() - .iter() - .chain(space.clients_left.lock().unwrap().iter()) - .chain(space.clients_right.lock().unwrap().iter()) - .any(|c| c.client.as_ref().map(|c| c.id()) == s_client) - }) { + if let Some(space) = space_for_client_mut(&mut self.space_list, s_client) { space.dirty_subsurface( self.renderer.as_mut(), compositor_state, diff --git a/cosmic-panel-bin/src/space_container/wrapper_space.rs b/cosmic-panel-bin/src/space_container/wrapper_space.rs index 4736394a..8d8ed007 100644 --- a/cosmic-panel-bin/src/space_container/wrapper_space.rs +++ b/cosmic-panel-bin/src/space_container/wrapper_space.rs @@ -29,7 +29,7 @@ use smithay::reexports::wayland_server::{self, Resource}; use crate::space::PanelSpace; -use super::SpaceContainer; +use super::{SpaceContainer, space_for_client_mut}; impl WrapperSpace for SpaceContainer { type Config = CosmicPanelContainerConfig; @@ -299,16 +299,7 @@ impl WrapperSpace for SpaceContainer { // add window to the space with a client that matches the window let w_client = s_top_level.toplevel().and_then(|t| t.wl_surface().client().map(|c| c.id())); - if let Some(space) = self.space_list.iter_mut().find(|space| { - space - .clients_center - .lock() - .unwrap() - .iter() - .chain(space.clients_left.lock().unwrap().iter()) - .chain(space.clients_right.lock().unwrap().iter()) - .any(|c| c.client.as_ref().zip(w_client.as_ref()).is_some_and(|c| c.0.id() == *c.1)) - }) { + if let Some(space) = space_for_client_mut(&mut self.space_list, w_client) { space.add_window(s_top_level); } } @@ -324,22 +315,11 @@ impl WrapperSpace for SpaceContainer { s_surface: smithay::wayland::shell::xdg::PopupSurface, positioner: sctk::shell::xdg::XdgPositioner, positioner_state: smithay::wayland::shell::xdg::PositionerState, - c_seat: &WlSeat, - last_serial: u32, ) -> anyhow::Result<()> { // add popup to the space with a client that matches the window let p_client = s_surface.wl_surface().client().map(|c| c.id()); - if let Some(space) = self.space_list.iter_mut().find(|space| { - space - .clients_center - .lock() - .unwrap() - .iter() - .chain(space.clients_left.lock().unwrap().iter()) - .chain(space.clients_right.lock().unwrap().iter()) - .any(|c| c.client.as_ref().zip(p_client.as_ref()).is_some_and(|c| c.0.id() == *c.1)) - }) { + if let Some(space) = space_for_client_mut(&mut self.space_list, p_client) { space.add_popup( compositor_state, fractional_scale_manager, @@ -350,14 +330,27 @@ impl WrapperSpace for SpaceContainer { s_surface, positioner, positioner_state, - c_seat, - last_serial, ) } else { anyhow::bail!("failed to find a matching panel space for this popup.") } } + fn grab_popup( + &mut self, + s_surface: smithay::wayland::shell::xdg::PopupSurface, + seat: WlSeat, + serial: u32, + ) -> anyhow::Result<()> { + let p_client = s_surface.wl_surface().client().map(|c| c.id()); + + if let Some(space) = space_for_client_mut(&mut self.space_list, p_client) { + space.grab_popup(s_surface, seat, serial) + } else { + anyhow::bail!("Failed to find popup with matching client id") + } + } + fn reposition_popup( &mut self, popup: smithay::wayland::shell::xdg::PopupSurface, @@ -367,16 +360,7 @@ impl WrapperSpace for SpaceContainer { // add popup to the space with a client that matches the window let p_client = popup.wl_surface().client().map(|c| c.id()); - if let Some(space) = self.space_list.iter_mut().find(|space| { - space - .clients_center - .lock() - .unwrap() - .iter() - .chain(space.clients_left.lock().unwrap().iter()) - .chain(space.clients_right.lock().unwrap().iter()) - .any(|c| c.client.as_ref().zip(p_client.as_ref()).is_some_and(|c| c.0.id() == *c.1)) - }) { + if let Some(space) = space_for_client_mut(&mut self.space_list, p_client) { space.reposition_popup(popup, positioner_state, token)? } anyhow::bail!("Failed to find popup with matching client id") @@ -435,16 +419,7 @@ impl WrapperSpace for SpaceContainer { // add window to the space with a client that matches the window let w_client = w.client().map(|c| c.id()); - if let Some(space) = self.space_list.iter_mut().find(|space| { - space - .clients_center - .lock() - .unwrap() - .iter() - .chain(space.clients_left.lock().unwrap().iter()) - .chain(space.clients_right.lock().unwrap().iter()) - .any(|c| c.client.as_ref().zip(w_client.as_ref()).is_some_and(|c| c.0.id() == *c.1)) - }) { + if let Some(space) = space_for_client_mut(&mut self.space_list, w_client) { space.dirty_window(dh, w); } } @@ -457,16 +432,7 @@ impl WrapperSpace for SpaceContainer { // add window to the space with a client that matches the window let p_client = w.client().map(|c| c.id()); - if let Some(space) = self.space_list.iter_mut().find(|space| { - space - .clients_center - .lock() - .unwrap() - .iter() - .chain(space.clients_left.lock().unwrap().iter()) - .chain(space.clients_right.lock().unwrap().iter()) - .any(|c| c.client.as_ref().zip(p_client.as_ref()).is_some_and(|c| c.0.id() == *c.1)) - }) { + if let Some(space) = space_for_client_mut(&mut self.space_list, p_client) { space.dirty_popup(dh, w); } } diff --git a/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/data_device/data_device.rs b/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/data_device/data_device.rs index 83842b9f..b296972a 100644 --- a/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/data_device/data_device.rs +++ b/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/data_device/data_device.rs @@ -1,32 +1,19 @@ use std::time::Instant; use cctk::wayland_client::protocol::wl_surface::WlSurface; -use sctk::{ - data_device_manager::{ - data_device::{DataDeviceData, DataDeviceHandler}, - data_offer::DataOfferData, - }, - reexports::client::{ - Proxy, - protocol::{ - wl_data_device::WlDataDevice, wl_data_device_manager::DndAction as ClientDndAction, - }, - }, - seat::pointer::{PointerEvent, PointerEventKind, PointerHandler}, -}; +use sctk::data_device_manager::data_device::{DataDeviceData, DataDeviceHandler}; +use sctk::data_device_manager::data_offer::DataOfferData; +use sctk::reexports::client::Proxy; +use sctk::reexports::client::protocol::wl_data_device::WlDataDevice; +use sctk::reexports::client::protocol::wl_data_device_manager::DndAction as ClientDndAction; +use sctk::seat::pointer::{PointerEvent, PointerEventKind, PointerHandler}; use smallvec::SmallVec; -use smithay::{ - input::{ - dnd::{DndAction, SourceMetadata}, - pointer::GrabStartData, - }, - reexports::wayland_server::Resource, - utils::SERIAL_COUNTER, - wayland::{ - seat::WaylandFocus, - selection::data_device::{set_data_device_focus, set_data_device_selection}, - }, -}; +use smithay::input::dnd::{DndAction, SourceMetadata}; +use smithay::input::pointer::GrabStartData; +use smithay::reexports::wayland_server::Resource; +use smithay::utils::SERIAL_COUNTER; +use smithay::wayland::seat::WaylandFocus; +use smithay::wayland::selection::data_device::{set_data_device_focus, set_data_device_selection}; use crate::xdg_shell_wrapper::client_state::FocusStatus; use crate::xdg_shell_wrapper::server_state::ServerPointerFocus; diff --git a/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/pointer.rs b/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/pointer.rs index cff32454..2a6bd4fe 100644 --- a/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/pointer.rs +++ b/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/pointer.rs @@ -77,15 +77,11 @@ impl GlobalState { let seat = &mut self.server_state.seats[seat_index]; match e.kind { sctk::seat::pointer::PointerEventKind::Leave { .. } => { - ptr.motion( - self, - None, - &MotionEvent { - location: (0.0, 0.0).into(), - serial: SERIAL_COUNTER.next_serial(), - time: time.try_into().unwrap(), - }, - ); + ptr.motion(self, None, &MotionEvent { + location: (0.0, 0.0).into(), + serial: SERIAL_COUNTER.next_serial(), + time: time.try_into().unwrap(), + }); ptr.frame(self); if let Some((..)) = self @@ -159,27 +155,19 @@ impl GlobalState { }) { *ev = (e.clone(), pointer.clone(), ev.2); } else { - ptr.motion( - self, - Some((surface, s_pos)), - &MotionEvent { - location: c_pos.to_f64() + Point::from((surface_x, surface_y)), - serial: SERIAL_COUNTER.next_serial(), - time: time.try_into().unwrap(), - }, - ); + ptr.motion(self, Some((surface, s_pos)), &MotionEvent { + location: c_pos.to_f64() + Point::from((surface_x, surface_y)), + serial: SERIAL_COUNTER.next_serial(), + time: time.try_into().unwrap(), + }); ptr.frame(self); } } else { - ptr.motion( - self, - None, - &MotionEvent { - location: Point::from((surface_x, surface_y)), - serial: SERIAL_COUNTER.next_serial(), - time: time.try_into().unwrap(), - }, - ); + ptr.motion(self, None, &MotionEvent { + location: Point::from((surface_x, surface_y)), + serial: SERIAL_COUNTER.next_serial(), + time: time.try_into().unwrap(), + }); ptr.frame(self); } }, @@ -235,27 +223,19 @@ impl GlobalState { }) { *ev = (e.clone(), pointer.clone(), ev.2); } else { - ptr.motion( - self, - Some((surface, s_pos)), - &MotionEvent { - location: c_pos.to_f64() + Point::from((surface_x, surface_y)), - serial: SERIAL_COUNTER.next_serial(), - time, - }, - ); + ptr.motion(self, Some((surface, s_pos)), &MotionEvent { + location: c_pos.to_f64() + Point::from((surface_x, surface_y)), + serial: SERIAL_COUNTER.next_serial(), + time, + }); ptr.frame(self); } } else { - ptr.motion( - self, - None, - &MotionEvent { - location: Point::from((surface_x, surface_y)), - serial: SERIAL_COUNTER.next_serial(), - time, - }, - ); + ptr.motion(self, None, &MotionEvent { + location: Point::from((surface_x, surface_y)), + serial: SERIAL_COUNTER.next_serial(), + time, + }); ptr.frame(self); if let Some(themed_pointer) = &self.server_state.seats[seat_index].client.ptr @@ -281,15 +261,12 @@ impl GlobalState { if let Some(s_surface) = s_surface { kbd.set_focus(self, Some(s_surface.into()), SERIAL_COUNTER.next_serial()); - ptr.button( - self, - &ButtonEvent { - serial: SERIAL_COUNTER.next_serial(), - time, - button, - state: ButtonState::Pressed, - }, - ); + ptr.button(self, &ButtonEvent { + serial: SERIAL_COUNTER.next_serial(), + time, + button, + state: ButtonState::Pressed, + }); ptr.frame(self); continue; @@ -298,15 +275,12 @@ impl GlobalState { let s = self.space.handle_button(&seat_name, true); kbd.set_focus(self, s, SERIAL_COUNTER.next_serial()); - ptr.button( - self, - &ButtonEvent { - serial: SERIAL_COUNTER.next_serial(), - time, - button, - state: ButtonState::Pressed, - }, - ); + ptr.button(self, &ButtonEvent { + serial: SERIAL_COUNTER.next_serial(), + time, + button, + state: ButtonState::Pressed, + }); ptr.frame(self); }, sctk::seat::pointer::PointerEventKind::Release { time, button, .. } => { @@ -325,15 +299,12 @@ impl GlobalState { if let Some(s_surface) = s_surface { kbd.set_focus(self, Some(s_surface.into()), SERIAL_COUNTER.next_serial()); - ptr.button( - self, - &ButtonEvent { - serial: SERIAL_COUNTER.next_serial(), - time, - button, - state: ButtonState::Released, - }, - ); + ptr.button(self, &ButtonEvent { + serial: SERIAL_COUNTER.next_serial(), + time, + button, + state: ButtonState::Released, + }); ptr.frame(self); continue; @@ -342,15 +313,12 @@ impl GlobalState { let s = self.space.handle_button(&seat_name, false); kbd.set_focus(self, s, SERIAL_COUNTER.next_serial()); - ptr.button( - self, - &ButtonEvent { - serial: SERIAL_COUNTER.next_serial(), - time, - button, - state: ButtonState::Released, - }, - ); + ptr.button(self, &ButtonEvent { + serial: SERIAL_COUNTER.next_serial(), + time, + button, + state: ButtonState::Released, + }); ptr.frame(self); }, sctk::seat::pointer::PointerEventKind::Axis { diff --git a/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/touch.rs b/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/touch.rs index 64c4278c..de87298d 100644 --- a/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/touch.rs +++ b/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/touch.rs @@ -52,16 +52,12 @@ impl TouchHandler for GlobalState { if let Some(ServerPointerFocus { surface, c_pos, s_pos, .. }) = self.space.touch_under((location.0 as i32, location.1 as i32), &seat_name, surface) { - touch.down( - self, - Some((surface, s_pos)), - &touch::DownEvent { - slot: Some(id as u32).into(), - location: c_pos.to_f64() + Point::from(location), - serial: SERIAL_COUNTER.next_serial(), - time, - }, - ); + touch.down(self, Some((surface, s_pos)), &touch::DownEvent { + slot: Some(id as u32).into(), + location: c_pos.to_f64() + Point::from(location), + serial: SERIAL_COUNTER.next_serial(), + time, + }); touch.frame(self); } } @@ -77,14 +73,11 @@ impl TouchHandler for GlobalState { ) { let (_, touch) = get_touch_handle(self, touch); - touch.up( - self, - &touch::UpEvent { - slot: Some(id as u32).into(), - serial: SERIAL_COUNTER.next_serial(), - time, - }, - ); + touch.up(self, &touch::UpEvent { + slot: Some(id as u32).into(), + serial: SERIAL_COUNTER.next_serial(), + time, + }); } fn motion( @@ -105,15 +98,11 @@ impl TouchHandler for GlobalState { surface.clone(), ) { - touch.motion( - self, - Some((surface, s_pos)), - &touch::MotionEvent { - slot: Some(id as u32).into(), - location: c_pos.to_f64() + Point::from(location), - time, - }, - ); + touch.motion(self, Some((surface, s_pos)), &touch::MotionEvent { + slot: Some(id as u32).into(), + location: c_pos.to_f64() + Point::from(location), + time, + }); touch.frame(self); } } diff --git a/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/wp_security_context.rs b/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/wp_security_context.rs index 74c0a55a..32a67943 100644 --- a/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/wp_security_context.rs +++ b/cosmic-panel-bin/src/xdg_shell_wrapper/client/handlers/wp_security_context.rs @@ -55,12 +55,10 @@ impl SecurityContextManager { let addr = SocketAddr::from_abstract_name(s)?; // this also listens on the socket let listener = UnixListener::bind_addr(&addr)?; - let wp_security_context: WpSecurityContextV1 = self.manager.create_listener( - listener.as_fd(), - close_fd.as_fd(), - qh, - SecurityContext { conn: Arc::new(Mutex::new(None)) }, - ); + let wp_security_context: WpSecurityContextV1 = + self.manager.create_listener(listener.as_fd(), close_fd.as_fd(), qh, SecurityContext { + conn: Arc::new(Mutex::new(None)), + }); let conn = UnixStream::connect_addr(&addr)?; // XXX make sure no one else can connect to the listener drop(close_fd_ours); diff --git a/cosmic-panel-bin/src/xdg_shell_wrapper/server/handlers/mod.rs b/cosmic-panel-bin/src/xdg_shell_wrapper/server/handlers/mod.rs index b4844548..6b8fa4d0 100644 --- a/cosmic-panel-bin/src/xdg_shell_wrapper/server/handlers/mod.rs +++ b/cosmic-panel-bin/src/xdg_shell_wrapper/server/handlers/mod.rs @@ -4,37 +4,33 @@ use std::os::fd::OwnedFd; use std::sync::Mutex; use itertools::Itertools; -use sctk::data_device_manager::{data_device::DataDeviceData, data_offer::receive_to_fd}; +use sctk::data_device_manager::data_device::DataDeviceData; +use sctk::data_device_manager::data_offer::receive_to_fd; use sctk::delegate_subcompositor; use sctk::reexports::client::protocol::wl_data_device_manager::DndAction as ClientDndAction; use sctk::shm::multi::MultiPool; +use smithay::backend::renderer::ImportDma; +use smithay::input::dnd::{DndAction, DndGrabHandler, DndTarget, SourceMetadata}; +use smithay::input::pointer::CursorImageAttributes; +use smithay::input::{Seat, SeatHandler, SeatState}; +use smithay::reexports::wayland_server::Resource; +use smithay::reexports::wayland_server::protocol::wl_data_source::WlDataSource; +use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; +use smithay::utils::{Logical, Point, Transform}; +use smithay::wayland::compositor::{SurfaceAttributes, with_states}; +use smithay::wayland::dmabuf::{DmabufHandler, ImportNotifier}; +use smithay::wayland::output::OutputHandler; +use smithay::wayland::seat::WaylandFocus; +use smithay::wayland::selection::data_device::{ + DataDeviceHandler, WaylandDndGrabHandler, set_data_device_focus, +}; +use smithay::wayland::selection::primary_selection::{ + PrimarySelectionHandler, PrimarySelectionState, set_primary_focus, +}; +use smithay::wayland::selection::{SelectionHandler, SelectionSource, SelectionTarget}; use smithay::{ - backend::renderer::ImportDma, delegate_data_device, delegate_dmabuf, delegate_output, delegate_primary_selection, delegate_seat, - input::{ - Seat, SeatHandler, SeatState, - dnd::{DndAction, DndGrabHandler, DndTarget, SourceMetadata}, - pointer::CursorImageAttributes, - }, - reexports::wayland_server::{ - Resource, - protocol::{wl_data_source::WlDataSource, wl_surface::WlSurface}, - }, - utils::{Logical, Point, Transform}, - wayland::{ - compositor::{SurfaceAttributes, with_states}, - dmabuf::{DmabufHandler, ImportNotifier}, - output::OutputHandler, - seat::WaylandFocus, - selection::{ - SelectionHandler, SelectionSource, SelectionTarget, - data_device::{DataDeviceHandler, WaylandDndGrabHandler, set_data_device_focus}, - primary_selection::{ - PrimarySelectionHandler, PrimarySelectionState, set_primary_focus, - }, - }, - }, }; use tracing::{error, info, trace}; @@ -255,9 +251,7 @@ impl DndGrabHandler for GlobalState { } use smithay::backend::renderer::damage::OutputDamageTracker; -use smithay::input::dnd::DnDGrab; -use smithay::input::dnd::GrabType; -use smithay::input::dnd::Source; +use smithay::input::dnd::{DnDGrab, GrabType, Source}; use smithay::input::pointer::Focus; use smithay::utils::Serial; impl WaylandDndGrabHandler for GlobalState { @@ -327,7 +321,7 @@ impl WaylandDndGrabHandler for GlobalState { seat.client.dnd_source = Some(dnd_source); } - //seat.server.dnd_source = source; + // seat.server.dnd_source = source; seat.server.dnd_icon = icon; let seat = seat.server.seat.clone(); diff --git a/cosmic-panel-bin/src/xdg_shell_wrapper/server/handlers/xdg_shell.rs b/cosmic-panel-bin/src/xdg_shell_wrapper/server/handlers/xdg_shell.rs index f8c4b97e..d0912967 100644 --- a/cosmic-panel-bin/src/xdg_shell_wrapper/server/handlers/xdg_shell.rs +++ b/cosmic-panel-bin/src/xdg_shell_wrapper/server/handlers/xdg_shell.rs @@ -2,6 +2,7 @@ use itertools::Itertools; use sctk::shell::xdg::XdgPositioner; use smithay::delegate_xdg_shell; use smithay::desktop::{PopupKind, Window}; +use smithay::input::Seat; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel; use smithay::reexports::wayland_server::protocol::wl_seat; use smithay::utils::{SERIAL_COUNTER, Serial}; @@ -31,14 +32,7 @@ impl XdgShellHandler for GlobalState { Ok(p) => p, Err(_) => return, }; - if let Some(f_seat) = self.server_state.seats.iter().find(|s| { - self.client_state - .hovered_surface - .borrow() - .iter() - .chain(self.client_state.focused_surface.borrow().iter()) - .any(|f| f.1 == s.name && matches!(f.2, FocusStatus::Focused)) - }) && self + if self .space .add_popup( &self.client_state.compositor_state, @@ -50,8 +44,6 @@ impl XdgShellHandler for GlobalState { surface.clone(), positioner, positioner_state, - &f_seat.client._seat, - f_seat.client.get_serial_of_last_seat_event(), ) .is_ok() { @@ -85,7 +77,17 @@ impl XdgShellHandler for GlobalState { ) { } - fn grab(&mut self, _surface: PopupSurface, _seat: wl_seat::WlSeat, _serial: Serial) { + // TODO: Validate serial + fn grab(&mut self, surface: PopupSurface, seat: wl_seat::WlSeat, _serial: Serial) { + let seat = Seat::from_resource(&seat).unwrap(); + let Some(seat_pair) = self.server_state.seats.iter().find(|s| s.server.seat == seat) else { + return; + }; + let _ = self.space.grab_popup( + surface, + seat_pair.client._seat.clone(), + seat_pair.client.get_serial_of_last_seat_event(), + ); if let Some(cosmic_workspaces) = &self.space.shared.cosmic_workspaces { cosmic_workspaces.hide(); } diff --git a/cosmic-panel-bin/src/xdg_shell_wrapper/space/space.rs b/cosmic-panel-bin/src/xdg_shell_wrapper/space/space.rs index fa390602..474ac4b5 100644 --- a/cosmic-panel-bin/src/xdg_shell_wrapper/space/space.rs +++ b/cosmic-panel-bin/src/xdg_shell_wrapper/space/space.rs @@ -166,10 +166,11 @@ pub trait WrapperSpace { s_surface: PopupSurface, positioner: XdgPositioner, positioner_state: PositionerState, - latest_seat: &WlSeat, - latest_serial: u32, ) -> anyhow::Result<()>; + /// Add a grab for the popup + fn grab_popup(&mut self, popup: PopupSurface, seat: WlSeat, serial: u32) -> anyhow::Result<()>; + /// handle a button press or release on a client surface /// optionally returns an interacted server wl surface fn handle_button(&mut self, seat_name: &str, press: bool) -> Option;