simple_window/common/protocols/xdg_shell/xdg_surface.rs
1//! desktop user interface surface base interface
2//!
3//! An interface that may be implemented by a wl_surface, for
4//! implementations that provide a desktop-style user interface.
5//!
6//! It provides a base set of functionality required to construct user
7//! interface elements requiring management by the compositor, such as
8//! toplevel windows, menus, etc. The types of functionality are split into
9//! xdg_surface roles.
10//!
11//! Creating an xdg_surface does not set the role for a wl_surface. In order
12//! to map an xdg_surface, the client must create a role-specific object
13//! using, e.g., get_toplevel, get_popup. The wl_surface for any given
14//! xdg_surface can have at most one role, and may not be assigned any role
15//! not based on xdg_surface.
16//!
17//! A role must be assigned before any other requests are made to the
18//! xdg_surface object.
19//!
20//! The client must call wl_surface.commit on the corresponding wl_surface
21//! for the xdg_surface state to take effect.
22//!
23//! Creating an xdg_surface from a wl_surface which has a buffer attached or
24//! committed is a client error, and any attempts by a client to attach or
25//! manipulate a buffer prior to the first xdg_surface.configure call must
26//! also be treated as errors.
27//!
28//! After creating a role-specific object and setting it up (e.g. by sending
29//! the title, app ID, size constraints, parent, etc), the client must
30//! perform an initial commit without any buffer attached. The compositor
31//! will reply with initial wl_surface state such as
32//! wl_surface.preferred_buffer_scale followed by an xdg_surface.configure
33//! event. The client must acknowledge it and is then allowed to attach a
34//! buffer to map the surface.
35//!
36//! Mapping an xdg_surface-based role surface is defined as making it
37//! possible for the surface to be shown by the compositor. Note that
38//! a mapped surface is not guaranteed to be visible once it is mapped.
39//!
40//! For an xdg_surface to be mapped by the compositor, the following
41//! conditions must be met:
42//! (1) the client has assigned an xdg_surface-based role to the surface
43//! (2) the client has set and committed the xdg_surface state and the
44//! role-dependent state to the surface
45//! (3) the client has committed a buffer to the surface
46//!
47//! A newly-unmapped surface is considered to have met condition (1) out
48//! of the 3 required conditions for mapping a surface if its role surface
49//! has not been destroyed, i.e. the client must perform the initial commit
50//! again before attaching a buffer.
51
52use {super::super::all_types::*, ::wl_client::builder::prelude::*};
53
54static INTERFACE: wl_interface = wl_interface {
55 name: c"xdg_surface".as_ptr(),
56 version: 6,
57 method_count: 5,
58 methods: {
59 static MESSAGES: [wl_message; 5] = [
60 wl_message {
61 name: c"destroy".as_ptr(),
62 signature: c"".as_ptr(),
63 types: {
64 static TYPES: [Option<&'static wl_interface>; 0] = [];
65 TYPES.as_ptr().cast()
66 },
67 },
68 wl_message {
69 name: c"get_toplevel".as_ptr(),
70 signature: c"n".as_ptr(),
71 types: {
72 static TYPES: [Option<&'static wl_interface>; 1] =
73 [Some(XdgToplevel::WL_INTERFACE)];
74 TYPES.as_ptr().cast()
75 },
76 },
77 wl_message {
78 name: c"get_popup".as_ptr(),
79 signature: c"n?oo".as_ptr(),
80 types: {
81 static TYPES: [Option<&'static wl_interface>; 3] = [
82 Some(XdgPopup::WL_INTERFACE),
83 Some(XdgSurface::WL_INTERFACE),
84 Some(XdgPositioner::WL_INTERFACE),
85 ];
86 TYPES.as_ptr().cast()
87 },
88 },
89 wl_message {
90 name: c"set_window_geometry".as_ptr(),
91 signature: c"iiii".as_ptr(),
92 types: {
93 static TYPES: [Option<&'static wl_interface>; 4] = [None, None, None, None];
94 TYPES.as_ptr().cast()
95 },
96 },
97 wl_message {
98 name: c"ack_configure".as_ptr(),
99 signature: c"u".as_ptr(),
100 types: {
101 static TYPES: [Option<&'static wl_interface>; 1] = [None];
102 TYPES.as_ptr().cast()
103 },
104 },
105 ];
106 MESSAGES.as_ptr()
107 },
108 event_count: 1,
109 events: {
110 static MESSAGES: [wl_message; 1] = [wl_message {
111 name: c"configure".as_ptr(),
112 signature: c"u".as_ptr(),
113 types: {
114 static TYPES: [Option<&'static wl_interface>; 1] = [None];
115 TYPES.as_ptr().cast()
116 },
117 }];
118 MESSAGES.as_ptr()
119 },
120};
121
122/// An owned xdg_surface proxy.
123///
124/// See the documentation of [the module][self] for the interface description.
125#[derive(Clone, Eq, PartialEq)]
126#[repr(transparent)]
127pub struct XdgSurface {
128 /// This proxy has the interface INTERFACE.
129 proxy: UntypedOwnedProxy,
130}
131
132/// A borrowed xdg_surface proxy.
133///
134/// See the documentation of [the module][self] for the interface description.
135#[derive(Eq, PartialEq)]
136#[repr(transparent)]
137pub struct XdgSurfaceRef {
138 /// This proxy has the interface INTERFACE.
139 proxy: UntypedBorrowedProxy,
140}
141
142// SAFETY: XdgSurface is a transparent wrapper around UntypedOwnedProxy
143unsafe impl UntypedOwnedProxyWrapper for XdgSurface {}
144
145// SAFETY: - INTERFACE is a valid wl_interface
146// - The only invariant is that self.proxy has a compatible interface
147unsafe impl OwnedProxy for XdgSurface {
148 const INTERFACE: &'static str = "xdg_surface";
149 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
150 const NO_OP_EVENT_HANDLER: Self::NoOpEventHandler =
151 private::EventHandler(private::NoOpEventHandler);
152 const MAX_VERSION: u32 = 6;
153
154 type Borrowed = XdgSurfaceRef;
155 type Api = private::ProxyApi;
156 type NoOpEventHandler = private::EventHandler<private::NoOpEventHandler>;
157}
158
159// SAFETY: XdgSurfaceRef is a transparent wrapper around UntypedBorrowedProxy
160unsafe impl UntypedBorrowedProxyWrapper for XdgSurfaceRef {}
161
162// SAFETY: - The only invariant is that self.proxy has a compatible interface
163unsafe impl BorrowedProxy for XdgSurfaceRef {
164 type Owned = XdgSurface;
165}
166
167impl Deref for XdgSurface {
168 type Target = XdgSurfaceRef;
169
170 fn deref(&self) -> &Self::Target {
171 proxy::low_level::deref(self)
172 }
173}
174
175mod private {
176 pub struct ProxyApi;
177
178 #[allow(dead_code)]
179 pub struct EventHandler<H>(pub(super) H);
180
181 #[allow(dead_code)]
182 pub struct NoOpEventHandler;
183}
184
185impl Debug for XdgSurface {
186 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
187 write!(f, "xdg_surface#{}", self.proxy.id())
188 }
189}
190
191impl Debug for XdgSurfaceRef {
192 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
193 write!(f, "xdg_surface#{}", self.proxy.id())
194 }
195}
196
197impl PartialEq<XdgSurfaceRef> for XdgSurface {
198 fn eq(&self, other: &XdgSurfaceRef) -> bool {
199 self.proxy == other.proxy
200 }
201}
202
203impl PartialEq<XdgSurface> for XdgSurfaceRef {
204 fn eq(&self, other: &XdgSurface) -> bool {
205 self.proxy == other.proxy
206 }
207}
208
209#[allow(dead_code)]
210impl XdgSurface {
211 /// Since when the destroy request is available.
212 #[allow(dead_code)]
213 pub const REQ__DESTROY__SINCE: u32 = 1;
214
215 /// destroy the xdg_surface
216 ///
217 /// Destroy the xdg_surface object. An xdg_surface must only be destroyed
218 /// after its role object has been destroyed, otherwise
219 /// a defunct_role_object error is raised.
220 #[inline]
221 pub fn destroy(&self) {
222 let mut args = [];
223 // SAFETY: - self.proxy has the interface INTERFACE
224 // - 0 < INTERFACE.method_count = 5
225 // - the request signature is ``
226 unsafe {
227 self.proxy.send_destructor(0, &mut args);
228 }
229 }
230
231 /// Since when the get_toplevel request is available.
232 #[allow(dead_code)]
233 pub const REQ__GET_TOPLEVEL__SINCE: u32 = 1;
234
235 /// assign the xdg_toplevel surface role
236 ///
237 /// This creates an xdg_toplevel object for the given xdg_surface and gives
238 /// the associated wl_surface the xdg_toplevel role.
239 ///
240 /// See the documentation of xdg_toplevel for more details about what an
241 /// xdg_toplevel is and how it is used.
242 #[inline]
243 pub fn get_toplevel(&self) -> XdgToplevel {
244 let mut args = [wl_argument { n: 0 }];
245 // SAFETY: - self.proxy has the interface INTERFACE
246 // - 1 < INTERFACE.method_count = 5
247 // - the request signature is `n`
248 // - OwnedProxy::WL_INTERFACE is always a valid interface
249 let data = unsafe {
250 self.proxy
251 .send_constructor::<false>(1, &mut args, XdgToplevel::WL_INTERFACE, None)
252 };
253 // SAFETY: data has the interface XdgToplevel::WL_INTERFACE
254 unsafe { proxy::low_level::from_untyped_owned(data) }
255 }
256
257 /// Since when the get_popup request is available.
258 #[allow(dead_code)]
259 pub const REQ__GET_POPUP__SINCE: u32 = 1;
260
261 /// assign the xdg_popup surface role
262 ///
263 /// This creates an xdg_popup object for the given xdg_surface and gives
264 /// the associated wl_surface the xdg_popup role.
265 ///
266 /// If null is passed as a parent, a parent surface must be specified using
267 /// some other protocol, before committing the initial state.
268 ///
269 /// See the documentation of xdg_popup for more details about what an
270 /// xdg_popup is and how it is used.
271 ///
272 /// # Arguments
273 ///
274 /// - `parent`:
275 /// - `positioner`:
276 #[inline]
277 pub fn get_popup(
278 &self,
279 parent: Option<&XdgSurfaceRef>,
280 positioner: &XdgPositionerRef,
281 ) -> XdgPopup {
282 let (arg1, arg2) = (parent, positioner);
283 let obj1_lock = arg1.map(|arg1| proxy::lock(arg1));
284 let obj1 = obj1_lock
285 .map(|obj1_lock| check_argument_proxy("parent", obj1_lock.wl_proxy()))
286 .unwrap_or(ptr::null_mut());
287 let obj2_lock = proxy::lock(arg2);
288 let obj2 = check_argument_proxy("positioner", obj2_lock.wl_proxy());
289 let mut args = [
290 wl_argument { n: 0 },
291 wl_argument { o: obj1 },
292 wl_argument { o: obj2 },
293 ];
294 // SAFETY: - self.proxy has the interface INTERFACE
295 // - 2 < INTERFACE.method_count = 5
296 // - the request signature is `n?oo`
297 // - OwnedProxy::WL_INTERFACE is always a valid interface
298 let data = unsafe {
299 self.proxy
300 .send_constructor::<false>(2, &mut args, XdgPopup::WL_INTERFACE, None)
301 };
302 // SAFETY: data has the interface XdgPopup::WL_INTERFACE
303 unsafe { proxy::low_level::from_untyped_owned(data) }
304 }
305}
306
307#[allow(dead_code)]
308impl XdgSurfaceRef {
309 /// assign the xdg_toplevel surface role
310 ///
311 /// This creates an xdg_toplevel object for the given xdg_surface and gives
312 /// the associated wl_surface the xdg_toplevel role.
313 ///
314 /// See the documentation of xdg_toplevel for more details about what an
315 /// xdg_toplevel is and how it is used.
316 ///
317 /// # Arguments
318 ///
319 /// - `_queue`: The queue that the returned proxy is assigned to.
320 #[inline]
321 pub fn get_toplevel(&self, _queue: &Queue) -> XdgToplevel {
322 let mut args = [wl_argument { n: 0 }];
323 // SAFETY: - self.proxy has the interface INTERFACE
324 // - 1 < INTERFACE.method_count = 5
325 // - the request signature is `n`
326 // - OwnedProxy::WL_INTERFACE is always a valid interface
327 let data = unsafe {
328 self.proxy
329 .send_constructor(_queue, 1, &mut args, XdgToplevel::WL_INTERFACE, None)
330 };
331 // SAFETY: data has the interface XdgToplevel::WL_INTERFACE
332 unsafe { proxy::low_level::from_untyped_owned(data) }
333 }
334
335 /// assign the xdg_popup surface role
336 ///
337 /// This creates an xdg_popup object for the given xdg_surface and gives
338 /// the associated wl_surface the xdg_popup role.
339 ///
340 /// If null is passed as a parent, a parent surface must be specified using
341 /// some other protocol, before committing the initial state.
342 ///
343 /// See the documentation of xdg_popup for more details about what an
344 /// xdg_popup is and how it is used.
345 ///
346 /// # Arguments
347 ///
348 /// - `_queue`: The queue that the returned proxy is assigned to.
349 /// - `parent`:
350 /// - `positioner`:
351 #[inline]
352 pub fn get_popup(
353 &self,
354 _queue: &Queue,
355 parent: Option<&XdgSurfaceRef>,
356 positioner: &XdgPositionerRef,
357 ) -> XdgPopup {
358 let (arg1, arg2) = (parent, positioner);
359 let obj1_lock = arg1.map(|arg1| proxy::lock(arg1));
360 let obj1 = obj1_lock
361 .map(|obj1_lock| check_argument_proxy("parent", obj1_lock.wl_proxy()))
362 .unwrap_or(ptr::null_mut());
363 let obj2_lock = proxy::lock(arg2);
364 let obj2 = check_argument_proxy("positioner", obj2_lock.wl_proxy());
365 let mut args = [
366 wl_argument { n: 0 },
367 wl_argument { o: obj1 },
368 wl_argument { o: obj2 },
369 ];
370 // SAFETY: - self.proxy has the interface INTERFACE
371 // - 2 < INTERFACE.method_count = 5
372 // - the request signature is `n?oo`
373 // - OwnedProxy::WL_INTERFACE is always a valid interface
374 let data = unsafe {
375 self.proxy
376 .send_constructor(_queue, 2, &mut args, XdgPopup::WL_INTERFACE, None)
377 };
378 // SAFETY: data has the interface XdgPopup::WL_INTERFACE
379 unsafe { proxy::low_level::from_untyped_owned(data) }
380 }
381
382 /// set the new window geometry
383 ///
384 /// The window geometry of a surface is its "visible bounds" from the
385 /// user's perspective. Client-side decorations often have invisible
386 /// portions like drop-shadows which should be ignored for the
387 /// purposes of aligning, placing and constraining windows.
388 ///
389 /// The window geometry is double-buffered state, see wl_surface.commit.
390 ///
391 /// When maintaining a position, the compositor should treat the (x, y)
392 /// coordinate of the window geometry as the top left corner of the window.
393 /// A client changing the (x, y) window geometry coordinate should in
394 /// general not alter the position of the window.
395 ///
396 /// Once the window geometry of the surface is set, it is not possible to
397 /// unset it, and it will remain the same until set_window_geometry is
398 /// called again, even if a new subsurface or buffer is attached.
399 ///
400 /// If never set, the value is the full bounds of the surface,
401 /// including any subsurfaces. This updates dynamically on every
402 /// commit. This unset is meant for extremely simple clients.
403 ///
404 /// The arguments are given in the surface-local coordinate space of
405 /// the wl_surface associated with this xdg_surface, and may extend outside
406 /// of the wl_surface itself to mark parts of the subsurface tree as part of
407 /// the window geometry.
408 ///
409 /// When applied, the effective window geometry will be the set window
410 /// geometry clamped to the bounding rectangle of the combined
411 /// geometry of the surface of the xdg_surface and the associated
412 /// subsurfaces.
413 ///
414 /// The effective geometry will not be recalculated unless a new call to
415 /// set_window_geometry is done and the new pending surface state is
416 /// subsequently applied.
417 ///
418 /// The width and height of the effective window geometry must be
419 /// greater than zero. Setting an invalid size will raise an
420 /// invalid_size error.
421 ///
422 /// # Arguments
423 ///
424 /// - `x`:
425 /// - `y`:
426 /// - `width`:
427 /// - `height`:
428 #[inline]
429 pub fn set_window_geometry(&self, x: i32, y: i32, width: i32, height: i32) {
430 let (arg0, arg1, arg2, arg3) = (x, y, width, height);
431 let mut args = [
432 wl_argument { i: arg0 },
433 wl_argument { i: arg1 },
434 wl_argument { i: arg2 },
435 wl_argument { i: arg3 },
436 ];
437 // SAFETY: - self.proxy has the interface INTERFACE
438 // - 3 < INTERFACE.method_count = 5
439 // - the request signature is `iiii`
440 unsafe {
441 self.proxy.send_request(3, &mut args);
442 }
443 }
444
445 /// ack a configure event
446 ///
447 /// When a configure event is received, if a client commits the
448 /// surface in response to the configure event, then the client
449 /// must make an ack_configure request sometime before the commit
450 /// request, passing along the serial of the configure event.
451 ///
452 /// For instance, for toplevel surfaces the compositor might use this
453 /// information to move a surface to the top left only when the client has
454 /// drawn itself for the maximized or fullscreen state.
455 ///
456 /// If the client receives multiple configure events before it
457 /// can respond to one, it only has to ack the last configure event.
458 /// Acking a configure event that was never sent raises an invalid_serial
459 /// error.
460 ///
461 /// A client is not required to commit immediately after sending
462 /// an ack_configure request - it may even ack_configure several times
463 /// before its next surface commit.
464 ///
465 /// A client may send multiple ack_configure requests before committing, but
466 /// only the last request sent before a commit indicates which configure
467 /// event the client really is responding to.
468 ///
469 /// Sending an ack_configure request consumes the serial number sent with
470 /// the request, as well as serial numbers sent by all configure events
471 /// sent on this xdg_surface prior to the configure event referenced by
472 /// the committed serial.
473 ///
474 /// It is an error to issue multiple ack_configure requests referencing a
475 /// serial from the same configure event, or to issue an ack_configure
476 /// request referencing a serial from a configure event issued before the
477 /// event identified by the last ack_configure request for the same
478 /// xdg_surface. Doing so will raise an invalid_serial error.
479 ///
480 /// # Arguments
481 ///
482 /// - `serial`: the serial from the configure event
483 #[inline]
484 pub fn ack_configure(&self, serial: u32) {
485 let (arg0,) = (serial,);
486 let mut args = [wl_argument { u: arg0 }];
487 // SAFETY: - self.proxy has the interface INTERFACE
488 // - 4 < INTERFACE.method_count = 5
489 // - the request signature is `u`
490 unsafe {
491 self.proxy.send_request(4, &mut args);
492 }
493 }
494}
495
496impl XdgSurface {
497 /// Since when the configure event is available.
498 #[allow(dead_code)]
499 pub const EVT__CONFIGURE__SINCE: u32 = 1;
500}
501
502/// An event handler for [XdgSurface] proxies.
503#[allow(dead_code)]
504pub trait XdgSurfaceEventHandler {
505 /// suggest a surface change
506 ///
507 /// The configure event marks the end of a configure sequence. A configure
508 /// sequence is a set of one or more events configuring the state of the
509 /// xdg_surface, including the final xdg_surface.configure event.
510 ///
511 /// Where applicable, xdg_surface surface roles will during a configure
512 /// sequence extend this event as a latched state sent as events before the
513 /// xdg_surface.configure event. Such events should be considered to make up
514 /// a set of atomically applied configuration states, where the
515 /// xdg_surface.configure commits the accumulated state.
516 ///
517 /// Clients should arrange their surface for the new states, and then send
518 /// an ack_configure request with the serial sent in this configure event at
519 /// some point before committing the new surface.
520 ///
521 /// If the client receives multiple configure events before it can respond
522 /// to one, it is free to discard all but the last event it received.
523 ///
524 /// # Arguments
525 ///
526 /// - `serial`: serial of the configure event
527 #[inline]
528 fn configure(&self, _slf: &XdgSurfaceRef, serial: u32) {
529 let _ = serial;
530 }
531}
532
533impl XdgSurfaceEventHandler for private::NoOpEventHandler {}
534
535// SAFETY: - INTERFACE is a valid wl_interface
536unsafe impl<H> EventHandler for private::EventHandler<H>
537where
538 H: XdgSurfaceEventHandler,
539{
540 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
541
542 #[allow(unused_variables)]
543 unsafe fn handle_event(
544 &self,
545 queue: &Queue,
546 data: *mut u8,
547 slf: &UntypedBorrowedProxy,
548 opcode: u32,
549 args: *mut wl_argument,
550 ) {
551 // SAFETY: This function requires that slf has the interface INTERFACE
552 let slf = unsafe { proxy::low_level::from_untyped_borrowed::<XdgSurfaceRef>(slf) };
553 match opcode {
554 0 => {
555 // SAFETY: INTERFACE requires that there are 1 arguments
556 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
557 // SAFETY: - INTERFACE requires that args[0] contains a uint
558 let arg0 = unsafe { args[0].u };
559 self.0.configure(slf, arg0);
560 }
561 _ => {
562 invalid_opcode("xdg_surface", opcode);
563 }
564 }
565 }
566}
567
568impl<H> CreateEventHandler<H> for private::ProxyApi
569where
570 H: XdgSurfaceEventHandler,
571{
572 type EventHandler = private::EventHandler<H>;
573
574 #[inline]
575 fn create_event_handler(handler: H) -> Self::EventHandler {
576 private::EventHandler(handler)
577 }
578}
579
580impl XdgSurface {
581 /// Since when the error.not_constructed enum variant is available.
582 #[allow(dead_code)]
583 pub const ENM__ERROR_NOT_CONSTRUCTED__SINCE: u32 = 1;
584 /// Since when the error.already_constructed enum variant is available.
585 #[allow(dead_code)]
586 pub const ENM__ERROR_ALREADY_CONSTRUCTED__SINCE: u32 = 1;
587 /// Since when the error.unconfigured_buffer enum variant is available.
588 #[allow(dead_code)]
589 pub const ENM__ERROR_UNCONFIGURED_BUFFER__SINCE: u32 = 1;
590 /// Since when the error.invalid_serial enum variant is available.
591 #[allow(dead_code)]
592 pub const ENM__ERROR_INVALID_SERIAL__SINCE: u32 = 1;
593 /// Since when the error.invalid_size enum variant is available.
594 #[allow(dead_code)]
595 pub const ENM__ERROR_INVALID_SIZE__SINCE: u32 = 1;
596 /// Since when the error.defunct_role_object enum variant is available.
597 #[allow(dead_code)]
598 pub const ENM__ERROR_DEFUNCT_ROLE_OBJECT__SINCE: u32 = 1;
599}
600
601#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
602#[allow(dead_code)]
603pub struct XdgSurfaceError(pub u32);
604
605impl XdgSurfaceError {
606 /// Surface was not fully constructed
607 #[allow(dead_code)]
608 pub const NOT_CONSTRUCTED: Self = Self(1);
609
610 /// Surface was already constructed
611 #[allow(dead_code)]
612 pub const ALREADY_CONSTRUCTED: Self = Self(2);
613
614 /// Attaching a buffer to an unconfigured surface
615 #[allow(dead_code)]
616 pub const UNCONFIGURED_BUFFER: Self = Self(3);
617
618 /// Invalid serial number when acking a configure event
619 #[allow(dead_code)]
620 pub const INVALID_SERIAL: Self = Self(4);
621
622 /// Width or height was zero or negative
623 #[allow(dead_code)]
624 pub const INVALID_SIZE: Self = Self(5);
625
626 /// Surface was destroyed before its role object
627 #[allow(dead_code)]
628 pub const DEFUNCT_ROLE_OBJECT: Self = Self(6);
629}
630
631impl Debug for XdgSurfaceError {
632 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
633 let name = match *self {
634 Self::NOT_CONSTRUCTED => "NOT_CONSTRUCTED",
635 Self::ALREADY_CONSTRUCTED => "ALREADY_CONSTRUCTED",
636 Self::UNCONFIGURED_BUFFER => "UNCONFIGURED_BUFFER",
637 Self::INVALID_SERIAL => "INVALID_SERIAL",
638 Self::INVALID_SIZE => "INVALID_SIZE",
639 Self::DEFUNCT_ROLE_OBJECT => "DEFUNCT_ROLE_OBJECT",
640 _ => return Debug::fmt(&self.0, f),
641 };
642 f.write_str(name)
643 }
644}
645
646/// Functional event handlers.
647pub mod event_handlers {
648 use super::*;
649
650 /// Event handler for configure events.
651 pub struct Configure<F>(F);
652 impl<F> XdgSurfaceEventHandler for Configure<F>
653 where
654 F: Fn(&XdgSurfaceRef, u32),
655 {
656 #[inline]
657 fn configure(&self, _slf: &XdgSurfaceRef, serial: u32) {
658 self.0(_slf, serial)
659 }
660 }
661
662 impl XdgSurface {
663 /// Creates an event handler for configure events.
664 ///
665 /// The event handler ignores all other events.
666 #[allow(dead_code)]
667 pub fn on_configure<F>(f: F) -> Configure<F>
668 where
669 F: Fn(&XdgSurfaceRef, u32),
670 {
671 Configure(f)
672 }
673 }
674}