1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
//! Traits and type related to wayland globals

use std::{future::Future, pin::Pin};

use runa_io::traits::WriteMessage;
use runa_wayland_protocols::wayland::{wl_display, wl_registry::v1 as wl_registry};

use crate::{
    client::traits::{
        Client, ClientParts, EventDispatcher, EventHandler, EventHandlerAction, StoreUpdate,
    },
    events::EventSource,
    objects::DISPLAY_ID,
    server::traits::{GlobalStore, GlobalsUpdate, Server},
};

/// A monomorphic global
///
/// i.e. a global with a concrete type. This is analogous to the
/// [`MonoObject`](crate::objects::MonoObject) trait for objects.
pub trait MonoGlobal: Sized {
    /// Type of the proxy object for this global.
    type Object;

    /// The interface name of this global.
    const INTERFACE: &'static str;
    /// The version number of this global.
    const VERSION: u32;
    /// A value that can be used to create an instance of `Self`. Or None if
    /// there is no compile time default value.
    const MAYBE_DEFAULT: Option<Self>;
    /// Create a new proxy object of this global.
    fn new_object() -> Self::Object;
}

/// Bind a global to a client
///
/// TODO: authorization support, i.e. some globals should only be accessible to
/// authorized clients.
pub trait Bind<Ctx> {
    /// Type of future returned by [`bind`](Self::bind).
    type BindFut<'a>: Future<Output = std::io::Result<()>> + 'a
    where
        Ctx: 'a,
        Self: 'a;

    /// Setup a proxy of this global, the proxy object has already been inserted
    /// into the client's object store, with the given object id.
    ///
    /// If Err() is returned, an protocol error will be sent to the client, and
    /// the client will be disconnected.
    fn bind<'a>(&'a self, client: &'a mut Ctx, object_id: u32) -> Self::BindFut<'a>;
}

/// A polymorphic global
///
/// This is analogous to the [`AnyObject`](crate::objects::AnyObject) trait for
/// objects, as well as the [`Any`](std::any::Any) trait.
///
/// Typically a polymorphic global type will be a enum of all the global types
/// used in the compositor. If you have such an enum, the
/// [`globals!`](crate::globals!) macro will generate this trait impl for you.
///
/// Unlike `AnyObject`, this trait doesn't have a `cast_mut` method because
/// globals are shared so it's not possible to get a unique reference to them.
pub trait AnyGlobal {
    /// Type of the proxy object for this global. Since this global is
    /// polymorphic, the type of the proxy object is also polymorphic. This
    /// should match the object type you have in you
    /// [`Client`](crate::client::traits::Client) trait implementation.
    type Object: crate::objects::AnyObject;

    /// Create a proxy of this global, called when the client tries to bound
    /// the global. The new proxy object will be incomplete until [`Bind::bind`]
    /// is called with that object.
    fn new_object(&self) -> Self::Object;

    /// The interface name of this global.
    fn interface(&self) -> &'static str;

    /// The version number of this global.
    fn version(&self) -> u32;

    /// Cast this polymorphic global to a more concrete type.
    fn cast<T: 'static>(&self) -> Option<&T>
    where
        Self: 'static + Sized;
}

/// Implementation of the `wl_display` global
#[derive(Debug, Clone, Copy, Default)]
pub struct Display;

impl MonoGlobal for Display {
    type Object = crate::objects::Display;

    const INTERFACE: &'static str = wl_display::v1::NAME;
    const MAYBE_DEFAULT: Option<Self> = Some(Self);
    const VERSION: u32 = wl_display::v1::VERSION;

    #[inline]
    fn new_object() -> Self::Object {
        crate::objects::Display { initialized: false }
    }
}

impl<Ctx: Client> Bind<Ctx> for Display {
    type BindFut<'a > = impl Future<Output = std::io::Result<()>> + 'a where Self: 'a, Ctx: 'a;

    fn bind<'a>(&'a self, client: &'a mut Ctx, object_id: u32) -> Self::BindFut<'a> {
        use crate::client::traits::Store;
        let ClientParts {
            objects,
            event_dispatcher,
            ..
        } = client.as_mut_parts();
        objects
            .get_mut::<<Self as MonoGlobal>::Object>(object_id)
            .unwrap()
            .initialized = true;

        struct DisplayEventHandler;
        impl<Ctx: Client> EventHandler<Ctx> for DisplayEventHandler {
            type Message = StoreUpdate;

            type Future<'ctx> = impl Future<
                    Output = Result<
                        EventHandlerAction,
                        Box<dyn std::error::Error + std::marker::Send + Sync + 'static>,
                    >,
                > + 'ctx;

            fn handle_event<'ctx>(
                &'ctx mut self,
                _objects: &'ctx mut <Ctx as Client>::ObjectStore,
                connection: &'ctx mut <Ctx as Client>::Connection,
                _server_context: &'ctx <Ctx as Client>::ServerContext,
                message: &'ctx mut Self::Message,
            ) -> Self::Future<'ctx> {
                async move {
                    use crate::client::traits::StoreUpdateKind::*;
                    if matches!(message.kind, Removed { .. } | Replaced { .. }) {
                        // Replaced can really only happen for server created objects, because
                        // we haven't sent the DeleteId event yet, so the client can't have
                        // reused that ID.
                        // For server create objects, it possible that the client destroyed
                        // that object and we immediately created another one with that ID,
                        // this should be the only case for us to get a Replaced event.
                        connection
                            .send(DISPLAY_ID, wl_display::v1::events::DeleteId {
                                id: message.object_id,
                            })
                            .await?;
                    }
                    Ok(EventHandlerAction::Keep)
                }
            }
        }
        event_dispatcher.add_event_handler(objects.subscribe(), DisplayEventHandler);
        futures_util::future::ok(())
    }
}

/// The registry singleton. This is an interface only object. The actual list of
/// globals is stored in the `Globals` implementation of the server context.
///
/// If you use this as your registry global implementation, you must also use
/// [`crate::objects::Registry`] as your client side registry proxy
/// implementation.
#[derive(Debug, Clone, Copy, Default)]
pub struct Registry;

impl MonoGlobal for Registry {
    type Object = crate::objects::Registry;

    const INTERFACE: &'static str = wl_registry::NAME;
    const MAYBE_DEFAULT: Option<Self> = Some(Self);
    const VERSION: u32 = wl_registry::VERSION;

    #[inline]
    fn new_object() -> Self::Object {
        crate::objects::Registry(None)
    }
}

impl<Ctx: Client> Bind<Ctx> for Registry {
    type BindFut<'a> = impl Future<Output = std::io::Result<()>> + 'a where Self: 'a, Ctx: 'a;

    fn bind<'a>(&'a self, client: &'a mut Ctx, object_id: u32) -> Self::BindFut<'a> {
        async move {
            let ClientParts {
                server_context,
                connection,
                event_dispatcher,
                ..
            } = client.as_mut_parts();
            let rx = server_context.globals().borrow().subscribe();
            // Send existing globals
            let globals: Vec<_> = server_context
                .globals()
                .borrow()
                .iter()
                .map(|(id, global)| (id, global.clone()))
                .collect();

            for (id, global) in globals {
                let interface = global.interface();
                let version = global.version();
                connection
                    .send(object_id, wl_registry::events::Global {
                        name: id,
                        interface: interface.as_bytes().into(),
                        version,
                    })
                    .await
                    .unwrap()
            }
            connection.flush().await.unwrap();
            event_dispatcher.add_event_handler(rx, RegistryEventHandler {
                registry_id: object_id,
            });
            Ok(())
        }
    }
}

struct RegistryEventHandler {
    registry_id: u32,
}

impl<Ctx: Client> EventHandler<Ctx> for RegistryEventHandler {
    type Message = GlobalsUpdate<<Ctx::ServerContext as Server>::Global>;

    type Future<'ctx> = impl Future<
            Output = Result<
                EventHandlerAction,
                Box<dyn std::error::Error + std::marker::Send + Sync + 'static>,
            >,
        > + 'ctx;

    fn handle_event<'ctx>(
        &'ctx mut self,
        _objects: &'ctx mut Ctx::ObjectStore,
        connection: &'ctx mut Ctx::Connection,
        _server_context: &'ctx Ctx::ServerContext,
        message: &'ctx mut Self::Message,
    ) -> Self::Future<'ctx> {
        async move {
            let mut connection = Pin::new(connection);
            match message {
                GlobalsUpdate::Removed(name) => {
                    connection
                        .send(self.registry_id, wl_registry::events::GlobalRemove {
                            name: *name,
                        })
                        .await?;
                },
                GlobalsUpdate::Added(name, global) => {
                    let interface = global.interface();
                    let version = global.version();
                    connection
                        .send(self.registry_id, wl_registry::events::Global {
                            name: *name,
                            interface: interface.as_bytes().into(),
                            version,
                        })
                        .await?;
                },
            }

            // Client can't drop the registry object, so we will never stop this listener
            Ok(EventHandlerAction::Keep)
        }
    }
}