async_roundtrip/common/protocols_data/wayland/wl_surface.rs
1//! an onscreen surface
2//!
3//! A surface is a rectangular area that may be displayed on zero
4//! or more outputs, and shown any number of times at the compositor's
5//! discretion. They can present wl_buffers, receive user input, and
6//! define a local coordinate system.
7//!
8//! The size of a surface (and relative positions on it) is described
9//! in surface-local coordinates, which may differ from the buffer
10//! coordinates of the pixel content, in case a buffer_transform
11//! or a buffer_scale is used.
12//!
13//! A surface without a "role" is fairly useless: a compositor does
14//! not know where, when or how to present it. The role is the
15//! purpose of a wl_surface. Examples of roles are a cursor for a
16//! pointer (as set by wl_pointer.set_cursor), a drag icon
17//! (wl_data_device.start_drag), a sub-surface
18//! (wl_subcompositor.get_subsurface), and a window as defined by a
19//! shell protocol (e.g. wl_shell.get_shell_surface).
20//!
21//! A surface can have only one role at a time. Initially a
22//! wl_surface does not have a role. Once a wl_surface is given a
23//! role, it is set permanently for the whole lifetime of the
24//! wl_surface object. Giving the current role again is allowed,
25//! unless explicitly forbidden by the relevant interface
26//! specification.
27//!
28//! Surface roles are given by requests in other interfaces such as
29//! wl_pointer.set_cursor. The request should explicitly mention
30//! that this request gives a role to a wl_surface. Often, this
31//! request also creates a new protocol object that represents the
32//! role and adds additional functionality to wl_surface. When a
33//! client wants to destroy a wl_surface, they must destroy this role
34//! object before the wl_surface, otherwise a defunct_role_object error is
35//! sent.
36//!
37//! Destroying the role object does not remove the role from the
38//! wl_surface, but it may stop the wl_surface from "playing the role".
39//! For instance, if a wl_subsurface object is destroyed, the wl_surface
40//! it was created for will be unmapped and forget its position and
41//! z-order. It is allowed to create a wl_subsurface for the same
42//! wl_surface again, but it is not allowed to use the wl_surface as
43//! a cursor (cursor is a different role than sub-surface, and role
44//! switching is not allowed).
45
46use {super::super::all_types::*, ::wl_client::builder::prelude::*};
47
48static INTERFACE: wl_interface = wl_interface {
49 name: c"wl_surface".as_ptr(),
50 version: 6,
51 method_count: 11,
52 methods: {
53 static MESSAGES: [wl_message; 11] = [
54 wl_message {
55 name: c"destroy".as_ptr(),
56 signature: c"".as_ptr(),
57 types: {
58 static TYPES: [Option<&'static wl_interface>; 0] = [];
59 TYPES.as_ptr().cast()
60 },
61 },
62 wl_message {
63 name: c"attach".as_ptr(),
64 signature: c"?oii".as_ptr(),
65 types: {
66 static TYPES: [Option<&'static wl_interface>; 3] =
67 [Some(WlBuffer::WL_INTERFACE), None, None];
68 TYPES.as_ptr().cast()
69 },
70 },
71 wl_message {
72 name: c"damage".as_ptr(),
73 signature: c"iiii".as_ptr(),
74 types: {
75 static TYPES: [Option<&'static wl_interface>; 4] = [None, None, None, None];
76 TYPES.as_ptr().cast()
77 },
78 },
79 wl_message {
80 name: c"frame".as_ptr(),
81 signature: c"n".as_ptr(),
82 types: {
83 static TYPES: [Option<&'static wl_interface>; 1] =
84 [Some(WlCallback::WL_INTERFACE)];
85 TYPES.as_ptr().cast()
86 },
87 },
88 wl_message {
89 name: c"set_opaque_region".as_ptr(),
90 signature: c"?o".as_ptr(),
91 types: {
92 static TYPES: [Option<&'static wl_interface>; 1] =
93 [Some(WlRegion::WL_INTERFACE)];
94 TYPES.as_ptr().cast()
95 },
96 },
97 wl_message {
98 name: c"set_input_region".as_ptr(),
99 signature: c"?o".as_ptr(),
100 types: {
101 static TYPES: [Option<&'static wl_interface>; 1] =
102 [Some(WlRegion::WL_INTERFACE)];
103 TYPES.as_ptr().cast()
104 },
105 },
106 wl_message {
107 name: c"commit".as_ptr(),
108 signature: c"".as_ptr(),
109 types: {
110 static TYPES: [Option<&'static wl_interface>; 0] = [];
111 TYPES.as_ptr().cast()
112 },
113 },
114 wl_message {
115 name: c"set_buffer_transform".as_ptr(),
116 signature: c"i".as_ptr(),
117 types: {
118 static TYPES: [Option<&'static wl_interface>; 1] = [None];
119 TYPES.as_ptr().cast()
120 },
121 },
122 wl_message {
123 name: c"set_buffer_scale".as_ptr(),
124 signature: c"i".as_ptr(),
125 types: {
126 static TYPES: [Option<&'static wl_interface>; 1] = [None];
127 TYPES.as_ptr().cast()
128 },
129 },
130 wl_message {
131 name: c"damage_buffer".as_ptr(),
132 signature: c"iiii".as_ptr(),
133 types: {
134 static TYPES: [Option<&'static wl_interface>; 4] = [None, None, None, None];
135 TYPES.as_ptr().cast()
136 },
137 },
138 wl_message {
139 name: c"offset".as_ptr(),
140 signature: c"ii".as_ptr(),
141 types: {
142 static TYPES: [Option<&'static wl_interface>; 2] = [None, None];
143 TYPES.as_ptr().cast()
144 },
145 },
146 ];
147 MESSAGES.as_ptr()
148 },
149 event_count: 4,
150 events: {
151 static MESSAGES: [wl_message; 4] = [
152 wl_message {
153 name: c"enter".as_ptr(),
154 signature: c"o".as_ptr(),
155 types: {
156 static TYPES: [Option<&'static wl_interface>; 1] =
157 [Some(WlOutput::WL_INTERFACE)];
158 TYPES.as_ptr().cast()
159 },
160 },
161 wl_message {
162 name: c"leave".as_ptr(),
163 signature: c"o".as_ptr(),
164 types: {
165 static TYPES: [Option<&'static wl_interface>; 1] =
166 [Some(WlOutput::WL_INTERFACE)];
167 TYPES.as_ptr().cast()
168 },
169 },
170 wl_message {
171 name: c"preferred_buffer_scale".as_ptr(),
172 signature: c"i".as_ptr(),
173 types: {
174 static TYPES: [Option<&'static wl_interface>; 1] = [None];
175 TYPES.as_ptr().cast()
176 },
177 },
178 wl_message {
179 name: c"preferred_buffer_transform".as_ptr(),
180 signature: c"u".as_ptr(),
181 types: {
182 static TYPES: [Option<&'static wl_interface>; 1] = [None];
183 TYPES.as_ptr().cast()
184 },
185 },
186 ];
187 MESSAGES.as_ptr()
188 },
189};
190
191/// An owned wl_surface proxy.
192///
193/// See the documentation of [the module][self] for the interface description.
194#[derive(Clone, Eq, PartialEq)]
195#[repr(transparent)]
196pub struct WlSurface {
197 /// This proxy has the interface INTERFACE.
198 proxy: UntypedOwnedProxy,
199}
200
201/// A borrowed wl_surface proxy.
202///
203/// See the documentation of [the module][self] for the interface description.
204#[derive(Eq, PartialEq)]
205#[repr(transparent)]
206pub struct WlSurfaceRef {
207 /// This proxy has the interface INTERFACE.
208 proxy: UntypedBorrowedProxy,
209}
210
211// SAFETY: WlSurface is a transparent wrapper around UntypedOwnedProxy
212unsafe impl UntypedOwnedProxyWrapper for WlSurface {}
213
214// SAFETY: - INTERFACE is a valid wl_interface
215// - The only invariant is that self.proxy has a compatible interface
216unsafe impl OwnedProxy for WlSurface {
217 const INTERFACE: &'static str = "wl_surface";
218 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
219 const NO_OP_EVENT_HANDLER: Self::NoOpEventHandler =
220 private::EventHandler(private::NoOpEventHandler);
221 const MAX_VERSION: u32 = 6;
222
223 type Borrowed = WlSurfaceRef;
224 type Api = private::ProxyApi;
225 type NoOpEventHandler = private::EventHandler<private::NoOpEventHandler>;
226}
227
228// SAFETY: WlSurfaceRef is a transparent wrapper around UntypedBorrowedProxy
229unsafe impl UntypedBorrowedProxyWrapper for WlSurfaceRef {}
230
231// SAFETY: - The only invariant is that self.proxy has a compatible interface
232unsafe impl BorrowedProxy for WlSurfaceRef {
233 type Owned = WlSurface;
234}
235
236impl Deref for WlSurface {
237 type Target = WlSurfaceRef;
238
239 fn deref(&self) -> &Self::Target {
240 proxy::low_level::deref(self)
241 }
242}
243
244mod private {
245 pub struct ProxyApi;
246
247 #[allow(dead_code)]
248 pub struct EventHandler<H>(pub(super) H);
249
250 #[allow(dead_code)]
251 pub struct NoOpEventHandler;
252}
253
254impl Debug for WlSurface {
255 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
256 write!(f, "wl_surface#{}", self.proxy.id())
257 }
258}
259
260impl Debug for WlSurfaceRef {
261 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
262 write!(f, "wl_surface#{}", self.proxy.id())
263 }
264}
265
266impl PartialEq<WlSurfaceRef> for WlSurface {
267 fn eq(&self, other: &WlSurfaceRef) -> bool {
268 self.proxy == other.proxy
269 }
270}
271
272impl PartialEq<WlSurface> for WlSurfaceRef {
273 fn eq(&self, other: &WlSurface) -> bool {
274 self.proxy == other.proxy
275 }
276}
277
278#[allow(dead_code)]
279impl WlSurface {
280 /// Since when the destroy request is available.
281 #[allow(dead_code)]
282 pub const REQ__DESTROY__SINCE: u32 = 1;
283
284 /// delete surface
285 ///
286 /// Deletes the surface and invalidates its object ID.
287 #[inline]
288 pub fn destroy(&self) {
289 let mut args = [];
290 // SAFETY: - self.proxy has the interface INTERFACE
291 // - 0 < INTERFACE.method_count = 11
292 // - the request signature is ``
293 unsafe {
294 self.proxy.send_destructor(0, &mut args);
295 }
296 }
297
298 /// Since when the frame request is available.
299 #[allow(dead_code)]
300 pub const REQ__FRAME__SINCE: u32 = 1;
301
302 /// request a frame throttling hint
303 ///
304 /// Request a notification when it is a good time to start drawing a new
305 /// frame, by creating a frame callback. This is useful for throttling
306 /// redrawing operations, and driving animations.
307 ///
308 /// When a client is animating on a wl_surface, it can use the 'frame'
309 /// request to get notified when it is a good time to draw and commit the
310 /// next frame of animation. If the client commits an update earlier than
311 /// that, it is likely that some updates will not make it to the display,
312 /// and the client is wasting resources by drawing too often.
313 ///
314 /// The frame request will take effect on the next wl_surface.commit.
315 /// The notification will only be posted for one frame unless
316 /// requested again. For a wl_surface, the notifications are posted in
317 /// the order the frame requests were committed.
318 ///
319 /// The server must send the notifications so that a client
320 /// will not send excessive updates, while still allowing
321 /// the highest possible update rate for clients that wait for the reply
322 /// before drawing again. The server should give some time for the client
323 /// to draw and commit after sending the frame callback events to let it
324 /// hit the next output refresh.
325 ///
326 /// A server should avoid signaling the frame callbacks if the
327 /// surface is not visible in any way, e.g. the surface is off-screen,
328 /// or completely obscured by other opaque surfaces.
329 ///
330 /// The object returned by this request will be destroyed by the
331 /// compositor after the callback is fired and as such the client must not
332 /// attempt to use it after that point.
333 ///
334 /// The callback_data passed in the callback is the current time, in
335 /// milliseconds, with an undefined base.
336 #[inline]
337 pub fn frame(&self) -> WlCallback {
338 let mut args = [wl_argument { n: 0 }];
339 // SAFETY: - self.proxy has the interface INTERFACE
340 // - 3 < INTERFACE.method_count = 11
341 // - the request signature is `n`
342 // - OwnedProxy::WL_INTERFACE is always a valid interface
343 let data = unsafe {
344 self.proxy
345 .send_constructor::<false>(3, &mut args, WlCallback::WL_INTERFACE, None)
346 };
347 // SAFETY: data has the interface WlCallback::WL_INTERFACE
348 unsafe { proxy::low_level::from_untyped_owned(data) }
349 }
350}
351
352#[allow(dead_code)]
353impl WlSurfaceRef {
354 /// set the surface contents
355 ///
356 /// Set a buffer as the content of this surface.
357 ///
358 /// The new size of the surface is calculated based on the buffer
359 /// size transformed by the inverse buffer_transform and the
360 /// inverse buffer_scale. This means that at commit time the supplied
361 /// buffer size must be an integer multiple of the buffer_scale. If
362 /// that's not the case, an invalid_size error is sent.
363 ///
364 /// The x and y arguments specify the location of the new pending
365 /// buffer's upper left corner, relative to the current buffer's upper
366 /// left corner, in surface-local coordinates. In other words, the
367 /// x and y, combined with the new surface size define in which
368 /// directions the surface's size changes. Setting anything other than 0
369 /// as x and y arguments is discouraged, and should instead be replaced
370 /// with using the separate wl_surface.offset request.
371 ///
372 /// When the bound wl_surface version is 5 or higher, passing any
373 /// non-zero x or y is a protocol violation, and will result in an
374 /// 'invalid_offset' error being raised. The x and y arguments are ignored
375 /// and do not change the pending state. To achieve equivalent semantics,
376 /// use wl_surface.offset.
377 ///
378 /// Surface contents are double-buffered state, see wl_surface.commit.
379 ///
380 /// The initial surface contents are void; there is no content.
381 /// wl_surface.attach assigns the given wl_buffer as the pending
382 /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
383 /// surface contents, and the size of the surface becomes the size
384 /// calculated from the wl_buffer, as described above. After commit,
385 /// there is no pending buffer until the next attach.
386 ///
387 /// Committing a pending wl_buffer allows the compositor to read the
388 /// pixels in the wl_buffer. The compositor may access the pixels at
389 /// any time after the wl_surface.commit request. When the compositor
390 /// will not access the pixels anymore, it will send the
391 /// wl_buffer.release event. Only after receiving wl_buffer.release,
392 /// the client may reuse the wl_buffer. A wl_buffer that has been
393 /// attached and then replaced by another attach instead of committed
394 /// will not receive a release event, and is not used by the
395 /// compositor.
396 ///
397 /// If a pending wl_buffer has been committed to more than one wl_surface,
398 /// the delivery of wl_buffer.release events becomes undefined. A well
399 /// behaved client should not rely on wl_buffer.release events in this
400 /// case. Alternatively, a client could create multiple wl_buffer objects
401 /// from the same backing storage or use wp_linux_buffer_release.
402 ///
403 /// Destroying the wl_buffer after wl_buffer.release does not change
404 /// the surface contents. Destroying the wl_buffer before wl_buffer.release
405 /// is allowed as long as the underlying buffer storage isn't re-used (this
406 /// can happen e.g. on client process termination). However, if the client
407 /// destroys the wl_buffer before receiving the wl_buffer.release event and
408 /// mutates the underlying buffer storage, the surface contents become
409 /// undefined immediately.
410 ///
411 /// If wl_surface.attach is sent with a NULL wl_buffer, the
412 /// following wl_surface.commit will remove the surface content.
413 ///
414 /// If a pending wl_buffer has been destroyed, the result is not specified.
415 /// Many compositors are known to remove the surface content on the following
416 /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
417 /// maximise compatibility should not destroy pending buffers and should
418 /// ensure that they explicitly remove content from surfaces, even after
419 /// destroying buffers.
420 ///
421 /// # Arguments
422 ///
423 /// - `buffer`: buffer of surface contents
424 /// - `x`: surface-local x coordinate
425 /// - `y`: surface-local y coordinate
426 #[inline]
427 pub fn attach(&self, buffer: Option<&WlBufferRef>, x: i32, y: i32) {
428 let (arg0, arg1, arg2) = (buffer, x, y);
429 let obj0_lock = arg0.map(|arg0| proxy::lock(arg0));
430 let obj0 = obj0_lock
431 .map(|obj0_lock| check_argument_proxy("buffer", obj0_lock.wl_proxy()))
432 .unwrap_or(ptr::null_mut());
433 let mut args = [
434 wl_argument { o: obj0 },
435 wl_argument { i: arg1 },
436 wl_argument { i: arg2 },
437 ];
438 // SAFETY: - self.proxy has the interface INTERFACE
439 // - 1 < INTERFACE.method_count = 11
440 // - the request signature is `?oii`
441 unsafe {
442 self.proxy.send_request(1, &mut args);
443 }
444 }
445
446 /// mark part of the surface damaged
447 ///
448 /// This request is used to describe the regions where the pending
449 /// buffer is different from the current surface contents, and where
450 /// the surface therefore needs to be repainted. The compositor
451 /// ignores the parts of the damage that fall outside of the surface.
452 ///
453 /// Damage is double-buffered state, see wl_surface.commit.
454 ///
455 /// The damage rectangle is specified in surface-local coordinates,
456 /// where x and y specify the upper left corner of the damage rectangle.
457 ///
458 /// The initial value for pending damage is empty: no damage.
459 /// wl_surface.damage adds pending damage: the new pending damage
460 /// is the union of old pending damage and the given rectangle.
461 ///
462 /// wl_surface.commit assigns pending damage as the current damage,
463 /// and clears pending damage. The server will clear the current
464 /// damage as it repaints the surface.
465 ///
466 /// Note! New clients should not use this request. Instead damage can be
467 /// posted with wl_surface.damage_buffer which uses buffer coordinates
468 /// instead of surface coordinates.
469 ///
470 /// # Arguments
471 ///
472 /// - `x`: surface-local x coordinate
473 /// - `y`: surface-local y coordinate
474 /// - `width`: width of damage rectangle
475 /// - `height`: height of damage rectangle
476 #[inline]
477 pub fn damage(&self, x: i32, y: i32, width: i32, height: i32) {
478 let (arg0, arg1, arg2, arg3) = (x, y, width, height);
479 let mut args = [
480 wl_argument { i: arg0 },
481 wl_argument { i: arg1 },
482 wl_argument { i: arg2 },
483 wl_argument { i: arg3 },
484 ];
485 // SAFETY: - self.proxy has the interface INTERFACE
486 // - 2 < INTERFACE.method_count = 11
487 // - the request signature is `iiii`
488 unsafe {
489 self.proxy.send_request(2, &mut args);
490 }
491 }
492
493 /// request a frame throttling hint
494 ///
495 /// Request a notification when it is a good time to start drawing a new
496 /// frame, by creating a frame callback. This is useful for throttling
497 /// redrawing operations, and driving animations.
498 ///
499 /// When a client is animating on a wl_surface, it can use the 'frame'
500 /// request to get notified when it is a good time to draw and commit the
501 /// next frame of animation. If the client commits an update earlier than
502 /// that, it is likely that some updates will not make it to the display,
503 /// and the client is wasting resources by drawing too often.
504 ///
505 /// The frame request will take effect on the next wl_surface.commit.
506 /// The notification will only be posted for one frame unless
507 /// requested again. For a wl_surface, the notifications are posted in
508 /// the order the frame requests were committed.
509 ///
510 /// The server must send the notifications so that a client
511 /// will not send excessive updates, while still allowing
512 /// the highest possible update rate for clients that wait for the reply
513 /// before drawing again. The server should give some time for the client
514 /// to draw and commit after sending the frame callback events to let it
515 /// hit the next output refresh.
516 ///
517 /// A server should avoid signaling the frame callbacks if the
518 /// surface is not visible in any way, e.g. the surface is off-screen,
519 /// or completely obscured by other opaque surfaces.
520 ///
521 /// The object returned by this request will be destroyed by the
522 /// compositor after the callback is fired and as such the client must not
523 /// attempt to use it after that point.
524 ///
525 /// The callback_data passed in the callback is the current time, in
526 /// milliseconds, with an undefined base.
527 ///
528 /// # Arguments
529 ///
530 /// - `_queue`: The queue that the returned proxy is assigned to.
531 #[inline]
532 pub fn frame(&self, _queue: &Queue) -> WlCallback {
533 let mut args = [wl_argument { n: 0 }];
534 // SAFETY: - self.proxy has the interface INTERFACE
535 // - 3 < INTERFACE.method_count = 11
536 // - the request signature is `n`
537 // - OwnedProxy::WL_INTERFACE is always a valid interface
538 let data = unsafe {
539 self.proxy
540 .send_constructor(_queue, 3, &mut args, WlCallback::WL_INTERFACE, None)
541 };
542 // SAFETY: data has the interface WlCallback::WL_INTERFACE
543 unsafe { proxy::low_level::from_untyped_owned(data) }
544 }
545
546 /// set opaque region
547 ///
548 /// This request sets the region of the surface that contains
549 /// opaque content.
550 ///
551 /// The opaque region is an optimization hint for the compositor
552 /// that lets it optimize the redrawing of content behind opaque
553 /// regions. Setting an opaque region is not required for correct
554 /// behaviour, but marking transparent content as opaque will result
555 /// in repaint artifacts.
556 ///
557 /// The opaque region is specified in surface-local coordinates.
558 ///
559 /// The compositor ignores the parts of the opaque region that fall
560 /// outside of the surface.
561 ///
562 /// Opaque region is double-buffered state, see wl_surface.commit.
563 ///
564 /// wl_surface.set_opaque_region changes the pending opaque region.
565 /// wl_surface.commit copies the pending region to the current region.
566 /// Otherwise, the pending and current regions are never changed.
567 ///
568 /// The initial value for an opaque region is empty. Setting the pending
569 /// opaque region has copy semantics, and the wl_region object can be
570 /// destroyed immediately. A NULL wl_region causes the pending opaque
571 /// region to be set to empty.
572 ///
573 /// # Arguments
574 ///
575 /// - `region`: opaque region of the surface
576 #[inline]
577 pub fn set_opaque_region(&self, region: Option<&WlRegionRef>) {
578 let (arg0,) = (region,);
579 let obj0_lock = arg0.map(|arg0| proxy::lock(arg0));
580 let obj0 = obj0_lock
581 .map(|obj0_lock| check_argument_proxy("region", obj0_lock.wl_proxy()))
582 .unwrap_or(ptr::null_mut());
583 let mut args = [wl_argument { o: obj0 }];
584 // SAFETY: - self.proxy has the interface INTERFACE
585 // - 4 < INTERFACE.method_count = 11
586 // - the request signature is `?o`
587 unsafe {
588 self.proxy.send_request(4, &mut args);
589 }
590 }
591
592 /// set input region
593 ///
594 /// This request sets the region of the surface that can receive
595 /// pointer and touch events.
596 ///
597 /// Input events happening outside of this region will try the next
598 /// surface in the server surface stack. The compositor ignores the
599 /// parts of the input region that fall outside of the surface.
600 ///
601 /// The input region is specified in surface-local coordinates.
602 ///
603 /// Input region is double-buffered state, see wl_surface.commit.
604 ///
605 /// wl_surface.set_input_region changes the pending input region.
606 /// wl_surface.commit copies the pending region to the current region.
607 /// Otherwise the pending and current regions are never changed,
608 /// except cursor and icon surfaces are special cases, see
609 /// wl_pointer.set_cursor and wl_data_device.start_drag.
610 ///
611 /// The initial value for an input region is infinite. That means the
612 /// whole surface will accept input. Setting the pending input region
613 /// has copy semantics, and the wl_region object can be destroyed
614 /// immediately. A NULL wl_region causes the input region to be set
615 /// to infinite.
616 ///
617 /// # Arguments
618 ///
619 /// - `region`: input region of the surface
620 #[inline]
621 pub fn set_input_region(&self, region: Option<&WlRegionRef>) {
622 let (arg0,) = (region,);
623 let obj0_lock = arg0.map(|arg0| proxy::lock(arg0));
624 let obj0 = obj0_lock
625 .map(|obj0_lock| check_argument_proxy("region", obj0_lock.wl_proxy()))
626 .unwrap_or(ptr::null_mut());
627 let mut args = [wl_argument { o: obj0 }];
628 // SAFETY: - self.proxy has the interface INTERFACE
629 // - 5 < INTERFACE.method_count = 11
630 // - the request signature is `?o`
631 unsafe {
632 self.proxy.send_request(5, &mut args);
633 }
634 }
635
636 /// commit pending surface state
637 ///
638 /// Surface state (input, opaque, and damage regions, attached buffers,
639 /// etc.) is double-buffered. Protocol requests modify the pending state,
640 /// as opposed to the active state in use by the compositor.
641 ///
642 /// A commit request atomically creates a content update from the pending
643 /// state, even if the pending state has not been touched. The content
644 /// update is placed in a queue until it becomes active. After commit, the
645 /// new pending state is as documented for each related request.
646 ///
647 /// When the content update is applied, the wl_buffer is applied before all
648 /// other state. This means that all coordinates in double-buffered state
649 /// are relative to the newly attached wl_buffers, except for
650 /// wl_surface.attach itself. If there is no newly attached wl_buffer, the
651 /// coordinates are relative to the previous content update.
652 ///
653 /// All requests that need a commit to become effective are documented
654 /// to affect double-buffered state.
655 ///
656 /// Other interfaces may add further double-buffered surface state.
657 #[inline]
658 pub fn commit(&self) {
659 let mut args = [];
660 // SAFETY: - self.proxy has the interface INTERFACE
661 // - 6 < INTERFACE.method_count = 11
662 // - the request signature is ``
663 unsafe {
664 self.proxy.send_request(6, &mut args);
665 }
666 }
667
668 /// sets the buffer transformation
669 ///
670 /// This request sets the transformation that the client has already applied
671 /// to the content of the buffer. The accepted values for the transform
672 /// parameter are the values for wl_output.transform.
673 ///
674 /// The compositor applies the inverse of this transformation whenever it
675 /// uses the buffer contents.
676 ///
677 /// Buffer transform is double-buffered state, see wl_surface.commit.
678 ///
679 /// A newly created surface has its buffer transformation set to normal.
680 ///
681 /// wl_surface.set_buffer_transform changes the pending buffer
682 /// transformation. wl_surface.commit copies the pending buffer
683 /// transformation to the current one. Otherwise, the pending and current
684 /// values are never changed.
685 ///
686 /// The purpose of this request is to allow clients to render content
687 /// according to the output transform, thus permitting the compositor to
688 /// use certain optimizations even if the display is rotated. Using
689 /// hardware overlays and scanning out a client buffer for fullscreen
690 /// surfaces are examples of such optimizations. Those optimizations are
691 /// highly dependent on the compositor implementation, so the use of this
692 /// request should be considered on a case-by-case basis.
693 ///
694 /// Note that if the transform value includes 90 or 270 degree rotation,
695 /// the width of the buffer will become the surface height and the height
696 /// of the buffer will become the surface width.
697 ///
698 /// If transform is not one of the values from the
699 /// wl_output.transform enum the invalid_transform protocol error
700 /// is raised.
701 ///
702 /// # Arguments
703 ///
704 /// - `transform`: transform for interpreting buffer contents
705 #[inline]
706 pub fn set_buffer_transform(&self, transform: WlOutputTransform) {
707 let (arg0,) = (transform,);
708 let mut args = [wl_argument { u: arg0.0 }];
709 // SAFETY: - self.proxy has the interface INTERFACE
710 // - 7 < INTERFACE.method_count = 11
711 // - the request signature is `i`
712 unsafe {
713 self.proxy.send_request(7, &mut args);
714 }
715 }
716
717 /// sets the buffer scaling factor
718 ///
719 /// This request sets an optional scaling factor on how the compositor
720 /// interprets the contents of the buffer attached to the window.
721 ///
722 /// Buffer scale is double-buffered state, see wl_surface.commit.
723 ///
724 /// A newly created surface has its buffer scale set to 1.
725 ///
726 /// wl_surface.set_buffer_scale changes the pending buffer scale.
727 /// wl_surface.commit copies the pending buffer scale to the current one.
728 /// Otherwise, the pending and current values are never changed.
729 ///
730 /// The purpose of this request is to allow clients to supply higher
731 /// resolution buffer data for use on high resolution outputs. It is
732 /// intended that you pick the same buffer scale as the scale of the
733 /// output that the surface is displayed on. This means the compositor
734 /// can avoid scaling when rendering the surface on that output.
735 ///
736 /// Note that if the scale is larger than 1, then you have to attach
737 /// a buffer that is larger (by a factor of scale in each dimension)
738 /// than the desired surface size.
739 ///
740 /// If scale is not greater than 0 the invalid_scale protocol error is
741 /// raised.
742 ///
743 /// # Arguments
744 ///
745 /// - `scale`: scale for interpreting buffer contents
746 #[inline]
747 pub fn set_buffer_scale(&self, scale: i32) {
748 let (arg0,) = (scale,);
749 let mut args = [wl_argument { i: arg0 }];
750 // SAFETY: - self.proxy has the interface INTERFACE
751 // - 8 < INTERFACE.method_count = 11
752 // - the request signature is `i`
753 unsafe {
754 self.proxy.send_request(8, &mut args);
755 }
756 }
757
758 /// mark part of the surface damaged using buffer coordinates
759 ///
760 /// This request is used to describe the regions where the pending
761 /// buffer is different from the current surface contents, and where
762 /// the surface therefore needs to be repainted. The compositor
763 /// ignores the parts of the damage that fall outside of the surface.
764 ///
765 /// Damage is double-buffered state, see wl_surface.commit.
766 ///
767 /// The damage rectangle is specified in buffer coordinates,
768 /// where x and y specify the upper left corner of the damage rectangle.
769 ///
770 /// The initial value for pending damage is empty: no damage.
771 /// wl_surface.damage_buffer adds pending damage: the new pending
772 /// damage is the union of old pending damage and the given rectangle.
773 ///
774 /// wl_surface.commit assigns pending damage as the current damage,
775 /// and clears pending damage. The server will clear the current
776 /// damage as it repaints the surface.
777 ///
778 /// This request differs from wl_surface.damage in only one way - it
779 /// takes damage in buffer coordinates instead of surface-local
780 /// coordinates. While this generally is more intuitive than surface
781 /// coordinates, it is especially desirable when using wp_viewport
782 /// or when a drawing library (like EGL) is unaware of buffer scale
783 /// and buffer transform.
784 ///
785 /// Note: Because buffer transformation changes and damage requests may
786 /// be interleaved in the protocol stream, it is impossible to determine
787 /// the actual mapping between surface and buffer damage until
788 /// wl_surface.commit time. Therefore, compositors wishing to take both
789 /// kinds of damage into account will have to accumulate damage from the
790 /// two requests separately and only transform from one to the other
791 /// after receiving the wl_surface.commit.
792 ///
793 /// # Arguments
794 ///
795 /// - `x`: buffer-local x coordinate
796 /// - `y`: buffer-local y coordinate
797 /// - `width`: width of damage rectangle
798 /// - `height`: height of damage rectangle
799 #[inline]
800 pub fn damage_buffer(&self, x: i32, y: i32, width: i32, height: i32) {
801 let (arg0, arg1, arg2, arg3) = (x, y, width, height);
802 let mut args = [
803 wl_argument { i: arg0 },
804 wl_argument { i: arg1 },
805 wl_argument { i: arg2 },
806 wl_argument { i: arg3 },
807 ];
808 // SAFETY: - self.proxy has the interface INTERFACE
809 // - 9 < INTERFACE.method_count = 11
810 // - the request signature is `iiii`
811 unsafe {
812 self.proxy.send_request(9, &mut args);
813 }
814 }
815
816 /// set the surface contents offset
817 ///
818 /// The x and y arguments specify the location of the new pending
819 /// buffer's upper left corner, relative to the current buffer's upper
820 /// left corner, in surface-local coordinates. In other words, the
821 /// x and y, combined with the new surface size define in which
822 /// directions the surface's size changes.
823 ///
824 /// The exact semantics of wl_surface.offset are role-specific. Refer to
825 /// the documentation of specific roles for more information.
826 ///
827 /// Surface location offset is double-buffered state, see
828 /// wl_surface.commit.
829 ///
830 /// This request is semantically equivalent to and the replaces the x and y
831 /// arguments in the wl_surface.attach request in wl_surface versions prior
832 /// to 5. See wl_surface.attach for details.
833 ///
834 /// # Arguments
835 ///
836 /// - `x`: surface-local x coordinate
837 /// - `y`: surface-local y coordinate
838 #[inline]
839 pub fn offset(&self, x: i32, y: i32) {
840 let (arg0, arg1) = (x, y);
841 let mut args = [wl_argument { i: arg0 }, wl_argument { i: arg1 }];
842 // SAFETY: - self.proxy has the interface INTERFACE
843 // - 10 < INTERFACE.method_count = 11
844 // - the request signature is `ii`
845 unsafe {
846 self.proxy.send_request(10, &mut args);
847 }
848 }
849}
850
851impl WlSurface {
852 /// Since when the enter event is available.
853 #[allow(dead_code)]
854 pub const EVT__ENTER__SINCE: u32 = 1;
855
856 /// Since when the leave event is available.
857 #[allow(dead_code)]
858 pub const EVT__LEAVE__SINCE: u32 = 1;
859
860 /// Since when the preferred_buffer_scale event is available.
861 #[allow(dead_code)]
862 pub const EVT__PREFERRED_BUFFER_SCALE__SINCE: u32 = 6;
863
864 /// Since when the preferred_buffer_transform event is available.
865 #[allow(dead_code)]
866 pub const EVT__PREFERRED_BUFFER_TRANSFORM__SINCE: u32 = 6;
867}
868
869/// An event handler for [WlSurface] proxies.
870#[allow(dead_code)]
871pub trait WlSurfaceEventHandler {
872 type Data: 'static;
873
874 /// surface enters an output
875 ///
876 /// This is emitted whenever a surface's creation, movement, or resizing
877 /// results in some part of it being within the scanout region of an
878 /// output.
879 ///
880 /// Note that a surface may be overlapping with zero or more outputs.
881 ///
882 /// # Arguments
883 ///
884 /// - `output`: output entered by the surface
885 ///
886 /// All borrowed proxies passed to this function are guaranteed to be
887 /// immutable and non-null.
888 #[inline]
889 fn enter(&self, _data: &mut Self::Data, _slf: &WlSurfaceRef, output: Option<&WlOutputRef>) {
890 let _ = output;
891 }
892
893 /// surface leaves an output
894 ///
895 /// This is emitted whenever a surface's creation, movement, or resizing
896 /// results in it no longer having any part of it within the scanout region
897 /// of an output.
898 ///
899 /// Clients should not use the number of outputs the surface is on for frame
900 /// throttling purposes. The surface might be hidden even if no leave event
901 /// has been sent, and the compositor might expect new surface content
902 /// updates even if no enter event has been sent. The frame event should be
903 /// used instead.
904 ///
905 /// # Arguments
906 ///
907 /// - `output`: output left by the surface
908 ///
909 /// All borrowed proxies passed to this function are guaranteed to be
910 /// immutable and non-null.
911 #[inline]
912 fn leave(&self, _data: &mut Self::Data, _slf: &WlSurfaceRef, output: Option<&WlOutputRef>) {
913 let _ = output;
914 }
915
916 /// preferred buffer scale for the surface
917 ///
918 /// This event indicates the preferred buffer scale for this surface. It is
919 /// sent whenever the compositor's preference changes.
920 ///
921 /// Before receiving this event the preferred buffer scale for this surface
922 /// is 1.
923 ///
924 /// It is intended that scaling aware clients use this event to scale their
925 /// content and use wl_surface.set_buffer_scale to indicate the scale they
926 /// have rendered with. This allows clients to supply a higher detail
927 /// buffer.
928 ///
929 /// The compositor shall emit a scale value greater than 0.
930 ///
931 /// # Arguments
932 ///
933 /// - `factor`: preferred scaling factor
934 #[inline]
935 fn preferred_buffer_scale(&self, _data: &mut Self::Data, _slf: &WlSurfaceRef, factor: i32) {
936 let _ = factor;
937 }
938
939 /// preferred buffer transform for the surface
940 ///
941 /// This event indicates the preferred buffer transform for this surface.
942 /// It is sent whenever the compositor's preference changes.
943 ///
944 /// Before receiving this event the preferred buffer transform for this
945 /// surface is normal.
946 ///
947 /// Applying this transformation to the surface buffer contents and using
948 /// wl_surface.set_buffer_transform might allow the compositor to use the
949 /// surface buffer more efficiently.
950 ///
951 /// # Arguments
952 ///
953 /// - `transform`: preferred transform
954 #[inline]
955 fn preferred_buffer_transform(
956 &self,
957 _data: &mut Self::Data,
958 _slf: &WlSurfaceRef,
959 transform: WlOutputTransform,
960 ) {
961 let _ = transform;
962 }
963}
964
965impl WlSurfaceEventHandler for private::NoOpEventHandler {
966 type Data = ();
967}
968
969// SAFETY: - INTERFACE is a valid wl_interface
970// - mutable_type always returns the same value
971unsafe impl<H> EventHandler for private::EventHandler<H>
972where
973 H: WlSurfaceEventHandler,
974{
975 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
976
977 #[inline]
978 fn mutable_type() -> Option<(TypeId, &'static str)> {
979 let id = TypeId::of::<H::Data>();
980 let name = std::any::type_name::<H::Data>();
981 Some((id, name))
982 }
983
984 #[allow(unused_variables)]
985 unsafe fn handle_event(
986 &self,
987 queue: &Queue,
988 data: *mut u8,
989 slf: &UntypedBorrowedProxy,
990 opcode: u32,
991 args: *mut wl_argument,
992 ) {
993 // SAFETY: This function requires that slf has the interface INTERFACE
994 let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlSurfaceRef>(slf) };
995 // SAFETY: This function requires that data is `&mut T` where `T`
996 // has the type id returned by `Self::mutable_type`, i.e.,
997 // `T = H::Data`.
998 let data: &mut H::Data = unsafe { &mut *data.cast() };
999 match opcode {
1000 0 => {
1001 // SAFETY: INTERFACE requires that there are 1 arguments
1002 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
1003 // SAFETY: - INTERFACE requires that args[0] contains an object
1004 let arg0 = unsafe {
1005 if let Some(p) = NonNull::new(args[0].o.cast()) {
1006 Some(UntypedBorrowedProxy::new_immutable(queue.libwayland(), p))
1007 } else {
1008 None
1009 }
1010 };
1011 // SAFETY: - INTERFACE requires that the object has the interface WlOutput::WL_INTERFACE
1012 let arg0 = arg0.as_ref().map(|arg0| unsafe {
1013 proxy::low_level::from_untyped_borrowed::<WlOutputRef>(arg0)
1014 });
1015 self.0.enter(data, slf, arg0);
1016 }
1017 1 => {
1018 // SAFETY: INTERFACE requires that there are 1 arguments
1019 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
1020 // SAFETY: - INTERFACE requires that args[0] contains an object
1021 let arg0 = unsafe {
1022 if let Some(p) = NonNull::new(args[0].o.cast()) {
1023 Some(UntypedBorrowedProxy::new_immutable(queue.libwayland(), p))
1024 } else {
1025 None
1026 }
1027 };
1028 // SAFETY: - INTERFACE requires that the object has the interface WlOutput::WL_INTERFACE
1029 let arg0 = arg0.as_ref().map(|arg0| unsafe {
1030 proxy::low_level::from_untyped_borrowed::<WlOutputRef>(arg0)
1031 });
1032 self.0.leave(data, slf, arg0);
1033 }
1034 2 => {
1035 // SAFETY: INTERFACE requires that there are 1 arguments
1036 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
1037 // SAFETY: - INTERFACE requires that args[0] contains an int
1038 let arg0 = unsafe { args[0].i };
1039 self.0.preferred_buffer_scale(data, slf, arg0);
1040 }
1041 3 => {
1042 // SAFETY: INTERFACE requires that there are 1 arguments
1043 let args = unsafe { &*args.cast::<[wl_argument; 1]>() };
1044 // SAFETY: - INTERFACE requires that args[0] contains a uint
1045 let arg0 = unsafe { WlOutputTransform(args[0].u) };
1046 self.0.preferred_buffer_transform(data, slf, arg0);
1047 }
1048 _ => {
1049 invalid_opcode("wl_surface", opcode);
1050 }
1051 }
1052 }
1053}
1054
1055impl<H> CreateEventHandler<H> for private::ProxyApi
1056where
1057 H: WlSurfaceEventHandler,
1058{
1059 type EventHandler = private::EventHandler<H>;
1060
1061 #[inline]
1062 fn create_event_handler(handler: H) -> Self::EventHandler {
1063 private::EventHandler(handler)
1064 }
1065}
1066
1067impl WlSurface {
1068 /// Since when the error.invalid_scale enum variant is available.
1069 #[allow(dead_code)]
1070 pub const ENM__ERROR_INVALID_SCALE__SINCE: u32 = 1;
1071 /// Since when the error.invalid_transform enum variant is available.
1072 #[allow(dead_code)]
1073 pub const ENM__ERROR_INVALID_TRANSFORM__SINCE: u32 = 1;
1074 /// Since when the error.invalid_size enum variant is available.
1075 #[allow(dead_code)]
1076 pub const ENM__ERROR_INVALID_SIZE__SINCE: u32 = 1;
1077 /// Since when the error.invalid_offset enum variant is available.
1078 #[allow(dead_code)]
1079 pub const ENM__ERROR_INVALID_OFFSET__SINCE: u32 = 1;
1080 /// Since when the error.defunct_role_object enum variant is available.
1081 #[allow(dead_code)]
1082 pub const ENM__ERROR_DEFUNCT_ROLE_OBJECT__SINCE: u32 = 1;
1083}
1084
1085/// wl_surface error values
1086///
1087/// These errors can be emitted in response to wl_surface requests.
1088#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1089#[allow(dead_code)]
1090pub struct WlSurfaceError(pub u32);
1091
1092impl WlSurfaceError {
1093 /// buffer scale value is invalid
1094 #[allow(dead_code)]
1095 pub const INVALID_SCALE: Self = Self(0);
1096
1097 /// buffer transform value is invalid
1098 #[allow(dead_code)]
1099 pub const INVALID_TRANSFORM: Self = Self(1);
1100
1101 /// buffer size is invalid
1102 #[allow(dead_code)]
1103 pub const INVALID_SIZE: Self = Self(2);
1104
1105 /// buffer offset is invalid
1106 #[allow(dead_code)]
1107 pub const INVALID_OFFSET: Self = Self(3);
1108
1109 /// surface was destroyed before its role object
1110 #[allow(dead_code)]
1111 pub const DEFUNCT_ROLE_OBJECT: Self = Self(4);
1112}
1113
1114impl Debug for WlSurfaceError {
1115 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1116 let name = match *self {
1117 Self::INVALID_SCALE => "INVALID_SCALE",
1118 Self::INVALID_TRANSFORM => "INVALID_TRANSFORM",
1119 Self::INVALID_SIZE => "INVALID_SIZE",
1120 Self::INVALID_OFFSET => "INVALID_OFFSET",
1121 Self::DEFUNCT_ROLE_OBJECT => "DEFUNCT_ROLE_OBJECT",
1122 _ => return Debug::fmt(&self.0, f),
1123 };
1124 f.write_str(name)
1125 }
1126}
1127
1128/// Functional event handlers.
1129pub mod event_handlers {
1130 use super::*;
1131
1132 /// Event handler for enter events.
1133 pub struct Enter<T, F>(F, PhantomData<fn(&mut T)>);
1134 impl<T, F> WlSurfaceEventHandler for Enter<T, F>
1135 where
1136 T: 'static,
1137 F: Fn(&mut T, &WlSurfaceRef, Option<&WlOutputRef>),
1138 {
1139 type Data = T;
1140
1141 #[inline]
1142 fn enter(&self, _data: &mut T, _slf: &WlSurfaceRef, output: Option<&WlOutputRef>) {
1143 self.0(_data, _slf, output)
1144 }
1145 }
1146
1147 /// Event handler for leave events.
1148 pub struct Leave<T, F>(F, PhantomData<fn(&mut T)>);
1149 impl<T, F> WlSurfaceEventHandler for Leave<T, F>
1150 where
1151 T: 'static,
1152 F: Fn(&mut T, &WlSurfaceRef, Option<&WlOutputRef>),
1153 {
1154 type Data = T;
1155
1156 #[inline]
1157 fn leave(&self, _data: &mut T, _slf: &WlSurfaceRef, output: Option<&WlOutputRef>) {
1158 self.0(_data, _slf, output)
1159 }
1160 }
1161
1162 /// Event handler for preferred_buffer_scale events.
1163 pub struct PreferredBufferScale<T, F>(F, PhantomData<fn(&mut T)>);
1164 impl<T, F> WlSurfaceEventHandler for PreferredBufferScale<T, F>
1165 where
1166 T: 'static,
1167 F: Fn(&mut T, &WlSurfaceRef, i32),
1168 {
1169 type Data = T;
1170
1171 #[inline]
1172 fn preferred_buffer_scale(&self, _data: &mut T, _slf: &WlSurfaceRef, factor: i32) {
1173 self.0(_data, _slf, factor)
1174 }
1175 }
1176
1177 /// Event handler for preferred_buffer_transform events.
1178 pub struct PreferredBufferTransform<T, F>(F, PhantomData<fn(&mut T)>);
1179 impl<T, F> WlSurfaceEventHandler for PreferredBufferTransform<T, F>
1180 where
1181 T: 'static,
1182 F: Fn(&mut T, &WlSurfaceRef, WlOutputTransform),
1183 {
1184 type Data = T;
1185
1186 #[inline]
1187 fn preferred_buffer_transform(
1188 &self,
1189 _data: &mut T,
1190 _slf: &WlSurfaceRef,
1191 transform: WlOutputTransform,
1192 ) {
1193 self.0(_data, _slf, transform)
1194 }
1195 }
1196
1197 impl WlSurface {
1198 /// Creates an event handler for enter events.
1199 ///
1200 /// The event handler ignores all other events.
1201 #[allow(dead_code)]
1202 pub fn on_enter<T, F>(f: F) -> Enter<T, F>
1203 where
1204 T: 'static,
1205 F: Fn(&mut T, &WlSurfaceRef, Option<&WlOutputRef>),
1206 {
1207 Enter(f, PhantomData)
1208 }
1209
1210 /// Creates an event handler for leave events.
1211 ///
1212 /// The event handler ignores all other events.
1213 #[allow(dead_code)]
1214 pub fn on_leave<T, F>(f: F) -> Leave<T, F>
1215 where
1216 T: 'static,
1217 F: Fn(&mut T, &WlSurfaceRef, Option<&WlOutputRef>),
1218 {
1219 Leave(f, PhantomData)
1220 }
1221
1222 /// Creates an event handler for preferred_buffer_scale events.
1223 ///
1224 /// The event handler ignores all other events.
1225 #[allow(dead_code)]
1226 pub fn on_preferred_buffer_scale<T, F>(f: F) -> PreferredBufferScale<T, F>
1227 where
1228 T: 'static,
1229 F: Fn(&mut T, &WlSurfaceRef, i32),
1230 {
1231 PreferredBufferScale(f, PhantomData)
1232 }
1233
1234 /// Creates an event handler for preferred_buffer_transform events.
1235 ///
1236 /// The event handler ignores all other events.
1237 #[allow(dead_code)]
1238 pub fn on_preferred_buffer_transform<T, F>(f: F) -> PreferredBufferTransform<T, F>
1239 where
1240 T: 'static,
1241 F: Fn(&mut T, &WlSurfaceRef, WlOutputTransform),
1242 {
1243 PreferredBufferTransform(f, PhantomData)
1244 }
1245 }
1246}