diff --git a/anvil/src/shell.rs b/anvil/src/shell.rs index 0663d31..f5b09ef 100644 --- a/anvil/src/shell.rs +++ b/anvil/src/shell.rs @@ -352,7 +352,7 @@ pub fn init_shell(display: Rc>, log: ::sl let xdg_output_map = output_map.clone(); let (xdg_shell_state, _, _) = xdg_shell_init( &mut *display.borrow_mut(), - move |shell_event| match shell_event { + move |shell_event, _dispatch_data| match shell_event { XdgRequest::NewToplevel { surface } => { // place the window at a random location on the primary output // or if there is not output in a [0;800]x[0;800] square diff --git a/anvil/src/window_map.rs b/anvil/src/window_map.rs index 0be8d84..b45bdee 100644 --- a/anvil/src/window_map.rs +++ b/anvil/src/window_map.rs @@ -17,7 +17,7 @@ use crate::shell::SurfaceData; #[cfg(feature = "xwayland")] use crate::xwayland::X11Surface; -#[derive(Clone)] +#[derive(Clone, PartialEq)] pub enum Kind { Xdg(ToplevelSurface), Wl(ShellSurface), @@ -44,17 +44,6 @@ impl Kind { } } - /// Do this handle and the other one actually refer to the same toplevel surface? - pub fn equals(&self, other: &Self) -> bool { - match (self, other) { - (Kind::Xdg(a), Kind::Xdg(b)) => a.equals(b), - (Kind::Wl(a), Kind::Wl(b)) => a.equals(b), - #[cfg(feature = "xwayland")] - (Kind::X11(a), Kind::X11(b)) => a.equals(b), - _ => false, - } - } - /// Activate/Deactivate this window pub fn set_activated(&self, active: bool) { if let Kind::Xdg(ref t) = self { @@ -357,7 +346,7 @@ impl WindowMap { /// Refreshes the state of the toplevel, if it exists. pub fn refresh_toplevel(&mut self, toplevel: &Kind) { - if let Some(w) = self.windows.iter_mut().find(|w| w.toplevel.equals(toplevel)) { + if let Some(w) = self.windows.iter_mut().find(|w| &w.toplevel == toplevel) { w.self_update(); } } @@ -400,13 +389,13 @@ impl WindowMap { pub fn location(&self, toplevel: &Kind) -> Option<(i32, i32)> { self.windows .iter() - .find(|w| w.toplevel.equals(toplevel)) + .find(|w| &w.toplevel == toplevel) .map(|w| w.location) } /// Sets the location of the toplevel, if it exists. pub fn set_location(&mut self, toplevel: &Kind, location: (i32, i32)) { - if let Some(w) = self.windows.iter_mut().find(|w| w.toplevel.equals(toplevel)) { + if let Some(w) = self.windows.iter_mut().find(|w| &w.toplevel == toplevel) { w.location = location; w.self_update(); } @@ -416,7 +405,7 @@ impl WindowMap { pub fn geometry(&self, toplevel: &Kind) -> Option { self.windows .iter() - .find(|w| w.toplevel.equals(toplevel)) + .find(|w| &w.toplevel == toplevel) .map(|w| w.geometry()) } diff --git a/anvil/src/xwayland/mod.rs b/anvil/src/xwayland/mod.rs index 59c4346..aae48e2 100644 --- a/anvil/src/xwayland/mod.rs +++ b/anvil/src/xwayland/mod.rs @@ -237,15 +237,17 @@ pub struct X11Surface { surface: WlSurface, } +impl std::cmp::PartialEq for X11Surface { + fn eq(&self, other: &Self) -> bool { + self.alive() && other.alive() && self.surface == other.surface + } +} + impl X11Surface { pub fn alive(&self) -> bool { self.surface.as_ref().is_alive() } - pub fn equals(&self, other: &Self) -> bool { - self.alive() && other.alive() && self.surface.as_ref().equals(&other.surface.as_ref()) - } - pub fn get_surface(&self) -> Option<&WlSurface> { if self.alive() { Some(&self.surface) diff --git a/src/wayland/shell/xdg/mod.rs b/src/wayland/shell/xdg/mod.rs index 333ad09..5a1fae2 100644 --- a/src/wayland/shell/xdg/mod.rs +++ b/src/wayland/shell/xdg/mod.rs @@ -22,24 +22,19 @@ //! ### Initialization //! //! To initialize this handler, simple use the [`xdg_shell_init`] function provided in this module. +//! You need to provide a closure that will be invoked whenever some action is required from you, +//! are represented by the [`XdgRequest`] enum. //! //! ```no_run //! # extern crate wayland_server; //! # //! use smithay::wayland::shell::xdg::{xdg_shell_init, XdgRequest}; //! -//! -//! // define the metadata you want associated with the shell clients -//! #[derive(Default)] -//! struct MyShellData { -//! /* ... */ -//! } -//! //! # let mut display = wayland_server::Display::new(); //! let (shell_state, _, _) = xdg_shell_init( //! &mut display, //! // your implementation -//! |event: XdgRequest| { /* ... */ }, +//! |event: XdgRequest, dispatch_data| { /* handle the shell requests here */ }, //! None // put a logger if you want //! ); //! @@ -52,8 +47,7 @@ //! //! - [`ShellClient`]: //! This is a handle representing an instantiation of a shell global -//! you can associate client-wise metadata to it (this is the `MyShellData` type in -//! the example above). +//! you can associate client-wise metadata to it through an [`UserDataMap`]. //! - [`ToplevelSurface`]: //! This is a handle representing a toplevel surface, you can //! retrieve a list of all currently alive toplevel surface from the @@ -84,6 +78,7 @@ use wayland_protocols::{ unstable::xdg_shell::v6::server::{zxdg_popup_v6, zxdg_shell_v6, zxdg_toplevel_v6}, xdg_shell::server::{xdg_popup, xdg_positioner, xdg_toplevel, xdg_wm_base}, }; +use wayland_server::DispatchData; use wayland_server::{ protocol::{wl_output, wl_seat, wl_surface}, Display, Filter, Global, UserDataMap, @@ -646,7 +641,7 @@ impl Cacheable for SurfaceCachedState { pub(crate) struct ShellData { log: ::slog::Logger, - user_impl: Rc>, + user_impl: Rc)>>, shell_state: Arc>, } @@ -672,7 +667,7 @@ pub fn xdg_shell_init( ) where L: Into>, - Impl: FnMut(XdgRequest) + 'static, + Impl: FnMut(XdgRequest, DispatchData<'_>) + 'static, { let log = crate::slog_or_fallback(logger); let shell_state = Arc::new(Mutex::new(ShellState { @@ -690,15 +685,15 @@ where let xdg_shell_global = display.create_global( 1, - Filter::new(move |(shell, _version), _, _data| { - self::xdg_handlers::implement_wm_base(shell, &shell_data); + Filter::new(move |(shell, _version), _, dispatch_data| { + self::xdg_handlers::implement_wm_base(shell, &shell_data, dispatch_data); }), ); let zxdgv6_shell_global = display.create_global( 1, - Filter::new(move |(shell, _version), _, _data| { - self::zxdgv6_handlers::implement_shell(shell, &shell_data_z); + Filter::new(move |(shell, _version), _, dispatch_data| { + self::zxdgv6_handlers::implement_shell(shell, &shell_data_z, dispatch_data); }), ); @@ -764,6 +759,16 @@ pub struct ShellClient { kind: ShellClientKind, } +impl std::cmp::PartialEq for ShellClient { + fn eq(&self, other: &Self) -> bool { + match (&self.kind, &other.kind) { + (&ShellClientKind::Xdg(ref s1), &ShellClientKind::Xdg(ref s2)) => s1 == s2, + (&ShellClientKind::ZxdgV6(ref s1), &ShellClientKind::ZxdgV6(ref s2)) => s1 == s2, + _ => false, + } + } +} + impl ShellClient { /// Is the shell client represented by this handle still connected? pub fn alive(&self) -> bool { @@ -773,18 +778,6 @@ impl ShellClient { } } - /// Checks if this handle and the other one actually refer to the - /// same shell client - pub fn equals(&self, other: &Self) -> bool { - match (&self.kind, &other.kind) { - (&ShellClientKind::Xdg(ref s1), &ShellClientKind::Xdg(ref s2)) => s1.as_ref().equals(s2.as_ref()), - (&ShellClientKind::ZxdgV6(ref s1), &ShellClientKind::ZxdgV6(ref s2)) => { - s1.as_ref().equals(s2.as_ref()) - } - _ => false, - } - } - /// Send a ping request to this shell client /// /// You'll receive the reply as a [`XdgRequest::ClientPong`] request. @@ -873,6 +866,12 @@ pub struct ToplevelSurface { shell_surface: ToplevelKind, } +impl std::cmp::PartialEq for ToplevelSurface { + fn eq(&self, other: &Self) -> bool { + self.alive() && other.alive() && self.wl_surface == other.wl_surface + } +} + impl ToplevelSurface { /// Is the toplevel surface referred by this handle still alive? pub fn alive(&self) -> bool { @@ -883,11 +882,6 @@ impl ToplevelSurface { shell_alive && self.wl_surface.as_ref().is_alive() } - /// Do this handle and the other one actually refer to the same toplevel surface? - pub fn equals(&self, other: &Self) -> bool { - self.alive() && other.alive() && self.wl_surface.as_ref().equals(&other.wl_surface.as_ref()) - } - /// Retrieve the shell client owning this toplevel surface /// /// Returns `None` if the surface does actually no longer exist. @@ -957,6 +951,9 @@ impl ToplevelSurface { /// Send a configure event to this toplevel surface to suggest it a new configuration /// /// The serial of this configure will be tracked waiting for the client to ACK it. + /// + /// You can manipulate the state that will be sent to the client with the [`with_pending_state`](#method.with_pending_state) + /// method. pub fn send_configure(&self) { if let Some(surface) = self.get_surface() { let configure = compositor::with_states(surface, |states| { @@ -1084,13 +1081,10 @@ impl ToplevelSurface { /// Allows the pending state of this toplevel to /// be manipulated. /// - /// This should be used to inform the client about - /// size and state changes. + /// This should be used to inform the client about size and state changes, + /// for example after a resize request from the client. /// - /// For example after a resize request from the client. - /// - /// The state will be sent to the client when calling - /// send_configure. + /// The state will be sent to the client when calling [`send_configure`](#method.send_configure). pub fn with_pending_state(&self, f: F) -> Result where F: FnOnce(&mut ToplevelState) -> T, @@ -1157,6 +1151,12 @@ pub struct PopupSurface { shell_surface: PopupKind, } +impl std::cmp::PartialEq for PopupSurface { + fn eq(&self, other: &Self) -> bool { + self.alive() && other.alive() && self.wl_surface == other.wl_surface + } +} + impl PopupSurface { /// Is the popup surface referred by this handle still alive? pub fn alive(&self) -> bool { @@ -1187,11 +1187,6 @@ impl PopupSurface { } } - /// Do this handle and the other one actually refer to the same popup surface? - pub fn equals(&self, other: &Self) -> bool { - self.alive() && other.alive() && self.wl_surface.as_ref().equals(&other.wl_surface.as_ref()) - } - /// Retrieve the shell client owning this popup surface /// /// Returns `None` if the surface does actually no longer exist. @@ -1225,6 +1220,9 @@ impl PopupSurface { /// Send a configure event to this popup surface to suggest it a new configuration /// /// The serial of this configure will be tracked waiting for the client to ACK it. + /// + /// You can manipulate the state that will be sent to the client with the [`with_pending_state`](#method.with_pending_state) + /// method. pub fn send_configure(&self) { if let Some(surface) = self.get_surface() { let next_configure = compositor::with_states(surface, |states| { @@ -1406,13 +1404,10 @@ impl PopupSurface { /// Allows the pending state of this popup to /// be manipulated. /// - /// This should be used to inform the client about - /// size and position changes. + /// This should be used to inform the client about size and position changes, + /// for example after a move of the parent toplevel. /// - /// For example after a move of the parent toplevel. - /// - /// The state will be sent to the client when calling - /// send_configure. + /// The state will be sent to the client when calling [`send_configure`](#method.send_configure). pub fn with_pending_state(&self, f: F) -> Result where F: FnOnce(&mut PopupState) -> T, @@ -1515,7 +1510,7 @@ pub enum XdgRequest { /// A new toplevel surface was created /// /// You likely need to send a [`ToplevelConfigure`] to the surface, to hint the - /// client as to how its window should be + /// client as to how its window should be sized. NewToplevel { /// the surface surface: ToplevelSurface, @@ -1523,7 +1518,7 @@ pub enum XdgRequest { /// A new popup surface was created /// /// You likely need to send a [`PopupConfigure`] to the surface, to hint the - /// client as to how its popup should be + /// client as to how its popup should be sized. NewPopup { /// the surface surface: PopupSurface, diff --git a/src/wayland/shell/xdg/xdg_handlers.rs b/src/wayland/shell/xdg/xdg_handlers.rs index 2741678..637e7f7 100644 --- a/src/wayland/shell/xdg/xdg_handlers.rs +++ b/src/wayland/shell/xdg/xdg_handlers.rs @@ -7,6 +7,7 @@ use crate::wayland::Serial; use wayland_protocols::xdg_shell::server::{ xdg_popup, xdg_positioner, xdg_surface, xdg_toplevel, xdg_wm_base, }; +use wayland_server::DispatchData; use wayland_server::{protocol::wl_surface, Filter, Main}; use crate::utils::Rectangle; @@ -23,16 +24,20 @@ static XDG_POPUP_ROLE: &str = "xdg_popup"; pub(crate) fn implement_wm_base( shell: Main, shell_data: &ShellData, + dispatch_data: DispatchData<'_>, ) -> xdg_wm_base::XdgWmBase { - shell.quick_assign(|shell, req, _data| wm_implementation(req, shell.deref().clone())); + shell.quick_assign(wm_implementation); shell.as_ref().user_data().set(|| ShellUserData { shell_data: shell_data.clone(), client_data: Mutex::new(make_shell_client_data()), }); let mut user_impl = shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::NewClient { - client: make_shell_client(&shell), - }); + (&mut *user_impl)( + XdgRequest::NewClient { + client: make_shell_client(&shell), + }, + dispatch_data, + ); shell.deref().clone() } @@ -51,7 +56,11 @@ pub(crate) fn make_shell_client(resource: &xdg_wm_base::XdgWmBase) -> ShellClien } } -fn wm_implementation(request: xdg_wm_base::Request, shell: xdg_wm_base::XdgWmBase) { +fn wm_implementation( + shell: Main, + request: xdg_wm_base::Request, + dispatch_data: DispatchData<'_>, +) { let data = shell.as_ref().user_data().get::().unwrap(); match request { xdg_wm_base::Request::Destroy => { @@ -64,12 +73,14 @@ fn wm_implementation(request: xdg_wm_base::Request, shell: xdg_wm_base::XdgWmBas // Do not assign a role to the surface here // xdg_surface is not role, only xdg_toplevel and // xdg_popup are defined as roles - id.quick_assign(|surface, req, _data| xdg_surface_implementation(req, surface.deref().clone())); + id.quick_assign(|surface, req, dispatch_data| { + xdg_surface_implementation(req, surface.deref().clone(), dispatch_data) + }); id.assign_destructor(Filter::new(|surface, _, _data| destroy_surface(surface))); id.as_ref().user_data().set(|| XdgSurfaceUserData { shell_data: data.shell_data.clone(), wl_surface: surface, - wm_base: shell.clone(), + wm_base: shell.deref().clone(), has_active_role: AtomicBool::new(false), }); } @@ -86,9 +97,12 @@ fn wm_implementation(request: xdg_wm_base::Request, shell: xdg_wm_base::XdgWmBas }; if valid { let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::ClientPong { - client: make_shell_client(&shell), - }); + (&mut *user_impl)( + XdgRequest::ClientPong { + client: make_shell_client(&shell), + }, + dispatch_data, + ); } } _ => unreachable!(), @@ -191,7 +205,11 @@ fn destroy_surface(surface: xdg_surface::XdgSurface) { } } -fn xdg_surface_implementation(request: xdg_surface::Request, xdg_surface: xdg_surface::XdgSurface) { +fn xdg_surface_implementation( + request: xdg_surface::Request, + xdg_surface: xdg_surface::XdgSurface, + dispatch_data: DispatchData<'_>, +) { let data = xdg_surface .as_ref() .user_data() @@ -225,7 +243,7 @@ fn xdg_surface_implementation(request: xdg_surface::Request, xdg_surface: xdg_su compositor::add_commit_hook(surface, super::ToplevelSurface::commit_hook); - id.quick_assign(|toplevel, req, _data| toplevel_implementation(req, toplevel.deref().clone())); + id.quick_assign(toplevel_implementation); id.assign_destructor(Filter::new(|toplevel, _, _data| destroy_toplevel(toplevel))); id.as_ref().user_data().set(|| ShellSurfaceUserData { shell_data: data.shell_data.clone(), @@ -243,7 +261,7 @@ fn xdg_surface_implementation(request: xdg_surface::Request, xdg_surface: xdg_su let handle = make_toplevel_handle(&id); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::NewToplevel { surface: handle }); + (&mut *user_impl)(XdgRequest::NewToplevel { surface: handle }, dispatch_data); } xdg_surface::Request::GetPopup { id, @@ -300,7 +318,7 @@ fn xdg_surface_implementation(request: xdg_surface::Request, xdg_surface: xdg_su compositor::add_commit_hook(surface, super::PopupSurface::commit_hook); - id.quick_assign(|popup, req, _data| xdg_popup_implementation(req, popup.deref().clone())); + id.quick_assign(xdg_popup_implementation); id.assign_destructor(Filter::new(|popup, _, _data| destroy_popup(popup))); id.as_ref().user_data().set(|| ShellSurfaceUserData { shell_data: data.shell_data.clone(), @@ -318,7 +336,7 @@ fn xdg_surface_implementation(request: xdg_surface::Request, xdg_surface: xdg_su let handle = make_popup_handle(&id); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::NewPopup { surface: handle }); + (&mut *user_impl)(XdgRequest::NewPopup { surface: handle }, dispatch_data); } xdg_surface::Request::SetWindowGeometry { x, y, width, height } => { // Check the role of the surface, this can be either xdg_toplevel @@ -417,10 +435,13 @@ fn xdg_surface_implementation(request: xdg_surface::Request, xdg_surface: xdg_su }; let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::AckConfigure { - surface: surface.clone(), - configure, - }); + (&mut *user_impl)( + XdgRequest::AckConfigure { + surface: surface.clone(), + configure, + }, + dispatch_data, + ); } _ => unreachable!(), } @@ -512,7 +533,11 @@ fn make_toplevel_handle(resource: &xdg_toplevel::XdgToplevel) -> super::Toplevel } } -fn toplevel_implementation(request: xdg_toplevel::Request, toplevel: xdg_toplevel::XdgToplevel) { +fn toplevel_implementation( + toplevel: Main, + request: xdg_toplevel::Request, + dispatch_data: DispatchData<'_>, +) { let data = toplevel .as_ref() .user_data() @@ -553,35 +578,44 @@ fn toplevel_implementation(request: xdg_toplevel::Request, toplevel: xdg_topleve let handle = make_toplevel_handle(&toplevel); let serial = Serial::from(serial); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::ShowWindowMenu { - surface: handle, - seat, - serial, - location: (x, y), - }); + (&mut *user_impl)( + XdgRequest::ShowWindowMenu { + surface: handle, + seat, + serial, + location: (x, y), + }, + dispatch_data, + ); } xdg_toplevel::Request::Move { seat, serial } => { // This has to be handled by the compositor let handle = make_toplevel_handle(&toplevel); let serial = Serial::from(serial); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::Move { - surface: handle, - seat, - serial, - }); + (&mut *user_impl)( + XdgRequest::Move { + surface: handle, + seat, + serial, + }, + dispatch_data, + ); } xdg_toplevel::Request::Resize { seat, serial, edges } => { // This has to be handled by the compositor let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); let serial = Serial::from(serial); - (&mut *user_impl)(XdgRequest::Resize { - surface: handle, - seat, - serial, - edges, - }); + (&mut *user_impl)( + XdgRequest::Resize { + surface: handle, + seat, + serial, + edges, + }, + dispatch_data, + ); } xdg_toplevel::Request::SetMaxSize { width, height } => { with_toplevel_pending_state(&toplevel, |toplevel_data| { @@ -596,32 +630,35 @@ fn toplevel_implementation(request: xdg_toplevel::Request, toplevel: xdg_topleve xdg_toplevel::Request::SetMaximized => { let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::Maximize { surface: handle }); + (&mut *user_impl)(XdgRequest::Maximize { surface: handle }, dispatch_data); } xdg_toplevel::Request::UnsetMaximized => { let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::UnMaximize { surface: handle }); + (&mut *user_impl)(XdgRequest::UnMaximize { surface: handle }, dispatch_data); } xdg_toplevel::Request::SetFullscreen { output } => { let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::Fullscreen { - surface: handle, - output, - }); + (&mut *user_impl)( + XdgRequest::Fullscreen { + surface: handle, + output, + }, + dispatch_data, + ); } xdg_toplevel::Request::UnsetFullscreen => { let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::UnFullscreen { surface: handle }); + (&mut *user_impl)(XdgRequest::UnFullscreen { surface: handle }, dispatch_data); } xdg_toplevel::Request::SetMinimized => { // This has to be handled by the compositor, may not be // supported and just ignored let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::Minimize { surface: handle }); + (&mut *user_impl)(XdgRequest::Minimize { surface: handle }, dispatch_data); } _ => unreachable!(), } @@ -679,7 +716,11 @@ fn make_popup_handle(resource: &xdg_popup::XdgPopup) -> super::PopupSurface { } } -fn xdg_popup_implementation(request: xdg_popup::Request, popup: xdg_popup::XdgPopup) { +fn xdg_popup_implementation( + popup: Main, + request: xdg_popup::Request, + dispatch_data: DispatchData<'_>, +) { let data = popup.as_ref().user_data().get::().unwrap(); match request { xdg_popup::Request::Destroy => { @@ -689,11 +730,14 @@ fn xdg_popup_implementation(request: xdg_popup::Request, popup: xdg_popup::XdgPo let handle = make_popup_handle(&popup); let mut user_impl = data.shell_data.user_impl.borrow_mut(); let serial = Serial::from(serial); - (&mut *user_impl)(XdgRequest::Grab { - surface: handle, - seat, - serial, - }); + (&mut *user_impl)( + XdgRequest::Grab { + surface: handle, + seat, + serial, + }, + dispatch_data, + ); } _ => unreachable!(), } diff --git a/src/wayland/shell/xdg/zxdgv6_handlers.rs b/src/wayland/shell/xdg/zxdgv6_handlers.rs index b762721..4ec11e0 100644 --- a/src/wayland/shell/xdg/zxdgv6_handlers.rs +++ b/src/wayland/shell/xdg/zxdgv6_handlers.rs @@ -10,6 +10,7 @@ use wayland_protocols::{ }, xdg_shell::server::{xdg_positioner, xdg_toplevel}, }; +use wayland_server::DispatchData; use wayland_server::{protocol::wl_surface, Filter, Main}; use crate::utils::Rectangle; @@ -26,16 +27,20 @@ static ZXDG_POPUP_ROLE: &str = "zxdg_toplevel"; pub(crate) fn implement_shell( shell: Main, shell_data: &ShellData, + dispatch_data: DispatchData<'_>, ) -> zxdg_shell_v6::ZxdgShellV6 { - shell.quick_assign(|shell, req, _data| shell_implementation(req, shell.deref().clone())); + shell.quick_assign(shell_implementation); shell.as_ref().user_data().set(|| ShellUserData { shell_data: shell_data.clone(), client_data: Mutex::new(make_shell_client_data()), }); let mut user_impl = shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::NewClient { - client: make_shell_client(&shell), - }); + (&mut *user_impl)( + XdgRequest::NewClient { + client: make_shell_client(&shell), + }, + dispatch_data, + ); shell.deref().clone() } @@ -54,7 +59,11 @@ pub(crate) fn make_shell_client(resource: &zxdg_shell_v6::ZxdgShellV6) -> ShellC } } -fn shell_implementation(request: zxdg_shell_v6::Request, shell: zxdg_shell_v6::ZxdgShellV6) { +fn shell_implementation( + shell: Main, + request: zxdg_shell_v6::Request, + dispatch_data: DispatchData<'_>, +) { let data = shell.as_ref().user_data().get::().unwrap(); match request { zxdg_shell_v6::Request::Destroy => { @@ -64,12 +73,12 @@ fn shell_implementation(request: zxdg_shell_v6::Request, shell: zxdg_shell_v6::Z implement_positioner(id); } zxdg_shell_v6::Request::GetXdgSurface { id, surface } => { - id.quick_assign(|surface, req, _data| xdg_surface_implementation(req, surface.deref().clone())); + id.quick_assign(xdg_surface_implementation); id.assign_destructor(Filter::new(|surface, _, _data| destroy_surface(surface))); id.as_ref().user_data().set(|| XdgSurfaceUserData { shell_data: data.shell_data.clone(), wl_surface: surface, - shell: shell.clone(), + shell: shell.deref().clone(), has_active_role: AtomicBool::new(false), }); } @@ -86,9 +95,12 @@ fn shell_implementation(request: zxdg_shell_v6::Request, shell: zxdg_shell_v6::Z }; if valid { let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::ClientPong { - client: make_shell_client(&shell), - }); + (&mut *user_impl)( + XdgRequest::ClientPong { + client: make_shell_client(&shell), + }, + dispatch_data, + ); } } _ => unreachable!(), @@ -208,8 +220,9 @@ fn destroy_surface(surface: zxdg_surface_v6::ZxdgSurfaceV6) { } fn xdg_surface_implementation( + xdg_surface: Main, request: zxdg_surface_v6::Request, - xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6, + dispatch_data: DispatchData<'_>, ) { let data = xdg_surface .as_ref() @@ -244,13 +257,13 @@ fn xdg_surface_implementation( compositor::add_commit_hook(surface, super::ToplevelSurface::commit_hook); - id.quick_assign(|toplevel, req, _data| toplevel_implementation(req, toplevel.deref().clone())); + id.quick_assign(toplevel_implementation); id.assign_destructor(Filter::new(|toplevel, _, _data| destroy_toplevel(toplevel))); id.as_ref().user_data().set(|| ShellSurfaceUserData { shell_data: data.shell_data.clone(), wl_surface: data.wl_surface.clone(), shell: data.shell.clone(), - xdg_surface: xdg_surface.clone(), + xdg_surface: xdg_surface.deref().clone(), }); data.shell_data @@ -262,7 +275,7 @@ fn xdg_surface_implementation( let handle = make_toplevel_handle(&id); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::NewToplevel { surface: handle }); + (&mut *user_impl)(XdgRequest::NewToplevel { surface: handle }, dispatch_data); } zxdg_surface_v6::Request::GetPopup { id, @@ -319,13 +332,13 @@ fn xdg_surface_implementation( compositor::add_commit_hook(surface, super::PopupSurface::commit_hook); - id.quick_assign(|popup, req, _data| popup_implementation(req, popup.deref().clone())); + id.quick_assign(popup_implementation); id.assign_destructor(Filter::new(|popup, _, _data| destroy_popup(popup))); id.as_ref().user_data().set(|| ShellSurfaceUserData { shell_data: data.shell_data.clone(), wl_surface: data.wl_surface.clone(), shell: data.shell.clone(), - xdg_surface: xdg_surface.clone(), + xdg_surface: xdg_surface.deref().clone(), }); data.shell_data @@ -337,7 +350,7 @@ fn xdg_surface_implementation( let handle = make_popup_handle(&id); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::NewPopup { surface: handle }); + (&mut *user_impl)(XdgRequest::NewPopup { surface: handle }, dispatch_data); } zxdg_surface_v6::Request::SetWindowGeometry { x, y, width, height } => { // Check the role of the surface, this can be either xdg_toplevel @@ -437,10 +450,13 @@ fn xdg_surface_implementation( }; let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::AckConfigure { - surface: surface.clone(), - configure, - }); + (&mut *user_impl)( + XdgRequest::AckConfigure { + surface: surface.clone(), + configure, + }, + dispatch_data, + ); } _ => unreachable!(), } @@ -532,7 +548,11 @@ fn make_toplevel_handle(resource: &zxdg_toplevel_v6::ZxdgToplevelV6) -> super::T } } -fn toplevel_implementation(request: zxdg_toplevel_v6::Request, toplevel: zxdg_toplevel_v6::ZxdgToplevelV6) { +fn toplevel_implementation( + toplevel: Main, + request: zxdg_toplevel_v6::Request, + dispatch_data: DispatchData<'_>, +) { let data = toplevel .as_ref() .user_data() @@ -570,22 +590,28 @@ fn toplevel_implementation(request: zxdg_toplevel_v6::Request, toplevel: zxdg_to let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); let serial = Serial::from(serial); - (&mut *user_impl)(XdgRequest::ShowWindowMenu { - surface: handle, - seat, - serial, - location: (x, y), - }); + (&mut *user_impl)( + XdgRequest::ShowWindowMenu { + surface: handle, + seat, + serial, + location: (x, y), + }, + dispatch_data, + ); } zxdg_toplevel_v6::Request::Move { seat, serial } => { let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); let serial = Serial::from(serial); - (&mut *user_impl)(XdgRequest::Move { - surface: handle, - seat, - serial, - }); + (&mut *user_impl)( + XdgRequest::Move { + surface: handle, + seat, + serial, + }, + dispatch_data, + ); } zxdg_toplevel_v6::Request::Resize { seat, serial, edges } => { let edges = @@ -593,12 +619,15 @@ fn toplevel_implementation(request: zxdg_toplevel_v6::Request, toplevel: zxdg_to let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); let serial = Serial::from(serial); - (&mut *user_impl)(XdgRequest::Resize { - surface: handle, - seat, - serial, - edges: zxdg_edges_to_xdg(edges), - }); + (&mut *user_impl)( + XdgRequest::Resize { + surface: handle, + seat, + serial, + edges: zxdg_edges_to_xdg(edges), + }, + dispatch_data, + ); } zxdg_toplevel_v6::Request::SetMaxSize { width, height } => { with_toplevel_pending_state(&toplevel, |toplevel_data| { @@ -613,32 +642,35 @@ fn toplevel_implementation(request: zxdg_toplevel_v6::Request, toplevel: zxdg_to zxdg_toplevel_v6::Request::SetMaximized => { let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::Maximize { surface: handle }); + (&mut *user_impl)(XdgRequest::Maximize { surface: handle }, dispatch_data); } zxdg_toplevel_v6::Request::UnsetMaximized => { let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::UnMaximize { surface: handle }); + (&mut *user_impl)(XdgRequest::UnMaximize { surface: handle }, dispatch_data); } zxdg_toplevel_v6::Request::SetFullscreen { output } => { let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::Fullscreen { - surface: handle, - output, - }); + (&mut *user_impl)( + XdgRequest::Fullscreen { + surface: handle, + output, + }, + dispatch_data, + ); } zxdg_toplevel_v6::Request::UnsetFullscreen => { let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::UnFullscreen { surface: handle }); + (&mut *user_impl)(XdgRequest::UnFullscreen { surface: handle }, dispatch_data); } zxdg_toplevel_v6::Request::SetMinimized => { // This has to be handled by the compositor, may not be // supported and just ignored let handle = make_toplevel_handle(&toplevel); let mut user_impl = data.shell_data.user_impl.borrow_mut(); - (&mut *user_impl)(XdgRequest::Minimize { surface: handle }); + (&mut *user_impl)(XdgRequest::Minimize { surface: handle }, dispatch_data); } _ => unreachable!(), } @@ -696,7 +728,11 @@ fn make_popup_handle(resource: &zxdg_popup_v6::ZxdgPopupV6) -> super::PopupSurfa } } -fn popup_implementation(request: zxdg_popup_v6::Request, popup: zxdg_popup_v6::ZxdgPopupV6) { +fn popup_implementation( + popup: Main, + request: zxdg_popup_v6::Request, + dispatch_data: DispatchData<'_>, +) { let data = popup.as_ref().user_data().get::().unwrap(); match request { zxdg_popup_v6::Request::Destroy => { @@ -706,11 +742,14 @@ fn popup_implementation(request: zxdg_popup_v6::Request, popup: zxdg_popup_v6::Z let handle = make_popup_handle(&popup); let mut user_impl = data.shell_data.user_impl.borrow_mut(); let serial = Serial::from(serial); - (&mut *user_impl)(XdgRequest::Grab { - surface: handle, - seat, - serial, - }); + (&mut *user_impl)( + XdgRequest::Grab { + surface: handle, + seat, + serial, + }, + dispatch_data, + ); } _ => unreachable!(), }