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 /// All requests that need a commit to become effective are documented
996 /// to affect double-buffered state.
997 ///
998 /// Other interfaces may add further double-buffered surface state.
999 ///
1000 /// A commit request atomically creates a Content Update (CU) from the
1001 /// pending state, even if the pending state has not been touched. The
1002 /// content update is placed at the end of a per-surface queue until it
1003 /// becomes active. After commit, the new pending state is as documented for
1004 /// each related request.
1005 ///
1006 /// A CU is either a Desync Content Update (DCU) or a Sync Content Update
1007 /// (SCU). If the surface is effectively synchronized at the commit request,
1008 /// it is a SCU, otherwise a DCU.
1009 ///
1010 /// When a surface transitions from effectively synchronized to effectively
1011 /// desynchronized, all SCUs in its queue which are not reachable by any
1012 /// DCU become DCUs and dependency edges from outside the queue to these CUs
1013 /// are removed.
1014 ///
1015 /// See wl_subsurface for the definition of 'effectively synchronized' and
1016 /// 'effectively desynchronized'.
1017 ///
1018 /// When a CU is placed in the queue, the CU has a dependency on the CU in
1019 /// front of it and to the SCU at end of the queue of every direct child
1020 /// surface if that SCU exists and does not have another dependent. This can
1021 /// form a directed acyclic graph of CUs with dependencies as edges.
1022 ///
1023 /// In addition to surface state, the CU can have constraints that must be
1024 /// satisfied before it can be applied. Other interfaces may add CU
1025 /// constraints.
1026 ///
1027 /// All DCUs which do not have a SCU in front of themselves in their queue,
1028 /// are candidates. If the graph that's reachable by a candidate does not
1029 /// have any unsatisfied constraints, the entire graph must be applied
1030 /// atomically.
1031 ///
1032 /// When a CU is applied, the wl_buffer is applied before all other state.
1033 /// This means that all coordinates in double-buffered state are relative to
1034 /// the newly attached wl_buffers, except for wl_surface.attach itself. If
1035 /// there is no newly attached wl_buffer, the coordinates are relative to
1036 /// the previous content update.
1037 #[inline]
1038 pub fn try_send_commit(
1039 &self,
1040 ) -> Result<(), ObjectError> {
1041 let core = self.core();
1042 let Some(id) = core.server_obj_id.get() else {
1043 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1044 };
1045 #[cfg(feature = "logging")]
1046 if self.core.state.log {
1047 #[cold]
1048 fn log(state: &State, id: u32) {
1049 let (millis, micros) = time_since_epoch();
1050 let prefix = &state.log_prefix;
1051 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.commit()\n", id);
1052 state.log(args);
1053 }
1054 log(&self.core.state, id);
1055 }
1056 let Some(endpoint) = &self.core.state.server else {
1057 return Ok(());
1058 };
1059 if !endpoint.flush_queued.replace(true) {
1060 self.core.state.add_flushable_endpoint(endpoint, None);
1061 }
1062 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1063 let outgoing = &mut *outgoing_ref;
1064 let mut fmt = outgoing.formatter();
1065 fmt.words([
1066 id,
1067 6,
1068 ]);
1069 Ok(())
1070 }
1071
1072 /// commit pending surface state
1073 ///
1074 /// Surface state (input, opaque, and damage regions, attached buffers,
1075 /// etc.) is double-buffered. Protocol requests modify the pending state,
1076 /// as opposed to the active state in use by the compositor.
1077 ///
1078 /// All requests that need a commit to become effective are documented
1079 /// to affect double-buffered state.
1080 ///
1081 /// Other interfaces may add further double-buffered surface state.
1082 ///
1083 /// A commit request atomically creates a Content Update (CU) from the
1084 /// pending state, even if the pending state has not been touched. The
1085 /// content update is placed at the end of a per-surface queue until it
1086 /// becomes active. After commit, the new pending state is as documented for
1087 /// each related request.
1088 ///
1089 /// A CU is either a Desync Content Update (DCU) or a Sync Content Update
1090 /// (SCU). If the surface is effectively synchronized at the commit request,
1091 /// it is a SCU, otherwise a DCU.
1092 ///
1093 /// When a surface transitions from effectively synchronized to effectively
1094 /// desynchronized, all SCUs in its queue which are not reachable by any
1095 /// DCU become DCUs and dependency edges from outside the queue to these CUs
1096 /// are removed.
1097 ///
1098 /// See wl_subsurface for the definition of 'effectively synchronized' and
1099 /// 'effectively desynchronized'.
1100 ///
1101 /// When a CU is placed in the queue, the CU has a dependency on the CU in
1102 /// front of it and to the SCU at end of the queue of every direct child
1103 /// surface if that SCU exists and does not have another dependent. This can
1104 /// form a directed acyclic graph of CUs with dependencies as edges.
1105 ///
1106 /// In addition to surface state, the CU can have constraints that must be
1107 /// satisfied before it can be applied. Other interfaces may add CU
1108 /// constraints.
1109 ///
1110 /// All DCUs which do not have a SCU in front of themselves in their queue,
1111 /// are candidates. If the graph that's reachable by a candidate does not
1112 /// have any unsatisfied constraints, the entire graph must be applied
1113 /// atomically.
1114 ///
1115 /// When a CU is applied, the wl_buffer is applied before all other state.
1116 /// This means that all coordinates in double-buffered state are relative to
1117 /// the newly attached wl_buffers, except for wl_surface.attach itself. If
1118 /// there is no newly attached wl_buffer, the coordinates are relative to
1119 /// the previous content update.
1120 #[inline]
1121 pub fn send_commit(
1122 &self,
1123 ) {
1124 let res = self.try_send_commit(
1125 );
1126 if let Err(e) = res {
1127 log_send("wl_surface.commit", &e);
1128 }
1129 }
1130
1131 /// Since when the enter message is available.
1132 pub const MSG__ENTER__SINCE: u32 = 1;
1133
1134 /// surface enters an output
1135 ///
1136 /// This is emitted whenever a surface's creation, movement, or resizing
1137 /// results in some part of it being within the scanout region of an
1138 /// output.
1139 ///
1140 /// Note that a surface may be overlapping with zero or more outputs.
1141 ///
1142 /// # Arguments
1143 ///
1144 /// - `output`: output entered by the surface
1145 #[inline]
1146 pub fn try_send_enter(
1147 &self,
1148 output: &Rc<WlOutput>,
1149 ) -> Result<(), ObjectError> {
1150 let (
1151 arg0,
1152 ) = (
1153 output,
1154 );
1155 let arg0 = arg0.core();
1156 let core = self.core();
1157 let client_ref = core.client.borrow();
1158 let Some(client) = &*client_ref else {
1159 return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1160 };
1161 let id = core.client_obj_id.get().unwrap_or(0);
1162 if arg0.client_id.get() != Some(client.endpoint.id) {
1163 return Err(ObjectError(ObjectErrorKind::ArgNoClientId("output", client.endpoint.id)));
1164 }
1165 let arg0_id = arg0.client_obj_id.get().unwrap_or(0);
1166 #[cfg(feature = "logging")]
1167 if self.core.state.log {
1168 #[cold]
1169 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
1170 let (millis, micros) = time_since_epoch();
1171 let prefix = &state.log_prefix;
1172 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.enter(output: wl_output#{})\n", client_id, id, arg0);
1173 state.log(args);
1174 }
1175 log(&self.core.state, client.endpoint.id, id, arg0_id);
1176 }
1177 let endpoint = &client.endpoint;
1178 if !endpoint.flush_queued.replace(true) {
1179 self.core.state.add_flushable_endpoint(endpoint, Some(client));
1180 }
1181 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1182 let outgoing = &mut *outgoing_ref;
1183 let mut fmt = outgoing.formatter();
1184 fmt.words([
1185 id,
1186 0,
1187 arg0_id,
1188 ]);
1189 Ok(())
1190 }
1191
1192 /// surface enters an output
1193 ///
1194 /// This is emitted whenever a surface's creation, movement, or resizing
1195 /// results in some part of it being within the scanout region of an
1196 /// output.
1197 ///
1198 /// Note that a surface may be overlapping with zero or more outputs.
1199 ///
1200 /// # Arguments
1201 ///
1202 /// - `output`: output entered by the surface
1203 #[inline]
1204 pub fn send_enter(
1205 &self,
1206 output: &Rc<WlOutput>,
1207 ) {
1208 let res = self.try_send_enter(
1209 output,
1210 );
1211 if let Err(e) = res {
1212 log_send("wl_surface.enter", &e);
1213 }
1214 }
1215
1216 /// Since when the leave message is available.
1217 pub const MSG__LEAVE__SINCE: u32 = 1;
1218
1219 /// surface leaves an output
1220 ///
1221 /// This is emitted whenever a surface's creation, movement, or resizing
1222 /// results in it no longer having any part of it within the scanout region
1223 /// of an output.
1224 ///
1225 /// Clients should not use the number of outputs the surface is on for frame
1226 /// throttling purposes. The surface might be hidden even if no leave event
1227 /// has been sent, and the compositor might expect new surface content
1228 /// updates even if no enter event has been sent. The frame event should be
1229 /// used instead.
1230 ///
1231 /// # Arguments
1232 ///
1233 /// - `output`: output left by the surface
1234 #[inline]
1235 pub fn try_send_leave(
1236 &self,
1237 output: &Rc<WlOutput>,
1238 ) -> Result<(), ObjectError> {
1239 let (
1240 arg0,
1241 ) = (
1242 output,
1243 );
1244 let arg0 = arg0.core();
1245 let core = self.core();
1246 let client_ref = core.client.borrow();
1247 let Some(client) = &*client_ref else {
1248 return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1249 };
1250 let id = core.client_obj_id.get().unwrap_or(0);
1251 if arg0.client_id.get() != Some(client.endpoint.id) {
1252 return Err(ObjectError(ObjectErrorKind::ArgNoClientId("output", client.endpoint.id)));
1253 }
1254 let arg0_id = arg0.client_obj_id.get().unwrap_or(0);
1255 #[cfg(feature = "logging")]
1256 if self.core.state.log {
1257 #[cold]
1258 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
1259 let (millis, micros) = time_since_epoch();
1260 let prefix = &state.log_prefix;
1261 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.leave(output: wl_output#{})\n", client_id, id, arg0);
1262 state.log(args);
1263 }
1264 log(&self.core.state, client.endpoint.id, id, arg0_id);
1265 }
1266 let endpoint = &client.endpoint;
1267 if !endpoint.flush_queued.replace(true) {
1268 self.core.state.add_flushable_endpoint(endpoint, Some(client));
1269 }
1270 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1271 let outgoing = &mut *outgoing_ref;
1272 let mut fmt = outgoing.formatter();
1273 fmt.words([
1274 id,
1275 1,
1276 arg0_id,
1277 ]);
1278 Ok(())
1279 }
1280
1281 /// surface leaves an output
1282 ///
1283 /// This is emitted whenever a surface's creation, movement, or resizing
1284 /// results in it no longer having any part of it within the scanout region
1285 /// of an output.
1286 ///
1287 /// Clients should not use the number of outputs the surface is on for frame
1288 /// throttling purposes. The surface might be hidden even if no leave event
1289 /// has been sent, and the compositor might expect new surface content
1290 /// updates even if no enter event has been sent. The frame event should be
1291 /// used instead.
1292 ///
1293 /// # Arguments
1294 ///
1295 /// - `output`: output left by the surface
1296 #[inline]
1297 pub fn send_leave(
1298 &self,
1299 output: &Rc<WlOutput>,
1300 ) {
1301 let res = self.try_send_leave(
1302 output,
1303 );
1304 if let Err(e) = res {
1305 log_send("wl_surface.leave", &e);
1306 }
1307 }
1308
1309 /// Since when the set_buffer_transform message is available.
1310 pub const MSG__SET_BUFFER_TRANSFORM__SINCE: u32 = 2;
1311
1312 /// sets the buffer transformation
1313 ///
1314 /// This request sets the transformation that the client has already applied
1315 /// to the content of the buffer. The accepted values for the transform
1316 /// parameter are the values for wl_output.transform.
1317 ///
1318 /// The compositor applies the inverse of this transformation whenever it
1319 /// uses the buffer contents.
1320 ///
1321 /// Buffer transform is double-buffered state, see wl_surface.commit.
1322 ///
1323 /// A newly created surface has its buffer transformation set to normal.
1324 ///
1325 /// wl_surface.set_buffer_transform changes the pending buffer
1326 /// transformation. wl_surface.commit copies the pending buffer
1327 /// transformation to the current one. Otherwise, the pending and current
1328 /// values are never changed.
1329 ///
1330 /// The purpose of this request is to allow clients to render content
1331 /// according to the output transform, thus permitting the compositor to
1332 /// use certain optimizations even if the display is rotated. Using
1333 /// hardware overlays and scanning out a client buffer for fullscreen
1334 /// surfaces are examples of such optimizations. Those optimizations are
1335 /// highly dependent on the compositor implementation, so the use of this
1336 /// request should be considered on a case-by-case basis.
1337 ///
1338 /// Note that if the transform value includes 90 or 270 degree rotation,
1339 /// the width of the buffer will become the surface height and the height
1340 /// of the buffer will become the surface width.
1341 ///
1342 /// If transform is not one of the values from the
1343 /// wl_output.transform enum the invalid_transform protocol error
1344 /// is raised.
1345 ///
1346 /// # Arguments
1347 ///
1348 /// - `transform`: transform for interpreting buffer contents
1349 #[inline]
1350 pub fn try_send_set_buffer_transform(
1351 &self,
1352 transform: WlOutputTransform,
1353 ) -> Result<(), ObjectError> {
1354 let (
1355 arg0,
1356 ) = (
1357 transform,
1358 );
1359 let core = self.core();
1360 let Some(id) = core.server_obj_id.get() else {
1361 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1362 };
1363 #[cfg(feature = "logging")]
1364 if self.core.state.log {
1365 #[cold]
1366 fn log(state: &State, id: u32, arg0: WlOutputTransform) {
1367 let (millis, micros) = time_since_epoch();
1368 let prefix = &state.log_prefix;
1369 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.set_buffer_transform(transform: {:?})\n", id, arg0);
1370 state.log(args);
1371 }
1372 log(&self.core.state, id, arg0);
1373 }
1374 let Some(endpoint) = &self.core.state.server else {
1375 return Ok(());
1376 };
1377 if !endpoint.flush_queued.replace(true) {
1378 self.core.state.add_flushable_endpoint(endpoint, None);
1379 }
1380 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1381 let outgoing = &mut *outgoing_ref;
1382 let mut fmt = outgoing.formatter();
1383 fmt.words([
1384 id,
1385 7,
1386 arg0.0,
1387 ]);
1388 Ok(())
1389 }
1390
1391 /// sets the buffer transformation
1392 ///
1393 /// This request sets the transformation that the client has already applied
1394 /// to the content of the buffer. The accepted values for the transform
1395 /// parameter are the values for wl_output.transform.
1396 ///
1397 /// The compositor applies the inverse of this transformation whenever it
1398 /// uses the buffer contents.
1399 ///
1400 /// Buffer transform is double-buffered state, see wl_surface.commit.
1401 ///
1402 /// A newly created surface has its buffer transformation set to normal.
1403 ///
1404 /// wl_surface.set_buffer_transform changes the pending buffer
1405 /// transformation. wl_surface.commit copies the pending buffer
1406 /// transformation to the current one. Otherwise, the pending and current
1407 /// values are never changed.
1408 ///
1409 /// The purpose of this request is to allow clients to render content
1410 /// according to the output transform, thus permitting the compositor to
1411 /// use certain optimizations even if the display is rotated. Using
1412 /// hardware overlays and scanning out a client buffer for fullscreen
1413 /// surfaces are examples of such optimizations. Those optimizations are
1414 /// highly dependent on the compositor implementation, so the use of this
1415 /// request should be considered on a case-by-case basis.
1416 ///
1417 /// Note that if the transform value includes 90 or 270 degree rotation,
1418 /// the width of the buffer will become the surface height and the height
1419 /// of the buffer will become the surface width.
1420 ///
1421 /// If transform is not one of the values from the
1422 /// wl_output.transform enum the invalid_transform protocol error
1423 /// is raised.
1424 ///
1425 /// # Arguments
1426 ///
1427 /// - `transform`: transform for interpreting buffer contents
1428 #[inline]
1429 pub fn send_set_buffer_transform(
1430 &self,
1431 transform: WlOutputTransform,
1432 ) {
1433 let res = self.try_send_set_buffer_transform(
1434 transform,
1435 );
1436 if let Err(e) = res {
1437 log_send("wl_surface.set_buffer_transform", &e);
1438 }
1439 }
1440
1441 /// Since when the set_buffer_scale message is available.
1442 pub const MSG__SET_BUFFER_SCALE__SINCE: u32 = 3;
1443
1444 /// sets the buffer scaling factor
1445 ///
1446 /// This request sets an optional scaling factor on how the compositor
1447 /// interprets the contents of the buffer attached to the window.
1448 ///
1449 /// Buffer scale is double-buffered state, see wl_surface.commit.
1450 ///
1451 /// A newly created surface has its buffer scale set to 1.
1452 ///
1453 /// wl_surface.set_buffer_scale changes the pending buffer scale.
1454 /// wl_surface.commit copies the pending buffer scale to the current one.
1455 /// Otherwise, the pending and current values are never changed.
1456 ///
1457 /// The purpose of this request is to allow clients to supply higher
1458 /// resolution buffer data for use on high resolution outputs. It is
1459 /// intended that you pick the same buffer scale as the scale of the
1460 /// output that the surface is displayed on. This means the compositor
1461 /// can avoid scaling when rendering the surface on that output.
1462 ///
1463 /// Note that if the scale is larger than 1, then you have to attach
1464 /// a buffer that is larger (by a factor of scale in each dimension)
1465 /// than the desired surface size.
1466 ///
1467 /// If scale is not greater than 0 the invalid_scale protocol error is
1468 /// raised.
1469 ///
1470 /// # Arguments
1471 ///
1472 /// - `scale`: scale for interpreting buffer contents
1473 #[inline]
1474 pub fn try_send_set_buffer_scale(
1475 &self,
1476 scale: i32,
1477 ) -> Result<(), ObjectError> {
1478 let (
1479 arg0,
1480 ) = (
1481 scale,
1482 );
1483 let core = self.core();
1484 let Some(id) = core.server_obj_id.get() else {
1485 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1486 };
1487 #[cfg(feature = "logging")]
1488 if self.core.state.log {
1489 #[cold]
1490 fn log(state: &State, id: u32, arg0: i32) {
1491 let (millis, micros) = time_since_epoch();
1492 let prefix = &state.log_prefix;
1493 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.set_buffer_scale(scale: {})\n", id, arg0);
1494 state.log(args);
1495 }
1496 log(&self.core.state, id, arg0);
1497 }
1498 let Some(endpoint) = &self.core.state.server else {
1499 return Ok(());
1500 };
1501 if !endpoint.flush_queued.replace(true) {
1502 self.core.state.add_flushable_endpoint(endpoint, None);
1503 }
1504 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1505 let outgoing = &mut *outgoing_ref;
1506 let mut fmt = outgoing.formatter();
1507 fmt.words([
1508 id,
1509 8,
1510 arg0 as u32,
1511 ]);
1512 Ok(())
1513 }
1514
1515 /// sets the buffer scaling factor
1516 ///
1517 /// This request sets an optional scaling factor on how the compositor
1518 /// interprets the contents of the buffer attached to the window.
1519 ///
1520 /// Buffer scale is double-buffered state, see wl_surface.commit.
1521 ///
1522 /// A newly created surface has its buffer scale set to 1.
1523 ///
1524 /// wl_surface.set_buffer_scale changes the pending buffer scale.
1525 /// wl_surface.commit copies the pending buffer scale to the current one.
1526 /// Otherwise, the pending and current values are never changed.
1527 ///
1528 /// The purpose of this request is to allow clients to supply higher
1529 /// resolution buffer data for use on high resolution outputs. It is
1530 /// intended that you pick the same buffer scale as the scale of the
1531 /// output that the surface is displayed on. This means the compositor
1532 /// can avoid scaling when rendering the surface on that output.
1533 ///
1534 /// Note that if the scale is larger than 1, then you have to attach
1535 /// a buffer that is larger (by a factor of scale in each dimension)
1536 /// than the desired surface size.
1537 ///
1538 /// If scale is not greater than 0 the invalid_scale protocol error is
1539 /// raised.
1540 ///
1541 /// # Arguments
1542 ///
1543 /// - `scale`: scale for interpreting buffer contents
1544 #[inline]
1545 pub fn send_set_buffer_scale(
1546 &self,
1547 scale: i32,
1548 ) {
1549 let res = self.try_send_set_buffer_scale(
1550 scale,
1551 );
1552 if let Err(e) = res {
1553 log_send("wl_surface.set_buffer_scale", &e);
1554 }
1555 }
1556
1557 /// Since when the damage_buffer message is available.
1558 pub const MSG__DAMAGE_BUFFER__SINCE: u32 = 4;
1559
1560 /// mark part of the surface damaged using buffer coordinates
1561 ///
1562 /// This request is used to describe the regions where the pending
1563 /// buffer is different from the current surface contents, and where
1564 /// the surface therefore needs to be repainted. The compositor
1565 /// ignores the parts of the damage that fall outside of the surface.
1566 ///
1567 /// Damage is double-buffered state, see wl_surface.commit.
1568 ///
1569 /// The damage rectangle is specified in buffer coordinates,
1570 /// where x and y specify the upper left corner of the damage rectangle.
1571 ///
1572 /// The initial value for pending damage is empty: no damage.
1573 /// wl_surface.damage_buffer adds pending damage: the new pending
1574 /// damage is the union of old pending damage and the given rectangle.
1575 ///
1576 /// wl_surface.commit assigns pending damage as the current damage,
1577 /// and clears pending damage. The server will clear the current
1578 /// damage as it repaints the surface.
1579 ///
1580 /// This request differs from wl_surface.damage in only one way - it
1581 /// takes damage in buffer coordinates instead of surface-local
1582 /// coordinates. While this generally is more intuitive than surface
1583 /// coordinates, it is especially desirable when using wp_viewport
1584 /// or when a drawing library (like EGL) is unaware of buffer scale
1585 /// and buffer transform.
1586 ///
1587 /// Note: Because buffer transformation changes and damage requests may
1588 /// be interleaved in the protocol stream, it is impossible to determine
1589 /// the actual mapping between surface and buffer damage until
1590 /// wl_surface.commit time. Therefore, compositors wishing to take both
1591 /// kinds of damage into account will have to accumulate damage from the
1592 /// two requests separately and only transform from one to the other
1593 /// after receiving the wl_surface.commit.
1594 ///
1595 /// # Arguments
1596 ///
1597 /// - `x`: buffer-local x coordinate
1598 /// - `y`: buffer-local y coordinate
1599 /// - `width`: width of damage rectangle
1600 /// - `height`: height of damage rectangle
1601 #[inline]
1602 pub fn try_send_damage_buffer(
1603 &self,
1604 x: i32,
1605 y: i32,
1606 width: i32,
1607 height: i32,
1608 ) -> Result<(), ObjectError> {
1609 let (
1610 arg0,
1611 arg1,
1612 arg2,
1613 arg3,
1614 ) = (
1615 x,
1616 y,
1617 width,
1618 height,
1619 );
1620 let core = self.core();
1621 let Some(id) = core.server_obj_id.get() else {
1622 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1623 };
1624 #[cfg(feature = "logging")]
1625 if self.core.state.log {
1626 #[cold]
1627 fn log(state: &State, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
1628 let (millis, micros) = time_since_epoch();
1629 let prefix = &state.log_prefix;
1630 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.damage_buffer(x: {}, y: {}, width: {}, height: {})\n", id, arg0, arg1, arg2, arg3);
1631 state.log(args);
1632 }
1633 log(&self.core.state, id, arg0, arg1, arg2, arg3);
1634 }
1635 let Some(endpoint) = &self.core.state.server else {
1636 return Ok(());
1637 };
1638 if !endpoint.flush_queued.replace(true) {
1639 self.core.state.add_flushable_endpoint(endpoint, None);
1640 }
1641 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1642 let outgoing = &mut *outgoing_ref;
1643 let mut fmt = outgoing.formatter();
1644 fmt.words([
1645 id,
1646 9,
1647 arg0 as u32,
1648 arg1 as u32,
1649 arg2 as u32,
1650 arg3 as u32,
1651 ]);
1652 Ok(())
1653 }
1654
1655 /// mark part of the surface damaged using buffer coordinates
1656 ///
1657 /// This request is used to describe the regions where the pending
1658 /// buffer is different from the current surface contents, and where
1659 /// the surface therefore needs to be repainted. The compositor
1660 /// ignores the parts of the damage that fall outside of the surface.
1661 ///
1662 /// Damage is double-buffered state, see wl_surface.commit.
1663 ///
1664 /// The damage rectangle is specified in buffer coordinates,
1665 /// where x and y specify the upper left corner of the damage rectangle.
1666 ///
1667 /// The initial value for pending damage is empty: no damage.
1668 /// wl_surface.damage_buffer adds pending damage: the new pending
1669 /// damage is the union of old pending damage and the given rectangle.
1670 ///
1671 /// wl_surface.commit assigns pending damage as the current damage,
1672 /// and clears pending damage. The server will clear the current
1673 /// damage as it repaints the surface.
1674 ///
1675 /// This request differs from wl_surface.damage in only one way - it
1676 /// takes damage in buffer coordinates instead of surface-local
1677 /// coordinates. While this generally is more intuitive than surface
1678 /// coordinates, it is especially desirable when using wp_viewport
1679 /// or when a drawing library (like EGL) is unaware of buffer scale
1680 /// and buffer transform.
1681 ///
1682 /// Note: Because buffer transformation changes and damage requests may
1683 /// be interleaved in the protocol stream, it is impossible to determine
1684 /// the actual mapping between surface and buffer damage until
1685 /// wl_surface.commit time. Therefore, compositors wishing to take both
1686 /// kinds of damage into account will have to accumulate damage from the
1687 /// two requests separately and only transform from one to the other
1688 /// after receiving the wl_surface.commit.
1689 ///
1690 /// # Arguments
1691 ///
1692 /// - `x`: buffer-local x coordinate
1693 /// - `y`: buffer-local y coordinate
1694 /// - `width`: width of damage rectangle
1695 /// - `height`: height of damage rectangle
1696 #[inline]
1697 pub fn send_damage_buffer(
1698 &self,
1699 x: i32,
1700 y: i32,
1701 width: i32,
1702 height: i32,
1703 ) {
1704 let res = self.try_send_damage_buffer(
1705 x,
1706 y,
1707 width,
1708 height,
1709 );
1710 if let Err(e) = res {
1711 log_send("wl_surface.damage_buffer", &e);
1712 }
1713 }
1714
1715 /// Since when the offset message is available.
1716 pub const MSG__OFFSET__SINCE: u32 = 5;
1717
1718 /// set the surface contents offset
1719 ///
1720 /// The x and y arguments specify the location of the new pending
1721 /// buffer's upper left corner, relative to the current buffer's upper
1722 /// left corner, in surface-local coordinates. In other words, the
1723 /// x and y, combined with the new surface size define in which
1724 /// directions the surface's size changes.
1725 ///
1726 /// The exact semantics of wl_surface.offset are role-specific. Refer to
1727 /// the documentation of specific roles for more information.
1728 ///
1729 /// Surface location offset is double-buffered state, see
1730 /// wl_surface.commit.
1731 ///
1732 /// This request is semantically equivalent to and the replaces the x and y
1733 /// arguments in the wl_surface.attach request in wl_surface versions prior
1734 /// to 5. See wl_surface.attach for details.
1735 ///
1736 /// # Arguments
1737 ///
1738 /// - `x`: surface-local x coordinate
1739 /// - `y`: surface-local y coordinate
1740 #[inline]
1741 pub fn try_send_offset(
1742 &self,
1743 x: i32,
1744 y: i32,
1745 ) -> Result<(), ObjectError> {
1746 let (
1747 arg0,
1748 arg1,
1749 ) = (
1750 x,
1751 y,
1752 );
1753 let core = self.core();
1754 let Some(id) = core.server_obj_id.get() else {
1755 return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
1756 };
1757 #[cfg(feature = "logging")]
1758 if self.core.state.log {
1759 #[cold]
1760 fn log(state: &State, id: u32, arg0: i32, arg1: i32) {
1761 let (millis, micros) = time_since_epoch();
1762 let prefix = &state.log_prefix;
1763 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server <= wl_surface#{}.offset(x: {}, y: {})\n", id, arg0, arg1);
1764 state.log(args);
1765 }
1766 log(&self.core.state, id, arg0, arg1);
1767 }
1768 let Some(endpoint) = &self.core.state.server else {
1769 return Ok(());
1770 };
1771 if !endpoint.flush_queued.replace(true) {
1772 self.core.state.add_flushable_endpoint(endpoint, None);
1773 }
1774 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1775 let outgoing = &mut *outgoing_ref;
1776 let mut fmt = outgoing.formatter();
1777 fmt.words([
1778 id,
1779 10,
1780 arg0 as u32,
1781 arg1 as u32,
1782 ]);
1783 Ok(())
1784 }
1785
1786 /// set the surface contents offset
1787 ///
1788 /// The x and y arguments specify the location of the new pending
1789 /// buffer's upper left corner, relative to the current buffer's upper
1790 /// left corner, in surface-local coordinates. In other words, the
1791 /// x and y, combined with the new surface size define in which
1792 /// directions the surface's size changes.
1793 ///
1794 /// The exact semantics of wl_surface.offset are role-specific. Refer to
1795 /// the documentation of specific roles for more information.
1796 ///
1797 /// Surface location offset is double-buffered state, see
1798 /// wl_surface.commit.
1799 ///
1800 /// This request is semantically equivalent to and the replaces the x and y
1801 /// arguments in the wl_surface.attach request in wl_surface versions prior
1802 /// to 5. See wl_surface.attach for details.
1803 ///
1804 /// # Arguments
1805 ///
1806 /// - `x`: surface-local x coordinate
1807 /// - `y`: surface-local y coordinate
1808 #[inline]
1809 pub fn send_offset(
1810 &self,
1811 x: i32,
1812 y: i32,
1813 ) {
1814 let res = self.try_send_offset(
1815 x,
1816 y,
1817 );
1818 if let Err(e) = res {
1819 log_send("wl_surface.offset", &e);
1820 }
1821 }
1822
1823 /// Since when the preferred_buffer_scale message is available.
1824 pub const MSG__PREFERRED_BUFFER_SCALE__SINCE: u32 = 6;
1825
1826 /// preferred buffer scale for the surface
1827 ///
1828 /// This event indicates the preferred buffer scale for this surface. It is
1829 /// sent whenever the compositor's preference changes.
1830 ///
1831 /// Before receiving this event the preferred buffer scale for this surface
1832 /// is 1.
1833 ///
1834 /// It is intended that scaling aware clients use this event to scale their
1835 /// content and use wl_surface.set_buffer_scale to indicate the scale they
1836 /// have rendered with. This allows clients to supply a higher detail
1837 /// buffer.
1838 ///
1839 /// The compositor shall emit a scale value greater than 0.
1840 ///
1841 /// # Arguments
1842 ///
1843 /// - `factor`: preferred scaling factor
1844 #[inline]
1845 pub fn try_send_preferred_buffer_scale(
1846 &self,
1847 factor: i32,
1848 ) -> Result<(), ObjectError> {
1849 let (
1850 arg0,
1851 ) = (
1852 factor,
1853 );
1854 let core = self.core();
1855 let client_ref = core.client.borrow();
1856 let Some(client) = &*client_ref else {
1857 return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1858 };
1859 let id = core.client_obj_id.get().unwrap_or(0);
1860 #[cfg(feature = "logging")]
1861 if self.core.state.log {
1862 #[cold]
1863 fn log(state: &State, client_id: u64, id: u32, arg0: i32) {
1864 let (millis, micros) = time_since_epoch();
1865 let prefix = &state.log_prefix;
1866 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.preferred_buffer_scale(factor: {})\n", client_id, id, arg0);
1867 state.log(args);
1868 }
1869 log(&self.core.state, client.endpoint.id, id, arg0);
1870 }
1871 let endpoint = &client.endpoint;
1872 if !endpoint.flush_queued.replace(true) {
1873 self.core.state.add_flushable_endpoint(endpoint, Some(client));
1874 }
1875 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1876 let outgoing = &mut *outgoing_ref;
1877 let mut fmt = outgoing.formatter();
1878 fmt.words([
1879 id,
1880 2,
1881 arg0 as u32,
1882 ]);
1883 Ok(())
1884 }
1885
1886 /// preferred buffer scale for the surface
1887 ///
1888 /// This event indicates the preferred buffer scale for this surface. It is
1889 /// sent whenever the compositor's preference changes.
1890 ///
1891 /// Before receiving this event the preferred buffer scale for this surface
1892 /// is 1.
1893 ///
1894 /// It is intended that scaling aware clients use this event to scale their
1895 /// content and use wl_surface.set_buffer_scale to indicate the scale they
1896 /// have rendered with. This allows clients to supply a higher detail
1897 /// buffer.
1898 ///
1899 /// The compositor shall emit a scale value greater than 0.
1900 ///
1901 /// # Arguments
1902 ///
1903 /// - `factor`: preferred scaling factor
1904 #[inline]
1905 pub fn send_preferred_buffer_scale(
1906 &self,
1907 factor: i32,
1908 ) {
1909 let res = self.try_send_preferred_buffer_scale(
1910 factor,
1911 );
1912 if let Err(e) = res {
1913 log_send("wl_surface.preferred_buffer_scale", &e);
1914 }
1915 }
1916
1917 /// Since when the preferred_buffer_transform message is available.
1918 pub const MSG__PREFERRED_BUFFER_TRANSFORM__SINCE: u32 = 6;
1919
1920 /// preferred buffer transform for the surface
1921 ///
1922 /// This event indicates the preferred buffer transform for this surface.
1923 /// It is sent whenever the compositor's preference changes.
1924 ///
1925 /// Before receiving this event the preferred buffer transform for this
1926 /// surface is normal.
1927 ///
1928 /// Applying this transformation to the surface buffer contents and using
1929 /// wl_surface.set_buffer_transform might allow the compositor to use the
1930 /// surface buffer more efficiently.
1931 ///
1932 /// # Arguments
1933 ///
1934 /// - `transform`: preferred transform
1935 #[inline]
1936 pub fn try_send_preferred_buffer_transform(
1937 &self,
1938 transform: WlOutputTransform,
1939 ) -> Result<(), ObjectError> {
1940 let (
1941 arg0,
1942 ) = (
1943 transform,
1944 );
1945 let core = self.core();
1946 let client_ref = core.client.borrow();
1947 let Some(client) = &*client_ref else {
1948 return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
1949 };
1950 let id = core.client_obj_id.get().unwrap_or(0);
1951 #[cfg(feature = "logging")]
1952 if self.core.state.log {
1953 #[cold]
1954 fn log(state: &State, client_id: u64, id: u32, arg0: WlOutputTransform) {
1955 let (millis, micros) = time_since_epoch();
1956 let prefix = &state.log_prefix;
1957 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_surface#{}.preferred_buffer_transform(transform: {:?})\n", client_id, id, arg0);
1958 state.log(args);
1959 }
1960 log(&self.core.state, client.endpoint.id, id, arg0);
1961 }
1962 let endpoint = &client.endpoint;
1963 if !endpoint.flush_queued.replace(true) {
1964 self.core.state.add_flushable_endpoint(endpoint, Some(client));
1965 }
1966 let mut outgoing_ref = endpoint.outgoing.borrow_mut();
1967 let outgoing = &mut *outgoing_ref;
1968 let mut fmt = outgoing.formatter();
1969 fmt.words([
1970 id,
1971 3,
1972 arg0.0,
1973 ]);
1974 Ok(())
1975 }
1976
1977 /// preferred buffer transform for the surface
1978 ///
1979 /// This event indicates the preferred buffer transform for this surface.
1980 /// It is sent whenever the compositor's preference changes.
1981 ///
1982 /// Before receiving this event the preferred buffer transform for this
1983 /// surface is normal.
1984 ///
1985 /// Applying this transformation to the surface buffer contents and using
1986 /// wl_surface.set_buffer_transform might allow the compositor to use the
1987 /// surface buffer more efficiently.
1988 ///
1989 /// # Arguments
1990 ///
1991 /// - `transform`: preferred transform
1992 #[inline]
1993 pub fn send_preferred_buffer_transform(
1994 &self,
1995 transform: WlOutputTransform,
1996 ) {
1997 let res = self.try_send_preferred_buffer_transform(
1998 transform,
1999 );
2000 if let Err(e) = res {
2001 log_send("wl_surface.preferred_buffer_transform", &e);
2002 }
2003 }
2004}
2005
2006/// A message handler for [`WlSurface`] proxies.
2007pub trait WlSurfaceHandler: Any {
2008 /// Event handler for wl_display.delete_id messages deleting the ID of this object.
2009 ///
2010 /// The default handler forwards the event to the client, if any.
2011 #[inline]
2012 fn delete_id(&mut self, slf: &Rc<WlSurface>) {
2013 slf.core.delete_id();
2014 }
2015
2016 /// delete surface
2017 ///
2018 /// Deletes the surface and invalidates its object ID.
2019 #[inline]
2020 fn handle_destroy(
2021 &mut self,
2022 slf: &Rc<WlSurface>,
2023 ) {
2024 if !slf.core.forward_to_server.get() {
2025 return;
2026 }
2027 let res = slf.try_send_destroy(
2028 );
2029 if let Err(e) = res {
2030 log_forward("wl_surface.destroy", &e);
2031 }
2032 }
2033
2034 /// set the surface contents
2035 ///
2036 /// Set a buffer as the content of this surface.
2037 ///
2038 /// The new size of the surface is calculated based on the buffer
2039 /// size transformed by the inverse buffer_transform and the
2040 /// inverse buffer_scale. This means that at commit time the supplied
2041 /// buffer size must be an integer multiple of the buffer_scale. If
2042 /// that's not the case, an invalid_size error is sent.
2043 ///
2044 /// The x and y arguments specify the location of the new pending
2045 /// buffer's upper left corner, relative to the current buffer's upper
2046 /// left corner, in surface-local coordinates. In other words, the
2047 /// x and y, combined with the new surface size define in which
2048 /// directions the surface's size changes. Setting anything other than 0
2049 /// as x and y arguments is discouraged, and should instead be replaced
2050 /// with using the separate wl_surface.offset request.
2051 ///
2052 /// When the bound wl_surface version is 5 or higher, passing any
2053 /// non-zero x or y is a protocol violation, and will result in an
2054 /// 'invalid_offset' error being raised. The x and y arguments are ignored
2055 /// and do not change the pending state. To achieve equivalent semantics,
2056 /// use wl_surface.offset.
2057 ///
2058 /// Surface contents are double-buffered state, see wl_surface.commit.
2059 ///
2060 /// The initial surface contents are void; there is no content.
2061 /// wl_surface.attach assigns the given wl_buffer as the pending
2062 /// wl_buffer. wl_surface.commit makes the pending wl_buffer the new
2063 /// surface contents, and the size of the surface becomes the size
2064 /// calculated from the wl_buffer, as described above. After commit,
2065 /// there is no pending buffer until the next attach.
2066 ///
2067 /// Committing a pending wl_buffer allows the compositor to read the
2068 /// pixels in the wl_buffer. The compositor may access the pixels at
2069 /// any time after the wl_surface.commit request. When the compositor
2070 /// will not access the pixels anymore, it will send the
2071 /// wl_buffer.release event. Only after receiving wl_buffer.release,
2072 /// the client may reuse the wl_buffer. A wl_buffer that has been
2073 /// attached and then replaced by another attach instead of committed
2074 /// will not receive a release event, and is not used by the
2075 /// compositor.
2076 ///
2077 /// If a pending wl_buffer has been committed to more than one wl_surface,
2078 /// the delivery of wl_buffer.release events becomes undefined. A well
2079 /// behaved client should not rely on wl_buffer.release events in this
2080 /// case. Alternatively, a client could create multiple wl_buffer objects
2081 /// from the same backing storage or use a protocol extension providing
2082 /// per-commit release notifications.
2083 ///
2084 /// Destroying the wl_buffer after wl_buffer.release does not change
2085 /// the surface contents. Destroying the wl_buffer before wl_buffer.release
2086 /// is allowed as long as the underlying buffer storage isn't re-used (this
2087 /// can happen e.g. on client process termination). However, if the client
2088 /// destroys the wl_buffer before receiving the wl_buffer.release event and
2089 /// mutates the underlying buffer storage, the surface contents become
2090 /// undefined immediately.
2091 ///
2092 /// If wl_surface.attach is sent with a NULL wl_buffer, the
2093 /// following wl_surface.commit will remove the surface content.
2094 ///
2095 /// If a pending wl_buffer has been destroyed, the result is not specified.
2096 /// Many compositors are known to remove the surface content on the following
2097 /// wl_surface.commit, but this behaviour is not universal. Clients seeking to
2098 /// maximise compatibility should not destroy pending buffers and should
2099 /// ensure that they explicitly remove content from surfaces, even after
2100 /// destroying buffers.
2101 ///
2102 /// # Arguments
2103 ///
2104 /// - `buffer`: buffer of surface contents
2105 /// - `x`: surface-local x coordinate
2106 /// - `y`: surface-local y coordinate
2107 ///
2108 /// All borrowed proxies passed to this function are guaranteed to be
2109 /// immutable and non-null.
2110 #[inline]
2111 fn handle_attach(
2112 &mut self,
2113 slf: &Rc<WlSurface>,
2114 buffer: Option<&Rc<WlBuffer>>,
2115 x: i32,
2116 y: i32,
2117 ) {
2118 if !slf.core.forward_to_server.get() {
2119 return;
2120 }
2121 let res = slf.try_send_attach(
2122 buffer,
2123 x,
2124 y,
2125 );
2126 if let Err(e) = res {
2127 log_forward("wl_surface.attach", &e);
2128 }
2129 }
2130
2131 /// mark part of the surface damaged
2132 ///
2133 /// This request is used to describe the regions where the pending
2134 /// buffer is different from the current surface contents, and where
2135 /// the surface therefore needs to be repainted. The compositor
2136 /// ignores the parts of the damage that fall outside of the surface.
2137 ///
2138 /// Damage is double-buffered state, see wl_surface.commit.
2139 ///
2140 /// The damage rectangle is specified in surface-local coordinates,
2141 /// where x and y specify the upper left corner of the damage rectangle.
2142 ///
2143 /// The initial value for pending damage is empty: no damage.
2144 /// wl_surface.damage adds pending damage: the new pending damage
2145 /// is the union of old pending damage and the given rectangle.
2146 ///
2147 /// wl_surface.commit assigns pending damage as the current damage,
2148 /// and clears pending damage. The server will clear the current
2149 /// damage as it repaints the surface.
2150 ///
2151 /// Note! New clients should not use this request. Instead damage can be
2152 /// posted with wl_surface.damage_buffer which uses buffer coordinates
2153 /// instead of surface coordinates.
2154 ///
2155 /// # Arguments
2156 ///
2157 /// - `x`: surface-local x coordinate
2158 /// - `y`: surface-local y coordinate
2159 /// - `width`: width of damage rectangle
2160 /// - `height`: height of damage rectangle
2161 #[inline]
2162 fn handle_damage(
2163 &mut self,
2164 slf: &Rc<WlSurface>,
2165 x: i32,
2166 y: i32,
2167 width: i32,
2168 height: i32,
2169 ) {
2170 if !slf.core.forward_to_server.get() {
2171 return;
2172 }
2173 let res = slf.try_send_damage(
2174 x,
2175 y,
2176 width,
2177 height,
2178 );
2179 if let Err(e) = res {
2180 log_forward("wl_surface.damage", &e);
2181 }
2182 }
2183
2184 /// request a frame throttling hint
2185 ///
2186 /// Request a notification when it is a good time to start drawing a new
2187 /// frame, by creating a frame callback. This is useful for throttling
2188 /// redrawing operations, and driving animations.
2189 ///
2190 /// When a client is animating on a wl_surface, it can use the 'frame'
2191 /// request to get notified when it is a good time to draw and commit the
2192 /// next frame of animation. If the client commits an update earlier than
2193 /// that, it is likely that some updates will not make it to the display,
2194 /// and the client is wasting resources by drawing too often.
2195 ///
2196 /// The frame request will take effect on the next wl_surface.commit.
2197 /// The notification will only be posted for one frame unless
2198 /// requested again. For a wl_surface, the notifications are posted in
2199 /// the order the frame requests were committed.
2200 ///
2201 /// The server must send the notifications so that a client
2202 /// will not send excessive updates, while still allowing
2203 /// the highest possible update rate for clients that wait for the reply
2204 /// before drawing again. The server should give some time for the client
2205 /// to draw and commit after sending the frame callback events to let it
2206 /// hit the next output refresh.
2207 ///
2208 /// A server should avoid signaling the frame callbacks if the
2209 /// surface is not visible in any way, e.g. the surface is off-screen,
2210 /// or completely obscured by other opaque surfaces.
2211 ///
2212 /// The object returned by this request will be destroyed by the
2213 /// compositor after the callback is fired and as such the client must not
2214 /// attempt to use it after that point.
2215 ///
2216 /// The callback_data passed in the callback is the current time, in
2217 /// milliseconds, with an undefined base.
2218 ///
2219 /// # Arguments
2220 ///
2221 /// - `callback`: callback object for the frame request
2222 #[inline]
2223 fn handle_frame(
2224 &mut self,
2225 slf: &Rc<WlSurface>,
2226 callback: &Rc<WlCallback>,
2227 ) {
2228 if !slf.core.forward_to_server.get() {
2229 return;
2230 }
2231 let res = slf.try_send_frame(
2232 callback,
2233 );
2234 if let Err(e) = res {
2235 log_forward("wl_surface.frame", &e);
2236 }
2237 }
2238
2239 /// set opaque region
2240 ///
2241 /// This request sets the region of the surface that contains
2242 /// opaque content.
2243 ///
2244 /// The opaque region is an optimization hint for the compositor
2245 /// that lets it optimize the redrawing of content behind opaque
2246 /// regions. Setting an opaque region is not required for correct
2247 /// behaviour, but marking transparent content as opaque will result
2248 /// in repaint artifacts.
2249 ///
2250 /// The opaque region is specified in surface-local coordinates.
2251 ///
2252 /// The compositor ignores the parts of the opaque region that fall
2253 /// outside of the surface.
2254 ///
2255 /// Opaque region is double-buffered state, see wl_surface.commit.
2256 ///
2257 /// wl_surface.set_opaque_region changes the pending opaque region.
2258 /// wl_surface.commit copies the pending region to the current region.
2259 /// Otherwise, the pending and current regions are never changed.
2260 ///
2261 /// The initial value for an opaque region is empty. Setting the pending
2262 /// opaque region has copy semantics, and the wl_region object can be
2263 /// destroyed immediately. A NULL wl_region causes the pending opaque
2264 /// region to be set to empty.
2265 ///
2266 /// # Arguments
2267 ///
2268 /// - `region`: opaque region of the surface
2269 ///
2270 /// All borrowed proxies passed to this function are guaranteed to be
2271 /// immutable and non-null.
2272 #[inline]
2273 fn handle_set_opaque_region(
2274 &mut self,
2275 slf: &Rc<WlSurface>,
2276 region: Option<&Rc<WlRegion>>,
2277 ) {
2278 if !slf.core.forward_to_server.get() {
2279 return;
2280 }
2281 let res = slf.try_send_set_opaque_region(
2282 region,
2283 );
2284 if let Err(e) = res {
2285 log_forward("wl_surface.set_opaque_region", &e);
2286 }
2287 }
2288
2289 /// set input region
2290 ///
2291 /// This request sets the region of the surface that can receive
2292 /// pointer and touch events.
2293 ///
2294 /// Input events happening outside of this region will try the next
2295 /// surface in the server surface stack. The compositor ignores the
2296 /// parts of the input region that fall outside of the surface.
2297 ///
2298 /// The input region is specified in surface-local coordinates.
2299 ///
2300 /// Input region is double-buffered state, see wl_surface.commit.
2301 ///
2302 /// wl_surface.set_input_region changes the pending input region.
2303 /// wl_surface.commit copies the pending region to the current region.
2304 /// Otherwise the pending and current regions are never changed,
2305 /// except cursor and icon surfaces are special cases, see
2306 /// wl_pointer.set_cursor and wl_data_device.start_drag.
2307 ///
2308 /// The initial value for an input region is infinite. That means the
2309 /// whole surface will accept input. Setting the pending input region
2310 /// has copy semantics, and the wl_region object can be destroyed
2311 /// immediately. A NULL wl_region causes the input region to be set
2312 /// to infinite.
2313 ///
2314 /// # Arguments
2315 ///
2316 /// - `region`: input region of the surface
2317 ///
2318 /// All borrowed proxies passed to this function are guaranteed to be
2319 /// immutable and non-null.
2320 #[inline]
2321 fn handle_set_input_region(
2322 &mut self,
2323 slf: &Rc<WlSurface>,
2324 region: Option<&Rc<WlRegion>>,
2325 ) {
2326 if !slf.core.forward_to_server.get() {
2327 return;
2328 }
2329 let res = slf.try_send_set_input_region(
2330 region,
2331 );
2332 if let Err(e) = res {
2333 log_forward("wl_surface.set_input_region", &e);
2334 }
2335 }
2336
2337 /// commit pending surface state
2338 ///
2339 /// Surface state (input, opaque, and damage regions, attached buffers,
2340 /// etc.) is double-buffered. Protocol requests modify the pending state,
2341 /// as opposed to the active state in use by the compositor.
2342 ///
2343 /// All requests that need a commit to become effective are documented
2344 /// to affect double-buffered state.
2345 ///
2346 /// Other interfaces may add further double-buffered surface state.
2347 ///
2348 /// A commit request atomically creates a Content Update (CU) from the
2349 /// pending state, even if the pending state has not been touched. The
2350 /// content update is placed at the end of a per-surface queue until it
2351 /// becomes active. After commit, the new pending state is as documented for
2352 /// each related request.
2353 ///
2354 /// A CU is either a Desync Content Update (DCU) or a Sync Content Update
2355 /// (SCU). If the surface is effectively synchronized at the commit request,
2356 /// it is a SCU, otherwise a DCU.
2357 ///
2358 /// When a surface transitions from effectively synchronized to effectively
2359 /// desynchronized, all SCUs in its queue which are not reachable by any
2360 /// DCU become DCUs and dependency edges from outside the queue to these CUs
2361 /// are removed.
2362 ///
2363 /// See wl_subsurface for the definition of 'effectively synchronized' and
2364 /// 'effectively desynchronized'.
2365 ///
2366 /// When a CU is placed in the queue, the CU has a dependency on the CU in
2367 /// front of it and to the SCU at end of the queue of every direct child
2368 /// surface if that SCU exists and does not have another dependent. This can
2369 /// form a directed acyclic graph of CUs with dependencies as edges.
2370 ///
2371 /// In addition to surface state, the CU can have constraints that must be
2372 /// satisfied before it can be applied. Other interfaces may add CU
2373 /// constraints.
2374 ///
2375 /// All DCUs which do not have a SCU in front of themselves in their queue,
2376 /// are candidates. If the graph that's reachable by a candidate does not
2377 /// have any unsatisfied constraints, the entire graph must be applied
2378 /// atomically.
2379 ///
2380 /// When a CU is applied, the wl_buffer is applied before all other state.
2381 /// This means that all coordinates in double-buffered state are relative to
2382 /// the newly attached wl_buffers, except for wl_surface.attach itself. If
2383 /// there is no newly attached wl_buffer, the coordinates are relative to
2384 /// the previous content update.
2385 #[inline]
2386 fn handle_commit(
2387 &mut self,
2388 slf: &Rc<WlSurface>,
2389 ) {
2390 if !slf.core.forward_to_server.get() {
2391 return;
2392 }
2393 let res = slf.try_send_commit(
2394 );
2395 if let Err(e) = res {
2396 log_forward("wl_surface.commit", &e);
2397 }
2398 }
2399
2400 /// surface enters an output
2401 ///
2402 /// This is emitted whenever a surface's creation, movement, or resizing
2403 /// results in some part of it being within the scanout region of an
2404 /// output.
2405 ///
2406 /// Note that a surface may be overlapping with zero or more outputs.
2407 ///
2408 /// # Arguments
2409 ///
2410 /// - `output`: output entered by the surface
2411 ///
2412 /// All borrowed proxies passed to this function are guaranteed to be
2413 /// immutable and non-null.
2414 #[inline]
2415 fn handle_enter(
2416 &mut self,
2417 slf: &Rc<WlSurface>,
2418 output: &Rc<WlOutput>,
2419 ) {
2420 if !slf.core.forward_to_client.get() {
2421 return;
2422 }
2423 if let Some(client_id) = slf.core.client_id.get() {
2424 if let Some(client_id_2) = output.core().client_id.get() {
2425 if client_id != client_id_2 {
2426 return;
2427 }
2428 }
2429 }
2430 let res = slf.try_send_enter(
2431 output,
2432 );
2433 if let Err(e) = res {
2434 log_forward("wl_surface.enter", &e);
2435 }
2436 }
2437
2438 /// surface leaves an output
2439 ///
2440 /// This is emitted whenever a surface's creation, movement, or resizing
2441 /// results in it no longer having any part of it within the scanout region
2442 /// of an output.
2443 ///
2444 /// Clients should not use the number of outputs the surface is on for frame
2445 /// throttling purposes. The surface might be hidden even if no leave event
2446 /// has been sent, and the compositor might expect new surface content
2447 /// updates even if no enter event has been sent. The frame event should be
2448 /// used instead.
2449 ///
2450 /// # Arguments
2451 ///
2452 /// - `output`: output left by the surface
2453 ///
2454 /// All borrowed proxies passed to this function are guaranteed to be
2455 /// immutable and non-null.
2456 #[inline]
2457 fn handle_leave(
2458 &mut self,
2459 slf: &Rc<WlSurface>,
2460 output: &Rc<WlOutput>,
2461 ) {
2462 if !slf.core.forward_to_client.get() {
2463 return;
2464 }
2465 if let Some(client_id) = slf.core.client_id.get() {
2466 if let Some(client_id_2) = output.core().client_id.get() {
2467 if client_id != client_id_2 {
2468 return;
2469 }
2470 }
2471 }
2472 let res = slf.try_send_leave(
2473 output,
2474 );
2475 if let Err(e) = res {
2476 log_forward("wl_surface.leave", &e);
2477 }
2478 }
2479
2480 /// sets the buffer transformation
2481 ///
2482 /// This request sets the transformation that the client has already applied
2483 /// to the content of the buffer. The accepted values for the transform
2484 /// parameter are the values for wl_output.transform.
2485 ///
2486 /// The compositor applies the inverse of this transformation whenever it
2487 /// uses the buffer contents.
2488 ///
2489 /// Buffer transform is double-buffered state, see wl_surface.commit.
2490 ///
2491 /// A newly created surface has its buffer transformation set to normal.
2492 ///
2493 /// wl_surface.set_buffer_transform changes the pending buffer
2494 /// transformation. wl_surface.commit copies the pending buffer
2495 /// transformation to the current one. Otherwise, the pending and current
2496 /// values are never changed.
2497 ///
2498 /// The purpose of this request is to allow clients to render content
2499 /// according to the output transform, thus permitting the compositor to
2500 /// use certain optimizations even if the display is rotated. Using
2501 /// hardware overlays and scanning out a client buffer for fullscreen
2502 /// surfaces are examples of such optimizations. Those optimizations are
2503 /// highly dependent on the compositor implementation, so the use of this
2504 /// request should be considered on a case-by-case basis.
2505 ///
2506 /// Note that if the transform value includes 90 or 270 degree rotation,
2507 /// the width of the buffer will become the surface height and the height
2508 /// of the buffer will become the surface width.
2509 ///
2510 /// If transform is not one of the values from the
2511 /// wl_output.transform enum the invalid_transform protocol error
2512 /// is raised.
2513 ///
2514 /// # Arguments
2515 ///
2516 /// - `transform`: transform for interpreting buffer contents
2517 #[inline]
2518 fn handle_set_buffer_transform(
2519 &mut self,
2520 slf: &Rc<WlSurface>,
2521 transform: WlOutputTransform,
2522 ) {
2523 if !slf.core.forward_to_server.get() {
2524 return;
2525 }
2526 let res = slf.try_send_set_buffer_transform(
2527 transform,
2528 );
2529 if let Err(e) = res {
2530 log_forward("wl_surface.set_buffer_transform", &e);
2531 }
2532 }
2533
2534 /// sets the buffer scaling factor
2535 ///
2536 /// This request sets an optional scaling factor on how the compositor
2537 /// interprets the contents of the buffer attached to the window.
2538 ///
2539 /// Buffer scale is double-buffered state, see wl_surface.commit.
2540 ///
2541 /// A newly created surface has its buffer scale set to 1.
2542 ///
2543 /// wl_surface.set_buffer_scale changes the pending buffer scale.
2544 /// wl_surface.commit copies the pending buffer scale to the current one.
2545 /// Otherwise, the pending and current values are never changed.
2546 ///
2547 /// The purpose of this request is to allow clients to supply higher
2548 /// resolution buffer data for use on high resolution outputs. It is
2549 /// intended that you pick the same buffer scale as the scale of the
2550 /// output that the surface is displayed on. This means the compositor
2551 /// can avoid scaling when rendering the surface on that output.
2552 ///
2553 /// Note that if the scale is larger than 1, then you have to attach
2554 /// a buffer that is larger (by a factor of scale in each dimension)
2555 /// than the desired surface size.
2556 ///
2557 /// If scale is not greater than 0 the invalid_scale protocol error is
2558 /// raised.
2559 ///
2560 /// # Arguments
2561 ///
2562 /// - `scale`: scale for interpreting buffer contents
2563 #[inline]
2564 fn handle_set_buffer_scale(
2565 &mut self,
2566 slf: &Rc<WlSurface>,
2567 scale: i32,
2568 ) {
2569 if !slf.core.forward_to_server.get() {
2570 return;
2571 }
2572 let res = slf.try_send_set_buffer_scale(
2573 scale,
2574 );
2575 if let Err(e) = res {
2576 log_forward("wl_surface.set_buffer_scale", &e);
2577 }
2578 }
2579
2580 /// mark part of the surface damaged using buffer coordinates
2581 ///
2582 /// This request is used to describe the regions where the pending
2583 /// buffer is different from the current surface contents, and where
2584 /// the surface therefore needs to be repainted. The compositor
2585 /// ignores the parts of the damage that fall outside of the surface.
2586 ///
2587 /// Damage is double-buffered state, see wl_surface.commit.
2588 ///
2589 /// The damage rectangle is specified in buffer coordinates,
2590 /// where x and y specify the upper left corner of the damage rectangle.
2591 ///
2592 /// The initial value for pending damage is empty: no damage.
2593 /// wl_surface.damage_buffer adds pending damage: the new pending
2594 /// damage is the union of old pending damage and the given rectangle.
2595 ///
2596 /// wl_surface.commit assigns pending damage as the current damage,
2597 /// and clears pending damage. The server will clear the current
2598 /// damage as it repaints the surface.
2599 ///
2600 /// This request differs from wl_surface.damage in only one way - it
2601 /// takes damage in buffer coordinates instead of surface-local
2602 /// coordinates. While this generally is more intuitive than surface
2603 /// coordinates, it is especially desirable when using wp_viewport
2604 /// or when a drawing library (like EGL) is unaware of buffer scale
2605 /// and buffer transform.
2606 ///
2607 /// Note: Because buffer transformation changes and damage requests may
2608 /// be interleaved in the protocol stream, it is impossible to determine
2609 /// the actual mapping between surface and buffer damage until
2610 /// wl_surface.commit time. Therefore, compositors wishing to take both
2611 /// kinds of damage into account will have to accumulate damage from the
2612 /// two requests separately and only transform from one to the other
2613 /// after receiving the wl_surface.commit.
2614 ///
2615 /// # Arguments
2616 ///
2617 /// - `x`: buffer-local x coordinate
2618 /// - `y`: buffer-local y coordinate
2619 /// - `width`: width of damage rectangle
2620 /// - `height`: height of damage rectangle
2621 #[inline]
2622 fn handle_damage_buffer(
2623 &mut self,
2624 slf: &Rc<WlSurface>,
2625 x: i32,
2626 y: i32,
2627 width: i32,
2628 height: i32,
2629 ) {
2630 if !slf.core.forward_to_server.get() {
2631 return;
2632 }
2633 let res = slf.try_send_damage_buffer(
2634 x,
2635 y,
2636 width,
2637 height,
2638 );
2639 if let Err(e) = res {
2640 log_forward("wl_surface.damage_buffer", &e);
2641 }
2642 }
2643
2644 /// set the surface contents offset
2645 ///
2646 /// The x and y arguments specify the location of the new pending
2647 /// buffer's upper left corner, relative to the current buffer's upper
2648 /// left corner, in surface-local coordinates. In other words, the
2649 /// x and y, combined with the new surface size define in which
2650 /// directions the surface's size changes.
2651 ///
2652 /// The exact semantics of wl_surface.offset are role-specific. Refer to
2653 /// the documentation of specific roles for more information.
2654 ///
2655 /// Surface location offset is double-buffered state, see
2656 /// wl_surface.commit.
2657 ///
2658 /// This request is semantically equivalent to and the replaces the x and y
2659 /// arguments in the wl_surface.attach request in wl_surface versions prior
2660 /// to 5. See wl_surface.attach for details.
2661 ///
2662 /// # Arguments
2663 ///
2664 /// - `x`: surface-local x coordinate
2665 /// - `y`: surface-local y coordinate
2666 #[inline]
2667 fn handle_offset(
2668 &mut self,
2669 slf: &Rc<WlSurface>,
2670 x: i32,
2671 y: i32,
2672 ) {
2673 if !slf.core.forward_to_server.get() {
2674 return;
2675 }
2676 let res = slf.try_send_offset(
2677 x,
2678 y,
2679 );
2680 if let Err(e) = res {
2681 log_forward("wl_surface.offset", &e);
2682 }
2683 }
2684
2685 /// preferred buffer scale for the surface
2686 ///
2687 /// This event indicates the preferred buffer scale for this surface. It is
2688 /// sent whenever the compositor's preference changes.
2689 ///
2690 /// Before receiving this event the preferred buffer scale for this surface
2691 /// is 1.
2692 ///
2693 /// It is intended that scaling aware clients use this event to scale their
2694 /// content and use wl_surface.set_buffer_scale to indicate the scale they
2695 /// have rendered with. This allows clients to supply a higher detail
2696 /// buffer.
2697 ///
2698 /// The compositor shall emit a scale value greater than 0.
2699 ///
2700 /// # Arguments
2701 ///
2702 /// - `factor`: preferred scaling factor
2703 #[inline]
2704 fn handle_preferred_buffer_scale(
2705 &mut self,
2706 slf: &Rc<WlSurface>,
2707 factor: i32,
2708 ) {
2709 if !slf.core.forward_to_client.get() {
2710 return;
2711 }
2712 let res = slf.try_send_preferred_buffer_scale(
2713 factor,
2714 );
2715 if let Err(e) = res {
2716 log_forward("wl_surface.preferred_buffer_scale", &e);
2717 }
2718 }
2719
2720 /// preferred buffer transform for the surface
2721 ///
2722 /// This event indicates the preferred buffer transform for this surface.
2723 /// It is sent whenever the compositor's preference changes.
2724 ///
2725 /// Before receiving this event the preferred buffer transform for this
2726 /// surface is normal.
2727 ///
2728 /// Applying this transformation to the surface buffer contents and using
2729 /// wl_surface.set_buffer_transform might allow the compositor to use the
2730 /// surface buffer more efficiently.
2731 ///
2732 /// # Arguments
2733 ///
2734 /// - `transform`: preferred transform
2735 #[inline]
2736 fn handle_preferred_buffer_transform(
2737 &mut self,
2738 slf: &Rc<WlSurface>,
2739 transform: WlOutputTransform,
2740 ) {
2741 if !slf.core.forward_to_client.get() {
2742 return;
2743 }
2744 let res = slf.try_send_preferred_buffer_transform(
2745 transform,
2746 );
2747 if let Err(e) = res {
2748 log_forward("wl_surface.preferred_buffer_transform", &e);
2749 }
2750 }
2751}
2752
2753impl ObjectPrivate for WlSurface {
2754 fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
2755 Rc::<Self>::new_cyclic(|slf| Self {
2756 core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlSurface, version),
2757 handler: Default::default(),
2758 })
2759 }
2760
2761 fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
2762 let Some(mut handler) = self.handler.try_borrow_mut() else {
2763 return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
2764 };
2765 if let Some(handler) = &mut *handler {
2766 handler.delete_id(&self);
2767 } else {
2768 self.core.delete_id();
2769 }
2770 Ok(())
2771 }
2772
2773 fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
2774 let Some(mut handler) = self.handler.try_borrow_mut() else {
2775 return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
2776 };
2777 let handler = &mut *handler;
2778 match msg[1] & 0xffff {
2779 0 => {
2780 if msg.len() != 2 {
2781 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
2782 }
2783 #[cfg(feature = "logging")]
2784 if self.core.state.log {
2785 #[cold]
2786 fn log(state: &State, client_id: u64, id: u32) {
2787 let (millis, micros) = time_since_epoch();
2788 let prefix = &state.log_prefix;
2789 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.destroy()\n", client_id, id);
2790 state.log(args);
2791 }
2792 log(&self.core.state, client.endpoint.id, msg[0]);
2793 }
2794 self.core.handle_client_destroy();
2795 if let Some(handler) = handler {
2796 (**handler).handle_destroy(&self);
2797 } else {
2798 DefaultHandler.handle_destroy(&self);
2799 }
2800 }
2801 1 => {
2802 let [
2803 arg0,
2804 arg1,
2805 arg2,
2806 ] = msg[2..] else {
2807 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 20)));
2808 };
2809 let arg1 = arg1 as i32;
2810 let arg2 = arg2 as i32;
2811 #[cfg(feature = "logging")]
2812 if self.core.state.log {
2813 #[cold]
2814 fn log(state: &State, client_id: u64, id: u32, arg0: u32, arg1: i32, arg2: i32) {
2815 let (millis, micros) = time_since_epoch();
2816 let prefix = &state.log_prefix;
2817 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);
2818 state.log(args);
2819 }
2820 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2);
2821 }
2822 let arg0 = if arg0 == 0 {
2823 None
2824 } else {
2825 let arg0_id = arg0;
2826 let Some(arg0) = client.endpoint.lookup(arg0_id) else {
2827 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
2828 };
2829 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlBuffer>() else {
2830 let o = client.endpoint.lookup(arg0_id).unwrap();
2831 return Err(ObjectError(ObjectErrorKind::WrongObjectType("buffer", o.core().interface, ObjectInterface::WlBuffer)));
2832 };
2833 Some(arg0)
2834 };
2835 let arg0 = arg0.as_ref();
2836 if let Some(handler) = handler {
2837 (**handler).handle_attach(&self, arg0, arg1, arg2);
2838 } else {
2839 DefaultHandler.handle_attach(&self, arg0, arg1, arg2);
2840 }
2841 }
2842 2 => {
2843 let [
2844 arg0,
2845 arg1,
2846 arg2,
2847 arg3,
2848 ] = msg[2..] else {
2849 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
2850 };
2851 let arg0 = arg0 as i32;
2852 let arg1 = arg1 as i32;
2853 let arg2 = arg2 as i32;
2854 let arg3 = arg3 as i32;
2855 #[cfg(feature = "logging")]
2856 if self.core.state.log {
2857 #[cold]
2858 fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
2859 let (millis, micros) = time_since_epoch();
2860 let prefix = &state.log_prefix;
2861 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);
2862 state.log(args);
2863 }
2864 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
2865 }
2866 if let Some(handler) = handler {
2867 (**handler).handle_damage(&self, arg0, arg1, arg2, arg3);
2868 } else {
2869 DefaultHandler.handle_damage(&self, arg0, arg1, arg2, arg3);
2870 }
2871 }
2872 3 => {
2873 let [
2874 arg0,
2875 ] = msg[2..] else {
2876 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2877 };
2878 #[cfg(feature = "logging")]
2879 if self.core.state.log {
2880 #[cold]
2881 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
2882 let (millis, micros) = time_since_epoch();
2883 let prefix = &state.log_prefix;
2884 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.frame(callback: wl_callback#{})\n", client_id, id, arg0);
2885 state.log(args);
2886 }
2887 log(&self.core.state, client.endpoint.id, msg[0], arg0);
2888 }
2889 let arg0_id = arg0;
2890 let arg0 = WlCallback::new(&self.core.state, self.core.version);
2891 arg0.core().set_client_id(client, arg0_id, arg0.clone())
2892 .map_err(|e| ObjectError(ObjectErrorKind::SetClientId(arg0_id, "callback", e)))?;
2893 let arg0 = &arg0;
2894 if let Some(handler) = handler {
2895 (**handler).handle_frame(&self, arg0);
2896 } else {
2897 DefaultHandler.handle_frame(&self, arg0);
2898 }
2899 }
2900 4 => {
2901 let [
2902 arg0,
2903 ] = msg[2..] else {
2904 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2905 };
2906 #[cfg(feature = "logging")]
2907 if self.core.state.log {
2908 #[cold]
2909 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
2910 let (millis, micros) = time_since_epoch();
2911 let prefix = &state.log_prefix;
2912 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_opaque_region(region: wl_region#{})\n", client_id, id, arg0);
2913 state.log(args);
2914 }
2915 log(&self.core.state, client.endpoint.id, msg[0], arg0);
2916 }
2917 let arg0 = if arg0 == 0 {
2918 None
2919 } else {
2920 let arg0_id = arg0;
2921 let Some(arg0) = client.endpoint.lookup(arg0_id) else {
2922 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
2923 };
2924 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlRegion>() else {
2925 let o = client.endpoint.lookup(arg0_id).unwrap();
2926 return Err(ObjectError(ObjectErrorKind::WrongObjectType("region", o.core().interface, ObjectInterface::WlRegion)));
2927 };
2928 Some(arg0)
2929 };
2930 let arg0 = arg0.as_ref();
2931 if let Some(handler) = handler {
2932 (**handler).handle_set_opaque_region(&self, arg0);
2933 } else {
2934 DefaultHandler.handle_set_opaque_region(&self, arg0);
2935 }
2936 }
2937 5 => {
2938 let [
2939 arg0,
2940 ] = msg[2..] else {
2941 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
2942 };
2943 #[cfg(feature = "logging")]
2944 if self.core.state.log {
2945 #[cold]
2946 fn log(state: &State, client_id: u64, id: u32, arg0: u32) {
2947 let (millis, micros) = time_since_epoch();
2948 let prefix = &state.log_prefix;
2949 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_input_region(region: wl_region#{})\n", client_id, id, arg0);
2950 state.log(args);
2951 }
2952 log(&self.core.state, client.endpoint.id, msg[0], arg0);
2953 }
2954 let arg0 = if arg0 == 0 {
2955 None
2956 } else {
2957 let arg0_id = arg0;
2958 let Some(arg0) = client.endpoint.lookup(arg0_id) else {
2959 return Err(ObjectError(ObjectErrorKind::NoClientObject(client.endpoint.id, arg0_id)));
2960 };
2961 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlRegion>() else {
2962 let o = client.endpoint.lookup(arg0_id).unwrap();
2963 return Err(ObjectError(ObjectErrorKind::WrongObjectType("region", o.core().interface, ObjectInterface::WlRegion)));
2964 };
2965 Some(arg0)
2966 };
2967 let arg0 = arg0.as_ref();
2968 if let Some(handler) = handler {
2969 (**handler).handle_set_input_region(&self, arg0);
2970 } else {
2971 DefaultHandler.handle_set_input_region(&self, arg0);
2972 }
2973 }
2974 6 => {
2975 if msg.len() != 2 {
2976 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
2977 }
2978 #[cfg(feature = "logging")]
2979 if self.core.state.log {
2980 #[cold]
2981 fn log(state: &State, client_id: u64, id: u32) {
2982 let (millis, micros) = time_since_epoch();
2983 let prefix = &state.log_prefix;
2984 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.commit()\n", client_id, id);
2985 state.log(args);
2986 }
2987 log(&self.core.state, client.endpoint.id, msg[0]);
2988 }
2989 if let Some(handler) = handler {
2990 (**handler).handle_commit(&self);
2991 } else {
2992 DefaultHandler.handle_commit(&self);
2993 }
2994 }
2995 7 => {
2996 let [
2997 arg0,
2998 ] = msg[2..] else {
2999 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3000 };
3001 let arg0 = WlOutputTransform(arg0);
3002 #[cfg(feature = "logging")]
3003 if self.core.state.log {
3004 #[cold]
3005 fn log(state: &State, client_id: u64, id: u32, arg0: WlOutputTransform) {
3006 let (millis, micros) = time_since_epoch();
3007 let prefix = &state.log_prefix;
3008 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_buffer_transform(transform: {:?})\n", client_id, id, arg0);
3009 state.log(args);
3010 }
3011 log(&self.core.state, client.endpoint.id, msg[0], arg0);
3012 }
3013 if let Some(handler) = handler {
3014 (**handler).handle_set_buffer_transform(&self, arg0);
3015 } else {
3016 DefaultHandler.handle_set_buffer_transform(&self, arg0);
3017 }
3018 }
3019 8 => {
3020 let [
3021 arg0,
3022 ] = msg[2..] else {
3023 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3024 };
3025 let arg0 = arg0 as i32;
3026 #[cfg(feature = "logging")]
3027 if self.core.state.log {
3028 #[cold]
3029 fn log(state: &State, client_id: u64, id: u32, arg0: i32) {
3030 let (millis, micros) = time_since_epoch();
3031 let prefix = &state.log_prefix;
3032 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.set_buffer_scale(scale: {})\n", client_id, id, arg0);
3033 state.log(args);
3034 }
3035 log(&self.core.state, client.endpoint.id, msg[0], arg0);
3036 }
3037 if let Some(handler) = handler {
3038 (**handler).handle_set_buffer_scale(&self, arg0);
3039 } else {
3040 DefaultHandler.handle_set_buffer_scale(&self, arg0);
3041 }
3042 }
3043 9 => {
3044 let [
3045 arg0,
3046 arg1,
3047 arg2,
3048 arg3,
3049 ] = msg[2..] else {
3050 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 24)));
3051 };
3052 let arg0 = arg0 as i32;
3053 let arg1 = arg1 as i32;
3054 let arg2 = arg2 as i32;
3055 let arg3 = arg3 as i32;
3056 #[cfg(feature = "logging")]
3057 if self.core.state.log {
3058 #[cold]
3059 fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32, arg2: i32, arg3: i32) {
3060 let (millis, micros) = time_since_epoch();
3061 let prefix = &state.log_prefix;
3062 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);
3063 state.log(args);
3064 }
3065 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1, arg2, arg3);
3066 }
3067 if let Some(handler) = handler {
3068 (**handler).handle_damage_buffer(&self, arg0, arg1, arg2, arg3);
3069 } else {
3070 DefaultHandler.handle_damage_buffer(&self, arg0, arg1, arg2, arg3);
3071 }
3072 }
3073 10 => {
3074 let [
3075 arg0,
3076 arg1,
3077 ] = msg[2..] else {
3078 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 16)));
3079 };
3080 let arg0 = arg0 as i32;
3081 let arg1 = arg1 as i32;
3082 #[cfg(feature = "logging")]
3083 if self.core.state.log {
3084 #[cold]
3085 fn log(state: &State, client_id: u64, id: u32, arg0: i32, arg1: i32) {
3086 let (millis, micros) = time_since_epoch();
3087 let prefix = &state.log_prefix;
3088 let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_surface#{}.offset(x: {}, y: {})\n", client_id, id, arg0, arg1);
3089 state.log(args);
3090 }
3091 log(&self.core.state, client.endpoint.id, msg[0], arg0, arg1);
3092 }
3093 if let Some(handler) = handler {
3094 (**handler).handle_offset(&self, arg0, arg1);
3095 } else {
3096 DefaultHandler.handle_offset(&self, arg0, arg1);
3097 }
3098 }
3099 n => {
3100 let _ = client;
3101 let _ = msg;
3102 let _ = fds;
3103 let _ = handler;
3104 return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
3105 }
3106 }
3107 Ok(())
3108 }
3109
3110 fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
3111 let Some(mut handler) = self.handler.try_borrow_mut() else {
3112 return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
3113 };
3114 let handler = &mut *handler;
3115 match msg[1] & 0xffff {
3116 0 => {
3117 let [
3118 arg0,
3119 ] = msg[2..] else {
3120 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3121 };
3122 #[cfg(feature = "logging")]
3123 if self.core.state.log {
3124 #[cold]
3125 fn log(state: &State, id: u32, arg0: u32) {
3126 let (millis, micros) = time_since_epoch();
3127 let prefix = &state.log_prefix;
3128 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server -> wl_surface#{}.enter(output: wl_output#{})\n", id, arg0);
3129 state.log(args);
3130 }
3131 log(&self.core.state, msg[0], arg0);
3132 }
3133 let arg0_id = arg0;
3134 let Some(arg0) = server.lookup(arg0_id) else {
3135 return Err(ObjectError(ObjectErrorKind::NoServerObject(arg0_id)));
3136 };
3137 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlOutput>() else {
3138 let o = server.lookup(arg0_id).unwrap();
3139 return Err(ObjectError(ObjectErrorKind::WrongObjectType("output", o.core().interface, ObjectInterface::WlOutput)));
3140 };
3141 let arg0 = &arg0;
3142 if let Some(handler) = handler {
3143 (**handler).handle_enter(&self, arg0);
3144 } else {
3145 DefaultHandler.handle_enter(&self, arg0);
3146 }
3147 }
3148 1 => {
3149 let [
3150 arg0,
3151 ] = msg[2..] else {
3152 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3153 };
3154 #[cfg(feature = "logging")]
3155 if self.core.state.log {
3156 #[cold]
3157 fn log(state: &State, id: u32, arg0: u32) {
3158 let (millis, micros) = time_since_epoch();
3159 let prefix = &state.log_prefix;
3160 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server -> wl_surface#{}.leave(output: wl_output#{})\n", id, arg0);
3161 state.log(args);
3162 }
3163 log(&self.core.state, msg[0], arg0);
3164 }
3165 let arg0_id = arg0;
3166 let Some(arg0) = server.lookup(arg0_id) else {
3167 return Err(ObjectError(ObjectErrorKind::NoServerObject(arg0_id)));
3168 };
3169 let Ok(arg0) = (arg0 as Rc<dyn Any>).downcast::<WlOutput>() else {
3170 let o = server.lookup(arg0_id).unwrap();
3171 return Err(ObjectError(ObjectErrorKind::WrongObjectType("output", o.core().interface, ObjectInterface::WlOutput)));
3172 };
3173 let arg0 = &arg0;
3174 if let Some(handler) = handler {
3175 (**handler).handle_leave(&self, arg0);
3176 } else {
3177 DefaultHandler.handle_leave(&self, arg0);
3178 }
3179 }
3180 2 => {
3181 let [
3182 arg0,
3183 ] = msg[2..] else {
3184 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3185 };
3186 let arg0 = arg0 as i32;
3187 #[cfg(feature = "logging")]
3188 if self.core.state.log {
3189 #[cold]
3190 fn log(state: &State, id: u32, arg0: i32) {
3191 let (millis, micros) = time_since_epoch();
3192 let prefix = &state.log_prefix;
3193 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server -> wl_surface#{}.preferred_buffer_scale(factor: {})\n", id, arg0);
3194 state.log(args);
3195 }
3196 log(&self.core.state, msg[0], arg0);
3197 }
3198 if let Some(handler) = handler {
3199 (**handler).handle_preferred_buffer_scale(&self, arg0);
3200 } else {
3201 DefaultHandler.handle_preferred_buffer_scale(&self, arg0);
3202 }
3203 }
3204 3 => {
3205 let [
3206 arg0,
3207 ] = msg[2..] else {
3208 return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 12)));
3209 };
3210 let arg0 = WlOutputTransform(arg0);
3211 #[cfg(feature = "logging")]
3212 if self.core.state.log {
3213 #[cold]
3214 fn log(state: &State, id: u32, arg0: WlOutputTransform) {
3215 let (millis, micros) = time_since_epoch();
3216 let prefix = &state.log_prefix;
3217 let args = format_args!("[{millis:7}.{micros:03}] {prefix}server -> wl_surface#{}.preferred_buffer_transform(transform: {:?})\n", id, arg0);
3218 state.log(args);
3219 }
3220 log(&self.core.state, msg[0], arg0);
3221 }
3222 if let Some(handler) = handler {
3223 (**handler).handle_preferred_buffer_transform(&self, arg0);
3224 } else {
3225 DefaultHandler.handle_preferred_buffer_transform(&self, arg0);
3226 }
3227 }
3228 n => {
3229 let _ = server;
3230 let _ = msg;
3231 let _ = fds;
3232 let _ = handler;
3233 return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
3234 }
3235 }
3236 Ok(())
3237 }
3238
3239 fn get_request_name(&self, id: u32) -> Option<&'static str> {
3240 let name = match id {
3241 0 => "destroy",
3242 1 => "attach",
3243 2 => "damage",
3244 3 => "frame",
3245 4 => "set_opaque_region",
3246 5 => "set_input_region",
3247 6 => "commit",
3248 7 => "set_buffer_transform",
3249 8 => "set_buffer_scale",
3250 9 => "damage_buffer",
3251 10 => "offset",
3252 _ => return None,
3253 };
3254 Some(name)
3255 }
3256
3257 fn get_event_name(&self, id: u32) -> Option<&'static str> {
3258 let name = match id {
3259 0 => "enter",
3260 1 => "leave",
3261 2 => "preferred_buffer_scale",
3262 3 => "preferred_buffer_transform",
3263 _ => return None,
3264 };
3265 Some(name)
3266 }
3267}
3268
3269impl Object for WlSurface {
3270 fn core(&self) -> &ObjectCore {
3271 &self.core
3272 }
3273
3274 fn unset_handler(&self) {
3275 self.handler.set(None);
3276 }
3277
3278 fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
3279 let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
3280 if borrowed.is_none() {
3281 return Err(HandlerAccessError::NoHandler);
3282 }
3283 Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
3284 }
3285
3286 fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
3287 let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
3288 if borrowed.is_none() {
3289 return Err(HandlerAccessError::NoHandler);
3290 }
3291 Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
3292 }
3293}
3294
3295impl WlSurface {
3296 /// Since when the error.invalid_scale enum variant is available.
3297 pub const ENM__ERROR_INVALID_SCALE__SINCE: u32 = 1;
3298 /// Since when the error.invalid_transform enum variant is available.
3299 pub const ENM__ERROR_INVALID_TRANSFORM__SINCE: u32 = 1;
3300 /// Since when the error.invalid_size enum variant is available.
3301 pub const ENM__ERROR_INVALID_SIZE__SINCE: u32 = 1;
3302 /// Since when the error.invalid_offset enum variant is available.
3303 pub const ENM__ERROR_INVALID_OFFSET__SINCE: u32 = 1;
3304 /// Since when the error.defunct_role_object enum variant is available.
3305 pub const ENM__ERROR_DEFUNCT_ROLE_OBJECT__SINCE: u32 = 1;
3306}
3307
3308/// wl_surface error values
3309///
3310/// These errors can be emitted in response to wl_surface requests.
3311#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
3312pub struct WlSurfaceError(pub u32);
3313
3314impl WlSurfaceError {
3315 /// buffer scale value is invalid
3316 pub const INVALID_SCALE: Self = Self(0);
3317
3318 /// buffer transform value is invalid
3319 pub const INVALID_TRANSFORM: Self = Self(1);
3320
3321 /// buffer size is invalid
3322 pub const INVALID_SIZE: Self = Self(2);
3323
3324 /// buffer offset is invalid
3325 pub const INVALID_OFFSET: Self = Self(3);
3326
3327 /// surface was destroyed before its role object
3328 pub const DEFUNCT_ROLE_OBJECT: Self = Self(4);
3329}
3330
3331impl Debug for WlSurfaceError {
3332 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
3333 let name = match *self {
3334 Self::INVALID_SCALE => "INVALID_SCALE",
3335 Self::INVALID_TRANSFORM => "INVALID_TRANSFORM",
3336 Self::INVALID_SIZE => "INVALID_SIZE",
3337 Self::INVALID_OFFSET => "INVALID_OFFSET",
3338 Self::DEFUNCT_ROLE_OBJECT => "DEFUNCT_ROLE_OBJECT",
3339 _ => return Debug::fmt(&self.0, f),
3340 };
3341 f.write_str(name)
3342 }
3343}