wayland.shell.xdg: use UserDataMap

This commit is contained in:
Victor Berger 2019-04-23 23:52:14 +02:00 committed by Victor Berger
parent 19432460cd
commit d62fb4c8b5
5 changed files with 179 additions and 281 deletions

View File

@ -31,12 +31,12 @@ use crate::window_map::{Kind as SurfaceKind, WindowMap};
define_roles!(Roles => define_roles!(Roles =>
[ XdgSurface, XdgSurfaceRole ] [ XdgSurface, XdgSurfaceRole ]
[ ShellSurface, ShellSurfaceRole<()>] [ ShellSurface, ShellSurfaceRole]
[ DnDIcon, DnDIconRole ] [ DnDIcon, DnDIconRole ]
[ CursorImage, CursorImageRole ] [ CursorImage, CursorImageRole ]
); );
pub type MyWindowMap = WindowMap<Roles, (), (), fn(&SurfaceAttributes) -> Option<(i32, i32)>>; pub type MyWindowMap = WindowMap<Roles, fn(&SurfaceAttributes) -> Option<(i32, i32)>>;
pub type MyCompositorToken = CompositorToken<Roles>; pub type MyCompositorToken = CompositorToken<Roles>;
@ -45,8 +45,8 @@ pub fn init_shell(
log: ::slog::Logger, log: ::slog::Logger,
) -> ( ) -> (
CompositorToken<Roles>, CompositorToken<Roles>,
Arc<Mutex<XdgShellState<Roles, ()>>>, Arc<Mutex<XdgShellState<Roles>>>,
Arc<Mutex<WlShellState<Roles, ()>>>, Arc<Mutex<WlShellState<Roles>>>,
Rc<RefCell<MyWindowMap>>, Rc<RefCell<MyWindowMap>>,
) { ) {
// Create the compositor // Create the compositor
@ -62,7 +62,7 @@ pub fn init_shell(
); );
// Init a window map, to track the location of our windows // Init a window map, to track the location of our windows
let window_map = Rc::new(RefCell::new(WindowMap::<_, (), (), _>::new( let window_map = Rc::new(RefCell::new(WindowMap::<_, _>::new(
compositor_token, compositor_token,
get_size as _, get_size as _,
))); )));
@ -104,7 +104,7 @@ pub fn init_shell(
let (wl_shell_state, _) = wl_shell_init( let (wl_shell_state, _) = wl_shell_init(
display, display,
compositor_token, compositor_token,
move |req: ShellRequest<_, ()>| { move |req: ShellRequest<_>| {
if let ShellRequest::SetKind { if let ShellRequest::SetKind {
surface, surface,
kind: ShellSurfaceKind::Toplevel, kind: ShellSurfaceKind::Toplevel,

View File

@ -12,16 +12,14 @@ use smithay::{
}, },
}; };
pub enum Kind<R, SD, D> { pub enum Kind<R> {
Xdg(ToplevelSurface<R, SD>), Xdg(ToplevelSurface<R>),
Wl(ShellSurface<R, D>), Wl(ShellSurface<R>),
} }
impl<R, SD, D> Kind<R, SD, D> impl<R> Kind<R>
where where
R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole<D>> + 'static, R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole> + 'static,
SD: 'static,
D: 'static,
{ {
pub fn alive(&self) -> bool { pub fn alive(&self) -> bool {
match *self { match *self {
@ -37,17 +35,15 @@ where
} }
} }
struct Window<R, SD, D> { struct Window<R> {
location: (i32, i32), location: (i32, i32),
surface: Rectangle, surface: Rectangle,
toplevel: Kind<R, SD, D>, toplevel: Kind<R>,
} }
impl<R, SD, D> Window<R, SD, D> impl<R> Window<R>
where where
R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole<D>> + 'static, R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole> + 'static,
SD: 'static,
D: 'static,
{ {
// Find the topmost surface under this point if any and the location of this surface // Find the topmost surface under this point if any and the location of this surface
fn matching<F>( fn matching<F>(
@ -146,20 +142,18 @@ where
} }
} }
pub struct WindowMap<R, SD, D, F> { pub struct WindowMap<R, F> {
ctoken: CompositorToken<R>, ctoken: CompositorToken<R>,
windows: Vec<Window<R, SD, D>>, windows: Vec<Window<R>>,
get_size: F, get_size: F,
} }
impl<R, SD, D, F> WindowMap<R, SD, D, F> impl<R, F> WindowMap<R, F>
where where
F: Fn(&SurfaceAttributes) -> Option<(i32, i32)>, F: Fn(&SurfaceAttributes) -> Option<(i32, i32)>,
R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole<D>> + 'static, R: Role<SubsurfaceRole> + Role<XdgSurfaceRole> + Role<ShellSurfaceRole> + 'static,
SD: 'static,
D: 'static,
{ {
pub fn new(ctoken: CompositorToken<R>, get_size: F) -> WindowMap<R, D, SD, F> { pub fn new(ctoken: CompositorToken<R>, get_size: F) -> WindowMap<R, F> {
WindowMap { WindowMap {
ctoken, ctoken,
windows: Vec::new(), windows: Vec::new(),
@ -167,7 +161,7 @@ where
} }
} }
pub fn insert(&mut self, toplevel: Kind<R, SD, D>, location: (i32, i32)) { pub fn insert(&mut self, toplevel: Kind<R>, location: (i32, i32)) {
let mut window = Window { let mut window = Window {
location, location,
surface: Rectangle { surface: Rectangle {
@ -213,7 +207,7 @@ where
pub fn with_windows_from_bottom_to_top<Func>(&self, mut f: Func) pub fn with_windows_from_bottom_to_top<Func>(&self, mut f: Func)
where where
Func: FnMut(&Kind<R, SD, D>, (i32, i32)), Func: FnMut(&Kind<R>, (i32, i32)),
{ {
for w in self.windows.iter().rev() { for w in self.windows.iter().rev() {
f(&w.toplevel, w.location) f(&w.toplevel, w.location)

View File

@ -60,7 +60,7 @@
//! // token from the compositor implementation //! // token from the compositor implementation
//! compositor_token, //! compositor_token,
//! // your implementation //! // your implementation
//! |event: XdgRequest<_, MyShellData>| { /* ... */ }, //! |event: XdgRequest<_>| { /* ... */ },
//! None // put a logger if you want //! None // put a logger if you want
//! ); //! );
//! //!
@ -96,6 +96,7 @@ use std::{
rc::Rc, rc::Rc,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
use wayland_commons::utils::UserDataMap;
use wayland_protocols::{ use wayland_protocols::{
unstable::xdg_shell::v6::server::{zxdg_popup_v6, zxdg_shell_v6, zxdg_surface_v6, zxdg_toplevel_v6}, unstable::xdg_shell::v6::server::{zxdg_popup_v6, zxdg_shell_v6, zxdg_surface_v6, zxdg_toplevel_v6},
xdg_shell::server::{xdg_popup, xdg_positioner, xdg_surface, xdg_toplevel, xdg_wm_base}, xdg_shell::server::{xdg_popup, xdg_positioner, xdg_surface, xdg_toplevel, xdg_wm_base},
@ -258,14 +259,14 @@ impl Default for XdgSurfacePendingState {
} }
} }
pub(crate) struct ShellData<R, SD> { pub(crate) struct ShellData<R> {
log: ::slog::Logger, log: ::slog::Logger,
compositor_token: CompositorToken<R>, compositor_token: CompositorToken<R>,
user_impl: Rc<RefCell<dyn FnMut(XdgRequest<R, SD>)>>, user_impl: Rc<RefCell<dyn FnMut(XdgRequest<R>)>>,
shell_state: Arc<Mutex<ShellState<R, SD>>>, shell_state: Arc<Mutex<ShellState<R>>>,
} }
impl<R, SD> Clone for ShellData<R, SD> { impl<R> Clone for ShellData<R> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
ShellData { ShellData {
log: self.log.clone(), log: self.log.clone(),
@ -277,21 +278,20 @@ impl<R, SD> Clone for ShellData<R, SD> {
} }
/// Create a new `xdg_shell` globals /// Create a new `xdg_shell` globals
pub fn xdg_shell_init<R, SD, L, Impl>( pub fn xdg_shell_init<R, L, Impl>(
display: &mut Display, display: &mut Display,
ctoken: CompositorToken<R>, ctoken: CompositorToken<R>,
implementation: Impl, implementation: Impl,
logger: L, logger: L,
) -> ( ) -> (
Arc<Mutex<ShellState<R, SD>>>, Arc<Mutex<ShellState<R>>>,
Global<xdg_wm_base::XdgWmBase>, Global<xdg_wm_base::XdgWmBase>,
Global<zxdg_shell_v6::ZxdgShellV6>, Global<zxdg_shell_v6::ZxdgShellV6>,
) )
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: Default + 'static,
L: Into<Option<::slog::Logger>>, L: Into<Option<::slog::Logger>>,
Impl: FnMut(XdgRequest<R, SD>) + 'static, Impl: FnMut(XdgRequest<R>) + 'static,
{ {
let log = crate::slog_or_stdlog(logger); let log = crate::slog_or_stdlog(logger);
let shell_state = Arc::new(Mutex::new(ShellState { let shell_state = Arc::new(Mutex::new(ShellState {
@ -323,23 +323,22 @@ where
/// ///
/// This state allows you to retrieve a list of surfaces /// This state allows you to retrieve a list of surfaces
/// currently known to the shell global. /// currently known to the shell global.
pub struct ShellState<R, SD> { pub struct ShellState<R> {
known_toplevels: Vec<ToplevelSurface<R, SD>>, known_toplevels: Vec<ToplevelSurface<R>>,
known_popups: Vec<PopupSurface<R, SD>>, known_popups: Vec<PopupSurface<R>>,
} }
impl<R, SD> ShellState<R, SD> impl<R> ShellState<R>
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
/// Access all the shell surfaces known by this handler /// Access all the shell surfaces known by this handler
pub fn toplevel_surfaces(&self) -> &[ToplevelSurface<R, SD>] { pub fn toplevel_surfaces(&self) -> &[ToplevelSurface<R>] {
&self.known_toplevels[..] &self.known_toplevels[..]
} }
/// Access all the popup surfaces known by this handler /// Access all the popup surfaces known by this handler
pub fn popup_surfaces(&self) -> &[PopupSurface<R, SD>] { pub fn popup_surfaces(&self) -> &[PopupSurface<R>] {
&self.known_popups[..] &self.known_popups[..]
} }
} }
@ -353,15 +352,15 @@ enum ShellClientKind {
ZxdgV6(zxdg_shell_v6::ZxdgShellV6), ZxdgV6(zxdg_shell_v6::ZxdgShellV6),
} }
pub(crate) struct ShellClientData<SD> { pub(crate) struct ShellClientData {
pending_ping: u32, pending_ping: u32,
data: SD, data: UserDataMap,
} }
fn make_shell_client_data<SD: Default>() -> ShellClientData<SD> { fn make_shell_client_data() -> ShellClientData {
ShellClientData { ShellClientData {
pending_ping: 0, pending_ping: 0,
data: Default::default(), data: UserDataMap::new(),
} }
} }
@ -375,16 +374,14 @@ fn make_shell_client_data<SD: Default>() -> ShellClientData<SD> {
/// ///
/// You can use this handle to access a storage for any /// You can use this handle to access a storage for any
/// client-specific data you wish to associate with it. /// client-specific data you wish to associate with it.
pub struct ShellClient<R, SD> { pub struct ShellClient<R> {
kind: ShellClientKind, kind: ShellClientKind,
_token: CompositorToken<R>, _token: CompositorToken<R>,
_data: ::std::marker::PhantomData<*mut SD>,
} }
impl<R, SD> ShellClient<R, SD> impl<R> ShellClient<R>
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
/// Is the shell client represented by this handle still connected? /// Is the shell client represented by this handle still connected?
pub fn alive(&self) -> bool { pub fn alive(&self) -> bool {
@ -423,7 +420,7 @@ where
ShellClientKind::Xdg(ref shell) => { ShellClientKind::Xdg(ref shell) => {
let user_data = shell let user_data = shell
.as_ref() .as_ref()
.user_data::<self::xdg_handlers::ShellUserData<R, SD>>() .user_data::<self::xdg_handlers::ShellUserData<R>>()
.unwrap(); .unwrap();
let mut guard = user_data.client_data.lock().unwrap(); let mut guard = user_data.client_data.lock().unwrap();
if guard.pending_ping == 0 { if guard.pending_ping == 0 {
@ -435,7 +432,7 @@ where
ShellClientKind::ZxdgV6(ref shell) => { ShellClientKind::ZxdgV6(ref shell) => {
let user_data = shell let user_data = shell
.as_ref() .as_ref()
.user_data::<self::zxdgv6_handlers::ShellUserData<R, SD>>() .user_data::<self::zxdgv6_handlers::ShellUserData<R>>()
.unwrap(); .unwrap();
let mut guard = user_data.client_data.lock().unwrap(); let mut guard = user_data.client_data.lock().unwrap();
if guard.pending_ping == 0 { if guard.pending_ping == 0 {
@ -451,7 +448,7 @@ where
/// Access the user data associated with this shell client /// Access the user data associated with this shell client
pub fn with_data<F, T>(&self, f: F) -> Result<T, ()> pub fn with_data<F, T>(&self, f: F) -> Result<T, ()>
where where
F: FnOnce(&mut SD) -> T, F: FnOnce(&mut UserDataMap) -> T,
{ {
if !self.alive() { if !self.alive() {
return Err(()); return Err(());
@ -460,7 +457,7 @@ where
ShellClientKind::Xdg(ref shell) => { ShellClientKind::Xdg(ref shell) => {
let data = shell let data = shell
.as_ref() .as_ref()
.user_data::<self::xdg_handlers::ShellUserData<R, SD>>() .user_data::<self::xdg_handlers::ShellUserData<R>>()
.unwrap(); .unwrap();
let mut guard = data.client_data.lock().unwrap(); let mut guard = data.client_data.lock().unwrap();
Ok(f(&mut guard.data)) Ok(f(&mut guard.data))
@ -468,7 +465,7 @@ where
ShellClientKind::ZxdgV6(ref shell) => { ShellClientKind::ZxdgV6(ref shell) => {
let data = shell let data = shell
.as_ref() .as_ref()
.user_data::<self::zxdgv6_handlers::ShellUserData<R, SD>>() .user_data::<self::zxdgv6_handlers::ShellUserData<R>>()
.unwrap(); .unwrap();
let mut guard = data.client_data.lock().unwrap(); let mut guard = data.client_data.lock().unwrap();
Ok(f(&mut guard.data)) Ok(f(&mut guard.data))
@ -483,17 +480,15 @@ pub(crate) enum ToplevelKind {
} }
/// A handle to a toplevel surface /// A handle to a toplevel surface
pub struct ToplevelSurface<R, SD> { pub struct ToplevelSurface<R> {
wl_surface: wl_surface::WlSurface, wl_surface: wl_surface::WlSurface,
shell_surface: ToplevelKind, shell_surface: ToplevelKind,
token: CompositorToken<R>, token: CompositorToken<R>,
_shell_data: ::std::marker::PhantomData<SD>,
} }
impl<R, SD> ToplevelSurface<R, SD> impl<R> ToplevelSurface<R>
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
/// Is the toplevel surface referred by this handle still alive? /// Is the toplevel surface referred by this handle still alive?
pub fn alive(&self) -> bool { pub fn alive(&self) -> bool {
@ -512,7 +507,7 @@ where
/// Retrieve the shell client owning this toplevel surface /// Retrieve the shell client owning this toplevel surface
/// ///
/// Returns `None` if the surface does actually no longer exist. /// Returns `None` if the surface does actually no longer exist.
pub fn client(&self) -> Option<ShellClient<R, SD>> { pub fn client(&self) -> Option<ShellClient<R>> {
if !self.alive() { if !self.alive() {
return None; return None;
} }
@ -521,14 +516,14 @@ where
ToplevelKind::Xdg(ref s) => { ToplevelKind::Xdg(ref s) => {
let data = s let data = s
.as_ref() .as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<R, SD>>() .user_data::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.unwrap(); .unwrap();
ShellClientKind::Xdg(data.wm_base.clone()) ShellClientKind::Xdg(data.wm_base.clone())
} }
ToplevelKind::ZxdgV6(ref s) => { ToplevelKind::ZxdgV6(ref s) => {
let data = s let data = s
.as_ref() .as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R, SD>>() .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.unwrap(); .unwrap();
ShellClientKind::ZxdgV6(data.shell.clone()) ShellClientKind::ZxdgV6(data.shell.clone())
} }
@ -537,7 +532,6 @@ where
Some(ShellClient { Some(ShellClient {
kind: shell, kind: shell,
_token: self.token, _token: self.token,
_data: ::std::marker::PhantomData,
}) })
} }
@ -549,8 +543,8 @@ where
return; return;
} }
match self.shell_surface { match self.shell_surface {
ToplevelKind::Xdg(ref s) => self::xdg_handlers::send_toplevel_configure::<R, SD>(s, cfg), ToplevelKind::Xdg(ref s) => self::xdg_handlers::send_toplevel_configure::<R>(s, cfg),
ToplevelKind::ZxdgV6(ref s) => self::zxdgv6_handlers::send_toplevel_configure::<R, SD>(s, cfg), ToplevelKind::ZxdgV6(ref s) => self::zxdgv6_handlers::send_toplevel_configure::<R>(s, cfg),
} }
} }
@ -575,7 +569,7 @@ where
ToplevelKind::Xdg(ref s) => { ToplevelKind::Xdg(ref s) => {
let data = s let data = s
.as_ref() .as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<R, SD>>() .user_data::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.unwrap(); .unwrap();
data.xdg_surface.as_ref().post_error( data.xdg_surface.as_ref().post_error(
xdg_surface::Error::NotConstructed as u32, xdg_surface::Error::NotConstructed as u32,
@ -585,7 +579,7 @@ where
ToplevelKind::ZxdgV6(ref s) => { ToplevelKind::ZxdgV6(ref s) => {
let data = s let data = s
.as_ref() .as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R, SD>>() .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.unwrap(); .unwrap();
data.xdg_surface.as_ref().post_error( data.xdg_surface.as_ref().post_error(
zxdg_surface_v6::Error::NotConstructed as u32, zxdg_surface_v6::Error::NotConstructed as u32,
@ -642,17 +636,15 @@ pub(crate) enum PopupKind {
/// ///
/// This is an unified abstraction over the popup surfaces /// This is an unified abstraction over the popup surfaces
/// of both `wl_shell` and `xdg_shell`. /// of both `wl_shell` and `xdg_shell`.
pub struct PopupSurface<R, SD> { pub struct PopupSurface<R> {
wl_surface: wl_surface::WlSurface, wl_surface: wl_surface::WlSurface,
shell_surface: PopupKind, shell_surface: PopupKind,
token: CompositorToken<R>, token: CompositorToken<R>,
_shell_data: ::std::marker::PhantomData<SD>,
} }
impl<R, SD> PopupSurface<R, SD> impl<R> PopupSurface<R>
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
/// Is the popup surface referred by this handle still alive? /// Is the popup surface referred by this handle still alive?
pub fn alive(&self) -> bool { pub fn alive(&self) -> bool {
@ -671,7 +663,7 @@ where
/// Retrieve the shell client owning this popup surface /// Retrieve the shell client owning this popup surface
/// ///
/// Returns `None` if the surface does actually no longer exist. /// Returns `None` if the surface does actually no longer exist.
pub fn client(&self) -> Option<ShellClient<R, SD>> { pub fn client(&self) -> Option<ShellClient<R>> {
if !self.alive() { if !self.alive() {
return None; return None;
} }
@ -680,14 +672,14 @@ where
PopupKind::Xdg(ref p) => { PopupKind::Xdg(ref p) => {
let data = p let data = p
.as_ref() .as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<R, SD>>() .user_data::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.unwrap(); .unwrap();
ShellClientKind::Xdg(data.wm_base.clone()) ShellClientKind::Xdg(data.wm_base.clone())
} }
PopupKind::ZxdgV6(ref p) => { PopupKind::ZxdgV6(ref p) => {
let data = p let data = p
.as_ref() .as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R, SD>>() .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.unwrap(); .unwrap();
ShellClientKind::ZxdgV6(data.shell.clone()) ShellClientKind::ZxdgV6(data.shell.clone())
} }
@ -696,7 +688,6 @@ where
Some(ShellClient { Some(ShellClient {
kind: shell, kind: shell,
_token: self.token, _token: self.token,
_data: ::std::marker::PhantomData,
}) })
} }
@ -709,10 +700,10 @@ where
} }
match self.shell_surface { match self.shell_surface {
PopupKind::Xdg(ref p) => { PopupKind::Xdg(ref p) => {
self::xdg_handlers::send_popup_configure::<R, SD>(p, cfg); self::xdg_handlers::send_popup_configure::<R>(p, cfg);
} }
PopupKind::ZxdgV6(ref p) => { PopupKind::ZxdgV6(ref p) => {
self::zxdgv6_handlers::send_popup_configure::<R, SD>(p, cfg); self::zxdgv6_handlers::send_popup_configure::<R>(p, cfg);
} }
} }
} }
@ -738,7 +729,7 @@ where
PopupKind::Xdg(ref s) => { PopupKind::Xdg(ref s) => {
let data = s let data = s
.as_ref() .as_ref()
.user_data::<self::xdg_handlers::ShellSurfaceUserData<R, SD>>() .user_data::<self::xdg_handlers::ShellSurfaceUserData<R>>()
.unwrap(); .unwrap();
data.xdg_surface.as_ref().post_error( data.xdg_surface.as_ref().post_error(
xdg_surface::Error::NotConstructed as u32, xdg_surface::Error::NotConstructed as u32,
@ -748,7 +739,7 @@ where
PopupKind::ZxdgV6(ref s) => { PopupKind::ZxdgV6(ref s) => {
let data = s let data = s
.as_ref() .as_ref()
.user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R, SD>>() .user_data::<self::zxdgv6_handlers::ShellSurfaceUserData<R>>()
.unwrap(); .unwrap();
data.xdg_surface.as_ref().post_error( data.xdg_surface.as_ref().post_error(
zxdg_surface_v6::Error::NotConstructed as u32, zxdg_surface_v6::Error::NotConstructed as u32,
@ -837,11 +828,11 @@ pub struct PopupConfigure {
/// for you directly. /// for you directly.
/// ///
/// Depending on what you want to do, you might ignore some of them /// Depending on what you want to do, you might ignore some of them
pub enum XdgRequest<R, SD> { pub enum XdgRequest<R> {
/// A new shell client was instantiated /// A new shell client was instantiated
NewClient { NewClient {
/// the client /// the client
client: ShellClient<R, SD>, client: ShellClient<R>,
}, },
/// The pong for a pending ping of this shell client was received /// The pong for a pending ping of this shell client was received
/// ///
@ -849,7 +840,7 @@ pub enum XdgRequest<R, SD> {
/// from the pending ping. /// from the pending ping.
ClientPong { ClientPong {
/// the client /// the client
client: ShellClient<R, SD>, client: ShellClient<R>,
}, },
/// A new toplevel surface was created /// A new toplevel surface was created
/// ///
@ -857,7 +848,7 @@ pub enum XdgRequest<R, SD> {
/// client as to how its window should be /// client as to how its window should be
NewToplevel { NewToplevel {
/// the surface /// the surface
surface: ToplevelSurface<R, SD>, surface: ToplevelSurface<R>,
}, },
/// A new popup surface was created /// A new popup surface was created
/// ///
@ -865,12 +856,12 @@ pub enum XdgRequest<R, SD> {
/// client as to how its popup should be /// client as to how its popup should be
NewPopup { NewPopup {
/// the surface /// the surface
surface: PopupSurface<R, SD>, surface: PopupSurface<R>,
}, },
/// The client requested the start of an interactive move for this surface /// The client requested the start of an interactive move for this surface
Move { Move {
/// the surface /// the surface
surface: ToplevelSurface<R, SD>, surface: ToplevelSurface<R>,
/// the seat associated to this move /// the seat associated to this move
seat: wl_seat::WlSeat, seat: wl_seat::WlSeat,
/// the grab serial /// the grab serial
@ -879,7 +870,7 @@ pub enum XdgRequest<R, SD> {
/// The client requested the start of an interactive resize for this surface /// The client requested the start of an interactive resize for this surface
Resize { Resize {
/// The surface /// The surface
surface: ToplevelSurface<R, SD>, surface: ToplevelSurface<R>,
/// The seat associated with this resize /// The seat associated with this resize
seat: wl_seat::WlSeat, seat: wl_seat::WlSeat,
/// The grab serial /// The grab serial
@ -893,7 +884,7 @@ pub enum XdgRequest<R, SD> {
/// the grab area. /// the grab area.
Grab { Grab {
/// The surface /// The surface
surface: PopupSurface<R, SD>, surface: PopupSurface<R>,
/// The seat to grab /// The seat to grab
seat: wl_seat::WlSeat, seat: wl_seat::WlSeat,
/// The grab serial /// The grab serial
@ -902,29 +893,29 @@ pub enum XdgRequest<R, SD> {
/// A toplevel surface requested to be maximized /// A toplevel surface requested to be maximized
Maximize { Maximize {
/// The surface /// The surface
surface: ToplevelSurface<R, SD>, surface: ToplevelSurface<R>,
}, },
/// A toplevel surface requested to stop being maximized /// A toplevel surface requested to stop being maximized
UnMaximize { UnMaximize {
/// The surface /// The surface
surface: ToplevelSurface<R, SD>, surface: ToplevelSurface<R>,
}, },
/// A toplevel surface requested to be set fullscreen /// A toplevel surface requested to be set fullscreen
Fullscreen { Fullscreen {
/// The surface /// The surface
surface: ToplevelSurface<R, SD>, surface: ToplevelSurface<R>,
/// The output (if any) on which the fullscreen is requested /// The output (if any) on which the fullscreen is requested
output: Option<wl_output::WlOutput>, output: Option<wl_output::WlOutput>,
}, },
/// A toplevel surface request to stop being fullscreen /// A toplevel surface request to stop being fullscreen
UnFullscreen { UnFullscreen {
/// The surface /// The surface
surface: ToplevelSurface<R, SD>, surface: ToplevelSurface<R>,
}, },
/// A toplevel surface requested to be minimized /// A toplevel surface requested to be minimized
Minimize { Minimize {
/// The surface /// The surface
surface: ToplevelSurface<R, SD>, surface: ToplevelSurface<R>,
}, },
/// The client requests the window menu to be displayed on this surface at this location /// The client requests the window menu to be displayed on this surface at this location
/// ///
@ -932,7 +923,7 @@ pub enum XdgRequest<R, SD> {
/// control of the window (maximize/minimize/close/move/etc...). /// control of the window (maximize/minimize/close/move/etc...).
ShowWindowMenu { ShowWindowMenu {
/// The surface /// The surface
surface: ToplevelSurface<R, SD>, surface: ToplevelSurface<R>,
/// The seat associated with this input grab /// The seat associated with this input grab
seat: wl_seat::WlSeat, seat: wl_seat::WlSeat,
/// the grab serial /// the grab serial

View File

@ -14,20 +14,19 @@ use super::{
XdgSurfacePendingState, XdgSurfaceRole, XdgSurfacePendingState, XdgSurfaceRole,
}; };
pub(crate) fn implement_wm_base<R, SD>( pub(crate) fn implement_wm_base<R>(
shell: NewResource<xdg_wm_base::XdgWmBase>, shell: NewResource<xdg_wm_base::XdgWmBase>,
shell_data: &ShellData<R, SD>, shell_data: &ShellData<R>,
) -> xdg_wm_base::XdgWmBase ) -> xdg_wm_base::XdgWmBase
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: Default + 'static,
{ {
let shell = shell.implement_closure( let shell = shell.implement_closure(
wm_implementation::<R, SD>, wm_implementation::<R>,
None::<fn(_)>, None::<fn(_)>,
ShellUserData { ShellUserData {
shell_data: shell_data.clone(), shell_data: shell_data.clone(),
client_data: Mutex::new(make_shell_client_data::<SD>()), client_data: Mutex::new(make_shell_client_data()),
}, },
); );
let mut user_impl = shell_data.user_impl.borrow_mut(); let mut user_impl = shell_data.user_impl.borrow_mut();
@ -41,28 +40,26 @@ where
* xdg_shell * xdg_shell
*/ */
pub(crate) struct ShellUserData<R, SD> { pub(crate) struct ShellUserData<R> {
shell_data: ShellData<R, SD>, shell_data: ShellData<R>,
pub(crate) client_data: Mutex<ShellClientData<SD>>, pub(crate) client_data: Mutex<ShellClientData>,
} }
pub(crate) fn make_shell_client<R, SD>( pub(crate) fn make_shell_client<R>(
resource: &xdg_wm_base::XdgWmBase, resource: &xdg_wm_base::XdgWmBase,
token: CompositorToken<R>, token: CompositorToken<R>,
) -> ShellClient<R, SD> { ) -> ShellClient<R> {
ShellClient { ShellClient {
kind: super::ShellClientKind::Xdg(resource.clone()), kind: super::ShellClientKind::Xdg(resource.clone()),
_token: token, _token: token,
_data: ::std::marker::PhantomData,
} }
} }
fn wm_implementation<R, SD>(request: xdg_wm_base::Request, shell: xdg_wm_base::XdgWmBase) fn wm_implementation<R>(request: xdg_wm_base::Request, shell: xdg_wm_base::XdgWmBase)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = shell.as_ref().user_data::<ShellUserData<R, SD>>().unwrap(); let data = shell.as_ref().user_data::<ShellUserData<R>>().unwrap();
match request { match request {
xdg_wm_base::Request::Destroy => { xdg_wm_base::Request::Destroy => {
// all is handled by destructor // all is handled by destructor
@ -90,8 +87,8 @@ where
return; return;
} }
id.implement_closure( id.implement_closure(
xdg_surface_implementation::<R, SD>, xdg_surface_implementation::<R>,
Some(destroy_surface::<R, SD>), Some(destroy_surface::<R>),
XdgSurfaceUserData { XdgSurfaceUserData {
shell_data: data.shell_data.clone(), shell_data: data.shell_data.clone(),
wl_surface: surface, wl_surface: surface,
@ -186,18 +183,17 @@ fn implement_positioner(
* xdg_surface * xdg_surface
*/ */
struct XdgSurfaceUserData<R, SD> { struct XdgSurfaceUserData<R> {
shell_data: ShellData<R, SD>, shell_data: ShellData<R>,
wl_surface: wl_surface::WlSurface, wl_surface: wl_surface::WlSurface,
wm_base: xdg_wm_base::XdgWmBase, wm_base: xdg_wm_base::XdgWmBase,
} }
fn destroy_surface<R, SD>(surface: xdg_surface::XdgSurface) fn destroy_surface<R>(surface: xdg_surface::XdgSurface)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = surface.as_ref().user_data::<XdgSurfaceUserData<R, SD>>().unwrap(); let data = surface.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
if !data.wl_surface.as_ref().is_alive() { if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
@ -219,15 +215,11 @@ where
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
} }
fn xdg_surface_implementation<R, SD>(request: xdg_surface::Request, xdg_surface: xdg_surface::XdgSurface) fn xdg_surface_implementation<R>(request: xdg_surface::Request, xdg_surface: xdg_surface::XdgSurface)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = xdg_surface let data = xdg_surface.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<XdgSurfaceUserData<R, SD>>()
.unwrap();
match request { match request {
xdg_surface::Request::Destroy => { xdg_surface::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
@ -246,8 +238,8 @@ where
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
let toplevel = id.implement_closure( let toplevel = id.implement_closure(
toplevel_implementation::<R, SD>, toplevel_implementation::<R>,
Some(destroy_toplevel::<R, SD>), Some(destroy_toplevel::<R>),
ShellSurfaceUserData { ShellSurfaceUserData {
shell_data: data.shell_data.clone(), shell_data: data.shell_data.clone(),
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
@ -278,7 +270,7 @@ where
.unwrap(); .unwrap();
let parent_surface = parent.map(|parent| { let parent_surface = parent.map(|parent| {
let parent_data = parent.as_ref().user_data::<XdgSurfaceUserData<R, SD>>().unwrap(); let parent_data = parent.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
parent_data.wl_surface.clone() parent_data.wl_surface.clone()
}); });
data.shell_data data.shell_data
@ -291,8 +283,8 @@ where
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
let popup = id.implement_closure( let popup = id.implement_closure(
xg_popup_implementation::<R, SD>, xg_popup_implementation::<R>,
Some(destroy_popup::<R, SD>), Some(destroy_popup::<R>),
ShellSurfaceUserData { ShellSurfaceUserData {
shell_data: data.shell_data.clone(), shell_data: data.shell_data.clone(),
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
@ -350,27 +342,20 @@ where
* xdg_toplevel * xdg_toplevel
*/ */
pub(crate) struct ShellSurfaceUserData<R, SD> { pub(crate) struct ShellSurfaceUserData<R> {
pub(crate) shell_data: ShellData<R, SD>, pub(crate) shell_data: ShellData<R>,
pub(crate) wl_surface: wl_surface::WlSurface, pub(crate) wl_surface: wl_surface::WlSurface,
pub(crate) wm_base: xdg_wm_base::XdgWmBase, pub(crate) wm_base: xdg_wm_base::XdgWmBase,
pub(crate) xdg_surface: xdg_surface::XdgSurface, pub(crate) xdg_surface: xdg_surface::XdgSurface,
} }
// Utility functions allowing to factor out a lot of the upcoming logic // Utility functions allowing to factor out a lot of the upcoming logic
fn with_surface_toplevel_data<R, SD, F>( fn with_surface_toplevel_data<R, F>(shell_data: &ShellData<R>, toplevel: &xdg_toplevel::XdgToplevel, f: F)
shell_data: &ShellData<R, SD>, where
toplevel: &xdg_toplevel::XdgToplevel,
f: F,
) where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
F: FnOnce(&mut ToplevelState), F: FnOnce(&mut ToplevelState),
{ {
let toplevel_data = toplevel let toplevel_data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
shell_data shell_data
.compositor_token .compositor_token
.with_role_data::<XdgSurfaceRole, _, _>(&toplevel_data.wl_surface, |data| match data.pending_state { .with_role_data::<XdgSurfaceRole, _, _>(&toplevel_data.wl_surface, |data| match data.pending_state {
@ -380,15 +365,11 @@ fn with_surface_toplevel_data<R, SD, F>(
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
pub fn send_toplevel_configure<R, SD>(resource: &xdg_toplevel::XdgToplevel, configure: ToplevelConfigure) pub fn send_toplevel_configure<R>(resource: &xdg_toplevel::XdgToplevel, configure: ToplevelConfigure)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = resource let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
let (width, height) = configure.size.unwrap_or((0, 0)); let (width, height) = configure.size.unwrap_or((0, 0));
// convert the Vec<State> (which is really a Vec<u32>) into Vec<u8> // convert the Vec<State> (which is really a Vec<u32>) into Vec<u8>
let states = { let states = {
@ -409,30 +390,20 @@ where
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
fn make_toplevel_handle<R: 'static, SD: 'static>( fn make_toplevel_handle<R: 'static>(resource: &xdg_toplevel::XdgToplevel) -> super::ToplevelSurface<R> {
resource: &xdg_toplevel::XdgToplevel, let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
) -> super::ToplevelSurface<R, SD> {
let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
super::ToplevelSurface { super::ToplevelSurface {
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
shell_surface: ToplevelKind::Xdg(resource.clone()), shell_surface: ToplevelKind::Xdg(resource.clone()),
token: data.shell_data.compositor_token, token: data.shell_data.compositor_token,
_shell_data: ::std::marker::PhantomData,
} }
} }
fn toplevel_implementation<R, SD>(request: xdg_toplevel::Request, toplevel: xdg_toplevel::XdgToplevel) fn toplevel_implementation<R>(request: xdg_toplevel::Request, toplevel: xdg_toplevel::XdgToplevel)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = toplevel let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
match request { match request {
xdg_toplevel::Request::Destroy => { xdg_toplevel::Request::Destroy => {
// all it done by the destructor // all it done by the destructor
@ -442,7 +413,7 @@ where
toplevel_data.parent = parent.map(|toplevel_surface_parent| { toplevel_data.parent = parent.map(|toplevel_surface_parent| {
toplevel_surface_parent toplevel_surface_parent
.as_ref() .as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>() .user_data::<ShellSurfaceUserData<R>>()
.unwrap() .unwrap()
.wl_surface .wl_surface
.clone() .clone()
@ -531,15 +502,11 @@ where
} }
} }
fn destroy_toplevel<R, SD>(toplevel: xdg_toplevel::XdgToplevel) fn destroy_toplevel<R>(toplevel: xdg_toplevel::XdgToplevel)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = toplevel let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
if !data.wl_surface.as_ref().is_alive() { if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
@ -566,15 +533,11 @@ where
* xdg_popup * xdg_popup
*/ */
pub(crate) fn send_popup_configure<R, SD>(resource: &xdg_popup::XdgPopup, configure: PopupConfigure) pub(crate) fn send_popup_configure<R>(resource: &xdg_popup::XdgPopup, configure: PopupConfigure)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = resource let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
let (x, y) = configure.position; let (x, y) = configure.position;
let (width, height) = configure.size; let (width, height) = configure.size;
let serial = configure.serial; let serial = configure.serial;
@ -587,25 +550,20 @@ where
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
fn make_popup_handle<R: 'static, SD: 'static>(resource: &xdg_popup::XdgPopup) -> super::PopupSurface<R, SD> { fn make_popup_handle<R: 'static>(resource: &xdg_popup::XdgPopup) -> super::PopupSurface<R> {
let data = resource let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
super::PopupSurface { super::PopupSurface {
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
shell_surface: PopupKind::Xdg(resource.clone()), shell_surface: PopupKind::Xdg(resource.clone()),
token: data.shell_data.compositor_token, token: data.shell_data.compositor_token,
_shell_data: ::std::marker::PhantomData,
} }
} }
fn xg_popup_implementation<R, SD>(request: xdg_popup::Request, popup: xdg_popup::XdgPopup) fn xg_popup_implementation<R>(request: xdg_popup::Request, popup: xdg_popup::XdgPopup)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = popup.as_ref().user_data::<ShellSurfaceUserData<R, SD>>().unwrap(); let data = popup.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
match request { match request {
xdg_popup::Request::Destroy => { xdg_popup::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
@ -623,12 +581,11 @@ where
} }
} }
fn destroy_popup<R, SD>(popup: xdg_popup::XdgPopup) fn destroy_popup<R>(popup: xdg_popup::XdgPopup)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = popup.as_ref().user_data::<ShellSurfaceUserData<R, SD>>().unwrap(); let data = popup.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
if !data.wl_surface.as_ref().is_alive() { if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a

View File

@ -17,20 +17,19 @@ use super::{
XdgSurfacePendingState, XdgSurfaceRole, XdgSurfacePendingState, XdgSurfaceRole,
}; };
pub(crate) fn implement_shell<R, SD>( pub(crate) fn implement_shell<R>(
shell: NewResource<zxdg_shell_v6::ZxdgShellV6>, shell: NewResource<zxdg_shell_v6::ZxdgShellV6>,
shell_data: &ShellData<R, SD>, shell_data: &ShellData<R>,
) -> zxdg_shell_v6::ZxdgShellV6 ) -> zxdg_shell_v6::ZxdgShellV6
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: Default + 'static,
{ {
let shell = shell.implement_closure( let shell = shell.implement_closure(
shell_implementation::<R, SD>, shell_implementation::<R>,
None::<fn(_)>, None::<fn(_)>,
ShellUserData { ShellUserData {
shell_data: shell_data.clone(), shell_data: shell_data.clone(),
client_data: Mutex::new(make_shell_client_data::<SD>()), client_data: Mutex::new(make_shell_client_data()),
}, },
); );
let mut user_impl = shell_data.user_impl.borrow_mut(); let mut user_impl = shell_data.user_impl.borrow_mut();
@ -44,28 +43,26 @@ where
* xdg_shell * xdg_shell
*/ */
pub(crate) struct ShellUserData<R, SD> { pub(crate) struct ShellUserData<R> {
shell_data: ShellData<R, SD>, shell_data: ShellData<R>,
pub(crate) client_data: Mutex<ShellClientData<SD>>, pub(crate) client_data: Mutex<ShellClientData>,
} }
pub(crate) fn make_shell_client<R, SD>( pub(crate) fn make_shell_client<R>(
resource: &zxdg_shell_v6::ZxdgShellV6, resource: &zxdg_shell_v6::ZxdgShellV6,
token: CompositorToken<R>, token: CompositorToken<R>,
) -> ShellClient<R, SD> { ) -> ShellClient<R> {
ShellClient { ShellClient {
kind: super::ShellClientKind::ZxdgV6(resource.clone()), kind: super::ShellClientKind::ZxdgV6(resource.clone()),
_token: token, _token: token,
_data: ::std::marker::PhantomData,
} }
} }
fn shell_implementation<R, SD>(request: zxdg_shell_v6::Request, shell: zxdg_shell_v6::ZxdgShellV6) fn shell_implementation<R>(request: zxdg_shell_v6::Request, shell: zxdg_shell_v6::ZxdgShellV6)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = shell.as_ref().user_data::<ShellUserData<R, SD>>().unwrap(); let data = shell.as_ref().user_data::<ShellUserData<R>>().unwrap();
match request { match request {
zxdg_shell_v6::Request::Destroy => { zxdg_shell_v6::Request::Destroy => {
// all is handled by destructor // all is handled by destructor
@ -93,8 +90,8 @@ where
return; return;
} }
id.implement_closure( id.implement_closure(
xdg_surface_implementation::<R, SD>, xdg_surface_implementation::<R>,
Some(destroy_surface::<R, SD>), Some(destroy_surface::<R>),
XdgSurfaceUserData { XdgSurfaceUserData {
shell_data: data.shell_data.clone(), shell_data: data.shell_data.clone(),
wl_surface: surface.clone(), wl_surface: surface.clone(),
@ -203,18 +200,17 @@ fn implement_positioner(
* xdg_surface * xdg_surface
*/ */
struct XdgSurfaceUserData<R, SD> { struct XdgSurfaceUserData<R> {
shell_data: ShellData<R, SD>, shell_data: ShellData<R>,
wl_surface: wl_surface::WlSurface, wl_surface: wl_surface::WlSurface,
shell: zxdg_shell_v6::ZxdgShellV6, shell: zxdg_shell_v6::ZxdgShellV6,
} }
fn destroy_surface<R, SD>(surface: zxdg_surface_v6::ZxdgSurfaceV6) fn destroy_surface<R>(surface: zxdg_surface_v6::ZxdgSurfaceV6)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = surface.as_ref().user_data::<XdgSurfaceUserData<R, SD>>().unwrap(); let data = surface.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
if !data.wl_surface.as_ref().is_alive() { if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
@ -236,17 +232,13 @@ where
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
} }
fn xdg_surface_implementation<R, SD>( fn xdg_surface_implementation<R>(
request: zxdg_surface_v6::Request, request: zxdg_surface_v6::Request,
xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6, xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6,
) where ) where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = xdg_surface let data = xdg_surface.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<XdgSurfaceUserData<R, SD>>()
.unwrap();
match request { match request {
zxdg_surface_v6::Request::Destroy => { zxdg_surface_v6::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
@ -265,8 +257,8 @@ fn xdg_surface_implementation<R, SD>(
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
let toplevel = id.implement_closure( let toplevel = id.implement_closure(
toplevel_implementation::<R, SD>, toplevel_implementation::<R>,
Some(destroy_toplevel::<R, SD>), Some(destroy_toplevel::<R>),
ShellSurfaceUserData { ShellSurfaceUserData {
shell_data: data.shell_data.clone(), shell_data: data.shell_data.clone(),
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
@ -296,7 +288,7 @@ fn xdg_surface_implementation<R, SD>(
.user_data::<RefCell<PositionerState>>() .user_data::<RefCell<PositionerState>>()
.unwrap(); .unwrap();
let parent_data = parent.as_ref().user_data::<XdgSurfaceUserData<R, SD>>().unwrap(); let parent_data = parent.as_ref().user_data::<XdgSurfaceUserData<R>>().unwrap();
data.shell_data data.shell_data
.compositor_token .compositor_token
.with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| { .with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| {
@ -307,8 +299,8 @@ fn xdg_surface_implementation<R, SD>(
}) })
.expect("xdg_surface exists but surface has not shell_surface role?!"); .expect("xdg_surface exists but surface has not shell_surface role?!");
let popup = id.implement_closure( let popup = id.implement_closure(
popup_implementation::<R, SD>, popup_implementation::<R>,
Some(destroy_popup::<R, SD>), Some(destroy_popup::<R>),
ShellSurfaceUserData { ShellSurfaceUserData {
shell_data: data.shell_data.clone(), shell_data: data.shell_data.clone(),
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
@ -366,24 +358,20 @@ fn xdg_surface_implementation<R, SD>(
* xdg_toplevel * xdg_toplevel
*/ */
pub struct ShellSurfaceUserData<R, SD> { pub struct ShellSurfaceUserData<R> {
pub(crate) shell_data: ShellData<R, SD>, pub(crate) shell_data: ShellData<R>,
pub(crate) wl_surface: wl_surface::WlSurface, pub(crate) wl_surface: wl_surface::WlSurface,
pub(crate) shell: zxdg_shell_v6::ZxdgShellV6, pub(crate) shell: zxdg_shell_v6::ZxdgShellV6,
pub(crate) xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6, pub(crate) xdg_surface: zxdg_surface_v6::ZxdgSurfaceV6,
} }
// Utility functions allowing to factor out a lot of the upcoming logic // Utility functions allowing to factor out a lot of the upcoming logic
fn with_surface_toplevel_data<R, SD, F>(toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, f: F) fn with_surface_toplevel_data<R, F>(toplevel: &zxdg_toplevel_v6::ZxdgToplevelV6, f: F)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
F: FnOnce(&mut ToplevelState), F: FnOnce(&mut ToplevelState),
{ {
let data = toplevel let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
data.shell_data data.shell_data
.compositor_token .compositor_token
.with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| match data.pending_state { .with_role_data::<XdgSurfaceRole, _, _>(&data.wl_surface, |data| match data.pending_state {
@ -393,17 +381,11 @@ where
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
pub fn send_toplevel_configure<R, SD>( pub fn send_toplevel_configure<R>(resource: &zxdg_toplevel_v6::ZxdgToplevelV6, configure: ToplevelConfigure)
resource: &zxdg_toplevel_v6::ZxdgToplevelV6, where
configure: ToplevelConfigure,
) where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = resource let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
let (width, height) = configure.size.unwrap_or((0, 0)); let (width, height) = configure.size.unwrap_or((0, 0));
// convert the Vec<State> (which is really a Vec<u32>) into Vec<u8> // convert the Vec<State> (which is really a Vec<u32>) into Vec<u8>
let states = { let states = {
@ -424,54 +406,44 @@ pub fn send_toplevel_configure<R, SD>(
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
fn make_toplevel_handle<R: 'static, SD: 'static>( fn make_toplevel_handle<R: 'static>(
resource: &zxdg_toplevel_v6::ZxdgToplevelV6, resource: &zxdg_toplevel_v6::ZxdgToplevelV6,
) -> super::ToplevelSurface<R, SD> { ) -> super::ToplevelSurface<R> {
let data = resource let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
super::ToplevelSurface { super::ToplevelSurface {
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
shell_surface: ToplevelKind::ZxdgV6(resource.clone()), shell_surface: ToplevelKind::ZxdgV6(resource.clone()),
token: data.shell_data.compositor_token, token: data.shell_data.compositor_token,
_shell_data: ::std::marker::PhantomData,
} }
} }
fn toplevel_implementation<R, SD>( fn toplevel_implementation<R>(request: zxdg_toplevel_v6::Request, toplevel: zxdg_toplevel_v6::ZxdgToplevelV6)
request: zxdg_toplevel_v6::Request, where
toplevel: zxdg_toplevel_v6::ZxdgToplevelV6,
) where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = toplevel let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
match request { match request {
zxdg_toplevel_v6::Request::Destroy => { zxdg_toplevel_v6::Request::Destroy => {
// all it done by the destructor // all it done by the destructor
} }
zxdg_toplevel_v6::Request::SetParent { parent } => { zxdg_toplevel_v6::Request::SetParent { parent } => {
with_surface_toplevel_data::<R, SD, _>(&toplevel, |toplevel_data| { with_surface_toplevel_data::<R, _>(&toplevel, |toplevel_data| {
toplevel_data.parent = parent.map(|toplevel_surface_parent| { toplevel_data.parent = parent.map(|toplevel_surface_parent| {
let parent_data = toplevel_surface_parent let parent_data = toplevel_surface_parent
.as_ref() .as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>() .user_data::<ShellSurfaceUserData<R>>()
.unwrap(); .unwrap();
parent_data.wl_surface.clone() parent_data.wl_surface.clone()
}) })
}); });
} }
zxdg_toplevel_v6::Request::SetTitle { title } => { zxdg_toplevel_v6::Request::SetTitle { title } => {
with_surface_toplevel_data::<R, SD, _>(&toplevel, |toplevel_data| { with_surface_toplevel_data::<R, _>(&toplevel, |toplevel_data| {
toplevel_data.title = title; toplevel_data.title = title;
}); });
} }
zxdg_toplevel_v6::Request::SetAppId { app_id } => { zxdg_toplevel_v6::Request::SetAppId { app_id } => {
with_surface_toplevel_data::<R, SD, _>(&toplevel, |toplevel_data| { with_surface_toplevel_data::<R, _>(&toplevel, |toplevel_data| {
toplevel_data.app_id = app_id; toplevel_data.app_id = app_id;
}); });
} }
@ -507,12 +479,12 @@ fn toplevel_implementation<R, SD>(
}); });
} }
zxdg_toplevel_v6::Request::SetMaxSize { width, height } => { zxdg_toplevel_v6::Request::SetMaxSize { width, height } => {
with_surface_toplevel_data::<R, SD, _>(&toplevel, |toplevel_data| { with_surface_toplevel_data::<R, _>(&toplevel, |toplevel_data| {
toplevel_data.max_size = (width, height); toplevel_data.max_size = (width, height);
}); });
} }
zxdg_toplevel_v6::Request::SetMinSize { width, height } => { zxdg_toplevel_v6::Request::SetMinSize { width, height } => {
with_surface_toplevel_data::<R, SD, _>(&toplevel, |toplevel_data| { with_surface_toplevel_data::<R, _>(&toplevel, |toplevel_data| {
toplevel_data.max_size = (width, height); toplevel_data.max_size = (width, height);
}); });
} }
@ -548,15 +520,11 @@ fn toplevel_implementation<R, SD>(
} }
} }
fn destroy_toplevel<R, SD>(toplevel: zxdg_toplevel_v6::ZxdgToplevelV6) fn destroy_toplevel<R>(toplevel: zxdg_toplevel_v6::ZxdgToplevelV6)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = toplevel let data = toplevel.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
if !data.wl_surface.as_ref().is_alive() { if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a
@ -583,15 +551,11 @@ where
* xdg_popup * xdg_popup
*/ */
pub(crate) fn send_popup_configure<R, SD>(resource: &zxdg_popup_v6::ZxdgPopupV6, configure: PopupConfigure) pub(crate) fn send_popup_configure<R>(resource: &zxdg_popup_v6::ZxdgPopupV6, configure: PopupConfigure)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = resource let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
let (x, y) = configure.position; let (x, y) = configure.position;
let (width, height) = configure.size; let (width, height) = configure.size;
let serial = configure.serial; let serial = configure.serial;
@ -604,27 +568,20 @@ where
.expect("xdg_toplevel exists but surface has not shell_surface role?!"); .expect("xdg_toplevel exists but surface has not shell_surface role?!");
} }
fn make_popup_handle<R: 'static, SD: 'static>( fn make_popup_handle<R: 'static>(resource: &zxdg_popup_v6::ZxdgPopupV6) -> super::PopupSurface<R> {
resource: &zxdg_popup_v6::ZxdgPopupV6, let data = resource.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
) -> super::PopupSurface<R, SD> {
let data = resource
.as_ref()
.user_data::<ShellSurfaceUserData<R, SD>>()
.unwrap();
super::PopupSurface { super::PopupSurface {
wl_surface: data.wl_surface.clone(), wl_surface: data.wl_surface.clone(),
shell_surface: PopupKind::ZxdgV6(resource.clone()), shell_surface: PopupKind::ZxdgV6(resource.clone()),
token: data.shell_data.compositor_token, token: data.shell_data.compositor_token,
_shell_data: ::std::marker::PhantomData,
} }
} }
fn popup_implementation<R, SD>(request: zxdg_popup_v6::Request, popup: zxdg_popup_v6::ZxdgPopupV6) fn popup_implementation<R>(request: zxdg_popup_v6::Request, popup: zxdg_popup_v6::ZxdgPopupV6)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = popup.as_ref().user_data::<ShellSurfaceUserData<R, SD>>().unwrap(); let data = popup.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
match request { match request {
zxdg_popup_v6::Request::Destroy => { zxdg_popup_v6::Request::Destroy => {
// all is handled by our destructor // all is handled by our destructor
@ -642,12 +599,11 @@ where
} }
} }
fn destroy_popup<R, SD>(popup: zxdg_popup_v6::ZxdgPopupV6) fn destroy_popup<R>(popup: zxdg_popup_v6::ZxdgPopupV6)
where where
R: Role<XdgSurfaceRole> + 'static, R: Role<XdgSurfaceRole> + 'static,
SD: 'static,
{ {
let data = popup.as_ref().user_data::<ShellSurfaceUserData<R, SD>>().unwrap(); let data = popup.as_ref().user_data::<ShellSurfaceUserData<R>>().unwrap();
if !data.wl_surface.as_ref().is_alive() { if !data.wl_surface.as_ref().is_alive() {
// the wl_surface is destroyed, this means the client is not // the wl_surface is destroyed, this means the client is not
// trying to change the role but it's a cleanup (possibly a // trying to change the role but it's a cleanup (possibly a