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
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
//! This crate provides safe wrappers around libwayland. It supports both blocking and
//! async operations with any async runtime. Both `'static` and `'scoped`, `Send` and
//! `!Send` event handlers are supported.
//!
//! The most important types provided by this crate are
//!
//! - [`Libwayland`]: A reference to a dynamically loaded `libwayland-client.so`.
//! - [`Connection`]: A connection to a wayland compositor.
//! - [`Queue`]/[`QueueWithData`]: An event queue.
//!
//! This crate does not itself provide type-safe wrappers for wayland protocol objects
//! (`wl_display`, `wl_keyboard`, etc). Instead, applications should use the
//! [`wl-client-builder`] crate to generate these wrappers ahead of time or in `build.rs`.
//!
//! [`wl-client-builder`]: https://docs.rs/wl-client-builder
//!
//! # Example: Hello wayland
//!
//! The code of this example can be found in the `hello-wayland` example binary.
//!
//! ```
//! # use wl_client::{proxy, Libwayland};
//! # use wl_client::test_protocols::core::wl_callback::WlCallback;
//! # use wl_client::test_protocols::core::wl_display::WlDisplay;
//! #
//! // Load the `libwayland-client.so` dynamic library.
//! let lib = Libwayland::open().unwrap();
//! // Connect to the default display determined by the `WAYLAND_DISPLAY` env var.
//! let con = lib.connect_to_default_display().unwrap();
//! // Create a new event queue with the name `hello-wayland`. This name will show up
//! // when debugging applications with `WAYLAND_DEBUG=1`.
//! let queue = con.create_queue(c"hello-wayland");
//! // Get a reference to the `wl_display` singleton. This type was generated with the
//! // `wl-client-builder` crate.
//! let display: WlDisplay = queue.display();
//! // Create a `wl_callback` object. The compositor will immediately respond with a
//! // `wl_callback.done` event.
//! let sync = display.sync();
//! // Set the event handler of the proxy.
//! proxy::set_event_handler(
//! &sync,
//! // When only handling a single event type, the following functional form can be
//! // used. In general, and when handling more than one event type, the event handler
//! // trait must be implemented. In this case, `WlCallbackEventHandler`.
//! WlCallback::on_done(|_, _| println!("Hello wayland!")),
//! );
//! // Perform a roundtrip to ensure that the `done` event has been dispatched.
//! queue.dispatch_roundtrip_blocking().unwrap();
//! ```
//!
//! # Example: Getting a registry snapshot
//!
//! The code of this example can be found in the `get-registry` example binary.
//!
//! ```
//! # use parking_lot::Mutex;
//! # use wl_client::Queue;
//! # use wl_client::test_protocols::core::wl_display::WlDisplay;
//! # use wl_client::test_protocols::core::wl_registry::WlRegistry;
//! #
//! struct Global {
//! pub name: u32,
//! pub interface: String,
//! pub version: u32,
//! }
//!
//! fn get_registry_snapshot(queue: &Queue) -> (WlRegistry, Vec<Global>) {
//! // Create a new registry that will receive the globals and can later be used to
//! // bind them.
//! let registry = queue.display::<WlDisplay>().get_registry();
//! let globals = Mutex::new(vec![]);
//! // Since we don't care about registry events after this function returns, we can
//! // use a dispatch scope. The event handlers in this scope will not be called after
//! // the function returns.
//! queue.dispatch_scope_blocking(|scope| {
//! scope.set_event_handler(
//! ®istry,
//! // Since we only want to create a snapshot, we don't care about
//! // global_remove events. This allows us to use the functional event handler
//! // form.
//! WlRegistry::on_global(|_, name, interface, version| {
//! globals.lock().push(Global {
//! name,
//! interface: interface.to_string(),
//! version,
//! });
//! }),
//! );
//! queue.dispatch_roundtrip_blocking().unwrap();
//! });
//! // The event handler will no longer be called after this function returns but
//! // the registry can still be used to bind globals.
//! (registry, globals.into_inner())
//! }
//! ```
//!
//! # Example: Passing mutable state to event handlers
//!
//! The code of this example can be found in the `get-registry-with-data` example binary.
//!
//! ```
//! # use wl_client::{proxy, Libwayland};
//! # use wl_client::test_protocols_data::core::wl_display::WlDisplay;
//! # use wl_client::test_protocols_data::core::wl_registry::WlRegistry;
//! #
//! struct State {
//! registry: WlRegistry,
//! globals: Vec<Global>,
//! }
//!
//! #[expect(dead_code)]
//! #[derive(Debug)]
//! struct Global {
//! name: u32,
//! interface: String,
//! version: u32,
//! }
//!
//! # fn f() {
//! let lib = Libwayland::open().unwrap();
//! let con = lib.connect_to_default_display().unwrap();
//! let (_queue, queue) = con.create_queue_with_data::<State>(c"get-registry");
//!
//! // Create a new registry that will receive the globals and can later be used to
//! // bind them.
//! let mut state = State {
//! registry: queue.display::<WlDisplay>().get_registry(),
//! globals: vec![],
//! };
//!
//! // Since we only want to create a snapshot, we don't care about
//! // global_remove events. This allows us to use the functional event handler
//! // form.
//! proxy::set_event_handler(
//! &state.registry,
//! WlRegistry::on_global(|state: &mut State, _, name, interface, version| {
//! state.globals.push(Global {
//! name,
//! interface: interface.to_string(),
//! version,
//! });
//! }),
//! );
//! queue.dispatch_roundtrip_blocking(&mut state).unwrap();
//!
//! println!("{:#?}", state.globals);
//! # }
//! ```
//!
//! # Example: Handling keyboard events
//!
//! The code of this example can be found in the `keyboard-events` example binary.
//!
//! ```
//! # use std::cell::RefCell;
//! # use std::rc::Rc;
//! # use wl_client::proxy;
//! # use wl_client::test_protocols::core::wl_keyboard::{WlKeyboard, WlKeyboardEventHandler, WlKeyboardKeyState, WlKeyboardRef};
//! # use wl_client::test_protocols::core::wl_seat::{WlSeat, WlSeatCapability, WlSeatEventHandler, WlSeatRef};
//! #
//! /// The state used to handle seat and keyboard events. In a real application this
//! /// would likely also contain a way to map keycodes to keysyms and to forward events
//! /// to the rest of the application.
//! struct Seat {
//! wl_seat: WlSeat,
//! wl_keyboard: RefCell<Option<WlKeyboard>>,
//! }
//!
//! #[derive(Clone)]
//! struct SeatEventHandler(Rc<Seat>);
//!
//! impl WlSeatEventHandler for SeatEventHandler {
//! fn capabilities(&self, _slf: &WlSeatRef, capabilities: WlSeatCapability) {
//! let kb = &mut *self.0.wl_keyboard.borrow_mut();
//! // When the seat loses/gains the keyboard capability, we need to
//! // destroy/create a wl_keyboard.
//! if capabilities.contains(WlSeatCapability::KEYBOARD) {
//! if kb.is_none() {
//! let wl_keyboard = self.0.wl_seat.get_keyboard();
//! // Since we're using `Rc` here, event handlers must be set with the
//! // `_local` function which allows `!Send` event handlers.
//! proxy::set_event_handler_local(&wl_keyboard, self.clone());
//! *kb = Some(wl_keyboard);
//! }
//! } else {
//! if let Some(kb) = kb.take() {
//! // The wl_keyboard.release request is only available since version 3.
//! // If it's not available, at least destroy the client-side object.
//! if proxy::version(&*kb) >= WlKeyboard::REQ__RELEASE__SINCE {
//! kb.release();
//! } else {
//! proxy::destroy(&kb);
//! }
//! }
//! }
//! }
//! }
//!
//! // If more than one event type needs to be handled by an event handler, the convenient
//! // functional API cannot be used. Instead the application needs to implement the
//! // `*EventHandler` trait manually.
//! impl WlKeyboardEventHandler for SeatEventHandler {
//! fn key(&self,
//! _slf: &WlKeyboardRef,
//! _serial: u32,
//! _time: u32,
//! key: u32,
//! state: WlKeyboardKeyState,
//! ) {
//! println!("key {key:} {state:?}");
//! }
//!
//! fn modifiers(
//! &self,
//! _slf: &WlKeyboardRef,
//! _serial: u32,
//! mods_depressed: u32,
//! mods_latched: u32,
//! mods_locked: u32,
//! group: u32,
//! ) {
//! println!("modifiers {mods_depressed:x}, {mods_latched:x}, {mods_locked:x}, {group}");
//! }
//! }
//! ```
//!
//! # Example: Async roundtrip
//!
//! The code of this example can be found in the `async-dispatch` example binary.
//!
//! ```
//! # use std::cell::Cell;
//! # use wl_client::Libwayland;
//! # use wl_client::test_protocols::core::wl_display::WlDisplay;
//! # use wl_client::test_protocols::core::wl_registry::WlRegistry;
//! #
//! # async fn async_roundtrip() {
//! let lib = Libwayland::open().unwrap();
//! let con = lib.connect_to_default_display().unwrap();
//! let queue = con.create_local_queue(c"async-roundtrip");
//! let registry = queue.display::<WlDisplay>().get_registry();
//! let num_globals = Cell::new(0);
//! queue
//! .dispatch_scope_async(async |scope| {
//! scope.set_event_handler_local(
//! ®istry,
//! WlRegistry::on_global(|_, _, _, _| {
//! num_globals.set(num_globals.get() + 1);
//! }),
//! );
//! // This function can be used to perform an async roundtrip. It is
//! // compatible with any async runtime. This example also demonstrates
//! // that this works in combination with scoped event handlers.
//! queue.dispatch_roundtrip_async().await.unwrap();
//! })
//! .await;
//! println!("number of globals: {}", num_globals.get());
//! # }
//! ```
//!
//! # Example: Async waiting for events
//!
//! The code of this example can be found in the `async-wait` example binary.
//!
//! ```
//! # use wl_client::{proxy, Libwayland};
//! # use wl_client::test_protocols::core::wl_callback::WlCallback;
//! # use wl_client::test_protocols::core::wl_display::WlDisplay;
//! #
//! # async fn wait_for_events() {
//! let lib = Libwayland::open().unwrap();
//! let con = lib.connect_to_default_display().unwrap();
//! let queue = con.create_local_queue(c"async-wait");
//!
//! let sync = queue.display::<WlDisplay>().sync();
//! proxy::set_event_handler(&sync, WlCallback::on_done(|_, _| println!("done!")));
//!
//! loop {
//! // This future completes once there are events to dispatch in the queue.
//! queue.wait_for_events().await.unwrap();
//! queue.dispatch_pending().unwrap();
//! }
//! # }
//! ```
//!
//! # Example: Poll-based event loop integration
//!
//! The code of this example can be found in the `poll-integration` example binary.
//!
//! ```
//! # use std::os::fd::AsRawFd;
//! # use mio::{Interest, Token};
//! # use mio::unix::SourceFd;
//! # use wl_client::{proxy, Libwayland};
//! # use wl_client::test_protocols::core::wl_callback::WlCallback;
//! # use wl_client::test_protocols::core::wl_display::WlDisplay;
//! #
//! # fn event_loop() {
//! let lib = Libwayland::open().unwrap();
//! let con = lib.connect_to_default_display().unwrap();
//! let queue = con.create_local_queue(c"poll-integration");
//!
//! // The watcher exposes a file descriptor that will become readable when the queue
//! // has new events.
//! let watcher = queue.create_watcher().unwrap();
//! let token = Token(0);
//!
//! let sync = queue.display::<WlDisplay>().sync();
//! proxy::set_event_handler(&sync, WlCallback::on_done(|_, _| println!("done!")));
//!
//! let mut events = mio::Events::with_capacity(2);
//! let mut poll = mio::Poll::new().unwrap();
//! poll.registry()
//! .register(
//! &mut SourceFd(&watcher.as_raw_fd()),
//! token,
//! Interest::READABLE,
//! )
//! .unwrap();
//!
//! loop {
//! // Flush requests before polling.
//! con.flush().unwrap();
//! poll.poll(&mut events, None).unwrap();
//! for event in events.iter() {
//! if event.token() == token {
//! queue.dispatch_pending().unwrap();
//! // Reset the watcher to clear the readability status.
//! watcher.reset().unwrap();
//! }
//! }
//! events.clear();
//! }
//! # }
//! ```
pub use ;