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