wl_proxy/protocols/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 crate::protocol_helpers::prelude::*;
47use super::super::all_types::*;
48
49/// A wl_surface object.
50///
51/// See the documentation of [the module][self] for the interface description.
52pub struct WlSurface {
53 core: ObjectCore,
54 handler: HandlerHolder<dyn WlSurfaceHandler>,
55}
56
57struct DefaultHandler;
58
59impl WlSurfaceHandler for DefaultHandler { }
60
61impl ConcreteObject for WlSurface {
62 const XML_VERSION: u32 = 6;
63 const INTERFACE: ObjectInterface = ObjectInterface::WlSurface;
64 const INTERFACE_NAME: &str = "wl_surface";
65}
66
67impl WlSurface {
68 /// Sets a new handler.
69 pub fn set_handler(&self, handler: impl WlSurfaceHandler) {
70 self.set_boxed_handler(Box::new(handler));
71 }
72
73 /// Sets a new, already boxed handler.
74 pub fn set_boxed_handler(&self, handler: Box<dyn WlSurfaceHandler>) {
75 if self.core.state.destroyed.get() {
76 return;
77 }
78 self.handler.set(Some(handler));
79 }
80}
81
82impl Debug for WlSurface {
83 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
84 f.debug_struct("WlSurface")
85 .field("server_obj_id", &self.core.server_obj_id.get())
86 .field("client_id", &self.core.client_id.get())
87 .field("client_obj_id", &self.core.client_obj_id.get())
88 .finish()
89 }
90}
91
92impl WlSurface {
93 /// Since when the destroy message is available.
94 pub const MSG__DESTROY__SINCE: u32 = 1;
95
96 /// delete surface
97 ///
98 /// Deletes the surface and invalidates its object ID.
99 #[inline]
100 pub fn try_send_destroy(
101 &self,
102 ) -> Result<(), ObjectError> {
103 let core = self.core();
104 let Some(id) = core.server_obj_id.get() else {
105 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
106 };
107 #[cfg(feature = "logging")]
108 if self.core.state.log {
109 #[cold]
110 fn log(state: &State, id: u32) {
111 let (millis, micros) = time_since_epoch();
112 let prefix = &state.log_prefix;
113 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.destroy()\n", id);
114 state.log(args);
115 }
116 log(&self.core.state, id);
117 }
118 let Some(endpoint) = &self.core.state.server else {
119 return Ok(());
120 };
121 if !endpoint.flush_queued.replace(true) {
122 self.core.state.add_flushable_endpoint(endpoint, None);
123 }
124 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
125 let outgoing = &mut *outgoing_ref;
126 let mut fmt = outgoing.formatter();
127 fmt.words([
128 id,
129 0,
130 ]);
131 self.core.handle_server_destroy();
132 Ok(())
133 }
134
135 /// delete surface
136 ///
137 /// Deletes the surface and invalidates its object ID.
138 #[inline]
139 pub fn send_destroy(
140 &self,
141 ) {
142 let res = self.try_send_destroy(
143 );
144 if let Err(e) = res {
145 log_send("wl_surface.destroy", &e);
146 }
147 }
148
149 /// Since when the attach message is available.
150 pub const MSG__ATTACH__SINCE: u32 = 1;
151
152 /// set the surface contents
153 ///
154 /// Set a buffer as the content of this surface.
155 ///
156 /// The new size of the surface is calculated based on the buffer
157 /// size transformed by the inverse buffer_transform and the
158 /// inverse buffer_scale. This means that at commit time the supplied
159 /// buffer size must be an integer multiple of the buffer_scale. If
160 /// that's not the case, an invalid_size error is sent.
161 ///
162 /// The x and y arguments specify the location of the new pending
163 /// buffer's upper left corner, relative to the current buffer's upper
164 /// left corner, in surface-local coordinates. In other words, the
165 /// x and y, combined with the new surface size define in which
166 /// directions the surface's size changes. Setting anything other than 0
167 /// as x and y arguments is discouraged, and should instead be replaced
168 /// with using the separate wl_surface.offset request.
169 ///
170 /// When the bound wl_surface version is 5 or higher, passing any
171 /// non-zero x or y is a protocol violation, and will result in an
172 /// 'invalid_offset' error being raised. The x and y arguments are ignored
173 /// and do not change the pending state. To achieve equivalent semantics,
174 /// use wl_surface.offset.
175 ///
176 /// Surface contents are double-buffered state, see wl_surface.commit.
177 ///
178 /// The initial surface contents are void; there is no content.
179 /// wl_surface.attach assigns the given wl_buffer as the pending
180 /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
181 /// surface contents, and the size of the surface becomes the size
182 /// calculated from the wl_buffer, as described above. After commit,
183 /// there is no pending buffer until the next attach.
184 ///
185 /// Committing a pending wl_buffer allows the compositor to read the
186 /// pixels in the wl_buffer. The compositor may access the pixels at
187 /// any time after the wl_surface.commit request. When the compositor
188 /// will not access the pixels anymore, it will send the
189 /// wl_buffer.release event. Only after receiving wl_buffer.release,
190 /// the client may reuse the wl_buffer. A wl_buffer that has been
191 /// attached and then replaced by another attach instead of committed
192 /// will not receive a release event, and is not used by the
193 /// compositor.
194 ///
195 /// If a pending wl_buffer has been committed to more than one wl_surface,
196 /// the delivery of wl_buffer.release events becomes undefined. A well
197 /// behaved client should not rely on wl_buffer.release events in this
198 /// case. Alternatively, a client could create multiple wl_buffer objects
199 /// from the same backing storage or use a protocol extension providing
200 /// per-commit release notifications.
201 ///
202 /// Destroying the wl_buffer after wl_buffer.release does not change
203 /// the surface contents. Destroying the wl_buffer before wl_buffer.release
204 /// is allowed as long as the underlying buffer storage isn't re-used (this
205 /// can happen e.g. on client process termination). However, if the client
206 /// destroys the wl_buffer before receiving the wl_buffer.release event and
207 /// mutates the underlying buffer storage, the surface contents become
208 /// undefined immediately.
209 ///
210 /// If wl_surface.attach is sent with a NULL wl_buffer, the
211 /// following wl_surface.commit will remove the surface content.
212 ///
213 /// If a pending wl_buffer has been destroyed, the result is not specified.
214 /// Many compositors are known to remove the surface content on the following
215 /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
216 /// maximise compatibility should not destroy pending buffers and should
217 /// ensure that they explicitly remove content from surfaces, even after
218 /// destroying buffers.
219 ///
220 /// # Arguments
221 ///
222 /// - `buffer`: buffer of surface contents
223 /// - `x`: surface-local x coordinate
224 /// - `y`: surface-local y coordinate
225 #[inline]
226 pub fn try_send_attach(
227 &self,
228 buffer: Option<&Rc<WlBuffer>>,
229 x: i32,
230 y: i32,
231 ) -> Result<(), ObjectError> {
232 let (
233 arg0,
234 arg1,
235 arg2,
236 ) = (
237 buffer,
238 x,
239 y,
240 );
241 let arg0 = arg0.map(|a| a.core());
242 let core = self.core();
243 let Some(id) = core.server_obj_id.get() else {
244 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
245 };
246 let arg0_id = match arg0 {
247 None => 0,
248 Some(arg0) => match arg0.server_obj_id.get() {
249 None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("buffer"))),
250 Some(id) => id,
251 },
252 };
253 #[cfg(feature = "logging")]
254 if self.core.state.log {
255 #[cold]
256 fn log(state: &State, id: u32, arg0: u32, arg1: i32, arg2: i32) {
257 let (millis, micros) = time_since_epoch();
258 let prefix = &state.log_prefix;
259 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.attach(buffer: wl_buffer#{}, x: {}, y: {})\n", id, arg0, arg1, arg2);
260 state.log(args);
261 }
262 log(&self.core.state, id, arg0_id, arg1, arg2);
263 }
264 let Some(endpoint) = &self.core.state.server else {
265 return Ok(());
266 };
267 if !endpoint.flush_queued.replace(true) {
268 self.core.state.add_flushable_endpoint(endpoint, None);
269 }
270 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
271 let outgoing = &mut *outgoing_ref;
272 let mut fmt = outgoing.formatter();
273 fmt.words([
274 id,
275 1,
276 arg0_id,
277 arg1 as u32,
278 arg2 as u32,
279 ]);
280 Ok(())
281 }
282
283 /// set the surface contents
284 ///
285 /// Set a buffer as the content of this surface.
286 ///
287 /// The new size of the surface is calculated based on the buffer
288 /// size transformed by the inverse buffer_transform and the
289 /// inverse buffer_scale. This means that at commit time the supplied
290 /// buffer size must be an integer multiple of the buffer_scale. If
291 /// that's not the case, an invalid_size error is sent.
292 ///
293 /// The x and y arguments specify the location of the new pending
294 /// buffer's upper left corner, relative to the current buffer's upper
295 /// left corner, in surface-local coordinates. In other words, the
296 /// x and y, combined with the new surface size define in which
297 /// directions the surface's size changes. Setting anything other than 0
298 /// as x and y arguments is discouraged, and should instead be replaced
299 /// with using the separate wl_surface.offset request.
300 ///
301 /// When the bound wl_surface version is 5 or higher, passing any
302 /// non-zero x or y is a protocol violation, and will result in an
303 /// 'invalid_offset' error being raised. The x and y arguments are ignored
304 /// and do not change the pending state. To achieve equivalent semantics,
305 /// use wl_surface.offset.
306 ///
307 /// Surface contents are double-buffered state, see wl_surface.commit.
308 ///
309 /// The initial surface contents are void; there is no content.
310 /// wl_surface.attach assigns the given wl_buffer as the pending
311 /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
312 /// surface contents, and the size of the surface becomes the size
313 /// calculated from the wl_buffer, as described above. After commit,
314 /// there is no pending buffer until the next attach.
315 ///
316 /// Committing a pending wl_buffer allows the compositor to read the
317 /// pixels in the wl_buffer. The compositor may access the pixels at
318 /// any time after the wl_surface.commit request. When the compositor
319 /// will not access the pixels anymore, it will send the
320 /// wl_buffer.release event. Only after receiving wl_buffer.release,
321 /// the client may reuse the wl_buffer. A wl_buffer that has been
322 /// attached and then replaced by another attach instead of committed
323 /// will not receive a release event, and is not used by the
324 /// compositor.
325 ///
326 /// If a pending wl_buffer has been committed to more than one wl_surface,
327 /// the delivery of wl_buffer.release events becomes undefined. A well
328 /// behaved client should not rely on wl_buffer.release events in this
329 /// case. Alternatively, a client could create multiple wl_buffer objects
330 /// from the same backing storage or use a protocol extension providing
331 /// per-commit release notifications.
332 ///
333 /// Destroying the wl_buffer after wl_buffer.release does not change
334 /// the surface contents. Destroying the wl_buffer before wl_buffer.release
335 /// is allowed as long as the underlying buffer storage isn't re-used (this
336 /// can happen e.g. on client process termination). However, if the client
337 /// destroys the wl_buffer before receiving the wl_buffer.release event and
338 /// mutates the underlying buffer storage, the surface contents become
339 /// undefined immediately.
340 ///
341 /// If wl_surface.attach is sent with a NULL wl_buffer, the
342 /// following wl_surface.commit will remove the surface content.
343 ///
344 /// If a pending wl_buffer has been destroyed, the result is not specified.
345 /// Many compositors are known to remove the surface content on the following
346 /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
347 /// maximise compatibility should not destroy pending buffers and should
348 /// ensure that they explicitly remove content from surfaces, even after
349 /// destroying buffers.
350 ///
351 /// # Arguments
352 ///
353 /// - `buffer`: buffer of surface contents
354 /// - `x`: surface-local x coordinate
355 /// - `y`: surface-local y coordinate
356 #[inline]
357 pub fn send_attach(
358 &self,
359 buffer: Option<&Rc<WlBuffer>>,
360 x: i32,
361 y: i32,
362 ) {
363 let res = self.try_send_attach(
364 buffer,
365 x,
366 y,
367 );
368 if let Err(e) = res {
369 log_send("wl_surface.attach", &e);
370 }
371 }
372
373 /// Since when the damage message is available.
374 pub const MSG__DAMAGE__SINCE: u32 = 1;
375
376 /// mark part of the surface damaged
377 ///
378 /// This request is used to describe the regions where the pending
379 /// buffer is different from the current surface contents, and where
380 /// the surface therefore needs to be repainted. The compositor
381 /// ignores the parts of the damage that fall outside of the surface.
382 ///
383 /// Damage is double-buffered state, see wl_surface.commit.
384 ///
385 /// The damage rectangle is specified in surface-local coordinates,
386 /// where x and y specify the upper left corner of the damage rectangle.
387 ///
388 /// The initial value for pending damage is empty: no damage.
389 /// wl_surface.damage adds pending damage: the new pending damage
390 /// is the union of old pending damage and the given rectangle.
391 ///
392 /// wl_surface.commit assigns pending damage as the current damage,
393 /// and clears pending damage. The server will clear the current
394 /// damage as it repaints the surface.
395 ///
396 /// Note! New clients should not use this request. Instead damage can be
397 /// posted with wl_surface.damage_buffer which uses buffer coordinates
398 /// instead of surface coordinates.
399 ///
400 /// # Arguments
401 ///
402 /// - `x`: surface-local x coordinate
403 /// - `y`: surface-local y coordinate
404 /// - `width`: width of damage rectangle
405 /// - `height`: height of damage rectangle
406 #[inline]
407 pub fn try_send_damage(
408 &self,
409 x: i32,
410 y: i32,
411 width: i32,
412 height: i32,
413 ) -> Result<(), ObjectError> {
414 let (
415 arg0,
416 arg1,
417 arg2,
418 arg3,
419 ) = (
420 x,
421 y,
422 width,
423 height,
424 );
425 let core = self.core();
426 let Some(id) = core.server_obj_id.get() else {
427 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
428 };
429 #[cfg(feature = "logging")]
430 if self.core.state.log {
431 #[cold]
432 fn log(state: &State, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
433 let (millis, micros) = time_since_epoch();
434 let prefix = &state.log_prefix;
435 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.damage(x: {}, y: {}, width: {}, height: {})\n", id, arg0, arg1, arg2, arg3);
436 state.log(args);
437 }
438 log(&self.core.state, id, arg0, arg1, arg2, arg3);
439 }
440 let Some(endpoint) = &self.core.state.server else {
441 return Ok(());
442 };
443 if !endpoint.flush_queued.replace(true) {
444 self.core.state.add_flushable_endpoint(endpoint, None);
445 }
446 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
447 let outgoing = &mut *outgoing_ref;
448 let mut fmt = outgoing.formatter();
449 fmt.words([
450 id,
451 2,
452 arg0 as u32,
453 arg1 as u32,
454 arg2 as u32,
455 arg3 as u32,
456 ]);
457 Ok(())
458 }
459
460 /// mark part of the surface damaged
461 ///
462 /// This request is used to describe the regions where the pending
463 /// buffer is different from the current surface contents, and where
464 /// the surface therefore needs to be repainted. The compositor
465 /// ignores the parts of the damage that fall outside of the surface.
466 ///
467 /// Damage is double-buffered state, see wl_surface.commit.
468 ///
469 /// The damage rectangle is specified in surface-local coordinates,
470 /// where x and y specify the upper left corner of the damage rectangle.
471 ///
472 /// The initial value for pending damage is empty: no damage.
473 /// wl_surface.damage adds pending damage: the new pending damage
474 /// is the union of old pending damage and the given rectangle.
475 ///
476 /// wl_surface.commit assigns pending damage as the current damage,
477 /// and clears pending damage. The server will clear the current
478 /// damage as it repaints the surface.
479 ///
480 /// Note! New clients should not use this request. Instead damage can be
481 /// posted with wl_surface.damage_buffer which uses buffer coordinates
482 /// instead of surface coordinates.
483 ///
484 /// # Arguments
485 ///
486 /// - `x`: surface-local x coordinate
487 /// - `y`: surface-local y coordinate
488 /// - `width`: width of damage rectangle
489 /// - `height`: height of damage rectangle
490 #[inline]
491 pub fn send_damage(
492 &self,
493 x: i32,
494 y: i32,
495 width: i32,
496 height: i32,
497 ) {
498 let res = self.try_send_damage(
499 x,
500 y,
501 width,
502 height,
503 );
504 if let Err(e) = res {
505 log_send("wl_surface.damage", &e);
506 }
507 }
508
509 /// Since when the frame message is available.
510 pub const MSG__FRAME__SINCE: u32 = 1;
511
512 /// request a frame throttling hint
513 ///
514 /// Request a notification when it is a good time to start drawing a new
515 /// frame, by creating a frame callback. This is useful for throttling
516 /// redrawing operations, and driving animations.
517 ///
518 /// When a client is animating on a wl_surface, it can use the 'frame'
519 /// request to get notified when it is a good time to draw and commit the
520 /// next frame of animation. If the client commits an update earlier than
521 /// that, it is likely that some updates will not make it to the display,
522 /// and the client is wasting resources by drawing too often.
523 ///
524 /// The frame request will take effect on the next wl_surface.commit.
525 /// The notification will only be posted for one frame unless
526 /// requested again. For a wl_surface, the notifications are posted in
527 /// the order the frame requests were committed.
528 ///
529 /// The server must send the notifications so that a client
530 /// will not send excessive updates, while still allowing
531 /// the highest possible update rate for clients that wait for the reply
532 /// before drawing again. The server should give some time for the client
533 /// to draw and commit after sending the frame callback events to let it
534 /// hit the next output refresh.
535 ///
536 /// A server should avoid signaling the frame callbacks if the
537 /// surface is not visible in any way, e.g. the surface is off-screen,
538 /// or completely obscured by other opaque surfaces.
539 ///
540 /// The object returned by this request will be destroyed by the
541 /// compositor after the callback is fired and as such the client must not
542 /// attempt to use it after that point.
543 ///
544 /// The callback_data passed in the callback is the current time, in
545 /// milliseconds, with an undefined base.
546 ///
547 /// # Arguments
548 ///
549 /// - `callback`: callback object for the frame request
550 #[inline]
551 pub fn try_send_frame(
552 &self,
553 callback: &Rc<WlCallback>,
554 ) -> Result<(), ObjectError> {
555 let (
556 arg0,
557 ) = (
558 callback,
559 );
560 let arg0_obj = arg0;
561 let arg0 = arg0_obj.core();
562 let core = self.core();
563 let Some(id) = core.server_obj_id.get() else {
564 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
565 };
566 arg0.generate_server_id(arg0_obj.clone())
567 .map_err(|e| ObjectError(ObjectErrorKind::GenerateServerId("callback", e)))?;
568 let arg0_id = arg0.server_obj_id.get().unwrap_or(0);
569 #[cfg(feature = "logging")]
570 if self.core.state.log {
571 #[cold]
572 fn log(state: &State, id: u32, arg0: u32) {
573 let (millis, micros) = time_since_epoch();
574 let prefix = &state.log_prefix;
575 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.frame(callback: wl_callback#{})\n", id, arg0);
576 state.log(args);
577 }
578 log(&self.core.state, id, arg0_id);
579 }
580 let Some(endpoint) = &self.core.state.server else {
581 return Ok(());
582 };
583 if !endpoint.flush_queued.replace(true) {
584 self.core.state.add_flushable_endpoint(endpoint, None);
585 }
586 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
587 let outgoing = &mut *outgoing_ref;
588 let mut fmt = outgoing.formatter();
589 fmt.words([
590 id,
591 3,
592 arg0_id,
593 ]);
594 Ok(())
595 }
596
597 /// request a frame throttling hint
598 ///
599 /// Request a notification when it is a good time to start drawing a new
600 /// frame, by creating a frame callback. This is useful for throttling
601 /// redrawing operations, and driving animations.
602 ///
603 /// When a client is animating on a wl_surface, it can use the 'frame'
604 /// request to get notified when it is a good time to draw and commit the
605 /// next frame of animation. If the client commits an update earlier than
606 /// that, it is likely that some updates will not make it to the display,
607 /// and the client is wasting resources by drawing too often.
608 ///
609 /// The frame request will take effect on the next wl_surface.commit.
610 /// The notification will only be posted for one frame unless
611 /// requested again. For a wl_surface, the notifications are posted in
612 /// the order the frame requests were committed.
613 ///
614 /// The server must send the notifications so that a client
615 /// will not send excessive updates, while still allowing
616 /// the highest possible update rate for clients that wait for the reply
617 /// before drawing again. The server should give some time for the client
618 /// to draw and commit after sending the frame callback events to let it
619 /// hit the next output refresh.
620 ///
621 /// A server should avoid signaling the frame callbacks if the
622 /// surface is not visible in any way, e.g. the surface is off-screen,
623 /// or completely obscured by other opaque surfaces.
624 ///
625 /// The object returned by this request will be destroyed by the
626 /// compositor after the callback is fired and as such the client must not
627 /// attempt to use it after that point.
628 ///
629 /// The callback_data passed in the callback is the current time, in
630 /// milliseconds, with an undefined base.
631 ///
632 /// # Arguments
633 ///
634 /// - `callback`: callback object for the frame request
635 #[inline]
636 pub fn send_frame(
637 &self,
638 callback: &Rc<WlCallback>,
639 ) {
640 let res = self.try_send_frame(
641 callback,
642 );
643 if let Err(e) = res {
644 log_send("wl_surface.frame", &e);
645 }
646 }
647
648 /// request a frame throttling hint
649 ///
650 /// Request a notification when it is a good time to start drawing a new
651 /// frame, by creating a frame callback. This is useful for throttling
652 /// redrawing operations, and driving animations.
653 ///
654 /// When a client is animating on a wl_surface, it can use the 'frame'
655 /// request to get notified when it is a good time to draw and commit the
656 /// next frame of animation. If the client commits an update earlier than
657 /// that, it is likely that some updates will not make it to the display,
658 /// and the client is wasting resources by drawing too often.
659 ///
660 /// The frame request will take effect on the next wl_surface.commit.
661 /// The notification will only be posted for one frame unless
662 /// requested again. For a wl_surface, the notifications are posted in
663 /// the order the frame requests were committed.
664 ///
665 /// The server must send the notifications so that a client
666 /// will not send excessive updates, while still allowing
667 /// the highest possible update rate for clients that wait for the reply
668 /// before drawing again. The server should give some time for the client
669 /// to draw and commit after sending the frame callback events to let it
670 /// hit the next output refresh.
671 ///
672 /// A server should avoid signaling the frame callbacks if the
673 /// surface is not visible in any way, e.g. the surface is off-screen,
674 /// or completely obscured by other opaque surfaces.
675 ///
676 /// The object returned by this request will be destroyed by the
677 /// compositor after the callback is fired and as such the client must not
678 /// attempt to use it after that point.
679 ///
680 /// The callback_data passed in the callback is the current time, in
681 /// milliseconds, with an undefined base.
682 #[inline]
683 pub fn new_try_send_frame(
684 &self,
685 ) -> Result<Rc<WlCallback>, ObjectError> {
686 let callback = self.core.create_child();
687 self.try_send_frame(
688 &callback,
689 )?;
690 Ok(callback)
691 }
692
693 /// request a frame throttling hint
694 ///
695 /// Request a notification when it is a good time to start drawing a new
696 /// frame, by creating a frame callback. This is useful for throttling
697 /// redrawing operations, and driving animations.
698 ///
699 /// When a client is animating on a wl_surface, it can use the 'frame'
700 /// request to get notified when it is a good time to draw and commit the
701 /// next frame of animation. If the client commits an update earlier than
702 /// that, it is likely that some updates will not make it to the display,
703 /// and the client is wasting resources by drawing too often.
704 ///
705 /// The frame request will take effect on the next wl_surface.commit.
706 /// The notification will only be posted for one frame unless
707 /// requested again. For a wl_surface, the notifications are posted in
708 /// the order the frame requests were committed.
709 ///
710 /// The server must send the notifications so that a client
711 /// will not send excessive updates, while still allowing
712 /// the highest possible update rate for clients that wait for the reply
713 /// before drawing again. The server should give some time for the client
714 /// to draw and commit after sending the frame callback events to let it
715 /// hit the next output refresh.
716 ///
717 /// A server should avoid signaling the frame callbacks if the
718 /// surface is not visible in any way, e.g. the surface is off-screen,
719 /// or completely obscured by other opaque surfaces.
720 ///
721 /// The object returned by this request will be destroyed by the
722 /// compositor after the callback is fired and as such the client must not
723 /// attempt to use it after that point.
724 ///
725 /// The callback_data passed in the callback is the current time, in
726 /// milliseconds, with an undefined base.
727 #[inline]
728 pub fn new_send_frame(
729 &self,
730 ) -> Rc<WlCallback> {
731 let callback = self.core.create_child();
732 self.send_frame(
733 &callback,
734 );
735 callback
736 }
737
738 /// Since when the set_opaque_region message is available.
739 pub const MSG__SET_OPAQUE_REGION__SINCE: u32 = 1;
740
741 /// set opaque region
742 ///
743 /// This request sets the region of the surface that contains
744 /// opaque content.
745 ///
746 /// The opaque region is an optimization hint for the compositor
747 /// that lets it optimize the redrawing of content behind opaque
748 /// regions. Setting an opaque region is not required for correct
749 /// behaviour, but marking transparent content as opaque will result
750 /// in repaint artifacts.
751 ///
752 /// The opaque region is specified in surface-local coordinates.
753 ///
754 /// The compositor ignores the parts of the opaque region that fall
755 /// outside of the surface.
756 ///
757 /// Opaque region is double-buffered state, see wl_surface.commit.
758 ///
759 /// wl_surface.set_opaque_region changes the pending opaque region.
760 /// wl_surface.commit copies the pending region to the current region.
761 /// Otherwise, the pending and current regions are never changed.
762 ///
763 /// The initial value for an opaque region is empty. Setting the pending
764 /// opaque region has copy semantics, and the wl_region object can be
765 /// destroyed immediately. A NULL wl_region causes the pending opaque
766 /// region to be set to empty.
767 ///
768 /// # Arguments
769 ///
770 /// - `region`: opaque region of the surface
771 #[inline]
772 pub fn try_send_set_opaque_region(
773 &self,
774 region: Option<&Rc<WlRegion>>,
775 ) -> Result<(), ObjectError> {
776 let (
777 arg0,
778 ) = (
779 region,
780 );
781 let arg0 = arg0.map(|a| a.core());
782 let core = self.core();
783 let Some(id) = core.server_obj_id.get() else {
784 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
785 };
786 let arg0_id = match arg0 {
787 None => 0,
788 Some(arg0) => match arg0.server_obj_id.get() {
789 None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("region"))),
790 Some(id) => id,
791 },
792 };
793 #[cfg(feature = "logging")]
794 if self.core.state.log {
795 #[cold]
796 fn log(state: &State, id: u32, arg0: u32) {
797 let (millis, micros) = time_since_epoch();
798 let prefix = &state.log_prefix;
799 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.set_opaque_region(region: wl_region#{})\n", id, arg0);
800 state.log(args);
801 }
802 log(&self.core.state, id, arg0_id);
803 }
804 let Some(endpoint) = &self.core.state.server else {
805 return Ok(());
806 };
807 if !endpoint.flush_queued.replace(true) {
808 self.core.state.add_flushable_endpoint(endpoint, None);
809 }
810 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
811 let outgoing = &mut *outgoing_ref;
812 let mut fmt = outgoing.formatter();
813 fmt.words([
814 id,
815 4,
816 arg0_id,
817 ]);
818 Ok(())
819 }
820
821 /// set opaque region
822 ///
823 /// This request sets the region of the surface that contains
824 /// opaque content.
825 ///
826 /// The opaque region is an optimization hint for the compositor
827 /// that lets it optimize the redrawing of content behind opaque
828 /// regions. Setting an opaque region is not required for correct
829 /// behaviour, but marking transparent content as opaque will result
830 /// in repaint artifacts.
831 ///
832 /// The opaque region is specified in surface-local coordinates.
833 ///
834 /// The compositor ignores the parts of the opaque region that fall
835 /// outside of the surface.
836 ///
837 /// Opaque region is double-buffered state, see wl_surface.commit.
838 ///
839 /// wl_surface.set_opaque_region changes the pending opaque region.
840 /// wl_surface.commit copies the pending region to the current region.
841 /// Otherwise, the pending and current regions are never changed.
842 ///
843 /// The initial value for an opaque region is empty. Setting the pending
844 /// opaque region has copy semantics, and the wl_region object can be
845 /// destroyed immediately. A NULL wl_region causes the pending opaque
846 /// region to be set to empty.
847 ///
848 /// # Arguments
849 ///
850 /// - `region`: opaque region of the surface
851 #[inline]
852 pub fn send_set_opaque_region(
853 &self,
854 region: Option<&Rc<WlRegion>>,
855 ) {
856 let res = self.try_send_set_opaque_region(
857 region,
858 );
859 if let Err(e) = res {
860 log_send("wl_surface.set_opaque_region", &e);
861 }
862 }
863
864 /// Since when the set_input_region message is available.
865 pub const MSG__SET_INPUT_REGION__SINCE: u32 = 1;
866
867 /// set input region
868 ///
869 /// This request sets the region of the surface that can receive
870 /// pointer and touch events.
871 ///
872 /// Input events happening outside of this region will try the next
873 /// surface in the server surface stack. The compositor ignores the
874 /// parts of the input region that fall outside of the surface.
875 ///
876 /// The input region is specified in surface-local coordinates.
877 ///
878 /// Input region is double-buffered state, see wl_surface.commit.
879 ///
880 /// wl_surface.set_input_region changes the pending input region.
881 /// wl_surface.commit copies the pending region to the current region.
882 /// Otherwise the pending and current regions are never changed,
883 /// except cursor and icon surfaces are special cases, see
884 /// wl_pointer.set_cursor and wl_data_device.start_drag.
885 ///
886 /// The initial value for an input region is infinite. That means the
887 /// whole surface will accept input. Setting the pending input region
888 /// has copy semantics, and the wl_region object can be destroyed
889 /// immediately. A NULL wl_region causes the input region to be set
890 /// to infinite.
891 ///
892 /// # Arguments
893 ///
894 /// - `region`: input region of the surface
895 #[inline]
896 pub fn try_send_set_input_region(
897 &self,
898 region: Option<&Rc<WlRegion>>,
899 ) -> Result<(), ObjectError> {
900 let (
901 arg0,
902 ) = (
903 region,
904 );
905 let arg0 = arg0.map(|a| a.core());
906 let core = self.core();
907 let Some(id) = core.server_obj_id.get() else {
908 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
909 };
910 let arg0_id = match arg0 {
911 None => 0,
912 Some(arg0) => match arg0.server_obj_id.get() {
913 None => return Err(ObjectError(ObjectErrorKind::ArgNoServerId("region"))),
914 Some(id) => id,
915 },
916 };
917 #[cfg(feature = "logging")]
918 if self.core.state.log {
919 #[cold]
920 fn log(state: &State, id: u32, arg0: u32) {
921 let (millis, micros) = time_since_epoch();
922 let prefix = &state.log_prefix;
923 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.set_input_region(region: wl_region#{})\n", id, arg0);
924 state.log(args);
925 }
926 log(&self.core.state, id, arg0_id);
927 }
928 let Some(endpoint) = &self.core.state.server else {
929 return Ok(());
930 };
931 if !endpoint.flush_queued.replace(true) {
932 self.core.state.add_flushable_endpoint(endpoint, None);
933 }
934 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
935 let outgoing = &mut *outgoing_ref;
936 let mut fmt = outgoing.formatter();
937 fmt.words([
938 id,
939 5,
940 arg0_id,
941 ]);
942 Ok(())
943 }
944
945 /// set input region
946 ///
947 /// This request sets the region of the surface that can receive
948 /// pointer and touch events.
949 ///
950 /// Input events happening outside of this region will try the next
951 /// surface in the server surface stack. The compositor ignores the
952 /// parts of the input region that fall outside of the surface.
953 ///
954 /// The input region is specified in surface-local coordinates.
955 ///
956 /// Input region is double-buffered state, see wl_surface.commit.
957 ///
958 /// wl_surface.set_input_region changes the pending input region.
959 /// wl_surface.commit copies the pending region to the current region.
960 /// Otherwise the pending and current regions are never changed,
961 /// except cursor and icon surfaces are special cases, see
962 /// wl_pointer.set_cursor and wl_data_device.start_drag.
963 ///
964 /// The initial value for an input region is infinite. That means the
965 /// whole surface will accept input. Setting the pending input region
966 /// has copy semantics, and the wl_region object can be destroyed
967 /// immediately. A NULL wl_region causes the input region to be set
968 /// to infinite.
969 ///
970 /// # Arguments
971 ///
972 /// - `region`: input region of the surface
973 #[inline]
974 pub fn send_set_input_region(
975 &self,
976 region: Option<&Rc<WlRegion>>,
977 ) {
978 let res = self.try_send_set_input_region(
979 region,
980 );
981 if let Err(e) = res {
982 log_send("wl_surface.set_input_region", &e);
983 }
984 }
985
986 /// Since when the commit message is available.
987 pub const MSG__COMMIT__SINCE: u32 = 1;
988
989 /// commit pending surface state
990 ///
991 /// Surface state (input, opaque, and damage regions, attached buffers,
992 /// etc.) is double-buffered. Protocol requests modify the pending state,
993 /// as opposed to the active state in use by the compositor.
994 ///
995 /// A commit request atomically creates a content update from the pending
996 /// state, even if the pending state has not been touched. The content
997 /// update is placed in a queue until it becomes active. After commit, the
998 /// new pending state is as documented for each related request.
999 ///
1000 /// When the content update is applied, the wl_buffer is applied before all
1001 /// other state. This means that all coordinates in double-buffered state
1002 /// are relative to the newly attached wl_buffers, except for
1003 /// wl_surface.attach itself. If there is no newly attached wl_buffer, the
1004 /// coordinates are relative to the previous content update.
1005 ///
1006 /// All requests that need a commit to become effective are documented
1007 /// to affect double-buffered state.
1008 ///
1009 /// Other interfaces may add further double-buffered surface state.
1010 #[inline]
1011 pub fn try_send_commit(
1012 &self,
1013 ) -> Result<(), ObjectError> {
1014 let core = self.core();
1015 let Some(id) = core.server_obj_id.get() else {
1016 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1017 };
1018 #[cfg(feature = "logging")]
1019 if self.core.state.log {
1020 #[cold]
1021 fn log(state: &State, id: u32) {
1022 let (millis, micros) = time_since_epoch();
1023 let prefix = &state.log_prefix;
1024 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.commit()\n", id);
1025 state.log(args);
1026 }
1027 log(&self.core.state, id);
1028 }
1029 let Some(endpoint) = &self.core.state.server else {
1030 return Ok(());
1031 };
1032 if !endpoint.flush_queued.replace(true) {
1033 self.core.state.add_flushable_endpoint(endpoint, None);
1034 }
1035 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1036 let outgoing = &mut *outgoing_ref;
1037 let mut fmt = outgoing.formatter();
1038 fmt.words([
1039 id,
1040 6,
1041 ]);
1042 Ok(())
1043 }
1044
1045 /// commit pending surface state
1046 ///
1047 /// Surface state (input, opaque, and damage regions, attached buffers,
1048 /// etc.) is double-buffered. Protocol requests modify the pending state,
1049 /// as opposed to the active state in use by the compositor.
1050 ///
1051 /// A commit request atomically creates a content update from the pending
1052 /// state, even if the pending state has not been touched. The content
1053 /// update is placed in a queue until it becomes active. After commit, the
1054 /// new pending state is as documented for each related request.
1055 ///
1056 /// When the content update is applied, the wl_buffer is applied before all
1057 /// other state. This means that all coordinates in double-buffered state
1058 /// are relative to the newly attached wl_buffers, except for
1059 /// wl_surface.attach itself. If there is no newly attached wl_buffer, the
1060 /// coordinates are relative to the previous content update.
1061 ///
1062 /// All requests that need a commit to become effective are documented
1063 /// to affect double-buffered state.
1064 ///
1065 /// Other interfaces may add further double-buffered surface state.
1066 #[inline]
1067 pub fn send_commit(
1068 &self,
1069 ) {
1070 let res = self.try_send_commit(
1071 );
1072 if let Err(e) = res {
1073 log_send("wl_surface.commit", &e);
1074 }
1075 }
1076
1077 /// Since when the enter message is available.
1078 pub const MSG__ENTER__SINCE: u32 = 1;
1079
1080 /// surface enters an output
1081 ///
1082 /// This is emitted whenever a surface's creation, movement, or resizing
1083 /// results in some part of it being within the scanout region of an
1084 /// output.
1085 ///
1086 /// Note that a surface may be overlapping with zero or more outputs.
1087 ///
1088 /// # Arguments
1089 ///
1090 /// - `output`: output entered by the surface
1091 #[inline]
1092 pub fn try_send_enter(
1093 &self,
1094 output: &Rc<WlOutput>,
1095 ) -> Result<(), ObjectError> {
1096 let (
1097 arg0,
1098 ) = (
1099 output,
1100 );
1101 let arg0 = arg0.core();
1102 let core = self.core();
1103 let client_ref = core.client.borrow();
1104 let Some(client) = &*client_ref else {
1105 return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1106 };
1107 let id = core.client_obj_id.get().unwrap_or(0);
1108 if arg0.client_id.get() != Some(client.endpoint.id) {
1109 return Err(ObjectError(ObjectErrorKind::ArgNoClientId("output", client.endpoint.id)));
1110 }
1111 let arg0_id = arg0.client_obj_id.get().unwrap_or(0);
1112 #[cfg(feature = "logging")]
1113 if self.core.state.log {
1114 #[cold]
1115 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
1116 let (millis, micros) = time_since_epoch();
1117 let prefix = &state.log_prefix;
1118 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.enter(output: wl_output#{})\n", client_id, id, arg0);
1119 state.log(args);
1120 }
1121 log(&self.core.state, client.endpoint.id, id, arg0_id);
1122 }
1123 let endpoint = &client.endpoint;
1124 if !endpoint.flush_queued.replace(true) {
1125 self.core.state.add_flushable_endpoint(endpoint, Some(client));
1126 }
1127 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1128 let outgoing = &mut *outgoing_ref;
1129 let mut fmt = outgoing.formatter();
1130 fmt.words([
1131 id,
1132 0,
1133 arg0_id,
1134 ]);
1135 Ok(())
1136 }
1137
1138 /// surface enters an output
1139 ///
1140 /// This is emitted whenever a surface's creation, movement, or resizing
1141 /// results in some part of it being within the scanout region of an
1142 /// output.
1143 ///
1144 /// Note that a surface may be overlapping with zero or more outputs.
1145 ///
1146 /// # Arguments
1147 ///
1148 /// - `output`: output entered by the surface
1149 #[inline]
1150 pub fn send_enter(
1151 &self,
1152 output: &Rc<WlOutput>,
1153 ) {
1154 let res = self.try_send_enter(
1155 output,
1156 );
1157 if let Err(e) = res {
1158 log_send("wl_surface.enter", &e);
1159 }
1160 }
1161
1162 /// Since when the leave message is available.
1163 pub const MSG__LEAVE__SINCE: u32 = 1;
1164
1165 /// surface leaves an output
1166 ///
1167 /// This is emitted whenever a surface's creation, movement, or resizing
1168 /// results in it no longer having any part of it within the scanout region
1169 /// of an output.
1170 ///
1171 /// Clients should not use the number of outputs the surface is on for frame
1172 /// throttling purposes. The surface might be hidden even if no leave event
1173 /// has been sent, and the compositor might expect new surface content
1174 /// updates even if no enter event has been sent. The frame event should be
1175 /// used instead.
1176 ///
1177 /// # Arguments
1178 ///
1179 /// - `output`: output left by the surface
1180 #[inline]
1181 pub fn try_send_leave(
1182 &self,
1183 output: &Rc<WlOutput>,
1184 ) -> Result<(), ObjectError> {
1185 let (
1186 arg0,
1187 ) = (
1188 output,
1189 );
1190 let arg0 = arg0.core();
1191 let core = self.core();
1192 let client_ref = core.client.borrow();
1193 let Some(client) = &*client_ref else {
1194 return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1195 };
1196 let id = core.client_obj_id.get().unwrap_or(0);
1197 if arg0.client_id.get() != Some(client.endpoint.id) {
1198 return Err(ObjectError(ObjectErrorKind::ArgNoClientId("output", client.endpoint.id)));
1199 }
1200 let arg0_id = arg0.client_obj_id.get().unwrap_or(0);
1201 #[cfg(feature = "logging")]
1202 if self.core.state.log {
1203 #[cold]
1204 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
1205 let (millis, micros) = time_since_epoch();
1206 let prefix = &state.log_prefix;
1207 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.leave(output: wl_output#{})\n", client_id, id, arg0);
1208 state.log(args);
1209 }
1210 log(&self.core.state, client.endpoint.id, id, arg0_id);
1211 }
1212 let endpoint = &client.endpoint;
1213 if !endpoint.flush_queued.replace(true) {
1214 self.core.state.add_flushable_endpoint(endpoint, Some(client));
1215 }
1216 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1217 let outgoing = &mut *outgoing_ref;
1218 let mut fmt = outgoing.formatter();
1219 fmt.words([
1220 id,
1221 1,
1222 arg0_id,
1223 ]);
1224 Ok(())
1225 }
1226
1227 /// surface leaves an output
1228 ///
1229 /// This is emitted whenever a surface's creation, movement, or resizing
1230 /// results in it no longer having any part of it within the scanout region
1231 /// of an output.
1232 ///
1233 /// Clients should not use the number of outputs the surface is on for frame
1234 /// throttling purposes. The surface might be hidden even if no leave event
1235 /// has been sent, and the compositor might expect new surface content
1236 /// updates even if no enter event has been sent. The frame event should be
1237 /// used instead.
1238 ///
1239 /// # Arguments
1240 ///
1241 /// - `output`: output left by the surface
1242 #[inline]
1243 pub fn send_leave(
1244 &self,
1245 output: &Rc<WlOutput>,
1246 ) {
1247 let res = self.try_send_leave(
1248 output,
1249 );
1250 if let Err(e) = res {
1251 log_send("wl_surface.leave", &e);
1252 }
1253 }
1254
1255 /// Since when the set_buffer_transform message is available.
1256 pub const MSG__SET_BUFFER_TRANSFORM__SINCE: u32 = 2;
1257
1258 /// sets the buffer transformation
1259 ///
1260 /// This request sets the transformation that the client has already applied
1261 /// to the content of the buffer. The accepted values for the transform
1262 /// parameter are the values for wl_output.transform.
1263 ///
1264 /// The compositor applies the inverse of this transformation whenever it
1265 /// uses the buffer contents.
1266 ///
1267 /// Buffer transform is double-buffered state, see wl_surface.commit.
1268 ///
1269 /// A newly created surface has its buffer transformation set to normal.
1270 ///
1271 /// wl_surface.set_buffer_transform changes the pending buffer
1272 /// transformation. wl_surface.commit copies the pending buffer
1273 /// transformation to the current one. Otherwise, the pending and current
1274 /// values are never changed.
1275 ///
1276 /// The purpose of this request is to allow clients to render content
1277 /// according to the output transform, thus permitting the compositor to
1278 /// use certain optimizations even if the display is rotated. Using
1279 /// hardware overlays and scanning out a client buffer for fullscreen
1280 /// surfaces are examples of such optimizations. Those optimizations are
1281 /// highly dependent on the compositor implementation, so the use of this
1282 /// request should be considered on a case-by-case basis.
1283 ///
1284 /// Note that if the transform value includes 90 or 270 degree rotation,
1285 /// the width of the buffer will become the surface height and the height
1286 /// of the buffer will become the surface width.
1287 ///
1288 /// If transform is not one of the values from the
1289 /// wl_output.transform enum the invalid_transform protocol error
1290 /// is raised.
1291 ///
1292 /// # Arguments
1293 ///
1294 /// - `transform`: transform for interpreting buffer contents
1295 #[inline]
1296 pub fn try_send_set_buffer_transform(
1297 &self,
1298 transform: WlOutputTransform,
1299 ) -> Result<(), ObjectError> {
1300 let (
1301 arg0,
1302 ) = (
1303 transform,
1304 );
1305 let core = self.core();
1306 let Some(id) = core.server_obj_id.get() else {
1307 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1308 };
1309 #[cfg(feature = "logging")]
1310 if self.core.state.log {
1311 #[cold]
1312 fn log(state: &State, id: u32, arg0: WlOutputTransform) {
1313 let (millis, micros) = time_since_epoch();
1314 let prefix = &state.log_prefix;
1315 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.set_buffer_transform(transform: {:?})\n", id, arg0);
1316 state.log(args);
1317 }
1318 log(&self.core.state, id, arg0);
1319 }
1320 let Some(endpoint) = &self.core.state.server else {
1321 return Ok(());
1322 };
1323 if !endpoint.flush_queued.replace(true) {
1324 self.core.state.add_flushable_endpoint(endpoint, None);
1325 }
1326 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1327 let outgoing = &mut *outgoing_ref;
1328 let mut fmt = outgoing.formatter();
1329 fmt.words([
1330 id,
1331 7,
1332 arg0.0,
1333 ]);
1334 Ok(())
1335 }
1336
1337 /// sets the buffer transformation
1338 ///
1339 /// This request sets the transformation that the client has already applied
1340 /// to the content of the buffer. The accepted values for the transform
1341 /// parameter are the values for wl_output.transform.
1342 ///
1343 /// The compositor applies the inverse of this transformation whenever it
1344 /// uses the buffer contents.
1345 ///
1346 /// Buffer transform is double-buffered state, see wl_surface.commit.
1347 ///
1348 /// A newly created surface has its buffer transformation set to normal.
1349 ///
1350 /// wl_surface.set_buffer_transform changes the pending buffer
1351 /// transformation. wl_surface.commit copies the pending buffer
1352 /// transformation to the current one. Otherwise, the pending and current
1353 /// values are never changed.
1354 ///
1355 /// The purpose of this request is to allow clients to render content
1356 /// according to the output transform, thus permitting the compositor to
1357 /// use certain optimizations even if the display is rotated. Using
1358 /// hardware overlays and scanning out a client buffer for fullscreen
1359 /// surfaces are examples of such optimizations. Those optimizations are
1360 /// highly dependent on the compositor implementation, so the use of this
1361 /// request should be considered on a case-by-case basis.
1362 ///
1363 /// Note that if the transform value includes 90 or 270 degree rotation,
1364 /// the width of the buffer will become the surface height and the height
1365 /// of the buffer will become the surface width.
1366 ///
1367 /// If transform is not one of the values from the
1368 /// wl_output.transform enum the invalid_transform protocol error
1369 /// is raised.
1370 ///
1371 /// # Arguments
1372 ///
1373 /// - `transform`: transform for interpreting buffer contents
1374 #[inline]
1375 pub fn send_set_buffer_transform(
1376 &self,
1377 transform: WlOutputTransform,
1378 ) {
1379 let res = self.try_send_set_buffer_transform(
1380 transform,
1381 );
1382 if let Err(e) = res {
1383 log_send("wl_surface.set_buffer_transform", &e);
1384 }
1385 }
1386
1387 /// Since when the set_buffer_scale message is available.
1388 pub const MSG__SET_BUFFER_SCALE__SINCE: u32 = 3;
1389
1390 /// sets the buffer scaling factor
1391 ///
1392 /// This request sets an optional scaling factor on how the compositor
1393 /// interprets the contents of the buffer attached to the window.
1394 ///
1395 /// Buffer scale is double-buffered state, see wl_surface.commit.
1396 ///
1397 /// A newly created surface has its buffer scale set to 1.
1398 ///
1399 /// wl_surface.set_buffer_scale changes the pending buffer scale.
1400 /// wl_surface.commit copies the pending buffer scale to the current one.
1401 /// Otherwise, the pending and current values are never changed.
1402 ///
1403 /// The purpose of this request is to allow clients to supply higher
1404 /// resolution buffer data for use on high resolution outputs. It is
1405 /// intended that you pick the same buffer scale as the scale of the
1406 /// output that the surface is displayed on. This means the compositor
1407 /// can avoid scaling when rendering the surface on that output.
1408 ///
1409 /// Note that if the scale is larger than 1, then you have to attach
1410 /// a buffer that is larger (by a factor of scale in each dimension)
1411 /// than the desired surface size.
1412 ///
1413 /// If scale is not greater than 0 the invalid_scale protocol error is
1414 /// raised.
1415 ///
1416 /// # Arguments
1417 ///
1418 /// - `scale`: scale for interpreting buffer contents
1419 #[inline]
1420 pub fn try_send_set_buffer_scale(
1421 &self,
1422 scale: i32,
1423 ) -> Result<(), ObjectError> {
1424 let (
1425 arg0,
1426 ) = (
1427 scale,
1428 );
1429 let core = self.core();
1430 let Some(id) = core.server_obj_id.get() else {
1431 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1432 };
1433 #[cfg(feature = "logging")]
1434 if self.core.state.log {
1435 #[cold]
1436 fn log(state: &State, id: u32, arg0: i32) {
1437 let (millis, micros) = time_since_epoch();
1438 let prefix = &state.log_prefix;
1439 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.set_buffer_scale(scale: {})\n", id, arg0);
1440 state.log(args);
1441 }
1442 log(&self.core.state, id, arg0);
1443 }
1444 let Some(endpoint) = &self.core.state.server else {
1445 return Ok(());
1446 };
1447 if !endpoint.flush_queued.replace(true) {
1448 self.core.state.add_flushable_endpoint(endpoint, None);
1449 }
1450 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1451 let outgoing = &mut *outgoing_ref;
1452 let mut fmt = outgoing.formatter();
1453 fmt.words([
1454 id,
1455 8,
1456 arg0 as u32,
1457 ]);
1458 Ok(())
1459 }
1460
1461 /// sets the buffer scaling factor
1462 ///
1463 /// This request sets an optional scaling factor on how the compositor
1464 /// interprets the contents of the buffer attached to the window.
1465 ///
1466 /// Buffer scale is double-buffered state, see wl_surface.commit.
1467 ///
1468 /// A newly created surface has its buffer scale set to 1.
1469 ///
1470 /// wl_surface.set_buffer_scale changes the pending buffer scale.
1471 /// wl_surface.commit copies the pending buffer scale to the current one.
1472 /// Otherwise, the pending and current values are never changed.
1473 ///
1474 /// The purpose of this request is to allow clients to supply higher
1475 /// resolution buffer data for use on high resolution outputs. It is
1476 /// intended that you pick the same buffer scale as the scale of the
1477 /// output that the surface is displayed on. This means the compositor
1478 /// can avoid scaling when rendering the surface on that output.
1479 ///
1480 /// Note that if the scale is larger than 1, then you have to attach
1481 /// a buffer that is larger (by a factor of scale in each dimension)
1482 /// than the desired surface size.
1483 ///
1484 /// If scale is not greater than 0 the invalid_scale protocol error is
1485 /// raised.
1486 ///
1487 /// # Arguments
1488 ///
1489 /// - `scale`: scale for interpreting buffer contents
1490 #[inline]
1491 pub fn send_set_buffer_scale(
1492 &self,
1493 scale: i32,
1494 ) {
1495 let res = self.try_send_set_buffer_scale(
1496 scale,
1497 );
1498 if let Err(e) = res {
1499 log_send("wl_surface.set_buffer_scale", &e);
1500 }
1501 }
1502
1503 /// Since when the damage_buffer message is available.
1504 pub const MSG__DAMAGE_BUFFER__SINCE: u32 = 4;
1505
1506 /// mark part of the surface damaged using buffer coordinates
1507 ///
1508 /// This request is used to describe the regions where the pending
1509 /// buffer is different from the current surface contents, and where
1510 /// the surface therefore needs to be repainted. The compositor
1511 /// ignores the parts of the damage that fall outside of the surface.
1512 ///
1513 /// Damage is double-buffered state, see wl_surface.commit.
1514 ///
1515 /// The damage rectangle is specified in buffer coordinates,
1516 /// where x and y specify the upper left corner of the damage rectangle.
1517 ///
1518 /// The initial value for pending damage is empty: no damage.
1519 /// wl_surface.damage_buffer adds pending damage: the new pending
1520 /// damage is the union of old pending damage and the given rectangle.
1521 ///
1522 /// wl_surface.commit assigns pending damage as the current damage,
1523 /// and clears pending damage. The server will clear the current
1524 /// damage as it repaints the surface.
1525 ///
1526 /// This request differs from wl_surface.damage in only one way - it
1527 /// takes damage in buffer coordinates instead of surface-local
1528 /// coordinates. While this generally is more intuitive than surface
1529 /// coordinates, it is especially desirable when using wp_viewport
1530 /// or when a drawing library (like EGL) is unaware of buffer scale
1531 /// and buffer transform.
1532 ///
1533 /// Note: Because buffer transformation changes and damage requests may
1534 /// be interleaved in the protocol stream, it is impossible to determine
1535 /// the actual mapping between surface and buffer damage until
1536 /// wl_surface.commit time. Therefore, compositors wishing to take both
1537 /// kinds of damage into account will have to accumulate damage from the
1538 /// two requests separately and only transform from one to the other
1539 /// after receiving the wl_surface.commit.
1540 ///
1541 /// # Arguments
1542 ///
1543 /// - `x`: buffer-local x coordinate
1544 /// - `y`: buffer-local y coordinate
1545 /// - `width`: width of damage rectangle
1546 /// - `height`: height of damage rectangle
1547 #[inline]
1548 pub fn try_send_damage_buffer(
1549 &self,
1550 x: i32,
1551 y: i32,
1552 width: i32,
1553 height: i32,
1554 ) -> Result<(), ObjectError> {
1555 let (
1556 arg0,
1557 arg1,
1558 arg2,
1559 arg3,
1560 ) = (
1561 x,
1562 y,
1563 width,
1564 height,
1565 );
1566 let core = self.core();
1567 let Some(id) = core.server_obj_id.get() else {
1568 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1569 };
1570 #[cfg(feature = "logging")]
1571 if self.core.state.log {
1572 #[cold]
1573 fn log(state: &State, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
1574 let (millis, micros) = time_since_epoch();
1575 let prefix = &state.log_prefix;
1576 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.damage_buffer(x: {}, y: {}, width: {}, height: {})\n", id, arg0, arg1, arg2, arg3);
1577 state.log(args);
1578 }
1579 log(&self.core.state, id, arg0, arg1, arg2, arg3);
1580 }
1581 let Some(endpoint) = &self.core.state.server else {
1582 return Ok(());
1583 };
1584 if !endpoint.flush_queued.replace(true) {
1585 self.core.state.add_flushable_endpoint(endpoint, None);
1586 }
1587 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1588 let outgoing = &mut *outgoing_ref;
1589 let mut fmt = outgoing.formatter();
1590 fmt.words([
1591 id,
1592 9,
1593 arg0 as u32,
1594 arg1 as u32,
1595 arg2 as u32,
1596 arg3 as u32,
1597 ]);
1598 Ok(())
1599 }
1600
1601 /// mark part of the surface damaged using buffer coordinates
1602 ///
1603 /// This request is used to describe the regions where the pending
1604 /// buffer is different from the current surface contents, and where
1605 /// the surface therefore needs to be repainted. The compositor
1606 /// ignores the parts of the damage that fall outside of the surface.
1607 ///
1608 /// Damage is double-buffered state, see wl_surface.commit.
1609 ///
1610 /// The damage rectangle is specified in buffer coordinates,
1611 /// where x and y specify the upper left corner of the damage rectangle.
1612 ///
1613 /// The initial value for pending damage is empty: no damage.
1614 /// wl_surface.damage_buffer adds pending damage: the new pending
1615 /// damage is the union of old pending damage and the given rectangle.
1616 ///
1617 /// wl_surface.commit assigns pending damage as the current damage,
1618 /// and clears pending damage. The server will clear the current
1619 /// damage as it repaints the surface.
1620 ///
1621 /// This request differs from wl_surface.damage in only one way - it
1622 /// takes damage in buffer coordinates instead of surface-local
1623 /// coordinates. While this generally is more intuitive than surface
1624 /// coordinates, it is especially desirable when using wp_viewport
1625 /// or when a drawing library (like EGL) is unaware of buffer scale
1626 /// and buffer transform.
1627 ///
1628 /// Note: Because buffer transformation changes and damage requests may
1629 /// be interleaved in the protocol stream, it is impossible to determine
1630 /// the actual mapping between surface and buffer damage until
1631 /// wl_surface.commit time. Therefore, compositors wishing to take both
1632 /// kinds of damage into account will have to accumulate damage from the
1633 /// two requests separately and only transform from one to the other
1634 /// after receiving the wl_surface.commit.
1635 ///
1636 /// # Arguments
1637 ///
1638 /// - `x`: buffer-local x coordinate
1639 /// - `y`: buffer-local y coordinate
1640 /// - `width`: width of damage rectangle
1641 /// - `height`: height of damage rectangle
1642 #[inline]
1643 pub fn send_damage_buffer(
1644 &self,
1645 x: i32,
1646 y: i32,
1647 width: i32,
1648 height: i32,
1649 ) {
1650 let res = self.try_send_damage_buffer(
1651 x,
1652 y,
1653 width,
1654 height,
1655 );
1656 if let Err(e) = res {
1657 log_send("wl_surface.damage_buffer", &e);
1658 }
1659 }
1660
1661 /// Since when the offset message is available.
1662 pub const MSG__OFFSET__SINCE: u32 = 5;
1663
1664 /// set the surface contents offset
1665 ///
1666 /// The x and y arguments specify the location of the new pending
1667 /// buffer's upper left corner, relative to the current buffer's upper
1668 /// left corner, in surface-local coordinates. In other words, the
1669 /// x and y, combined with the new surface size define in which
1670 /// directions the surface's size changes.
1671 ///
1672 /// The exact semantics of wl_surface.offset are role-specific. Refer to
1673 /// the documentation of specific roles for more information.
1674 ///
1675 /// Surface location offset is double-buffered state, see
1676 /// wl_surface.commit.
1677 ///
1678 /// This request is semantically equivalent to and the replaces the x and y
1679 /// arguments in the wl_surface.attach request in wl_surface versions prior
1680 /// to 5. See wl_surface.attach for details.
1681 ///
1682 /// # Arguments
1683 ///
1684 /// - `x`: surface-local x coordinate
1685 /// - `y`: surface-local y coordinate
1686 #[inline]
1687 pub fn try_send_offset(
1688 &self,
1689 x: i32,
1690 y: i32,
1691 ) -> Result<(), ObjectError> {
1692 let (
1693 arg0,
1694 arg1,
1695 ) = (
1696 x,
1697 y,
1698 );
1699 let core = self.core();
1700 let Some(id) = core.server_obj_id.get() else {
1701 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1702 };
1703 #[cfg(feature = "logging")]
1704 if self.core.state.log {
1705 #[cold]
1706 fn log(state: &State, id: u32, arg0: i32, arg1: i32) {
1707 let (millis, micros) = time_since_epoch();
1708 let prefix = &state.log_prefix;
1709 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.offset(x: {}, y: {})\n", id, arg0, arg1);
1710 state.log(args);
1711 }
1712 log(&self.core.state, id, arg0, arg1);
1713 }
1714 let Some(endpoint) = &self.core.state.server else {
1715 return Ok(());
1716 };
1717 if !endpoint.flush_queued.replace(true) {
1718 self.core.state.add_flushable_endpoint(endpoint, None);
1719 }
1720 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1721 let outgoing = &mut *outgoing_ref;
1722 let mut fmt = outgoing.formatter();
1723 fmt.words([
1724 id,
1725 10,
1726 arg0 as u32,
1727 arg1 as u32,
1728 ]);
1729 Ok(())
1730 }
1731
1732 /// set the surface contents offset
1733 ///
1734 /// The x and y arguments specify the location of the new pending
1735 /// buffer's upper left corner, relative to the current buffer's upper
1736 /// left corner, in surface-local coordinates. In other words, the
1737 /// x and y, combined with the new surface size define in which
1738 /// directions the surface's size changes.
1739 ///
1740 /// The exact semantics of wl_surface.offset are role-specific. Refer to
1741 /// the documentation of specific roles for more information.
1742 ///
1743 /// Surface location offset is double-buffered state, see
1744 /// wl_surface.commit.
1745 ///
1746 /// This request is semantically equivalent to and the replaces the x and y
1747 /// arguments in the wl_surface.attach request in wl_surface versions prior
1748 /// to 5. See wl_surface.attach for details.
1749 ///
1750 /// # Arguments
1751 ///
1752 /// - `x`: surface-local x coordinate
1753 /// - `y`: surface-local y coordinate
1754 #[inline]
1755 pub fn send_offset(
1756 &self,
1757 x: i32,
1758 y: i32,
1759 ) {
1760 let res = self.try_send_offset(
1761 x,
1762 y,
1763 );
1764 if let Err(e) = res {
1765 log_send("wl_surface.offset", &e);
1766 }
1767 }
1768
1769 /// Since when the preferred_buffer_scale message is available.
1770 pub const MSG__PREFERRED_BUFFER_SCALE__SINCE: u32 = 6;
1771
1772 /// preferred buffer scale for the surface
1773 ///
1774 /// This event indicates the preferred buffer scale for this surface. It is
1775 /// sent whenever the compositor's preference changes.
1776 ///
1777 /// Before receiving this event the preferred buffer scale for this surface
1778 /// is 1.
1779 ///
1780 /// It is intended that scaling aware clients use this event to scale their
1781 /// content and use wl_surface.set_buffer_scale to indicate the scale they
1782 /// have rendered with. This allows clients to supply a higher detail
1783 /// buffer.
1784 ///
1785 /// The compositor shall emit a scale value greater than 0.
1786 ///
1787 /// # Arguments
1788 ///
1789 /// - `factor`: preferred scaling factor
1790 #[inline]
1791 pub fn try_send_preferred_buffer_scale(
1792 &self,
1793 factor: i32,
1794 ) -> Result<(), ObjectError> {
1795 let (
1796 arg0,
1797 ) = (
1798 factor,
1799 );
1800 let core = self.core();
1801 let client_ref = core.client.borrow();
1802 let Some(client) = &*client_ref else {
1803 return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1804 };
1805 let id = core.client_obj_id.get().unwrap_or(0);
1806 #[cfg(feature = "logging")]
1807 if self.core.state.log {
1808 #[cold]
1809 fn log(state: &State, client_id: u64, id: u32, arg0: i32) {
1810 let (millis, micros) = time_since_epoch();
1811 let prefix = &state.log_prefix;
1812 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.preferred_buffer_scale(factor: {})\n", client_id, id, arg0);
1813 state.log(args);
1814 }
1815 log(&self.core.state, client.endpoint.id, id, arg0);
1816 }
1817 let endpoint = &client.endpoint;
1818 if !endpoint.flush_queued.replace(true) {
1819 self.core.state.add_flushable_endpoint(endpoint, Some(client));
1820 }
1821 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1822 let outgoing = &mut *outgoing_ref;
1823 let mut fmt = outgoing.formatter();
1824 fmt.words([
1825 id,
1826 2,
1827 arg0 as u32,
1828 ]);
1829 Ok(())
1830 }
1831
1832 /// preferred buffer scale for the surface
1833 ///
1834 /// This event indicates the preferred buffer scale for this surface. It is
1835 /// sent whenever the compositor's preference changes.
1836 ///
1837 /// Before receiving this event the preferred buffer scale for this surface
1838 /// is 1.
1839 ///
1840 /// It is intended that scaling aware clients use this event to scale their
1841 /// content and use wl_surface.set_buffer_scale to indicate the scale they
1842 /// have rendered with. This allows clients to supply a higher detail
1843 /// buffer.
1844 ///
1845 /// The compositor shall emit a scale value greater than 0.
1846 ///
1847 /// # Arguments
1848 ///
1849 /// - `factor`: preferred scaling factor
1850 #[inline]
1851 pub fn send_preferred_buffer_scale(
1852 &self,
1853 factor: i32,
1854 ) {
1855 let res = self.try_send_preferred_buffer_scale(
1856 factor,
1857 );
1858 if let Err(e) = res {
1859 log_send("wl_surface.preferred_buffer_scale", &e);
1860 }
1861 }
1862
1863 /// Since when the preferred_buffer_transform message is available.
1864 pub const MSG__PREFERRED_BUFFER_TRANSFORM__SINCE: u32 = 6;
1865
1866 /// preferred buffer transform for the surface
1867 ///
1868 /// This event indicates the preferred buffer transform for this surface.
1869 /// It is sent whenever the compositor's preference changes.
1870 ///
1871 /// Before receiving this event the preferred buffer transform for this
1872 /// surface is normal.
1873 ///
1874 /// Applying this transformation to the surface buffer contents and using
1875 /// wl_surface.set_buffer_transform might allow the compositor to use the
1876 /// surface buffer more efficiently.
1877 ///
1878 /// # Arguments
1879 ///
1880 /// - `transform`: preferred transform
1881 #[inline]
1882 pub fn try_send_preferred_buffer_transform(
1883 &self,
1884 transform: WlOutputTransform,
1885 ) -> Result<(), ObjectError> {
1886 let (
1887 arg0,
1888 ) = (
1889 transform,
1890 );
1891 let core = self.core();
1892 let client_ref = core.client.borrow();
1893 let Some(client) = &*client_ref else {
1894 return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1895 };
1896 let id = core.client_obj_id.get().unwrap_or(0);
1897 #[cfg(feature = "logging")]
1898 if self.core.state.log {
1899 #[cold]
1900 fn log(state: &State, client_id: u64, id: u32, arg0: WlOutputTransform) {
1901 let (millis, micros) = time_since_epoch();
1902 let prefix = &state.log_prefix;
1903 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.preferred_buffer_transform(transform: {:?})\n", client_id, id, arg0);
1904 state.log(args);
1905 }
1906 log(&self.core.state, client.endpoint.id, id, arg0);
1907 }
1908 let endpoint = &client.endpoint;
1909 if !endpoint.flush_queued.replace(true) {
1910 self.core.state.add_flushable_endpoint(endpoint, Some(client));
1911 }
1912 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1913 let outgoing = &mut *outgoing_ref;
1914 let mut fmt = outgoing.formatter();
1915 fmt.words([
1916 id,
1917 3,
1918 arg0.0,
1919 ]);
1920 Ok(())
1921 }
1922
1923 /// preferred buffer transform for the surface
1924 ///
1925 /// This event indicates the preferred buffer transform for this surface.
1926 /// It is sent whenever the compositor's preference changes.
1927 ///
1928 /// Before receiving this event the preferred buffer transform for this
1929 /// surface is normal.
1930 ///
1931 /// Applying this transformation to the surface buffer contents and using
1932 /// wl_surface.set_buffer_transform might allow the compositor to use the
1933 /// surface buffer more efficiently.
1934 ///
1935 /// # Arguments
1936 ///
1937 /// - `transform`: preferred transform
1938 #[inline]
1939 pub fn send_preferred_buffer_transform(
1940 &self,
1941 transform: WlOutputTransform,
1942 ) {
1943 let res = self.try_send_preferred_buffer_transform(
1944 transform,
1945 );
1946 if let Err(e) = res {
1947 log_send("wl_surface.preferred_buffer_transform", &e);
1948 }
1949 }
1950}
1951
1952/// A message handler for [`WlSurface`] proxies.
1953pub trait WlSurfaceHandler: Any {
1954 /// Event handler for wl_display.delete_id messages deleting the ID of this object.
1955 ///
1956 /// The default handler forwards the event to the client, if any.
1957 #[inline]
1958 fn delete_id(&mut self, slf: &Rc<WlSurface>) {
1959 slf.core.delete_id();
1960 }
1961
1962 /// delete surface
1963 ///
1964 /// Deletes the surface and invalidates its object ID.
1965 #[inline]
1966 fn handle_destroy(
1967 &mut self,
1968 slf: &Rc<WlSurface>,
1969 ) {
1970 if !slf.core.forward_to_server.get() {
1971 return;
1972 }
1973 let res = slf.try_send_destroy(
1974 );
1975 if let Err(e) = res {
1976 log_forward("wl_surface.destroy", &e);
1977 }
1978 }
1979
1980 /// set the surface contents
1981 ///
1982 /// Set a buffer as the content of this surface.
1983 ///
1984 /// The new size of the surface is calculated based on the buffer
1985 /// size transformed by the inverse buffer_transform and the
1986 /// inverse buffer_scale. This means that at commit time the supplied
1987 /// buffer size must be an integer multiple of the buffer_scale. If
1988 /// that's not the case, an invalid_size error is sent.
1989 ///
1990 /// The x and y arguments specify the location of the new pending
1991 /// buffer's upper left corner, relative to the current buffer's upper
1992 /// left corner, in surface-local coordinates. In other words, the
1993 /// x and y, combined with the new surface size define in which
1994 /// directions the surface's size changes. Setting anything other than 0
1995 /// as x and y arguments is discouraged, and should instead be replaced
1996 /// with using the separate wl_surface.offset request.
1997 ///
1998 /// When the bound wl_surface version is 5 or higher, passing any
1999 /// non-zero x or y is a protocol violation, and will result in an
2000 /// 'invalid_offset' error being raised. The x and y arguments are ignored
2001 /// and do not change the pending state. To achieve equivalent semantics,
2002 /// use wl_surface.offset.
2003 ///
2004 /// Surface contents are double-buffered state, see wl_surface.commit.
2005 ///
2006 /// The initial surface contents are void; there is no content.
2007 /// wl_surface.attach assigns the given wl_buffer as the pending
2008 /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
2009 /// surface contents, and the size of the surface becomes the size
2010 /// calculated from the wl_buffer, as described above. After commit,
2011 /// there is no pending buffer until the next attach.
2012 ///
2013 /// Committing a pending wl_buffer allows the compositor to read the
2014 /// pixels in the wl_buffer. The compositor may access the pixels at
2015 /// any time after the wl_surface.commit request. When the compositor
2016 /// will not access the pixels anymore, it will send the
2017 /// wl_buffer.release event. Only after receiving wl_buffer.release,
2018 /// the client may reuse the wl_buffer. A wl_buffer that has been
2019 /// attached and then replaced by another attach instead of committed
2020 /// will not receive a release event, and is not used by the
2021 /// compositor.
2022 ///
2023 /// If a pending wl_buffer has been committed to more than one wl_surface,
2024 /// the delivery of wl_buffer.release events becomes undefined. A well
2025 /// behaved client should not rely on wl_buffer.release events in this
2026 /// case. Alternatively, a client could create multiple wl_buffer objects
2027 /// from the same backing storage or use a protocol extension providing
2028 /// per-commit release notifications.
2029 ///
2030 /// Destroying the wl_buffer after wl_buffer.release does not change
2031 /// the surface contents. Destroying the wl_buffer before wl_buffer.release
2032 /// is allowed as long as the underlying buffer storage isn't re-used (this
2033 /// can happen e.g. on client process termination). However, if the client
2034 /// destroys the wl_buffer before receiving the wl_buffer.release event and
2035 /// mutates the underlying buffer storage, the surface contents become
2036 /// undefined immediately.
2037 ///
2038 /// If wl_surface.attach is sent with a NULL wl_buffer, the
2039 /// following wl_surface.commit will remove the surface content.
2040 ///
2041 /// If a pending wl_buffer has been destroyed, the result is not specified.
2042 /// Many compositors are known to remove the surface content on the following
2043 /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
2044 /// maximise compatibility should not destroy pending buffers and should
2045 /// ensure that they explicitly remove content from surfaces, even after
2046 /// destroying buffers.
2047 ///
2048 /// # Arguments
2049 ///
2050 /// - `buffer`: buffer of surface contents
2051 /// - `x`: surface-local x coordinate
2052 /// - `y`: surface-local y coordinate
2053 ///
2054 /// All borrowed proxies passed to this function are guaranteed to be
2055 /// immutable and non-null.
2056 #[inline]
2057 fn handle_attach(
2058 &mut self,
2059 slf: &Rc<WlSurface>,
2060 buffer: Option<&Rc<WlBuffer>>,
2061 x: i32,
2062 y: i32,
2063 ) {
2064 if !slf.core.forward_to_server.get() {
2065 return;
2066 }
2067 let res = slf.try_send_attach(
2068 buffer,
2069 x,
2070 y,
2071 );
2072 if let Err(e) = res {
2073 log_forward("wl_surface.attach", &e);
2074 }
2075 }
2076
2077 /// mark part of the surface damaged
2078 ///
2079 /// This request is used to describe the regions where the pending
2080 /// buffer is different from the current surface contents, and where
2081 /// the surface therefore needs to be repainted. The compositor
2082 /// ignores the parts of the damage that fall outside of the surface.
2083 ///
2084 /// Damage is double-buffered state, see wl_surface.commit.
2085 ///
2086 /// The damage rectangle is specified in surface-local coordinates,
2087 /// where x and y specify the upper left corner of the damage rectangle.
2088 ///
2089 /// The initial value for pending damage is empty: no damage.
2090 /// wl_surface.damage adds pending damage: the new pending damage
2091 /// is the union of old pending damage and the given rectangle.
2092 ///
2093 /// wl_surface.commit assigns pending damage as the current damage,
2094 /// and clears pending damage. The server will clear the current
2095 /// damage as it repaints the surface.
2096 ///
2097 /// Note! New clients should not use this request. Instead damage can be
2098 /// posted with wl_surface.damage_buffer which uses buffer coordinates
2099 /// instead of surface coordinates.
2100 ///
2101 /// # Arguments
2102 ///
2103 /// - `x`: surface-local x coordinate
2104 /// - `y`: surface-local y coordinate
2105 /// - `width`: width of damage rectangle
2106 /// - `height`: height of damage rectangle
2107 #[inline]
2108 fn handle_damage(
2109 &mut self,
2110 slf: &Rc<WlSurface>,
2111 x: i32,
2112 y: i32,
2113 width: i32,
2114 height: i32,
2115 ) {
2116 if !slf.core.forward_to_server.get() {
2117 return;
2118 }
2119 let res = slf.try_send_damage(
2120 x,
2121 y,
2122 width,
2123 height,
2124 );
2125 if let Err(e) = res {
2126 log_forward("wl_surface.damage", &e);
2127 }
2128 }
2129
2130 /// request a frame throttling hint
2131 ///
2132 /// Request a notification when it is a good time to start drawing a new
2133 /// frame, by creating a frame callback. This is useful for throttling
2134 /// redrawing operations, and driving animations.
2135 ///
2136 /// When a client is animating on a wl_surface, it can use the 'frame'
2137 /// request to get notified when it is a good time to draw and commit the
2138 /// next frame of animation. If the client commits an update earlier than
2139 /// that, it is likely that some updates will not make it to the display,
2140 /// and the client is wasting resources by drawing too often.
2141 ///
2142 /// The frame request will take effect on the next wl_surface.commit.
2143 /// The notification will only be posted for one frame unless
2144 /// requested again. For a wl_surface, the notifications are posted in
2145 /// the order the frame requests were committed.
2146 ///
2147 /// The server must send the notifications so that a client
2148 /// will not send excessive updates, while still allowing
2149 /// the highest possible update rate for clients that wait for the reply
2150 /// before drawing again. The server should give some time for the client
2151 /// to draw and commit after sending the frame callback events to let it
2152 /// hit the next output refresh.
2153 ///
2154 /// A server should avoid signaling the frame callbacks if the
2155 /// surface is not visible in any way, e.g. the surface is off-screen,
2156 /// or completely obscured by other opaque surfaces.
2157 ///
2158 /// The object returned by this request will be destroyed by the
2159 /// compositor after the callback is fired and as such the client must not
2160 /// attempt to use it after that point.
2161 ///
2162 /// The callback_data passed in the callback is the current time, in
2163 /// milliseconds, with an undefined base.
2164 ///
2165 /// # Arguments
2166 ///
2167 /// - `callback`: callback object for the frame request
2168 #[inline]
2169 fn handle_frame(
2170 &mut self,
2171 slf: &Rc<WlSurface>,
2172 callback: &Rc<WlCallback>,
2173 ) {
2174 if !slf.core.forward_to_server.get() {
2175 return;
2176 }
2177 let res = slf.try_send_frame(
2178 callback,
2179 );
2180 if let Err(e) = res {
2181 log_forward("wl_surface.frame", &e);
2182 }
2183 }
2184
2185 /// set opaque region
2186 ///
2187 /// This request sets the region of the surface that contains
2188 /// opaque content.
2189 ///
2190 /// The opaque region is an optimization hint for the compositor
2191 /// that lets it optimize the redrawing of content behind opaque
2192 /// regions. Setting an opaque region is not required for correct
2193 /// behaviour, but marking transparent content as opaque will result
2194 /// in repaint artifacts.
2195 ///
2196 /// The opaque region is specified in surface-local coordinates.
2197 ///
2198 /// The compositor ignores the parts of the opaque region that fall
2199 /// outside of the surface.
2200 ///
2201 /// Opaque region is double-buffered state, see wl_surface.commit.
2202 ///
2203 /// wl_surface.set_opaque_region changes the pending opaque region.
2204 /// wl_surface.commit copies the pending region to the current region.
2205 /// Otherwise, the pending and current regions are never changed.
2206 ///
2207 /// The initial value for an opaque region is empty. Setting the pending
2208 /// opaque region has copy semantics, and the wl_region object can be
2209 /// destroyed immediately. A NULL wl_region causes the pending opaque
2210 /// region to be set to empty.
2211 ///
2212 /// # Arguments
2213 ///
2214 /// - `region`: opaque region of the surface
2215 ///
2216 /// All borrowed proxies passed to this function are guaranteed to be
2217 /// immutable and non-null.
2218 #[inline]
2219 fn handle_set_opaque_region(
2220 &mut self,
2221 slf: &Rc<WlSurface>,
2222 region: Option<&Rc<WlRegion>>,
2223 ) {
2224 if !slf.core.forward_to_server.get() {
2225 return;
2226 }
2227 let res = slf.try_send_set_opaque_region(
2228 region,
2229 );
2230 if let Err(e) = res {
2231 log_forward("wl_surface.set_opaque_region", &e);
2232 }
2233 }
2234
2235 /// set input region
2236 ///
2237 /// This request sets the region of the surface that can receive
2238 /// pointer and touch events.
2239 ///
2240 /// Input events happening outside of this region will try the next
2241 /// surface in the server surface stack. The compositor ignores the
2242 /// parts of the input region that fall outside of the surface.
2243 ///
2244 /// The input region is specified in surface-local coordinates.
2245 ///
2246 /// Input region is double-buffered state, see wl_surface.commit.
2247 ///
2248 /// wl_surface.set_input_region changes the pending input region.
2249 /// wl_surface.commit copies the pending region to the current region.
2250 /// Otherwise the pending and current regions are never changed,
2251 /// except cursor and icon surfaces are special cases, see
2252 /// wl_pointer.set_cursor and wl_data_device.start_drag.
2253 ///
2254 /// The initial value for an input region is infinite. That means the
2255 /// whole surface will accept input. Setting the pending input region
2256 /// has copy semantics, and the wl_region object can be destroyed
2257 /// immediately. A NULL wl_region causes the input region to be set
2258 /// to infinite.
2259 ///
2260 /// # Arguments
2261 ///
2262 /// - `region`: input region of the surface
2263 ///
2264 /// All borrowed proxies passed to this function are guaranteed to be
2265 /// immutable and non-null.
2266 #[inline]
2267 fn handle_set_input_region(
2268 &mut self,
2269 slf: &Rc<WlSurface>,
2270 region: Option<&Rc<WlRegion>>,
2271 ) {
2272 if !slf.core.forward_to_server.get() {
2273 return;
2274 }
2275 let res = slf.try_send_set_input_region(
2276 region,
2277 );
2278 if let Err(e) = res {
2279 log_forward("wl_surface.set_input_region", &e);
2280 }
2281 }
2282
2283 /// commit pending surface state
2284 ///
2285 /// Surface state (input, opaque, and damage regions, attached buffers,
2286 /// etc.) is double-buffered. Protocol requests modify the pending state,
2287 /// as opposed to the active state in use by the compositor.
2288 ///
2289 /// A commit request atomically creates a content update from the pending
2290 /// state, even if the pending state has not been touched. The content
2291 /// update is placed in a queue until it becomes active. After commit, the
2292 /// new pending state is as documented for each related request.
2293 ///
2294 /// When the content update is applied, the wl_buffer is applied before all
2295 /// other state. This means that all coordinates in double-buffered state
2296 /// are relative to the newly attached wl_buffers, except for
2297 /// wl_surface.attach itself. If there is no newly attached wl_buffer, the
2298 /// coordinates are relative to the previous content update.
2299 ///
2300 /// All requests that need a commit to become effective are documented
2301 /// to affect double-buffered state.
2302 ///
2303 /// Other interfaces may add further double-buffered surface state.
2304 #[inline]
2305 fn handle_commit(
2306 &mut self,
2307 slf: &Rc<WlSurface>,
2308 ) {
2309 if !slf.core.forward_to_server.get() {
2310 return;
2311 }
2312 let res = slf.try_send_commit(
2313 );
2314 if let Err(e) = res {
2315 log_forward("wl_surface.commit", &e);
2316 }
2317 }
2318
2319 /// surface enters an output
2320 ///
2321 /// This is emitted whenever a surface's creation, movement, or resizing
2322 /// results in some part of it being within the scanout region of an
2323 /// output.
2324 ///
2325 /// Note that a surface may be overlapping with zero or more outputs.
2326 ///
2327 /// # Arguments
2328 ///
2329 /// - `output`: output entered by the surface
2330 ///
2331 /// All borrowed proxies passed to this function are guaranteed to be
2332 /// immutable and non-null.
2333 #[inline]
2334 fn handle_enter(
2335 &mut self,
2336 slf: &Rc<WlSurface>,
2337 output: &Rc<WlOutput>,
2338 ) {
2339 if !slf.core.forward_to_client.get() {
2340 return;
2341 }
2342 if let Some(client_id) = slf.core.client_id.get() {
2343 if let Some(client_id_2) = output.core().client_id.get() {
2344 if client_id != client_id_2 {
2345 return;
2346 }
2347 }
2348 }
2349 let res = slf.try_send_enter(
2350 output,
2351 );
2352 if let Err(e) = res {
2353 log_forward("wl_surface.enter", &e);
2354 }
2355 }
2356
2357 /// surface leaves an output
2358 ///
2359 /// This is emitted whenever a surface's creation, movement, or resizing
2360 /// results in it no longer having any part of it within the scanout region
2361 /// of an output.
2362 ///
2363 /// Clients should not use the number of outputs the surface is on for frame
2364 /// throttling purposes. The surface might be hidden even if no leave event
2365 /// has been sent, and the compositor might expect new surface content
2366 /// updates even if no enter event has been sent. The frame event should be
2367 /// used instead.
2368 ///
2369 /// # Arguments
2370 ///
2371 /// - `output`: output left by the surface
2372 ///
2373 /// All borrowed proxies passed to this function are guaranteed to be
2374 /// immutable and non-null.
2375 #[inline]
2376 fn handle_leave(
2377 &mut self,
2378 slf: &Rc<WlSurface>,
2379 output: &Rc<WlOutput>,
2380 ) {
2381 if !slf.core.forward_to_client.get() {
2382 return;
2383 }
2384 if let Some(client_id) = slf.core.client_id.get() {
2385 if let Some(client_id_2) = output.core().client_id.get() {
2386 if client_id != client_id_2 {
2387 return;
2388 }
2389 }
2390 }
2391 let res = slf.try_send_leave(
2392 output,
2393 );
2394 if let Err(e) = res {
2395 log_forward("wl_surface.leave", &e);
2396 }
2397 }
2398
2399 /// sets the buffer transformation
2400 ///
2401 /// This request sets the transformation that the client has already applied
2402 /// to the content of the buffer. The accepted values for the transform
2403 /// parameter are the values for wl_output.transform.
2404 ///
2405 /// The compositor applies the inverse of this transformation whenever it
2406 /// uses the buffer contents.
2407 ///
2408 /// Buffer transform is double-buffered state, see wl_surface.commit.
2409 ///
2410 /// A newly created surface has its buffer transformation set to normal.
2411 ///
2412 /// wl_surface.set_buffer_transform changes the pending buffer
2413 /// transformation. wl_surface.commit copies the pending buffer
2414 /// transformation to the current one. Otherwise, the pending and current
2415 /// values are never changed.
2416 ///
2417 /// The purpose of this request is to allow clients to render content
2418 /// according to the output transform, thus permitting the compositor to
2419 /// use certain optimizations even if the display is rotated. Using
2420 /// hardware overlays and scanning out a client buffer for fullscreen
2421 /// surfaces are examples of such optimizations. Those optimizations are
2422 /// highly dependent on the compositor implementation, so the use of this
2423 /// request should be considered on a case-by-case basis.
2424 ///
2425 /// Note that if the transform value includes 90 or 270 degree rotation,
2426 /// the width of the buffer will become the surface height and the height
2427 /// of the buffer will become the surface width.
2428 ///
2429 /// If transform is not one of the values from the
2430 /// wl_output.transform enum the invalid_transform protocol error
2431 /// is raised.
2432 ///
2433 /// # Arguments
2434 ///
2435 /// - `transform`: transform for interpreting buffer contents
2436 #[inline]
2437 fn handle_set_buffer_transform(
2438 &mut self,
2439 slf: &Rc<WlSurface>,
2440 transform: WlOutputTransform,
2441 ) {
2442 if !slf.core.forward_to_server.get() {
2443 return;
2444 }
2445 let res = slf.try_send_set_buffer_transform(
2446 transform,
2447 );
2448 if let Err(e) = res {
2449 log_forward("wl_surface.set_buffer_transform", &e);
2450 }
2451 }
2452
2453 /// sets the buffer scaling factor
2454 ///
2455 /// This request sets an optional scaling factor on how the compositor
2456 /// interprets the contents of the buffer attached to the window.
2457 ///
2458 /// Buffer scale is double-buffered state, see wl_surface.commit.
2459 ///
2460 /// A newly created surface has its buffer scale set to 1.
2461 ///
2462 /// wl_surface.set_buffer_scale changes the pending buffer scale.
2463 /// wl_surface.commit copies the pending buffer scale to the current one.
2464 /// Otherwise, the pending and current values are never changed.
2465 ///
2466 /// The purpose of this request is to allow clients to supply higher
2467 /// resolution buffer data for use on high resolution outputs. It is
2468 /// intended that you pick the same buffer scale as the scale of the
2469 /// output that the surface is displayed on. This means the compositor
2470 /// can avoid scaling when rendering the surface on that output.
2471 ///
2472 /// Note that if the scale is larger than 1, then you have to attach
2473 /// a buffer that is larger (by a factor of scale in each dimension)
2474 /// than the desired surface size.
2475 ///
2476 /// If scale is not greater than 0 the invalid_scale protocol error is
2477 /// raised.
2478 ///
2479 /// # Arguments
2480 ///
2481 /// - `scale`: scale for interpreting buffer contents
2482 #[inline]
2483 fn handle_set_buffer_scale(
2484 &mut self,
2485 slf: &Rc<WlSurface>,
2486 scale: i32,
2487 ) {
2488 if !slf.core.forward_to_server.get() {
2489 return;
2490 }
2491 let res = slf.try_send_set_buffer_scale(
2492 scale,
2493 );
2494 if let Err(e) = res {
2495 log_forward("wl_surface.set_buffer_scale", &e);
2496 }
2497 }
2498
2499 /// mark part of the surface damaged using buffer coordinates
2500 ///
2501 /// This request is used to describe the regions where the pending
2502 /// buffer is different from the current surface contents, and where
2503 /// the surface therefore needs to be repainted. The compositor
2504 /// ignores the parts of the damage that fall outside of the surface.
2505 ///
2506 /// Damage is double-buffered state, see wl_surface.commit.
2507 ///
2508 /// The damage rectangle is specified in buffer coordinates,
2509 /// where x and y specify the upper left corner of the damage rectangle.
2510 ///
2511 /// The initial value for pending damage is empty: no damage.
2512 /// wl_surface.damage_buffer adds pending damage: the new pending
2513 /// damage is the union of old pending damage and the given rectangle.
2514 ///
2515 /// wl_surface.commit assigns pending damage as the current damage,
2516 /// and clears pending damage. The server will clear the current
2517 /// damage as it repaints the surface.
2518 ///
2519 /// This request differs from wl_surface.damage in only one way - it
2520 /// takes damage in buffer coordinates instead of surface-local
2521 /// coordinates. While this generally is more intuitive than surface
2522 /// coordinates, it is especially desirable when using wp_viewport
2523 /// or when a drawing library (like EGL) is unaware of buffer scale
2524 /// and buffer transform.
2525 ///
2526 /// Note: Because buffer transformation changes and damage requests may
2527 /// be interleaved in the protocol stream, it is impossible to determine
2528 /// the actual mapping between surface and buffer damage until
2529 /// wl_surface.commit time. Therefore, compositors wishing to take both
2530 /// kinds of damage into account will have to accumulate damage from the
2531 /// two requests separately and only transform from one to the other
2532 /// after receiving the wl_surface.commit.
2533 ///
2534 /// # Arguments
2535 ///
2536 /// - `x`: buffer-local x coordinate
2537 /// - `y`: buffer-local y coordinate
2538 /// - `width`: width of damage rectangle
2539 /// - `height`: height of damage rectangle
2540 #[inline]
2541 fn handle_damage_buffer(
2542 &mut self,
2543 slf: &Rc<WlSurface>,
2544 x: i32,
2545 y: i32,
2546 width: i32,
2547 height: i32,
2548 ) {
2549 if !slf.core.forward_to_server.get() {
2550 return;
2551 }
2552 let res = slf.try_send_damage_buffer(
2553 x,
2554 y,
2555 width,
2556 height,
2557 );
2558 if let Err(e) = res {
2559 log_forward("wl_surface.damage_buffer", &e);
2560 }
2561 }
2562
2563 /// set the surface contents offset
2564 ///
2565 /// The x and y arguments specify the location of the new pending
2566 /// buffer's upper left corner, relative to the current buffer's upper
2567 /// left corner, in surface-local coordinates. In other words, the
2568 /// x and y, combined with the new surface size define in which
2569 /// directions the surface's size changes.
2570 ///
2571 /// The exact semantics of wl_surface.offset are role-specific. Refer to
2572 /// the documentation of specific roles for more information.
2573 ///
2574 /// Surface location offset is double-buffered state, see
2575 /// wl_surface.commit.
2576 ///
2577 /// This request is semantically equivalent to and the replaces the x and y
2578 /// arguments in the wl_surface.attach request in wl_surface versions prior
2579 /// to 5. See wl_surface.attach for details.
2580 ///
2581 /// # Arguments
2582 ///
2583 /// - `x`: surface-local x coordinate
2584 /// - `y`: surface-local y coordinate
2585 #[inline]
2586 fn handle_offset(
2587 &mut self,
2588 slf: &Rc<WlSurface>,
2589 x: i32,
2590 y: i32,
2591 ) {
2592 if !slf.core.forward_to_server.get() {
2593 return;
2594 }
2595 let res = slf.try_send_offset(
2596 x,
2597 y,
2598 );
2599 if let Err(e) = res {
2600 log_forward("wl_surface.offset", &e);
2601 }
2602 }
2603
2604 /// preferred buffer scale for the surface
2605 ///
2606 /// This event indicates the preferred buffer scale for this surface. It is
2607 /// sent whenever the compositor's preference changes.
2608 ///
2609 /// Before receiving this event the preferred buffer scale for this surface
2610 /// is 1.
2611 ///
2612 /// It is intended that scaling aware clients use this event to scale their
2613 /// content and use wl_surface.set_buffer_scale to indicate the scale they
2614 /// have rendered with. This allows clients to supply a higher detail
2615 /// buffer.
2616 ///
2617 /// The compositor shall emit a scale value greater than 0.
2618 ///
2619 /// # Arguments
2620 ///
2621 /// - `factor`: preferred scaling factor
2622 #[inline]
2623 fn handle_preferred_buffer_scale(
2624 &mut self,
2625 slf: &Rc<WlSurface>,
2626 factor: i32,
2627 ) {
2628 if !slf.core.forward_to_client.get() {
2629 return;
2630 }
2631 let res = slf.try_send_preferred_buffer_scale(
2632 factor,
2633 );
2634 if let Err(e) = res {
2635 log_forward("wl_surface.preferred_buffer_scale", &e);
2636 }
2637 }
2638
2639 /// preferred buffer transform for the surface
2640 ///
2641 /// This event indicates the preferred buffer transform for this surface.
2642 /// It is sent whenever the compositor's preference changes.
2643 ///
2644 /// Before receiving this event the preferred buffer transform for this
2645 /// surface is normal.
2646 ///
2647 /// Applying this transformation to the surface buffer contents and using
2648 /// wl_surface.set_buffer_transform might allow the compositor to use the
2649 /// surface buffer more efficiently.
2650 ///
2651 /// # Arguments
2652 ///
2653 /// - `transform`: preferred transform
2654 #[inline]
2655 fn handle_preferred_buffer_transform(
2656 &mut self,
2657 slf: &Rc<WlSurface>,
2658 transform: WlOutputTransform,
2659 ) {
2660 if !slf.core.forward_to_client.get() {
2661 return;
2662 }
2663 let res = slf.try_send_preferred_buffer_transform(
2664 transform,
2665 );
2666 if let Err(e) = res {
2667 log_forward("wl_surface.preferred_buffer_transform", &e);
2668 }
2669 }
2670}
2671
2672impl ObjectPrivate for WlSurface {
2673 fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
2674 Rc::<Self>::new_cyclic(|slf| Self {
2675 core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlSurface, version),
2676 handler: Default::default(),
2677 })
2678 }
2679
2680 fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
2681 let Some(mut handler) = self.handler.try_borrow_mut() else {
2682 return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
2683 };
2684 if let Some(handler) = &mut *handler {
2685 handler.delete_id(&self);
2686 } else {
2687 self.core.delete_id();
2688 }
2689 Ok(())
2690 }
2691
2692 fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
2693 let Some(mut handler) = self.handler.try_borrow_mut() else {
2694 return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
2695 };
2696 let handler = &mut *handler;
2697 match msg[1] & 0xffff {
2698 0 => {
2699 if msg.len() != 2 {
2700 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
2701 }
2702 #[cfg(feature = "logging")]
2703 if self.core.state.log {
2704 #[cold]
2705 fn log(state: &State, client_id: u64, id: u32) {
2706 let (millis, micros) = time_since_epoch();
2707 let prefix = &state.log_prefix;
2708 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.destroy()\n", client_id, id);
2709 state.log(args);
2710 }
2711 log(&self.core.state, client.endpoint.id, msg[0]);
2712 }
2713 self.core.handle_client_destroy();
2714 if let Some(handler) = handler {
2715 (**handler).handle_destroy(&self);
2716 } else {
2717 DefaultHandler.handle_destroy(&self);
2718 }
2719 }
2720 1 => {
2721 let [
2722 arg0,
2723 arg1,
2724 arg2,
2725 ] = msg[2..] else {
2726 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
2727 };
2728 let arg1 = arg1 as i32;
2729 let arg2 = arg2 as i32;
2730 #[cfg(feature = "logging")]
2731 if self.core.state.log {
2732 #[cold]
2733 fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: i32, arg2: i32) {
2734 let (millis, micros) = time_since_epoch();
2735 let prefix = &state.log_prefix;
2736 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.attach(buffer: wl_buffer#{}, x: {}, y: {})\n", client_id, id, arg0, arg1, arg2);
2737 state.log(args);
2738 }
2739 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2);
2740 }
2741 let arg0 = if arg0 == 0 {
2742 None
2743 } else {
2744 let arg0_id = arg0;
2745 let Some(arg0) = client.endpoint.lookup(arg0_id) else {
2746 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
2747 };
2748 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlBuffer>() else {
2749 let o = client.endpoint.lookup(arg0_id).unwrap();
2750 return Err(ObjectError(ObjectErrorKind::WrongObjectType("buffer", o.core().interface, ObjectInterface::WlBuffer)));
2751 };
2752 Some(arg0)
2753 };
2754 let arg0 = arg0.as_ref();
2755 if let Some(handler) = handler {
2756 (**handler).handle_attach(&self, arg0, arg1, arg2);
2757 } else {
2758 DefaultHandler.handle_attach(&self, arg0, arg1, arg2);
2759 }
2760 }
2761 2 => {
2762 let [
2763 arg0,
2764 arg1,
2765 arg2,
2766 arg3,
2767 ] = msg[2..] else {
2768 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
2769 };
2770 let arg0 = arg0 as i32;
2771 let arg1 = arg1 as i32;
2772 let arg2 = arg2 as i32;
2773 let arg3 = arg3 as i32;
2774 #[cfg(feature = "logging")]
2775 if self.core.state.log {
2776 #[cold]
2777 fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
2778 let (millis, micros) = time_since_epoch();
2779 let prefix = &state.log_prefix;
2780 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.damage(x: {}, y: {}, width: {}, height: {})\n", client_id, id, arg0, arg1, arg2, arg3);
2781 state.log(args);
2782 }
2783 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
2784 }
2785 if let Some(handler) = handler {
2786 (**handler).handle_damage(&self, arg0, arg1, arg2, arg3);
2787 } else {
2788 DefaultHandler.handle_damage(&self, arg0, arg1, arg2, arg3);
2789 }
2790 }
2791 3 => {
2792 let [
2793 arg0,
2794 ] = msg[2..] else {
2795 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2796 };
2797 #[cfg(feature = "logging")]
2798 if self.core.state.log {
2799 #[cold]
2800 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
2801 let (millis, micros) = time_since_epoch();
2802 let prefix = &state.log_prefix;
2803 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.frame(callback: wl_callback#{})\n", client_id, id, arg0);
2804 state.log(args);
2805 }
2806 log(&self.core.state, client.endpoint.id, msg[0], arg0);
2807 }
2808 let arg0_id = arg0;
2809 let arg0 = WlCallback::new(&self.core.state, self.core.version);
2810 arg0.core().set_client_id(client, arg0_id, arg0.clone())
2811 .map_err(|e| ObjectError(ObjectErrorKind::SetClientId(arg0_id, "callback", e)))?;
2812 let arg0 = &arg0;
2813 if let Some(handler) = handler {
2814 (**handler).handle_frame(&self, arg0);
2815 } else {
2816 DefaultHandler.handle_frame(&self, arg0);
2817 }
2818 }
2819 4 => {
2820 let [
2821 arg0,
2822 ] = msg[2..] else {
2823 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2824 };
2825 #[cfg(feature = "logging")]
2826 if self.core.state.log {
2827 #[cold]
2828 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
2829 let (millis, micros) = time_since_epoch();
2830 let prefix = &state.log_prefix;
2831 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_opaque_region(region: wl_region#{})\n", client_id, id, arg0);
2832 state.log(args);
2833 }
2834 log(&self.core.state, client.endpoint.id, msg[0], arg0);
2835 }
2836 let arg0 = if arg0 == 0 {
2837 None
2838 } else {
2839 let arg0_id = arg0;
2840 let Some(arg0) = client.endpoint.lookup(arg0_id) else {
2841 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
2842 };
2843 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlRegion>() else {
2844 let o = client.endpoint.lookup(arg0_id).unwrap();
2845 return Err(ObjectError(ObjectErrorKind::WrongObjectType("region", o.core().interface, ObjectInterface::WlRegion)));
2846 };
2847 Some(arg0)
2848 };
2849 let arg0 = arg0.as_ref();
2850 if let Some(handler) = handler {
2851 (**handler).handle_set_opaque_region(&self, arg0);
2852 } else {
2853 DefaultHandler.handle_set_opaque_region(&self, arg0);
2854 }
2855 }
2856 5 => {
2857 let [
2858 arg0,
2859 ] = msg[2..] else {
2860 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2861 };
2862 #[cfg(feature = "logging")]
2863 if self.core.state.log {
2864 #[cold]
2865 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
2866 let (millis, micros) = time_since_epoch();
2867 let prefix = &state.log_prefix;
2868 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_input_region(region: wl_region#{})\n", client_id, id, arg0);
2869 state.log(args);
2870 }
2871 log(&self.core.state, client.endpoint.id, msg[0], arg0);
2872 }
2873 let arg0 = if arg0 == 0 {
2874 None
2875 } else {
2876 let arg0_id = arg0;
2877 let Some(arg0) = client.endpoint.lookup(arg0_id) else {
2878 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
2879 };
2880 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlRegion>() else {
2881 let o = client.endpoint.lookup(arg0_id).unwrap();
2882 return Err(ObjectError(ObjectErrorKind::WrongObjectType("region", o.core().interface, ObjectInterface::WlRegion)));
2883 };
2884 Some(arg0)
2885 };
2886 let arg0 = arg0.as_ref();
2887 if let Some(handler) = handler {
2888 (**handler).handle_set_input_region(&self, arg0);
2889 } else {
2890 DefaultHandler.handle_set_input_region(&self, arg0);
2891 }
2892 }
2893 6 => {
2894 if msg.len() != 2 {
2895 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
2896 }
2897 #[cfg(feature = "logging")]
2898 if self.core.state.log {
2899 #[cold]
2900 fn log(state: &State, client_id: u64, id: u32) {
2901 let (millis, micros) = time_since_epoch();
2902 let prefix = &state.log_prefix;
2903 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.commit()\n", client_id, id);
2904 state.log(args);
2905 }
2906 log(&self.core.state, client.endpoint.id, msg[0]);
2907 }
2908 if let Some(handler) = handler {
2909 (**handler).handle_commit(&self);
2910 } else {
2911 DefaultHandler.handle_commit(&self);
2912 }
2913 }
2914 7 => {
2915 let [
2916 arg0,
2917 ] = msg[2..] else {
2918 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2919 };
2920 let arg0 = WlOutputTransform(arg0);
2921 #[cfg(feature = "logging")]
2922 if self.core.state.log {
2923 #[cold]
2924 fn log(state: &State, client_id: u64, id: u32, arg0: WlOutputTransform) {
2925 let (millis, micros) = time_since_epoch();
2926 let prefix = &state.log_prefix;
2927 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_buffer_transform(transform: {:?})\n", client_id, id, arg0);
2928 state.log(args);
2929 }
2930 log(&self.core.state, client.endpoint.id, msg[0], arg0);
2931 }
2932 if let Some(handler) = handler {
2933 (**handler).handle_set_buffer_transform(&self, arg0);
2934 } else {
2935 DefaultHandler.handle_set_buffer_transform(&self, arg0);
2936 }
2937 }
2938 8 => {
2939 let [
2940 arg0,
2941 ] = msg[2..] else {
2942 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2943 };
2944 let arg0 = arg0 as i32;
2945 #[cfg(feature = "logging")]
2946 if self.core.state.log {
2947 #[cold]
2948 fn log(state: &State, client_id: u64, id: u32, arg0: i32) {
2949 let (millis, micros) = time_since_epoch();
2950 let prefix = &state.log_prefix;
2951 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_buffer_scale(scale: {})\n", client_id, id, arg0);
2952 state.log(args);
2953 }
2954 log(&self.core.state, client.endpoint.id, msg[0], arg0);
2955 }
2956 if let Some(handler) = handler {
2957 (**handler).handle_set_buffer_scale(&self, arg0);
2958 } else {
2959 DefaultHandler.handle_set_buffer_scale(&self, arg0);
2960 }
2961 }
2962 9 => {
2963 let [
2964 arg0,
2965 arg1,
2966 arg2,
2967 arg3,
2968 ] = msg[2..] else {
2969 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
2970 };
2971 let arg0 = arg0 as i32;
2972 let arg1 = arg1 as i32;
2973 let arg2 = arg2 as i32;
2974 let arg3 = arg3 as i32;
2975 #[cfg(feature = "logging")]
2976 if self.core.state.log {
2977 #[cold]
2978 fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
2979 let (millis, micros) = time_since_epoch();
2980 let prefix = &state.log_prefix;
2981 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.damage_buffer(x: {}, y: {}, width: {}, height: {})\n", client_id, id, arg0, arg1, arg2, arg3);
2982 state.log(args);
2983 }
2984 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
2985 }
2986 if let Some(handler) = handler {
2987 (**handler).handle_damage_buffer(&self, arg0, arg1, arg2, arg3);
2988 } else {
2989 DefaultHandler.handle_damage_buffer(&self, arg0, arg1, arg2, arg3);
2990 }
2991 }
2992 10 => {
2993 let [
2994 arg0,
2995 arg1,
2996 ] = msg[2..] else {
2997 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
2998 };
2999 let arg0 = arg0 as i32;
3000 let arg1 = arg1 as i32;
3001 #[cfg(feature = "logging")]
3002 if self.core.state.log {
3003 #[cold]
3004 fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32) {
3005 let (millis, micros) = time_since_epoch();
3006 let prefix = &state.log_prefix;
3007 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.offset(x: {}, y: {})\n", client_id, id, arg0, arg1);
3008 state.log(args);
3009 }
3010 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1);
3011 }
3012 if let Some(handler) = handler {
3013 (**handler).handle_offset(&self, arg0, arg1);
3014 } else {
3015 DefaultHandler.handle_offset(&self, arg0, arg1);
3016 }
3017 }
3018 n => {
3019 let _ = client;
3020 let _ = msg;
3021 let _ = fds;
3022 let _ = handler;
3023 return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
3024 }
3025 }
3026 Ok(())
3027 }
3028
3029 fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
3030 let Some(mut handler) = self.handler.try_borrow_mut() else {
3031 return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
3032 };
3033 let handler = &mut *handler;
3034 match msg[1] & 0xffff {
3035 0 => {
3036 let [
3037 arg0,
3038 ] = msg[2..] else {
3039 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3040 };
3041 #[cfg(feature = "logging")]
3042 if self.core.state.log {
3043 #[cold]
3044 fn log(state: &State, id: u32, arg0: u32) {
3045 let (millis, micros) = time_since_epoch();
3046 let prefix = &state.log_prefix;
3047 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server -> wl_surface#{}.enter(output: wl_output#{})\n", id, arg0);
3048 state.log(args);
3049 }
3050 log(&self.core.state, msg[0], arg0);
3051 }
3052 let arg0_id = arg0;
3053 let Some(arg0) = server.lookup(arg0_id) else {
3054 return Err(ObjectError(ObjectErrorKind::NoServerObject(arg0_id)));
3055 };
3056 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlOutput>() else {
3057 let o = server.lookup(arg0_id).unwrap();
3058 return Err(ObjectError(ObjectErrorKind::WrongObjectType("output", o.core().interface, ObjectInterface::WlOutput)));
3059 };
3060 let arg0 = &arg0;
3061 if let Some(handler) = handler {
3062 (**handler).handle_enter(&self, arg0);
3063 } else {
3064 DefaultHandler.handle_enter(&self, arg0);
3065 }
3066 }
3067 1 => {
3068 let [
3069 arg0,
3070 ] = msg[2..] else {
3071 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3072 };
3073 #[cfg(feature = "logging")]
3074 if self.core.state.log {
3075 #[cold]
3076 fn log(state: &State, id: u32, arg0: u32) {
3077 let (millis, micros) = time_since_epoch();
3078 let prefix = &state.log_prefix;
3079 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server -> wl_surface#{}.leave(output: wl_output#{})\n", id, arg0);
3080 state.log(args);
3081 }
3082 log(&self.core.state, msg[0], arg0);
3083 }
3084 let arg0_id = arg0;
3085 let Some(arg0) = server.lookup(arg0_id) else {
3086 return Err(ObjectError(ObjectErrorKind::NoServerObject(arg0_id)));
3087 };
3088 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlOutput>() else {
3089 let o = server.lookup(arg0_id).unwrap();
3090 return Err(ObjectError(ObjectErrorKind::WrongObjectType("output", o.core().interface, ObjectInterface::WlOutput)));
3091 };
3092 let arg0 = &arg0;
3093 if let Some(handler) = handler {
3094 (**handler).handle_leave(&self, arg0);
3095 } else {
3096 DefaultHandler.handle_leave(&self, arg0);
3097 }
3098 }
3099 2 => {
3100 let [
3101 arg0,
3102 ] = msg[2..] else {
3103 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3104 };
3105 let arg0 = arg0 as i32;
3106 #[cfg(feature = "logging")]
3107 if self.core.state.log {
3108 #[cold]
3109 fn log(state: &State, id: u32, arg0: i32) {
3110 let (millis, micros) = time_since_epoch();
3111 let prefix = &state.log_prefix;
3112 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server -> wl_surface#{}.preferred_buffer_scale(factor: {})\n", id, arg0);
3113 state.log(args);
3114 }
3115 log(&self.core.state, msg[0], arg0);
3116 }
3117 if let Some(handler) = handler {
3118 (**handler).handle_preferred_buffer_scale(&self, arg0);
3119 } else {
3120 DefaultHandler.handle_preferred_buffer_scale(&self, arg0);
3121 }
3122 }
3123 3 => {
3124 let [
3125 arg0,
3126 ] = msg[2..] else {
3127 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3128 };
3129 let arg0 = WlOutputTransform(arg0);
3130 #[cfg(feature = "logging")]
3131 if self.core.state.log {
3132 #[cold]
3133 fn log(state: &State, id: u32, arg0: WlOutputTransform) {
3134 let (millis, micros) = time_since_epoch();
3135 let prefix = &state.log_prefix;
3136 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server -> wl_surface#{}.preferred_buffer_transform(transform: {:?})\n", id, arg0);
3137 state.log(args);
3138 }
3139 log(&self.core.state, msg[0], arg0);
3140 }
3141 if let Some(handler) = handler {
3142 (**handler).handle_preferred_buffer_transform(&self, arg0);
3143 } else {
3144 DefaultHandler.handle_preferred_buffer_transform(&self, arg0);
3145 }
3146 }
3147 n => {
3148 let _ = server;
3149 let _ = msg;
3150 let _ = fds;
3151 let _ = handler;
3152 return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
3153 }
3154 }
3155 Ok(())
3156 }
3157
3158 fn get_request_name(&self, id: u32) -> Option<&'static str> {
3159 let name = match id {
3160 0 => "destroy",
3161 1 => "attach",
3162 2 => "damage",
3163 3 => "frame",
3164 4 => "set_opaque_region",
3165 5 => "set_input_region",
3166 6 => "commit",
3167 7 => "set_buffer_transform",
3168 8 => "set_buffer_scale",
3169 9 => "damage_buffer",
3170 10 => "offset",
3171 _ => return None,
3172 };
3173 Some(name)
3174 }
3175
3176 fn get_event_name(&self, id: u32) -> Option<&'static str> {
3177 let name = match id {
3178 0 => "enter",
3179 1 => "leave",
3180 2 => "preferred_buffer_scale",
3181 3 => "preferred_buffer_transform",
3182 _ => return None,
3183 };
3184 Some(name)
3185 }
3186}
3187
3188impl Object for WlSurface {
3189 fn core(&self) -> &ObjectCore {
3190 &self.core
3191 }
3192
3193 fn unset_handler(&self) {
3194 self.handler.set(None);
3195 }
3196
3197 fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
3198 let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
3199 if borrowed.is_none() {
3200 return Err(HandlerAccessError::NoHandler);
3201 }
3202 Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
3203 }
3204
3205 fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
3206 let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
3207 if borrowed.is_none() {
3208 return Err(HandlerAccessError::NoHandler);
3209 }
3210 Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
3211 }
3212}
3213
3214impl WlSurface {
3215 /// Since when the error.invalid_scale enum variant is available.
3216 pub const ENM__ERROR_INVALID_SCALE__SINCE: u32 = 1;
3217 /// Since when the error.invalid_transform enum variant is available.
3218 pub const ENM__ERROR_INVALID_TRANSFORM__SINCE: u32 = 1;
3219 /// Since when the error.invalid_size enum variant is available.
3220 pub const ENM__ERROR_INVALID_SIZE__SINCE: u32 = 1;
3221 /// Since when the error.invalid_offset enum variant is available.
3222 pub const ENM__ERROR_INVALID_OFFSET__SINCE: u32 = 1;
3223 /// Since when the error.defunct_role_object enum variant is available.
3224 pub const ENM__ERROR_DEFUNCT_ROLE_OBJECT__SINCE: u32 = 1;
3225}
3226
3227/// wl_surface error values
3228///
3229/// These errors can be emitted in response to wl_surface requests.
3230#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
3231pub struct WlSurfaceError(pub u32);
3232
3233impl WlSurfaceError {
3234 /// buffer scale value is invalid
3235 pub const INVALID_SCALE: Self = Self(0);
3236
3237 /// buffer transform value is invalid
3238 pub const INVALID_TRANSFORM: Self = Self(1);
3239
3240 /// buffer size is invalid
3241 pub const INVALID_SIZE: Self = Self(2);
3242
3243 /// buffer offset is invalid
3244 pub const INVALID_OFFSET: Self = Self(3);
3245
3246 /// surface was destroyed before its role object
3247 pub const DEFUNCT_ROLE_OBJECT: Self = Self(4);
3248}
3249
3250impl Debug for WlSurfaceError {
3251 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
3252 let name = match *self {
3253 Self::INVALID_SCALE => "INVALID_SCALE",
3254 Self::INVALID_TRANSFORM => "INVALID_TRANSFORM",
3255 Self::INVALID_SIZE => "INVALID_SIZE",
3256 Self::INVALID_OFFSET => "INVALID_OFFSET",
3257 Self::DEFUNCT_ROLE_OBJECT => "DEFUNCT_ROLE_OBJECT",
3258 _ => return Debug::fmt(&self.0, f),
3259 };
3260 f.write_str(name)
3261 }
3262}