xdg_shell_server_protocol/xdg_shell_server_protocol.rs
1// GENERATED FILE -- DO NOT EDIT
2//
3// Copyright © 2008-2013 Kristian Høgsberg
4// Copyright © 2013 Rafael Antognolli
5// Copyright © 2013 Jasper St. Pierre
6// Copyright © 2010-2013 Intel Corporation
7// Copyright © 2015-2017 Samsung Electronics Co., Ltd
8// Copyright © 2015-2017 Red Hat Inc.
9//
10// Permission is hereby granted, free of charge, to any person obtaining a
11// copy of this software and associated documentation files (the "Software"),
12// to deal in the Software without restriction, including without limitation
13// the rights to use, copy, modify, merge, publish, distribute, sublicense,
14// and/or sell copies of the Software, and to permit persons to whom the
15// Software is furnished to do so, subject to the following conditions:
16//
17// The above copyright notice and this permission notice (including the next
18// paragraph) shall be included in all copies or substantial portions of the
19// Software.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27// DEALINGS IN THE SOFTWARE.
28
29#![allow(warnings)]
30#![allow(clippy::all)]
31use anyhow;
32#[allow(unused_imports)]
33use fuchsia_wayland_core::{Array, Enum, Fixed, NewId, NewObject};
34use fuchsia_wayland_core::{ArgKind, Arg, FromArgs, IntoMessage, Message,
35 MessageGroupSpec, MessageHeader, MessageSpec, MessageType,
36 ObjectId, EncodeError, DecodeError, Interface};
37pub mod xdg_wm_base {
38use super::*;
39
40/// create desktop-style surfaces
41///
42/// The xdg_wm_base interface is exposed as a global object enabling clients
43/// to turn their wl_surfaces into windows in a desktop environment. It
44/// defines the basic functionality needed for clients and the compositor to
45/// create windows that can be dragged, resized, maximized, etc, as well as
46/// creating transient windows such as popup menus.
47#[derive(Debug)]
48pub struct XdgWmBase;
49
50impl Interface for XdgWmBase {
51 const NAME: &'static str = "xdg_wm_base";
52 const VERSION: u32 = 3;
53 const REQUESTS: MessageGroupSpec = MessageGroupSpec(&[
54 // destroy
55 MessageSpec(&[
56 ]),
57 // create_positioner
58 MessageSpec(&[
59 ArgKind::NewId,
60 ]),
61 // get_xdg_surface
62 MessageSpec(&[
63 ArgKind::NewId,
64 ArgKind::Object,
65 ]),
66 // pong
67 MessageSpec(&[
68 ArgKind::Uint,
69 ]),
70 ]);
71 const EVENTS: MessageGroupSpec = MessageGroupSpec(&[
72 // ping
73 MessageSpec(&[
74 ArgKind::Uint,
75 ]),
76 ]);
77 type Incoming = Request;
78 type Outgoing = Event;
79}
80
81#[derive(Debug)]
82pub enum Request {
83
84 /// destroy xdg_wm_base
85 ///
86 /// Destroy this xdg_wm_base object.
87 ///
88 /// Destroying a bound xdg_wm_base object while there are surfaces
89 /// still alive created by this xdg_wm_base object instance is illegal
90 /// and will result in a protocol error.
91 Destroy,
92
93 /// create a positioner object
94 ///
95 /// Create a positioner object. A positioner object is used to position
96 /// surfaces relative to some parent surface. See the interface description
97 /// and xdg_surface.get_popup for details.
98 CreatePositioner {
99 id: NewObject<XdgPositioner>,
100 },
101
102 /// create a shell surface from a surface
103 ///
104 /// This creates an xdg_surface for the given surface. While xdg_surface
105 /// itself is not a role, the corresponding surface may only be assigned
106 /// a role extending xdg_surface, such as xdg_toplevel or xdg_popup.
107 ///
108 /// This creates an xdg_surface for the given surface. An xdg_surface is
109 /// used as basis to define a role to a given surface, such as xdg_toplevel
110 /// or xdg_popup. It also manages functionality shared between xdg_surface
111 /// based surface roles.
112 ///
113 /// See the documentation of xdg_surface for more details about what an
114 /// xdg_surface is and how it is used.
115 GetXdgSurface {
116 id: NewObject<XdgSurface>,
117 surface: ObjectId,
118 },
119
120 /// respond to a ping event
121 ///
122 /// A client must respond to a ping event with a pong request or
123 /// the client may be deemed unresponsive. See xdg_wm_base.ping.
124 Pong {
125 /// serial of the ping event
126 serial: u32,
127 },
128}
129
130impl MessageType for Request {
131 fn log(&self, this: ObjectId) -> String {
132 match *self {
133 Request::Destroy {
134 } => {
135 format!("xdg_wm_base@{:?}::destroy()", this)
136 }
137 Request::CreatePositioner {
138 ref id,
139 } => {
140 format!("xdg_wm_base@{:?}::create_positioner(id: {:?})", this, id)
141 }
142 Request::GetXdgSurface {
143 ref id,
144 ref surface,
145 } => {
146 format!("xdg_wm_base@{:?}::get_xdg_surface(id: {:?}, surface: {:?})", this, id, surface)
147 }
148 Request::Pong {
149 ref serial,
150 } => {
151 format!("xdg_wm_base@{:?}::pong(serial: {:?})", this, serial)
152 }
153 }
154 }
155 fn message_name(&self) -> &'static std::ffi::CStr{
156 match *self {
157 Request::Destroy { .. } => c"xdg_wm_base::destroy",
158 Request::CreatePositioner { .. } => c"xdg_wm_base::create_positioner",
159 Request::GetXdgSurface { .. } => c"xdg_wm_base::get_xdg_surface",
160 Request::Pong { .. } => c"xdg_wm_base::pong",
161 }
162 }
163}
164#[derive(Debug)]
165pub enum Event {
166
167 /// check if the client is alive
168 ///
169 /// The ping event asks the client if it's still alive. Pass the
170 /// serial specified in the event back to the compositor by sending
171 /// a "pong" request back with the specified serial. See xdg_wm_base.pong.
172 ///
173 /// Compositors can use this to determine if the client is still
174 /// alive. It's unspecified what will happen if the client doesn't
175 /// respond to the ping request, or in what timeframe. Clients should
176 /// try to respond in a reasonable amount of time.
177 ///
178 /// A compositor is free to ping in any way it wants, but a client must
179 /// always respond to any xdg_wm_base object it created.
180 Ping {
181 /// pass this to the pong request
182 serial: u32,
183 },
184}
185
186impl MessageType for Event {
187 fn log(&self, this: ObjectId) -> String {
188 match *self {
189 Event::Ping {
190 ref serial,
191 } => {
192 format!("xdg_wm_base@{:?}::ping(serial: {:?})", this, serial)
193 }
194 }
195 }
196 fn message_name(&self) -> &'static std::ffi::CStr{
197 match *self {
198 Event::Ping { .. } => c"xdg_wm_base::ping",
199 }
200 }
201}
202impl IntoMessage for Event {
203 type Error = EncodeError;
204 fn into_message(self, id: u32) -> Result<Message, <Self as IntoMessage>::Error> {
205 let mut header = MessageHeader {
206 sender: id,
207 opcode: 0,
208 length: 0,
209 };
210 let mut msg = Message::new();
211 msg.write_header(&header)?;
212 match self {
213 Event::Ping {
214 serial,
215 } => {
216 msg.write_arg(Arg::Uint(serial))?;
217 header.opcode = 0;
218 },
219 }
220 header.length = msg.bytes().len() as u16;
221 msg.rewind();
222 msg.write_header(&header)?;
223 Ok(msg)
224 }
225}
226impl FromArgs for Request {
227 fn from_args(op: u16, mut args: Vec<Arg>) -> Result<Self, anyhow::Error> {
228 match op {
229 0 /* destroy */ => {
230 let mut iter = args.into_iter();
231 Ok(Request::Destroy {
232
233 })
234 },
235 1 /* create_positioner */ => {
236 let mut iter = args.into_iter();
237 Ok(Request::CreatePositioner {
238 id: iter.next()
239 .ok_or(DecodeError::InsufficientArgs)?
240 .as_new_id()?.into(),
241
242 })
243 },
244 2 /* get_xdg_surface */ => {
245 let mut iter = args.into_iter();
246 Ok(Request::GetXdgSurface {
247 id: iter.next()
248 .ok_or(DecodeError::InsufficientArgs)?
249 .as_new_id()?.into(),
250 surface: iter.next()
251 .ok_or(DecodeError::InsufficientArgs)?
252 .as_object()?,
253
254 })
255 },
256 3 /* pong */ => {
257 let mut iter = args.into_iter();
258 Ok(Request::Pong {
259 serial: iter.next()
260 .ok_or(DecodeError::InsufficientArgs)?
261 .as_uint()?,
262
263 })
264 },
265 _ => {
266 Err(DecodeError::InvalidOpcode(op).into())
267 },
268 }
269 }
270}
271#[derive(Copy, Clone, Debug, Eq, PartialEq)]
272#[repr(u32)]
273pub enum Error {
274 /// given wl_surface has another role,
275 Role = 0,
276 /// xdg_wm_base was destroyed before children,
277 DefunctSurfaces = 1,
278 /// the client tried to map or destroy a non-topmost popup,
279 NotTheTopmostPopup = 2,
280 /// the client specified an invalid popup parent surface,
281 InvalidPopupParent = 3,
282 /// the client provided an invalid surface state,
283 InvalidSurfaceState = 4,
284 /// the client provided an invalid positioner,
285 InvalidPositioner = 5,
286}
287
288impl Error {
289 pub fn from_bits(v: u32) -> Option<Self> {
290 match v {
291 0 => Some(Error::Role),
292 1 => Some(Error::DefunctSurfaces),
293 2 => Some(Error::NotTheTopmostPopup),
294 3 => Some(Error::InvalidPopupParent),
295 4 => Some(Error::InvalidSurfaceState),
296 5 => Some(Error::InvalidPositioner),
297 _ => None,
298 }
299 }
300
301 pub fn bits(&self) -> u32 {
302 *self as u32
303 }
304}
305impl Into<Arg> for Error {
306 fn into(self) -> Arg {
307 Arg::Uint(self.bits())
308 }
309}
310} // mod xdg_wm_base
311
312pub use crate::xdg_wm_base::XdgWmBase;
313pub use crate::xdg_wm_base::Request as XdgWmBaseRequest;
314pub use crate::xdg_wm_base::Event as XdgWmBaseEvent;
315pub mod xdg_positioner {
316use super::*;
317
318/// child surface positioner
319///
320/// The xdg_positioner provides a collection of rules for the placement of a
321/// child surface relative to a parent surface. Rules can be defined to ensure
322/// the child surface remains within the visible area's borders, and to
323/// specify how the child surface changes its position, such as sliding along
324/// an axis, or flipping around a rectangle. These positioner-created rules are
325/// constrained by the requirement that a child surface must intersect with or
326/// be at least partially adjacent to its parent surface.
327///
328/// See the various requests for details about possible rules.
329///
330/// At the time of the request, the compositor makes a copy of the rules
331/// specified by the xdg_positioner. Thus, after the request is complete the
332/// xdg_positioner object can be destroyed or reused; further changes to the
333/// object will have no effect on previous usages.
334///
335/// For an xdg_positioner object to be considered complete, it must have a
336/// non-zero size set by set_size, and a non-zero anchor rectangle set by
337/// set_anchor_rect. Passing an incomplete xdg_positioner object when
338/// positioning a surface raises an error.
339#[derive(Debug)]
340pub struct XdgPositioner;
341
342impl Interface for XdgPositioner {
343 const NAME: &'static str = "xdg_positioner";
344 const VERSION: u32 = 3;
345 const REQUESTS: MessageGroupSpec = MessageGroupSpec(&[
346 // destroy
347 MessageSpec(&[
348 ]),
349 // set_size
350 MessageSpec(&[
351 ArgKind::Int,
352 ArgKind::Int,
353 ]),
354 // set_anchor_rect
355 MessageSpec(&[
356 ArgKind::Int,
357 ArgKind::Int,
358 ArgKind::Int,
359 ArgKind::Int,
360 ]),
361 // set_anchor
362 MessageSpec(&[
363 ArgKind::Uint,
364 ]),
365 // set_gravity
366 MessageSpec(&[
367 ArgKind::Uint,
368 ]),
369 // set_constraint_adjustment
370 MessageSpec(&[
371 ArgKind::Uint,
372 ]),
373 // set_offset
374 MessageSpec(&[
375 ArgKind::Int,
376 ArgKind::Int,
377 ]),
378 // set_reactive
379 MessageSpec(&[
380 ]),
381 // set_parent_size
382 MessageSpec(&[
383 ArgKind::Int,
384 ArgKind::Int,
385 ]),
386 // set_parent_configure
387 MessageSpec(&[
388 ArgKind::Uint,
389 ]),
390 ]);
391 const EVENTS: MessageGroupSpec = MessageGroupSpec(&[
392 ]);
393 type Incoming = Request;
394 type Outgoing = Event;
395}
396
397#[derive(Debug)]
398pub enum Request {
399
400 /// destroy the xdg_positioner object
401 ///
402 /// Notify the compositor that the xdg_positioner will no longer be used.
403 Destroy,
404
405 /// set the size of the to-be positioned rectangle
406 ///
407 /// Set the size of the surface that is to be positioned with the positioner
408 /// object. The size is in surface-local coordinates and corresponds to the
409 /// window geometry. See xdg_surface.set_window_geometry.
410 ///
411 /// If a zero or negative size is set the invalid_input error is raised.
412 SetSize {
413 /// width of positioned rectangle
414 width: i32,
415 /// height of positioned rectangle
416 height: i32,
417 },
418
419 /// set the anchor rectangle within the parent surface
420 ///
421 /// Specify the anchor rectangle within the parent surface that the child
422 /// surface will be placed relative to. The rectangle is relative to the
423 /// window geometry as defined by xdg_surface.set_window_geometry of the
424 /// parent surface.
425 ///
426 /// When the xdg_positioner object is used to position a child surface, the
427 /// anchor rectangle may not extend outside the window geometry of the
428 /// positioned child's parent surface.
429 ///
430 /// If a negative size is set the invalid_input error is raised.
431 SetAnchorRect {
432 /// x position of anchor rectangle
433 x: i32,
434 /// y position of anchor rectangle
435 y: i32,
436 /// width of anchor rectangle
437 width: i32,
438 /// height of anchor rectangle
439 height: i32,
440 },
441
442 /// set anchor rectangle anchor
443 ///
444 /// Defines the anchor point for the anchor rectangle. The specified anchor
445 /// is used derive an anchor point that the child surface will be
446 /// positioned relative to. If a corner anchor is set (e.g. 'top_left' or
447 /// 'bottom_right'), the anchor point will be at the specified corner;
448 /// otherwise, the derived anchor point will be centered on the specified
449 /// edge, or in the center of the anchor rectangle if no edge is specified.
450 SetAnchor {
451 /// anchor
452 anchor: Enum<Anchor>,
453 },
454
455 /// set child surface gravity
456 ///
457 /// Defines in what direction a surface should be positioned, relative to
458 /// the anchor point of the parent surface. If a corner gravity is
459 /// specified (e.g. 'bottom_right' or 'top_left'), then the child surface
460 /// will be placed towards the specified gravity; otherwise, the child
461 /// surface will be centered over the anchor point on any axis that had no
462 /// gravity specified.
463 SetGravity {
464 /// gravity direction
465 gravity: Enum<Gravity>,
466 },
467
468 /// set the adjustment to be done when constrained
469 ///
470 /// Specify how the window should be positioned if the originally intended
471 /// position caused the surface to be constrained, meaning at least
472 /// partially outside positioning boundaries set by the compositor. The
473 /// adjustment is set by constructing a bitmask describing the adjustment to
474 /// be made when the surface is constrained on that axis.
475 ///
476 /// If no bit for one axis is set, the compositor will assume that the child
477 /// surface should not change its position on that axis when constrained.
478 ///
479 /// If more than one bit for one axis is set, the order of how adjustments
480 /// are applied is specified in the corresponding adjustment descriptions.
481 ///
482 /// The default adjustment is none.
483 SetConstraintAdjustment {
484 /// bit mask of constraint adjustments
485 constraint_adjustment: u32,
486 },
487
488 /// set surface position offset
489 ///
490 /// Specify the surface position offset relative to the position of the
491 /// anchor on the anchor rectangle and the anchor on the surface. For
492 /// example if the anchor of the anchor rectangle is at (x, y), the surface
493 /// has the gravity bottom|right, and the offset is (ox, oy), the calculated
494 /// surface position will be (x + ox, y + oy). The offset position of the
495 /// surface is the one used for constraint testing. See
496 /// set_constraint_adjustment.
497 ///
498 /// An example use case is placing a popup menu on top of a user interface
499 /// element, while aligning the user interface element of the parent surface
500 /// with some user interface element placed somewhere in the popup surface.
501 SetOffset {
502 /// surface position x offset
503 x: i32,
504 /// surface position y offset
505 y: i32,
506 },
507
508 /// continuously reconstrain the surface
509 ///
510 /// When set reactive, the surface is reconstrained if the conditions used
511 /// for constraining changed, e.g. the parent window moved.
512 ///
513 /// If the conditions changed and the popup was reconstrained, an
514 /// xdg_popup.configure event is sent with updated geometry, followed by an
515 /// xdg_surface.configure event.
516 SetReactive,
517
518 ///
519 /// Set the parent window geometry the compositor should use when
520 /// positioning the popup. The compositor may use this information to
521 /// determine the future state the popup should be constrained using. If
522 /// this doesn't match the dimension of the parent the popup is eventually
523 /// positioned against, the behavior is undefined.
524 ///
525 /// The arguments are given in the surface-local coordinate space.
526 SetParentSize {
527 /// future window geometry width of parent
528 parent_width: i32,
529 /// future window geometry height of parent
530 parent_height: i32,
531 },
532
533 /// set parent configure this is a response to
534 ///
535 /// Set the serial of an xdg_surface.configure event this positioner will be
536 /// used in response to. The compositor may use this information together
537 /// with set_parent_size to determine what future state the popup should be
538 /// constrained using.
539 SetParentConfigure {
540 /// serial of parent configure event
541 serial: u32,
542 },
543}
544
545impl MessageType for Request {
546 fn log(&self, this: ObjectId) -> String {
547 match *self {
548 Request::Destroy {
549 } => {
550 format!("xdg_positioner@{:?}::destroy()", this)
551 }
552 Request::SetSize {
553 ref width,
554 ref height,
555 } => {
556 format!("xdg_positioner@{:?}::set_size(width: {:?}, height: {:?})", this, width, height)
557 }
558 Request::SetAnchorRect {
559 ref x,
560 ref y,
561 ref width,
562 ref height,
563 } => {
564 format!("xdg_positioner@{:?}::set_anchor_rect(x: {:?}, y: {:?}, width: {:?}, height: {:?})", this, x, y, width, height)
565 }
566 Request::SetAnchor {
567 ref anchor,
568 } => {
569 format!("xdg_positioner@{:?}::set_anchor(anchor: {:?})", this, anchor)
570 }
571 Request::SetGravity {
572 ref gravity,
573 } => {
574 format!("xdg_positioner@{:?}::set_gravity(gravity: {:?})", this, gravity)
575 }
576 Request::SetConstraintAdjustment {
577 ref constraint_adjustment,
578 } => {
579 format!("xdg_positioner@{:?}::set_constraint_adjustment(constraint_adjustment: {:?})", this, constraint_adjustment)
580 }
581 Request::SetOffset {
582 ref x,
583 ref y,
584 } => {
585 format!("xdg_positioner@{:?}::set_offset(x: {:?}, y: {:?})", this, x, y)
586 }
587 Request::SetReactive {
588 } => {
589 format!("xdg_positioner@{:?}::set_reactive()", this)
590 }
591 Request::SetParentSize {
592 ref parent_width,
593 ref parent_height,
594 } => {
595 format!("xdg_positioner@{:?}::set_parent_size(parent_width: {:?}, parent_height: {:?})", this, parent_width, parent_height)
596 }
597 Request::SetParentConfigure {
598 ref serial,
599 } => {
600 format!("xdg_positioner@{:?}::set_parent_configure(serial: {:?})", this, serial)
601 }
602 }
603 }
604 fn message_name(&self) -> &'static std::ffi::CStr{
605 match *self {
606 Request::Destroy { .. } => c"xdg_positioner::destroy",
607 Request::SetSize { .. } => c"xdg_positioner::set_size",
608 Request::SetAnchorRect { .. } => c"xdg_positioner::set_anchor_rect",
609 Request::SetAnchor { .. } => c"xdg_positioner::set_anchor",
610 Request::SetGravity { .. } => c"xdg_positioner::set_gravity",
611 Request::SetConstraintAdjustment { .. } => c"xdg_positioner::set_constraint_adjustment",
612 Request::SetOffset { .. } => c"xdg_positioner::set_offset",
613 Request::SetReactive { .. } => c"xdg_positioner::set_reactive",
614 Request::SetParentSize { .. } => c"xdg_positioner::set_parent_size",
615 Request::SetParentConfigure { .. } => c"xdg_positioner::set_parent_configure",
616 }
617 }
618}
619#[derive(Debug)]
620pub enum Event {
621}
622
623impl MessageType for Event {
624 fn log(&self, this: ObjectId) -> String {
625 match *self {
626 }
627 }
628 fn message_name(&self) -> &'static std::ffi::CStr{
629 match *self {
630 }
631 }
632}
633impl IntoMessage for Event {
634 type Error = EncodeError;
635 fn into_message(self, id: u32) -> Result<Message, <Self as IntoMessage>::Error> {
636 let mut header = MessageHeader {
637 sender: id,
638 opcode: 0,
639 length: 0,
640 };
641 let mut msg = Message::new();
642 msg.write_header(&header)?;
643 match self {
644 }
645 header.length = msg.bytes().len() as u16;
646 msg.rewind();
647 msg.write_header(&header)?;
648 Ok(msg)
649 }
650}
651impl FromArgs for Request {
652 fn from_args(op: u16, mut args: Vec<Arg>) -> Result<Self, anyhow::Error> {
653 match op {
654 0 /* destroy */ => {
655 let mut iter = args.into_iter();
656 Ok(Request::Destroy {
657
658 })
659 },
660 1 /* set_size */ => {
661 let mut iter = args.into_iter();
662 Ok(Request::SetSize {
663 width: iter.next()
664 .ok_or(DecodeError::InsufficientArgs)?
665 .as_int()?,
666 height: iter.next()
667 .ok_or(DecodeError::InsufficientArgs)?
668 .as_int()?,
669
670 })
671 },
672 2 /* set_anchor_rect */ => {
673 let mut iter = args.into_iter();
674 Ok(Request::SetAnchorRect {
675 x: iter.next()
676 .ok_or(DecodeError::InsufficientArgs)?
677 .as_int()?,
678 y: iter.next()
679 .ok_or(DecodeError::InsufficientArgs)?
680 .as_int()?,
681 width: iter.next()
682 .ok_or(DecodeError::InsufficientArgs)?
683 .as_int()?,
684 height: iter.next()
685 .ok_or(DecodeError::InsufficientArgs)?
686 .as_int()?,
687
688 })
689 },
690 3 /* set_anchor */ => {
691 let mut iter = args.into_iter();
692 Ok(Request::SetAnchor {
693 anchor: iter.next()
694 .ok_or(DecodeError::InsufficientArgs)?
695 .as_uint().map(|i| match Anchor::from_bits(i) {
696 Some(e) => Enum::Recognized(e),
697 None => Enum::Unrecognized(i),
698 })?,
699
700 })
701 },
702 4 /* set_gravity */ => {
703 let mut iter = args.into_iter();
704 Ok(Request::SetGravity {
705 gravity: iter.next()
706 .ok_or(DecodeError::InsufficientArgs)?
707 .as_uint().map(|i| match Gravity::from_bits(i) {
708 Some(e) => Enum::Recognized(e),
709 None => Enum::Unrecognized(i),
710 })?,
711
712 })
713 },
714 5 /* set_constraint_adjustment */ => {
715 let mut iter = args.into_iter();
716 Ok(Request::SetConstraintAdjustment {
717 constraint_adjustment: iter.next()
718 .ok_or(DecodeError::InsufficientArgs)?
719 .as_uint()?,
720
721 })
722 },
723 6 /* set_offset */ => {
724 let mut iter = args.into_iter();
725 Ok(Request::SetOffset {
726 x: iter.next()
727 .ok_or(DecodeError::InsufficientArgs)?
728 .as_int()?,
729 y: iter.next()
730 .ok_or(DecodeError::InsufficientArgs)?
731 .as_int()?,
732
733 })
734 },
735 7 /* set_reactive */ => {
736 let mut iter = args.into_iter();
737 Ok(Request::SetReactive {
738
739 })
740 },
741 8 /* set_parent_size */ => {
742 let mut iter = args.into_iter();
743 Ok(Request::SetParentSize {
744 parent_width: iter.next()
745 .ok_or(DecodeError::InsufficientArgs)?
746 .as_int()?,
747 parent_height: iter.next()
748 .ok_or(DecodeError::InsufficientArgs)?
749 .as_int()?,
750
751 })
752 },
753 9 /* set_parent_configure */ => {
754 let mut iter = args.into_iter();
755 Ok(Request::SetParentConfigure {
756 serial: iter.next()
757 .ok_or(DecodeError::InsufficientArgs)?
758 .as_uint()?,
759
760 })
761 },
762 _ => {
763 Err(DecodeError::InvalidOpcode(op).into())
764 },
765 }
766 }
767}
768#[derive(Copy, Clone, Debug, Eq, PartialEq)]
769#[repr(u32)]
770pub enum Error {
771 /// invalid input provided,
772 InvalidInput = 0,
773}
774
775impl Error {
776 pub fn from_bits(v: u32) -> Option<Self> {
777 match v {
778 0 => Some(Error::InvalidInput),
779 _ => None,
780 }
781 }
782
783 pub fn bits(&self) -> u32 {
784 *self as u32
785 }
786}
787impl Into<Arg> for Error {
788 fn into(self) -> Arg {
789 Arg::Uint(self.bits())
790 }
791}
792#[derive(Copy, Clone, Debug, Eq, PartialEq)]
793#[repr(u32)]
794pub enum Anchor {
795 None = 0,
796 Top = 1,
797 Bottom = 2,
798 Left = 3,
799 Right = 4,
800 TopLeft = 5,
801 BottomLeft = 6,
802 TopRight = 7,
803 BottomRight = 8,
804}
805
806impl Anchor {
807 pub fn from_bits(v: u32) -> Option<Self> {
808 match v {
809 0 => Some(Anchor::None),
810 1 => Some(Anchor::Top),
811 2 => Some(Anchor::Bottom),
812 3 => Some(Anchor::Left),
813 4 => Some(Anchor::Right),
814 5 => Some(Anchor::TopLeft),
815 6 => Some(Anchor::BottomLeft),
816 7 => Some(Anchor::TopRight),
817 8 => Some(Anchor::BottomRight),
818 _ => None,
819 }
820 }
821
822 pub fn bits(&self) -> u32 {
823 *self as u32
824 }
825}
826impl Into<Arg> for Anchor {
827 fn into(self) -> Arg {
828 Arg::Uint(self.bits())
829 }
830}
831#[derive(Copy, Clone, Debug, Eq, PartialEq)]
832#[repr(u32)]
833pub enum Gravity {
834 None = 0,
835 Top = 1,
836 Bottom = 2,
837 Left = 3,
838 Right = 4,
839 TopLeft = 5,
840 BottomLeft = 6,
841 TopRight = 7,
842 BottomRight = 8,
843}
844
845impl Gravity {
846 pub fn from_bits(v: u32) -> Option<Self> {
847 match v {
848 0 => Some(Gravity::None),
849 1 => Some(Gravity::Top),
850 2 => Some(Gravity::Bottom),
851 3 => Some(Gravity::Left),
852 4 => Some(Gravity::Right),
853 5 => Some(Gravity::TopLeft),
854 6 => Some(Gravity::BottomLeft),
855 7 => Some(Gravity::TopRight),
856 8 => Some(Gravity::BottomRight),
857 _ => None,
858 }
859 }
860
861 pub fn bits(&self) -> u32 {
862 *self as u32
863 }
864}
865impl Into<Arg> for Gravity {
866 fn into(self) -> Arg {
867 Arg::Uint(self.bits())
868 }
869}
870::bitflags::bitflags! {
871
872 /// constraint adjustments
873 ///
874 /// The constraint adjustment value define ways the compositor will adjust
875 /// the position of the surface, if the unadjusted position would result
876 /// in the surface being partly constrained.
877 ///
878 /// Whether a surface is considered 'constrained' is left to the compositor
879 /// to determine. For example, the surface may be partly outside the
880 /// compositor's defined 'work area', thus necessitating the child surface's
881 /// position be adjusted until it is entirely inside the work area.
882 ///
883 /// The adjustments can be combined, according to a defined precedence: 1)
884 /// Flip, 2) Slide, 3) Resize.
885 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
886 pub struct ConstraintAdjustment: u32 {
887 const None = 0;
888 const SlideX = 1;
889 const SlideY = 2;
890 const FlipX = 4;
891 const FlipY = 8;
892 const ResizeX = 16;
893 const ResizeY = 32;
894 }
895}
896impl Into<Arg> for ConstraintAdjustment {
897 fn into(self) -> Arg {
898 Arg::Uint(self.bits())
899 }
900}
901} // mod xdg_positioner
902
903pub use crate::xdg_positioner::XdgPositioner;
904pub use crate::xdg_positioner::Request as XdgPositionerRequest;
905pub use crate::xdg_positioner::Event as XdgPositionerEvent;
906pub mod xdg_surface {
907use super::*;
908
909/// desktop user interface surface base interface
910///
911/// An interface that may be implemented by a wl_surface, for
912/// implementations that provide a desktop-style user interface.
913///
914/// It provides a base set of functionality required to construct user
915/// interface elements requiring management by the compositor, such as
916/// toplevel windows, menus, etc. The types of functionality are split into
917/// xdg_surface roles.
918///
919/// Creating an xdg_surface does not set the role for a wl_surface. In order
920/// to map an xdg_surface, the client must create a role-specific object
921/// using, e.g., get_toplevel, get_popup. The wl_surface for any given
922/// xdg_surface can have at most one role, and may not be assigned any role
923/// not based on xdg_surface.
924///
925/// A role must be assigned before any other requests are made to the
926/// xdg_surface object.
927///
928/// The client must call wl_surface.commit on the corresponding wl_surface
929/// for the xdg_surface state to take effect.
930///
931/// Creating an xdg_surface from a wl_surface which has a buffer attached or
932/// committed is a client error, and any attempts by a client to attach or
933/// manipulate a buffer prior to the first xdg_surface.configure call must
934/// also be treated as errors.
935///
936/// After creating a role-specific object and setting it up, the client must
937/// perform an initial commit without any buffer attached. The compositor
938/// will reply with an xdg_surface.configure event. The client must
939/// acknowledge it and is then allowed to attach a buffer to map the surface.
940///
941/// Mapping an xdg_surface-based role surface is defined as making it
942/// possible for the surface to be shown by the compositor. Note that
943/// a mapped surface is not guaranteed to be visible once it is mapped.
944///
945/// For an xdg_surface to be mapped by the compositor, the following
946/// conditions must be met:
947/// (1) the client has assigned an xdg_surface-based role to the surface
948/// (2) the client has set and committed the xdg_surface state and the
949/// role-dependent state to the surface
950/// (3) the client has committed a buffer to the surface
951///
952/// A newly-unmapped surface is considered to have met condition (1) out
953/// of the 3 required conditions for mapping a surface if its role surface
954/// has not been destroyed.
955#[derive(Debug)]
956pub struct XdgSurface;
957
958impl Interface for XdgSurface {
959 const NAME: &'static str = "xdg_surface";
960 const VERSION: u32 = 3;
961 const REQUESTS: MessageGroupSpec = MessageGroupSpec(&[
962 // destroy
963 MessageSpec(&[
964 ]),
965 // get_toplevel
966 MessageSpec(&[
967 ArgKind::NewId,
968 ]),
969 // get_popup
970 MessageSpec(&[
971 ArgKind::NewId,
972 ArgKind::Object,
973 ArgKind::Object,
974 ]),
975 // set_window_geometry
976 MessageSpec(&[
977 ArgKind::Int,
978 ArgKind::Int,
979 ArgKind::Int,
980 ArgKind::Int,
981 ]),
982 // ack_configure
983 MessageSpec(&[
984 ArgKind::Uint,
985 ]),
986 ]);
987 const EVENTS: MessageGroupSpec = MessageGroupSpec(&[
988 // configure
989 MessageSpec(&[
990 ArgKind::Uint,
991 ]),
992 ]);
993 type Incoming = Request;
994 type Outgoing = Event;
995}
996
997#[derive(Debug)]
998pub enum Request {
999
1000 /// destroy the xdg_surface
1001 ///
1002 /// Destroy the xdg_surface object. An xdg_surface must only be destroyed
1003 /// after its role object has been destroyed.
1004 Destroy,
1005
1006 /// assign the xdg_toplevel surface role
1007 ///
1008 /// This creates an xdg_toplevel object for the given xdg_surface and gives
1009 /// the associated wl_surface the xdg_toplevel role.
1010 ///
1011 /// See the documentation of xdg_toplevel for more details about what an
1012 /// xdg_toplevel is and how it is used.
1013 GetToplevel {
1014 id: NewObject<XdgToplevel>,
1015 },
1016
1017 /// assign the xdg_popup surface role
1018 ///
1019 /// This creates an xdg_popup object for the given xdg_surface and gives
1020 /// the associated wl_surface the xdg_popup role.
1021 ///
1022 /// If null is passed as a parent, a parent surface must be specified using
1023 /// some other protocol, before committing the initial state.
1024 ///
1025 /// See the documentation of xdg_popup for more details about what an
1026 /// xdg_popup is and how it is used.
1027 GetPopup {
1028 id: NewObject<XdgPopup>,
1029 parent: ObjectId,
1030 positioner: ObjectId,
1031 },
1032
1033 /// set the new window geometry
1034 ///
1035 /// The window geometry of a surface is its "visible bounds" from the
1036 /// user's perspective. Client-side decorations often have invisible
1037 /// portions like drop-shadows which should be ignored for the
1038 /// purposes of aligning, placing and constraining windows.
1039 ///
1040 /// The window geometry is double buffered, and will be applied at the
1041 /// time wl_surface.commit of the corresponding wl_surface is called.
1042 ///
1043 /// When maintaining a position, the compositor should treat the (x, y)
1044 /// coordinate of the window geometry as the top left corner of the window.
1045 /// A client changing the (x, y) window geometry coordinate should in
1046 /// general not alter the position of the window.
1047 ///
1048 /// Once the window geometry of the surface is set, it is not possible to
1049 /// unset it, and it will remain the same until set_window_geometry is
1050 /// called again, even if a new subsurface or buffer is attached.
1051 ///
1052 /// If never set, the value is the full bounds of the surface,
1053 /// including any subsurfaces. This updates dynamically on every
1054 /// commit. This unset is meant for extremely simple clients.
1055 ///
1056 /// The arguments are given in the surface-local coordinate space of
1057 /// the wl_surface associated with this xdg_surface.
1058 ///
1059 /// The width and height must be greater than zero. Setting an invalid size
1060 /// will raise an error. When applied, the effective window geometry will be
1061 /// the set window geometry clamped to the bounding rectangle of the
1062 /// combined geometry of the surface of the xdg_surface and the associated
1063 /// subsurfaces.
1064 SetWindowGeometry {
1065 x: i32,
1066 y: i32,
1067 width: i32,
1068 height: i32,
1069 },
1070
1071 /// ack a configure event
1072 ///
1073 /// When a configure event is received, if a client commits the
1074 /// surface in response to the configure event, then the client
1075 /// must make an ack_configure request sometime before the commit
1076 /// request, passing along the serial of the configure event.
1077 ///
1078 /// For instance, for toplevel surfaces the compositor might use this
1079 /// information to move a surface to the top left only when the client has
1080 /// drawn itself for the maximized or fullscreen state.
1081 ///
1082 /// If the client receives multiple configure events before it
1083 /// can respond to one, it only has to ack the last configure event.
1084 ///
1085 /// A client is not required to commit immediately after sending
1086 /// an ack_configure request - it may even ack_configure several times
1087 /// before its next surface commit.
1088 ///
1089 /// A client may send multiple ack_configure requests before committing, but
1090 /// only the last request sent before a commit indicates which configure
1091 /// event the client really is responding to.
1092 AckConfigure {
1093 /// the serial from the configure event
1094 serial: u32,
1095 },
1096}
1097
1098impl MessageType for Request {
1099 fn log(&self, this: ObjectId) -> String {
1100 match *self {
1101 Request::Destroy {
1102 } => {
1103 format!("xdg_surface@{:?}::destroy()", this)
1104 }
1105 Request::GetToplevel {
1106 ref id,
1107 } => {
1108 format!("xdg_surface@{:?}::get_toplevel(id: {:?})", this, id)
1109 }
1110 Request::GetPopup {
1111 ref id,
1112 ref parent,
1113 ref positioner,
1114 } => {
1115 format!("xdg_surface@{:?}::get_popup(id: {:?}, parent: {:?}, positioner: {:?})", this, id, parent, positioner)
1116 }
1117 Request::SetWindowGeometry {
1118 ref x,
1119 ref y,
1120 ref width,
1121 ref height,
1122 } => {
1123 format!("xdg_surface@{:?}::set_window_geometry(x: {:?}, y: {:?}, width: {:?}, height: {:?})", this, x, y, width, height)
1124 }
1125 Request::AckConfigure {
1126 ref serial,
1127 } => {
1128 format!("xdg_surface@{:?}::ack_configure(serial: {:?})", this, serial)
1129 }
1130 }
1131 }
1132 fn message_name(&self) -> &'static std::ffi::CStr{
1133 match *self {
1134 Request::Destroy { .. } => c"xdg_surface::destroy",
1135 Request::GetToplevel { .. } => c"xdg_surface::get_toplevel",
1136 Request::GetPopup { .. } => c"xdg_surface::get_popup",
1137 Request::SetWindowGeometry { .. } => c"xdg_surface::set_window_geometry",
1138 Request::AckConfigure { .. } => c"xdg_surface::ack_configure",
1139 }
1140 }
1141}
1142#[derive(Debug)]
1143pub enum Event {
1144
1145 /// suggest a surface change
1146 ///
1147 /// The configure event marks the end of a configure sequence. A configure
1148 /// sequence is a set of one or more events configuring the state of the
1149 /// xdg_surface, including the final xdg_surface.configure event.
1150 ///
1151 /// Where applicable, xdg_surface surface roles will during a configure
1152 /// sequence extend this event as a latched state sent as events before the
1153 /// xdg_surface.configure event. Such events should be considered to make up
1154 /// a set of atomically applied configuration states, where the
1155 /// xdg_surface.configure commits the accumulated state.
1156 ///
1157 /// Clients should arrange their surface for the new states, and then send
1158 /// an ack_configure request with the serial sent in this configure event at
1159 /// some point before committing the new surface.
1160 ///
1161 /// If the client receives multiple configure events before it can respond
1162 /// to one, it is free to discard all but the last event it received.
1163 Configure {
1164 /// serial of the configure event
1165 serial: u32,
1166 },
1167}
1168
1169impl MessageType for Event {
1170 fn log(&self, this: ObjectId) -> String {
1171 match *self {
1172 Event::Configure {
1173 ref serial,
1174 } => {
1175 format!("xdg_surface@{:?}::configure(serial: {:?})", this, serial)
1176 }
1177 }
1178 }
1179 fn message_name(&self) -> &'static std::ffi::CStr{
1180 match *self {
1181 Event::Configure { .. } => c"xdg_surface::configure",
1182 }
1183 }
1184}
1185impl IntoMessage for Event {
1186 type Error = EncodeError;
1187 fn into_message(self, id: u32) -> Result<Message, <Self as IntoMessage>::Error> {
1188 let mut header = MessageHeader {
1189 sender: id,
1190 opcode: 0,
1191 length: 0,
1192 };
1193 let mut msg = Message::new();
1194 msg.write_header(&header)?;
1195 match self {
1196 Event::Configure {
1197 serial,
1198 } => {
1199 msg.write_arg(Arg::Uint(serial))?;
1200 header.opcode = 0;
1201 },
1202 }
1203 header.length = msg.bytes().len() as u16;
1204 msg.rewind();
1205 msg.write_header(&header)?;
1206 Ok(msg)
1207 }
1208}
1209impl FromArgs for Request {
1210 fn from_args(op: u16, mut args: Vec<Arg>) -> Result<Self, anyhow::Error> {
1211 match op {
1212 0 /* destroy */ => {
1213 let mut iter = args.into_iter();
1214 Ok(Request::Destroy {
1215
1216 })
1217 },
1218 1 /* get_toplevel */ => {
1219 let mut iter = args.into_iter();
1220 Ok(Request::GetToplevel {
1221 id: iter.next()
1222 .ok_or(DecodeError::InsufficientArgs)?
1223 .as_new_id()?.into(),
1224
1225 })
1226 },
1227 2 /* get_popup */ => {
1228 let mut iter = args.into_iter();
1229 Ok(Request::GetPopup {
1230 id: iter.next()
1231 .ok_or(DecodeError::InsufficientArgs)?
1232 .as_new_id()?.into(),
1233 parent: iter.next()
1234 .ok_or(DecodeError::InsufficientArgs)?
1235 .as_object()?,
1236 positioner: iter.next()
1237 .ok_or(DecodeError::InsufficientArgs)?
1238 .as_object()?,
1239
1240 })
1241 },
1242 3 /* set_window_geometry */ => {
1243 let mut iter = args.into_iter();
1244 Ok(Request::SetWindowGeometry {
1245 x: iter.next()
1246 .ok_or(DecodeError::InsufficientArgs)?
1247 .as_int()?,
1248 y: iter.next()
1249 .ok_or(DecodeError::InsufficientArgs)?
1250 .as_int()?,
1251 width: iter.next()
1252 .ok_or(DecodeError::InsufficientArgs)?
1253 .as_int()?,
1254 height: iter.next()
1255 .ok_or(DecodeError::InsufficientArgs)?
1256 .as_int()?,
1257
1258 })
1259 },
1260 4 /* ack_configure */ => {
1261 let mut iter = args.into_iter();
1262 Ok(Request::AckConfigure {
1263 serial: iter.next()
1264 .ok_or(DecodeError::InsufficientArgs)?
1265 .as_uint()?,
1266
1267 })
1268 },
1269 _ => {
1270 Err(DecodeError::InvalidOpcode(op).into())
1271 },
1272 }
1273 }
1274}
1275#[derive(Copy, Clone, Debug, Eq, PartialEq)]
1276#[repr(u32)]
1277pub enum Error {
1278 NotConstructed = 1,
1279 AlreadyConstructed = 2,
1280 UnconfiguredBuffer = 3,
1281}
1282
1283impl Error {
1284 pub fn from_bits(v: u32) -> Option<Self> {
1285 match v {
1286 1 => Some(Error::NotConstructed),
1287 2 => Some(Error::AlreadyConstructed),
1288 3 => Some(Error::UnconfiguredBuffer),
1289 _ => None,
1290 }
1291 }
1292
1293 pub fn bits(&self) -> u32 {
1294 *self as u32
1295 }
1296}
1297impl Into<Arg> for Error {
1298 fn into(self) -> Arg {
1299 Arg::Uint(self.bits())
1300 }
1301}
1302} // mod xdg_surface
1303
1304pub use crate::xdg_surface::XdgSurface;
1305pub use crate::xdg_surface::Request as XdgSurfaceRequest;
1306pub use crate::xdg_surface::Event as XdgSurfaceEvent;
1307pub mod xdg_toplevel {
1308use super::*;
1309
1310/// toplevel surface
1311///
1312/// This interface defines an xdg_surface role which allows a surface to,
1313/// among other things, set window-like properties such as maximize,
1314/// fullscreen, and minimize, set application-specific metadata like title and
1315/// id, and well as trigger user interactive operations such as interactive
1316/// resize and move.
1317///
1318/// Unmapping an xdg_toplevel means that the surface cannot be shown
1319/// by the compositor until it is explicitly mapped again.
1320/// All active operations (e.g., move, resize) are canceled and all
1321/// attributes (e.g. title, state, stacking, ...) are discarded for
1322/// an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
1323/// the state it had right after xdg_surface.get_toplevel. The client
1324/// can re-map the toplevel by perfoming a commit without any buffer
1325/// attached, waiting for a configure event and handling it as usual (see
1326/// xdg_surface description).
1327///
1328/// Attaching a null buffer to a toplevel unmaps the surface.
1329#[derive(Debug)]
1330pub struct XdgToplevel;
1331
1332impl Interface for XdgToplevel {
1333 const NAME: &'static str = "xdg_toplevel";
1334 const VERSION: u32 = 3;
1335 const REQUESTS: MessageGroupSpec = MessageGroupSpec(&[
1336 // destroy
1337 MessageSpec(&[
1338 ]),
1339 // set_parent
1340 MessageSpec(&[
1341 ArgKind::Object,
1342 ]),
1343 // set_title
1344 MessageSpec(&[
1345 ArgKind::String,
1346 ]),
1347 // set_app_id
1348 MessageSpec(&[
1349 ArgKind::String,
1350 ]),
1351 // show_window_menu
1352 MessageSpec(&[
1353 ArgKind::Object,
1354 ArgKind::Uint,
1355 ArgKind::Int,
1356 ArgKind::Int,
1357 ]),
1358 // move
1359 MessageSpec(&[
1360 ArgKind::Object,
1361 ArgKind::Uint,
1362 ]),
1363 // resize
1364 MessageSpec(&[
1365 ArgKind::Object,
1366 ArgKind::Uint,
1367 ArgKind::Uint,
1368 ]),
1369 // set_max_size
1370 MessageSpec(&[
1371 ArgKind::Int,
1372 ArgKind::Int,
1373 ]),
1374 // set_min_size
1375 MessageSpec(&[
1376 ArgKind::Int,
1377 ArgKind::Int,
1378 ]),
1379 // set_maximized
1380 MessageSpec(&[
1381 ]),
1382 // unset_maximized
1383 MessageSpec(&[
1384 ]),
1385 // set_fullscreen
1386 MessageSpec(&[
1387 ArgKind::Object,
1388 ]),
1389 // unset_fullscreen
1390 MessageSpec(&[
1391 ]),
1392 // set_minimized
1393 MessageSpec(&[
1394 ]),
1395 ]);
1396 const EVENTS: MessageGroupSpec = MessageGroupSpec(&[
1397 // configure
1398 MessageSpec(&[
1399 ArgKind::Int,
1400 ArgKind::Int,
1401 ArgKind::Array,
1402 ]),
1403 // close
1404 MessageSpec(&[
1405 ]),
1406 ]);
1407 type Incoming = Request;
1408 type Outgoing = Event;
1409}
1410
1411#[derive(Debug)]
1412pub enum Request {
1413
1414 /// destroy the xdg_toplevel
1415 ///
1416 /// This request destroys the role surface and unmaps the surface;
1417 /// see "Unmapping" behavior in interface section for details.
1418 Destroy,
1419
1420 /// set the parent of this surface
1421 ///
1422 /// Set the "parent" of this surface. This surface should be stacked
1423 /// above the parent surface and all other ancestor surfaces.
1424 ///
1425 /// Parent windows should be set on dialogs, toolboxes, or other
1426 /// "auxiliary" surfaces, so that the parent is raised when the dialog
1427 /// is raised.
1428 ///
1429 /// Setting a null parent for a child window removes any parent-child
1430 /// relationship for the child. Setting a null parent for a window which
1431 /// currently has no parent is a no-op.
1432 ///
1433 /// If the parent is unmapped then its children are managed as
1434 /// though the parent of the now-unmapped parent has become the
1435 /// parent of this surface. If no parent exists for the now-unmapped
1436 /// parent then the children are managed as though they have no
1437 /// parent surface.
1438 SetParent {
1439 parent: ObjectId,
1440 },
1441
1442 /// set surface title
1443 ///
1444 /// Set a short title for the surface.
1445 ///
1446 /// This string may be used to identify the surface in a task bar,
1447 /// window list, or other user interface elements provided by the
1448 /// compositor.
1449 ///
1450 /// The string must be encoded in UTF-8.
1451 SetTitle {
1452 title: String,
1453 },
1454
1455 /// set application ID
1456 ///
1457 /// Set an application identifier for the surface.
1458 ///
1459 /// The app ID identifies the general class of applications to which
1460 /// the surface belongs. The compositor can use this to group multiple
1461 /// surfaces together, or to determine how to launch a new application.
1462 ///
1463 /// For D-Bus activatable applications, the app ID is used as the D-Bus
1464 /// service name.
1465 ///
1466 /// The compositor shell will try to group application surfaces together
1467 /// by their app ID. As a best practice, it is suggested to select app
1468 /// ID's that match the basename of the application's .desktop file.
1469 /// For example, "org.freedesktop.FooViewer" where the .desktop file is
1470 /// "org.freedesktop.FooViewer.desktop".
1471 ///
1472 /// Like other properties, a set_app_id request can be sent after the
1473 /// xdg_toplevel has been mapped to update the property.
1474 ///
1475 /// See the desktop-entry specification [0] for more details on
1476 /// application identifiers and how they relate to well-known D-Bus
1477 /// names and .desktop files.
1478 ///
1479 /// [0] http://standards.freedesktop.org/desktop-entry-spec/
1480 SetAppId {
1481 app_id: String,
1482 },
1483
1484 /// show the window menu
1485 ///
1486 /// Clients implementing client-side decorations might want to show
1487 /// a context menu when right-clicking on the decorations, giving the
1488 /// user a menu that they can use to maximize or minimize the window.
1489 ///
1490 /// This request asks the compositor to pop up such a window menu at
1491 /// the given position, relative to the local surface coordinates of
1492 /// the parent surface. There are no guarantees as to what menu items
1493 /// the window menu contains.
1494 ///
1495 /// This request must be used in response to some sort of user action
1496 /// like a button press, key press, or touch down event.
1497 ShowWindowMenu {
1498 /// the wl_seat of the user event
1499 seat: ObjectId,
1500 /// the serial of the user event
1501 serial: u32,
1502 /// the x position to pop up the window menu at
1503 x: i32,
1504 /// the y position to pop up the window menu at
1505 y: i32,
1506 },
1507
1508 /// start an interactive move
1509 ///
1510 /// Start an interactive, user-driven move of the surface.
1511 ///
1512 /// This request must be used in response to some sort of user action
1513 /// like a button press, key press, or touch down event. The passed
1514 /// serial is used to determine the type of interactive move (touch,
1515 /// pointer, etc).
1516 ///
1517 /// The server may ignore move requests depending on the state of
1518 /// the surface (e.g. fullscreen or maximized), or if the passed serial
1519 /// is no longer valid.
1520 ///
1521 /// If triggered, the surface will lose the focus of the device
1522 /// (wl_pointer, wl_touch, etc) used for the move. It is up to the
1523 /// compositor to visually indicate that the move is taking place, such as
1524 /// updating a pointer cursor, during the move. There is no guarantee
1525 /// that the device focus will return when the move is completed.
1526 Move {
1527 /// the wl_seat of the user event
1528 seat: ObjectId,
1529 /// the serial of the user event
1530 serial: u32,
1531 },
1532
1533 /// start an interactive resize
1534 ///
1535 /// Start a user-driven, interactive resize of the surface.
1536 ///
1537 /// This request must be used in response to some sort of user action
1538 /// like a button press, key press, or touch down event. The passed
1539 /// serial is used to determine the type of interactive resize (touch,
1540 /// pointer, etc).
1541 ///
1542 /// The server may ignore resize requests depending on the state of
1543 /// the surface (e.g. fullscreen or maximized).
1544 ///
1545 /// If triggered, the client will receive configure events with the
1546 /// "resize" state enum value and the expected sizes. See the "resize"
1547 /// enum value for more details about what is required. The client
1548 /// must also acknowledge configure events using "ack_configure". After
1549 /// the resize is completed, the client will receive another "configure"
1550 /// event without the resize state.
1551 ///
1552 /// If triggered, the surface also will lose the focus of the device
1553 /// (wl_pointer, wl_touch, etc) used for the resize. It is up to the
1554 /// compositor to visually indicate that the resize is taking place,
1555 /// such as updating a pointer cursor, during the resize. There is no
1556 /// guarantee that the device focus will return when the resize is
1557 /// completed.
1558 ///
1559 /// The edges parameter specifies how the surface should be resized,
1560 /// and is one of the values of the resize_edge enum. The compositor
1561 /// may use this information to update the surface position for
1562 /// example when dragging the top left corner. The compositor may also
1563 /// use this information to adapt its behavior, e.g. choose an
1564 /// appropriate cursor image.
1565 Resize {
1566 /// the wl_seat of the user event
1567 seat: ObjectId,
1568 /// the serial of the user event
1569 serial: u32,
1570 /// which edge or corner is being dragged
1571 edges: Enum<ResizeEdge>,
1572 },
1573
1574 /// set the maximum size
1575 ///
1576 /// Set a maximum size for the window.
1577 ///
1578 /// The client can specify a maximum size so that the compositor does
1579 /// not try to configure the window beyond this size.
1580 ///
1581 /// The width and height arguments are in window geometry coordinates.
1582 /// See xdg_surface.set_window_geometry.
1583 ///
1584 /// Values set in this way are double-buffered. They will get applied
1585 /// on the next commit.
1586 ///
1587 /// The compositor can use this information to allow or disallow
1588 /// different states like maximize or fullscreen and draw accurate
1589 /// animations.
1590 ///
1591 /// Similarly, a tiling window manager may use this information to
1592 /// place and resize client windows in a more effective way.
1593 ///
1594 /// The client should not rely on the compositor to obey the maximum
1595 /// size. The compositor may decide to ignore the values set by the
1596 /// client and request a larger size.
1597 ///
1598 /// If never set, or a value of zero in the request, means that the
1599 /// client has no expected maximum size in the given dimension.
1600 /// As a result, a client wishing to reset the maximum size
1601 /// to an unspecified state can use zero for width and height in the
1602 /// request.
1603 ///
1604 /// Requesting a maximum size to be smaller than the minimum size of
1605 /// a surface is illegal and will result in a protocol error.
1606 ///
1607 /// The width and height must be greater than or equal to zero. Using
1608 /// strictly negative values for width and height will result in a
1609 /// protocol error.
1610 SetMaxSize {
1611 width: i32,
1612 height: i32,
1613 },
1614
1615 /// set the minimum size
1616 ///
1617 /// Set a minimum size for the window.
1618 ///
1619 /// The client can specify a minimum size so that the compositor does
1620 /// not try to configure the window below this size.
1621 ///
1622 /// The width and height arguments are in window geometry coordinates.
1623 /// See xdg_surface.set_window_geometry.
1624 ///
1625 /// Values set in this way are double-buffered. They will get applied
1626 /// on the next commit.
1627 ///
1628 /// The compositor can use this information to allow or disallow
1629 /// different states like maximize or fullscreen and draw accurate
1630 /// animations.
1631 ///
1632 /// Similarly, a tiling window manager may use this information to
1633 /// place and resize client windows in a more effective way.
1634 ///
1635 /// The client should not rely on the compositor to obey the minimum
1636 /// size. The compositor may decide to ignore the values set by the
1637 /// client and request a smaller size.
1638 ///
1639 /// If never set, or a value of zero in the request, means that the
1640 /// client has no expected minimum size in the given dimension.
1641 /// As a result, a client wishing to reset the minimum size
1642 /// to an unspecified state can use zero for width and height in the
1643 /// request.
1644 ///
1645 /// Requesting a minimum size to be larger than the maximum size of
1646 /// a surface is illegal and will result in a protocol error.
1647 ///
1648 /// The width and height must be greater than or equal to zero. Using
1649 /// strictly negative values for width and height will result in a
1650 /// protocol error.
1651 SetMinSize {
1652 width: i32,
1653 height: i32,
1654 },
1655
1656 /// maximize the window
1657 ///
1658 /// Maximize the surface.
1659 ///
1660 /// After requesting that the surface should be maximized, the compositor
1661 /// will respond by emitting a configure event. Whether this configure
1662 /// actually sets the window maximized is subject to compositor policies.
1663 /// The client must then update its content, drawing in the configured
1664 /// state. The client must also acknowledge the configure when committing
1665 /// the new content (see ack_configure).
1666 ///
1667 /// It is up to the compositor to decide how and where to maximize the
1668 /// surface, for example which output and what region of the screen should
1669 /// be used.
1670 ///
1671 /// If the surface was already maximized, the compositor will still emit
1672 /// a configure event with the "maximized" state.
1673 ///
1674 /// If the surface is in a fullscreen state, this request has no direct
1675 /// effect. It may alter the state the surface is returned to when
1676 /// unmaximized unless overridden by the compositor.
1677 SetMaximized,
1678
1679 /// unmaximize the window
1680 ///
1681 /// Unmaximize the surface.
1682 ///
1683 /// After requesting that the surface should be unmaximized, the compositor
1684 /// will respond by emitting a configure event. Whether this actually
1685 /// un-maximizes the window is subject to compositor policies.
1686 /// If available and applicable, the compositor will include the window
1687 /// geometry dimensions the window had prior to being maximized in the
1688 /// configure event. The client must then update its content, drawing it in
1689 /// the configured state. The client must also acknowledge the configure
1690 /// when committing the new content (see ack_configure).
1691 ///
1692 /// It is up to the compositor to position the surface after it was
1693 /// unmaximized; usually the position the surface had before maximizing, if
1694 /// applicable.
1695 ///
1696 /// If the surface was already not maximized, the compositor will still
1697 /// emit a configure event without the "maximized" state.
1698 ///
1699 /// If the surface is in a fullscreen state, this request has no direct
1700 /// effect. It may alter the state the surface is returned to when
1701 /// unmaximized unless overridden by the compositor.
1702 UnsetMaximized,
1703
1704 /// set the window as fullscreen on an output
1705 ///
1706 /// Make the surface fullscreen.
1707 ///
1708 /// After requesting that the surface should be fullscreened, the
1709 /// compositor will respond by emitting a configure event. Whether the
1710 /// client is actually put into a fullscreen state is subject to compositor
1711 /// policies. The client must also acknowledge the configure when
1712 /// committing the new content (see ack_configure).
1713 ///
1714 /// The output passed by the request indicates the client's preference as
1715 /// to which display it should be set fullscreen on. If this value is NULL,
1716 /// it's up to the compositor to choose which display will be used to map
1717 /// this surface.
1718 ///
1719 /// If the surface doesn't cover the whole output, the compositor will
1720 /// position the surface in the center of the output and compensate with
1721 /// with border fill covering the rest of the output. The content of the
1722 /// border fill is undefined, but should be assumed to be in some way that
1723 /// attempts to blend into the surrounding area (e.g. solid black).
1724 ///
1725 /// If the fullscreened surface is not opaque, the compositor must make
1726 /// sure that other screen content not part of the same surface tree (made
1727 /// up of subsurfaces, popups or similarly coupled surfaces) are not
1728 /// visible below the fullscreened surface.
1729 SetFullscreen {
1730 output: ObjectId,
1731 },
1732
1733 /// unset the window as fullscreen
1734 ///
1735 /// Make the surface no longer fullscreen.
1736 ///
1737 /// After requesting that the surface should be unfullscreened, the
1738 /// compositor will respond by emitting a configure event.
1739 /// Whether this actually removes the fullscreen state of the client is
1740 /// subject to compositor policies.
1741 ///
1742 /// Making a surface unfullscreen sets states for the surface based on the following:
1743 /// * the state(s) it may have had before becoming fullscreen
1744 /// * any state(s) decided by the compositor
1745 /// * any state(s) requested by the client while the surface was fullscreen
1746 ///
1747 /// The compositor may include the previous window geometry dimensions in
1748 /// the configure event, if applicable.
1749 ///
1750 /// The client must also acknowledge the configure when committing the new
1751 /// content (see ack_configure).
1752 UnsetFullscreen,
1753
1754 /// set the window as minimized
1755 ///
1756 /// Request that the compositor minimize your surface. There is no
1757 /// way to know if the surface is currently minimized, nor is there
1758 /// any way to unset minimization on this surface.
1759 ///
1760 /// If you are looking to throttle redrawing when minimized, please
1761 /// instead use the wl_surface.frame event for this, as this will
1762 /// also work with live previews on windows in Alt-Tab, Expose or
1763 /// similar compositor features.
1764 SetMinimized,
1765}
1766
1767impl MessageType for Request {
1768 fn log(&self, this: ObjectId) -> String {
1769 match *self {
1770 Request::Destroy {
1771 } => {
1772 format!("xdg_toplevel@{:?}::destroy()", this)
1773 }
1774 Request::SetParent {
1775 ref parent,
1776 } => {
1777 format!("xdg_toplevel@{:?}::set_parent(parent: {:?})", this, parent)
1778 }
1779 Request::SetTitle {
1780 ref title,
1781 } => {
1782 format!("xdg_toplevel@{:?}::set_title(title: {:?})", this, title)
1783 }
1784 Request::SetAppId {
1785 ref app_id,
1786 } => {
1787 format!("xdg_toplevel@{:?}::set_app_id(app_id: {:?})", this, app_id)
1788 }
1789 Request::ShowWindowMenu {
1790 ref seat,
1791 ref serial,
1792 ref x,
1793 ref y,
1794 } => {
1795 format!("xdg_toplevel@{:?}::show_window_menu(seat: {:?}, serial: {:?}, x: {:?}, y: {:?})", this, seat, serial, x, y)
1796 }
1797 Request::Move {
1798 ref seat,
1799 ref serial,
1800 } => {
1801 format!("xdg_toplevel@{:?}::move(seat: {:?}, serial: {:?})", this, seat, serial)
1802 }
1803 Request::Resize {
1804 ref seat,
1805 ref serial,
1806 ref edges,
1807 } => {
1808 format!("xdg_toplevel@{:?}::resize(seat: {:?}, serial: {:?}, edges: {:?})", this, seat, serial, edges)
1809 }
1810 Request::SetMaxSize {
1811 ref width,
1812 ref height,
1813 } => {
1814 format!("xdg_toplevel@{:?}::set_max_size(width: {:?}, height: {:?})", this, width, height)
1815 }
1816 Request::SetMinSize {
1817 ref width,
1818 ref height,
1819 } => {
1820 format!("xdg_toplevel@{:?}::set_min_size(width: {:?}, height: {:?})", this, width, height)
1821 }
1822 Request::SetMaximized {
1823 } => {
1824 format!("xdg_toplevel@{:?}::set_maximized()", this)
1825 }
1826 Request::UnsetMaximized {
1827 } => {
1828 format!("xdg_toplevel@{:?}::unset_maximized()", this)
1829 }
1830 Request::SetFullscreen {
1831 ref output,
1832 } => {
1833 format!("xdg_toplevel@{:?}::set_fullscreen(output: {:?})", this, output)
1834 }
1835 Request::UnsetFullscreen {
1836 } => {
1837 format!("xdg_toplevel@{:?}::unset_fullscreen()", this)
1838 }
1839 Request::SetMinimized {
1840 } => {
1841 format!("xdg_toplevel@{:?}::set_minimized()", this)
1842 }
1843 }
1844 }
1845 fn message_name(&self) -> &'static std::ffi::CStr{
1846 match *self {
1847 Request::Destroy { .. } => c"xdg_toplevel::destroy",
1848 Request::SetParent { .. } => c"xdg_toplevel::set_parent",
1849 Request::SetTitle { .. } => c"xdg_toplevel::set_title",
1850 Request::SetAppId { .. } => c"xdg_toplevel::set_app_id",
1851 Request::ShowWindowMenu { .. } => c"xdg_toplevel::show_window_menu",
1852 Request::Move { .. } => c"xdg_toplevel::move",
1853 Request::Resize { .. } => c"xdg_toplevel::resize",
1854 Request::SetMaxSize { .. } => c"xdg_toplevel::set_max_size",
1855 Request::SetMinSize { .. } => c"xdg_toplevel::set_min_size",
1856 Request::SetMaximized { .. } => c"xdg_toplevel::set_maximized",
1857 Request::UnsetMaximized { .. } => c"xdg_toplevel::unset_maximized",
1858 Request::SetFullscreen { .. } => c"xdg_toplevel::set_fullscreen",
1859 Request::UnsetFullscreen { .. } => c"xdg_toplevel::unset_fullscreen",
1860 Request::SetMinimized { .. } => c"xdg_toplevel::set_minimized",
1861 }
1862 }
1863}
1864#[derive(Debug)]
1865pub enum Event {
1866
1867 /// suggest a surface change
1868 ///
1869 /// This configure event asks the client to resize its toplevel surface or
1870 /// to change its state. The configured state should not be applied
1871 /// immediately. See xdg_surface.configure for details.
1872 ///
1873 /// The width and height arguments specify a hint to the window
1874 /// about how its surface should be resized in window geometry
1875 /// coordinates. See set_window_geometry.
1876 ///
1877 /// If the width or height arguments are zero, it means the client
1878 /// should decide its own window dimension. This may happen when the
1879 /// compositor needs to configure the state of the surface but doesn't
1880 /// have any information about any previous or expected dimension.
1881 ///
1882 /// The states listed in the event specify how the width/height
1883 /// arguments should be interpreted, and possibly how it should be
1884 /// drawn.
1885 ///
1886 /// Clients must send an ack_configure in response to this event. See
1887 /// xdg_surface.configure and xdg_surface.ack_configure for details.
1888 Configure {
1889 width: i32,
1890 height: i32,
1891 states: Array,
1892 },
1893
1894 /// surface wants to be closed
1895 ///
1896 /// The close event is sent by the compositor when the user
1897 /// wants the surface to be closed. This should be equivalent to
1898 /// the user clicking the close button in client-side decorations,
1899 /// if your application has any.
1900 ///
1901 /// This is only a request that the user intends to close the
1902 /// window. The client may choose to ignore this request, or show
1903 /// a dialog to ask the user to save their data, etc.
1904 Close,
1905}
1906
1907impl MessageType for Event {
1908 fn log(&self, this: ObjectId) -> String {
1909 match *self {
1910 Event::Configure {
1911 ref width,
1912 ref height,
1913 ref states,
1914 } => {
1915 format!("xdg_toplevel@{:?}::configure(width: {:?}, height: {:?}, states: Array[{}])", this, width, height, states.len())
1916 }
1917 Event::Close {
1918 } => {
1919 format!("xdg_toplevel@{:?}::close()", this)
1920 }
1921 }
1922 }
1923 fn message_name(&self) -> &'static std::ffi::CStr{
1924 match *self {
1925 Event::Configure { .. } => c"xdg_toplevel::configure",
1926 Event::Close { .. } => c"xdg_toplevel::close",
1927 }
1928 }
1929}
1930impl IntoMessage for Event {
1931 type Error = EncodeError;
1932 fn into_message(self, id: u32) -> Result<Message, <Self as IntoMessage>::Error> {
1933 let mut header = MessageHeader {
1934 sender: id,
1935 opcode: 0,
1936 length: 0,
1937 };
1938 let mut msg = Message::new();
1939 msg.write_header(&header)?;
1940 match self {
1941 Event::Configure {
1942 width,
1943 height,
1944 states,
1945 } => {
1946 msg.write_arg(Arg::Int(width))?;
1947 msg.write_arg(Arg::Int(height))?;
1948 msg.write_arg(Arg::Array(states))?;
1949 header.opcode = 0;
1950 },
1951 Event::Close {
1952 } => {
1953 header.opcode = 1;
1954 },
1955 }
1956 header.length = msg.bytes().len() as u16;
1957 msg.rewind();
1958 msg.write_header(&header)?;
1959 Ok(msg)
1960 }
1961}
1962impl FromArgs for Request {
1963 fn from_args(op: u16, mut args: Vec<Arg>) -> Result<Self, anyhow::Error> {
1964 match op {
1965 0 /* destroy */ => {
1966 let mut iter = args.into_iter();
1967 Ok(Request::Destroy {
1968
1969 })
1970 },
1971 1 /* set_parent */ => {
1972 let mut iter = args.into_iter();
1973 Ok(Request::SetParent {
1974 parent: iter.next()
1975 .ok_or(DecodeError::InsufficientArgs)?
1976 .as_object()?,
1977
1978 })
1979 },
1980 2 /* set_title */ => {
1981 let mut iter = args.into_iter();
1982 Ok(Request::SetTitle {
1983 title: iter.next()
1984 .ok_or(DecodeError::InsufficientArgs)?
1985 .as_string()?,
1986
1987 })
1988 },
1989 3 /* set_app_id */ => {
1990 let mut iter = args.into_iter();
1991 Ok(Request::SetAppId {
1992 app_id: iter.next()
1993 .ok_or(DecodeError::InsufficientArgs)?
1994 .as_string()?,
1995
1996 })
1997 },
1998 4 /* show_window_menu */ => {
1999 let mut iter = args.into_iter();
2000 Ok(Request::ShowWindowMenu {
2001 seat: iter.next()
2002 .ok_or(DecodeError::InsufficientArgs)?
2003 .as_object()?,
2004 serial: iter.next()
2005 .ok_or(DecodeError::InsufficientArgs)?
2006 .as_uint()?,
2007 x: iter.next()
2008 .ok_or(DecodeError::InsufficientArgs)?
2009 .as_int()?,
2010 y: iter.next()
2011 .ok_or(DecodeError::InsufficientArgs)?
2012 .as_int()?,
2013
2014 })
2015 },
2016 5 /* move */ => {
2017 let mut iter = args.into_iter();
2018 Ok(Request::Move {
2019 seat: iter.next()
2020 .ok_or(DecodeError::InsufficientArgs)?
2021 .as_object()?,
2022 serial: iter.next()
2023 .ok_or(DecodeError::InsufficientArgs)?
2024 .as_uint()?,
2025
2026 })
2027 },
2028 6 /* resize */ => {
2029 let mut iter = args.into_iter();
2030 Ok(Request::Resize {
2031 seat: iter.next()
2032 .ok_or(DecodeError::InsufficientArgs)?
2033 .as_object()?,
2034 serial: iter.next()
2035 .ok_or(DecodeError::InsufficientArgs)?
2036 .as_uint()?,
2037 edges: iter.next()
2038 .ok_or(DecodeError::InsufficientArgs)?
2039 .as_uint().map(|i| match ResizeEdge::from_bits(i) {
2040 Some(e) => Enum::Recognized(e),
2041 None => Enum::Unrecognized(i),
2042 })?,
2043
2044 })
2045 },
2046 7 /* set_max_size */ => {
2047 let mut iter = args.into_iter();
2048 Ok(Request::SetMaxSize {
2049 width: iter.next()
2050 .ok_or(DecodeError::InsufficientArgs)?
2051 .as_int()?,
2052 height: iter.next()
2053 .ok_or(DecodeError::InsufficientArgs)?
2054 .as_int()?,
2055
2056 })
2057 },
2058 8 /* set_min_size */ => {
2059 let mut iter = args.into_iter();
2060 Ok(Request::SetMinSize {
2061 width: iter.next()
2062 .ok_or(DecodeError::InsufficientArgs)?
2063 .as_int()?,
2064 height: iter.next()
2065 .ok_or(DecodeError::InsufficientArgs)?
2066 .as_int()?,
2067
2068 })
2069 },
2070 9 /* set_maximized */ => {
2071 let mut iter = args.into_iter();
2072 Ok(Request::SetMaximized {
2073
2074 })
2075 },
2076 10 /* unset_maximized */ => {
2077 let mut iter = args.into_iter();
2078 Ok(Request::UnsetMaximized {
2079
2080 })
2081 },
2082 11 /* set_fullscreen */ => {
2083 let mut iter = args.into_iter();
2084 Ok(Request::SetFullscreen {
2085 output: iter.next()
2086 .ok_or(DecodeError::InsufficientArgs)?
2087 .as_object()?,
2088
2089 })
2090 },
2091 12 /* unset_fullscreen */ => {
2092 let mut iter = args.into_iter();
2093 Ok(Request::UnsetFullscreen {
2094
2095 })
2096 },
2097 13 /* set_minimized */ => {
2098 let mut iter = args.into_iter();
2099 Ok(Request::SetMinimized {
2100
2101 })
2102 },
2103 _ => {
2104 Err(DecodeError::InvalidOpcode(op).into())
2105 },
2106 }
2107 }
2108}
2109
2110/// edge values for resizing
2111///
2112/// These values are used to indicate which edge of a surface
2113/// is being dragged in a resize operation.
2114#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2115#[repr(u32)]
2116pub enum ResizeEdge {
2117 None = 0,
2118 Top = 1,
2119 Bottom = 2,
2120 Left = 4,
2121 TopLeft = 5,
2122 BottomLeft = 6,
2123 Right = 8,
2124 TopRight = 9,
2125 BottomRight = 10,
2126}
2127
2128impl ResizeEdge {
2129 pub fn from_bits(v: u32) -> Option<Self> {
2130 match v {
2131 0 => Some(ResizeEdge::None),
2132 1 => Some(ResizeEdge::Top),
2133 2 => Some(ResizeEdge::Bottom),
2134 4 => Some(ResizeEdge::Left),
2135 5 => Some(ResizeEdge::TopLeft),
2136 6 => Some(ResizeEdge::BottomLeft),
2137 8 => Some(ResizeEdge::Right),
2138 9 => Some(ResizeEdge::TopRight),
2139 10 => Some(ResizeEdge::BottomRight),
2140 _ => None,
2141 }
2142 }
2143
2144 pub fn bits(&self) -> u32 {
2145 *self as u32
2146 }
2147}
2148impl Into<Arg> for ResizeEdge {
2149 fn into(self) -> Arg {
2150 Arg::Uint(self.bits())
2151 }
2152}
2153
2154/// types of state on the surface
2155///
2156/// The different state values used on the surface. This is designed for
2157/// state values like maximized, fullscreen. It is paired with the
2158/// configure event to ensure that both the client and the compositor
2159/// setting the state can be synchronized.
2160///
2161/// States set in this way are double-buffered. They will get applied on
2162/// the next commit.
2163#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2164#[repr(u32)]
2165pub enum State {
2166 /// the surface is maximized,
2167 Maximized = 1,
2168 /// the surface is fullscreen,
2169 Fullscreen = 2,
2170 /// the surface is being resized,
2171 Resizing = 3,
2172 /// the surface is now activated,
2173 Activated = 4,
2174 TiledLeft = 5,
2175 TiledRight = 6,
2176 TiledTop = 7,
2177 TiledBottom = 8,
2178}
2179
2180impl State {
2181 pub fn from_bits(v: u32) -> Option<Self> {
2182 match v {
2183 1 => Some(State::Maximized),
2184 2 => Some(State::Fullscreen),
2185 3 => Some(State::Resizing),
2186 4 => Some(State::Activated),
2187 5 => Some(State::TiledLeft),
2188 6 => Some(State::TiledRight),
2189 7 => Some(State::TiledTop),
2190 8 => Some(State::TiledBottom),
2191 _ => None,
2192 }
2193 }
2194
2195 pub fn bits(&self) -> u32 {
2196 *self as u32
2197 }
2198}
2199impl Into<Arg> for State {
2200 fn into(self) -> Arg {
2201 Arg::Uint(self.bits())
2202 }
2203}
2204} // mod xdg_toplevel
2205
2206pub use crate::xdg_toplevel::XdgToplevel;
2207pub use crate::xdg_toplevel::Request as XdgToplevelRequest;
2208pub use crate::xdg_toplevel::Event as XdgToplevelEvent;
2209pub mod xdg_popup {
2210use super::*;
2211
2212/// short-lived, popup surfaces for menus
2213///
2214/// A popup surface is a short-lived, temporary surface. It can be used to
2215/// implement for example menus, popovers, tooltips and other similar user
2216/// interface concepts.
2217///
2218/// A popup can be made to take an explicit grab. See xdg_popup.grab for
2219/// details.
2220///
2221/// When the popup is dismissed, a popup_done event will be sent out, and at
2222/// the same time the surface will be unmapped. See the xdg_popup.popup_done
2223/// event for details.
2224///
2225/// Explicitly destroying the xdg_popup object will also dismiss the popup and
2226/// unmap the surface. Clients that want to dismiss the popup when another
2227/// surface of their own is clicked should dismiss the popup using the destroy
2228/// request.
2229///
2230/// A newly created xdg_popup will be stacked on top of all previously created
2231/// xdg_popup surfaces associated with the same xdg_toplevel.
2232///
2233/// The parent of an xdg_popup must be mapped (see the xdg_surface
2234/// description) before the xdg_popup itself.
2235///
2236/// The client must call wl_surface.commit on the corresponding wl_surface
2237/// for the xdg_popup state to take effect.
2238#[derive(Debug)]
2239pub struct XdgPopup;
2240
2241impl Interface for XdgPopup {
2242 const NAME: &'static str = "xdg_popup";
2243 const VERSION: u32 = 3;
2244 const REQUESTS: MessageGroupSpec = MessageGroupSpec(&[
2245 // destroy
2246 MessageSpec(&[
2247 ]),
2248 // grab
2249 MessageSpec(&[
2250 ArgKind::Object,
2251 ArgKind::Uint,
2252 ]),
2253 // reposition
2254 MessageSpec(&[
2255 ArgKind::Object,
2256 ArgKind::Uint,
2257 ]),
2258 ]);
2259 const EVENTS: MessageGroupSpec = MessageGroupSpec(&[
2260 // configure
2261 MessageSpec(&[
2262 ArgKind::Int,
2263 ArgKind::Int,
2264 ArgKind::Int,
2265 ArgKind::Int,
2266 ]),
2267 // popup_done
2268 MessageSpec(&[
2269 ]),
2270 // repositioned
2271 MessageSpec(&[
2272 ArgKind::Uint,
2273 ]),
2274 ]);
2275 type Incoming = Request;
2276 type Outgoing = Event;
2277}
2278
2279#[derive(Debug)]
2280pub enum Request {
2281
2282 /// remove xdg_popup interface
2283 ///
2284 /// This destroys the popup. Explicitly destroying the xdg_popup
2285 /// object will also dismiss the popup, and unmap the surface.
2286 ///
2287 /// If this xdg_popup is not the "topmost" popup, a protocol error
2288 /// will be sent.
2289 Destroy,
2290
2291 /// make the popup take an explicit grab
2292 ///
2293 /// This request makes the created popup take an explicit grab. An explicit
2294 /// grab will be dismissed when the user dismisses the popup, or when the
2295 /// client destroys the xdg_popup. This can be done by the user clicking
2296 /// outside the surface, using the keyboard, or even locking the screen
2297 /// through closing the lid or a timeout.
2298 ///
2299 /// If the compositor denies the grab, the popup will be immediately
2300 /// dismissed.
2301 ///
2302 /// This request must be used in response to some sort of user action like a
2303 /// button press, key press, or touch down event. The serial number of the
2304 /// event should be passed as 'serial'.
2305 ///
2306 /// The parent of a grabbing popup must either be an xdg_toplevel surface or
2307 /// another xdg_popup with an explicit grab. If the parent is another
2308 /// xdg_popup it means that the popups are nested, with this popup now being
2309 /// the topmost popup.
2310 ///
2311 /// Nested popups must be destroyed in the reverse order they were created
2312 /// in, e.g. the only popup you are allowed to destroy at all times is the
2313 /// topmost one.
2314 ///
2315 /// When compositors choose to dismiss a popup, they may dismiss every
2316 /// nested grabbing popup as well. When a compositor dismisses popups, it
2317 /// will follow the same dismissing order as required from the client.
2318 ///
2319 /// The parent of a grabbing popup must either be another xdg_popup with an
2320 /// active explicit grab, or an xdg_popup or xdg_toplevel, if there are no
2321 /// explicit grabs already taken.
2322 ///
2323 /// If the topmost grabbing popup is destroyed, the grab will be returned to
2324 /// the parent of the popup, if that parent previously had an explicit grab.
2325 ///
2326 /// If the parent is a grabbing popup which has already been dismissed, this
2327 /// popup will be immediately dismissed. If the parent is a popup that did
2328 /// not take an explicit grab, an error will be raised.
2329 ///
2330 /// During a popup grab, the client owning the grab will receive pointer
2331 /// and touch events for all their surfaces as normal (similar to an
2332 /// "owner-events" grab in X11 parlance), while the top most grabbing popup
2333 /// will always have keyboard focus.
2334 Grab {
2335 /// the wl_seat of the user event
2336 seat: ObjectId,
2337 /// the serial of the user event
2338 serial: u32,
2339 },
2340
2341 /// recalculate the popup's location
2342 ///
2343 /// Reposition an already-mapped popup. The popup will be placed given the
2344 /// details in the passed xdg_positioner object, and a
2345 /// xdg_popup.repositioned followed by xdg_popup.configure and
2346 /// xdg_surface.configure will be emitted in response. Any parameters set
2347 /// by the previous positioner will be discarded.
2348 ///
2349 /// The passed token will be sent in the corresponding
2350 /// xdg_popup.repositioned event. The new popup position will not take
2351 /// effect until the corresponding configure event is acknowledged by the
2352 /// client. See xdg_popup.repositioned for details. The token itself is
2353 /// opaque, and has no other special meaning.
2354 ///
2355 /// If multiple reposition requests are sent, the compositor may skip all
2356 /// but the last one.
2357 ///
2358 /// If the popup is repositioned in response to a configure event for its
2359 /// parent, the client should send an xdg_positioner.set_parent_configure
2360 /// and possibly an xdg_positioner.set_parent_size request to allow the
2361 /// compositor to properly constrain the popup.
2362 ///
2363 /// If the popup is repositioned together with a parent that is being
2364 /// resized, but not in response to a configure event, the client should
2365 /// send an xdg_positioner.set_parent_size request.
2366 Reposition {
2367 positioner: ObjectId,
2368 /// reposition request token
2369 token: u32,
2370 },
2371}
2372
2373impl MessageType for Request {
2374 fn log(&self, this: ObjectId) -> String {
2375 match *self {
2376 Request::Destroy {
2377 } => {
2378 format!("xdg_popup@{:?}::destroy()", this)
2379 }
2380 Request::Grab {
2381 ref seat,
2382 ref serial,
2383 } => {
2384 format!("xdg_popup@{:?}::grab(seat: {:?}, serial: {:?})", this, seat, serial)
2385 }
2386 Request::Reposition {
2387 ref positioner,
2388 ref token,
2389 } => {
2390 format!("xdg_popup@{:?}::reposition(positioner: {:?}, token: {:?})", this, positioner, token)
2391 }
2392 }
2393 }
2394 fn message_name(&self) -> &'static std::ffi::CStr{
2395 match *self {
2396 Request::Destroy { .. } => c"xdg_popup::destroy",
2397 Request::Grab { .. } => c"xdg_popup::grab",
2398 Request::Reposition { .. } => c"xdg_popup::reposition",
2399 }
2400 }
2401}
2402#[derive(Debug)]
2403pub enum Event {
2404
2405 /// configure the popup surface
2406 ///
2407 /// This event asks the popup surface to configure itself given the
2408 /// configuration. The configured state should not be applied immediately.
2409 /// See xdg_surface.configure for details.
2410 ///
2411 /// The x and y arguments represent the position the popup was placed at
2412 /// given the xdg_positioner rule, relative to the upper left corner of the
2413 /// window geometry of the parent surface.
2414 ///
2415 /// For version 2 or older, the configure event for an xdg_popup is only
2416 /// ever sent once for the initial configuration. Starting with version 3,
2417 /// it may be sent again if the popup is setup with an xdg_positioner with
2418 /// set_reactive requested, or in response to xdg_popup.reposition requests.
2419 Configure {
2420 /// x position relative to parent surface window geometry
2421 x: i32,
2422 /// y position relative to parent surface window geometry
2423 y: i32,
2424 /// window geometry width
2425 width: i32,
2426 /// window geometry height
2427 height: i32,
2428 },
2429
2430 /// popup interaction is done
2431 ///
2432 /// The popup_done event is sent out when a popup is dismissed by the
2433 /// compositor. The client should destroy the xdg_popup object at this
2434 /// point.
2435 PopupDone,
2436
2437 /// signal the completion of a repositioned request
2438 ///
2439 /// The repositioned event is sent as part of a popup configuration
2440 /// sequence, together with xdg_popup.configure and lastly
2441 /// xdg_surface.configure to notify the completion of a reposition request.
2442 ///
2443 /// The repositioned event is to notify about the completion of a
2444 /// xdg_popup.reposition request. The token argument is the token passed
2445 /// in the xdg_popup.reposition request.
2446 ///
2447 /// Immediately after this event is emitted, xdg_popup.configure and
2448 /// xdg_surface.configure will be sent with the updated size and position,
2449 /// as well as a new configure serial.
2450 ///
2451 /// The client should optionally update the content of the popup, but must
2452 /// acknowledge the new popup configuration for the new position to take
2453 /// effect. See xdg_surface.ack_configure for details.
2454 Repositioned {
2455 /// reposition request token
2456 token: u32,
2457 },
2458}
2459
2460impl MessageType for Event {
2461 fn log(&self, this: ObjectId) -> String {
2462 match *self {
2463 Event::Configure {
2464 ref x,
2465 ref y,
2466 ref width,
2467 ref height,
2468 } => {
2469 format!("xdg_popup@{:?}::configure(x: {:?}, y: {:?}, width: {:?}, height: {:?})", this, x, y, width, height)
2470 }
2471 Event::PopupDone {
2472 } => {
2473 format!("xdg_popup@{:?}::popup_done()", this)
2474 }
2475 Event::Repositioned {
2476 ref token,
2477 } => {
2478 format!("xdg_popup@{:?}::repositioned(token: {:?})", this, token)
2479 }
2480 }
2481 }
2482 fn message_name(&self) -> &'static std::ffi::CStr{
2483 match *self {
2484 Event::Configure { .. } => c"xdg_popup::configure",
2485 Event::PopupDone { .. } => c"xdg_popup::popup_done",
2486 Event::Repositioned { .. } => c"xdg_popup::repositioned",
2487 }
2488 }
2489}
2490impl IntoMessage for Event {
2491 type Error = EncodeError;
2492 fn into_message(self, id: u32) -> Result<Message, <Self as IntoMessage>::Error> {
2493 let mut header = MessageHeader {
2494 sender: id,
2495 opcode: 0,
2496 length: 0,
2497 };
2498 let mut msg = Message::new();
2499 msg.write_header(&header)?;
2500 match self {
2501 Event::Configure {
2502 x,
2503 y,
2504 width,
2505 height,
2506 } => {
2507 msg.write_arg(Arg::Int(x))?;
2508 msg.write_arg(Arg::Int(y))?;
2509 msg.write_arg(Arg::Int(width))?;
2510 msg.write_arg(Arg::Int(height))?;
2511 header.opcode = 0;
2512 },
2513 Event::PopupDone {
2514 } => {
2515 header.opcode = 1;
2516 },
2517 Event::Repositioned {
2518 token,
2519 } => {
2520 msg.write_arg(Arg::Uint(token))?;
2521 header.opcode = 2;
2522 },
2523 }
2524 header.length = msg.bytes().len() as u16;
2525 msg.rewind();
2526 msg.write_header(&header)?;
2527 Ok(msg)
2528 }
2529}
2530impl FromArgs for Request {
2531 fn from_args(op: u16, mut args: Vec<Arg>) -> Result<Self, anyhow::Error> {
2532 match op {
2533 0 /* destroy */ => {
2534 let mut iter = args.into_iter();
2535 Ok(Request::Destroy {
2536
2537 })
2538 },
2539 1 /* grab */ => {
2540 let mut iter = args.into_iter();
2541 Ok(Request::Grab {
2542 seat: iter.next()
2543 .ok_or(DecodeError::InsufficientArgs)?
2544 .as_object()?,
2545 serial: iter.next()
2546 .ok_or(DecodeError::InsufficientArgs)?
2547 .as_uint()?,
2548
2549 })
2550 },
2551 2 /* reposition */ => {
2552 let mut iter = args.into_iter();
2553 Ok(Request::Reposition {
2554 positioner: iter.next()
2555 .ok_or(DecodeError::InsufficientArgs)?
2556 .as_object()?,
2557 token: iter.next()
2558 .ok_or(DecodeError::InsufficientArgs)?
2559 .as_uint()?,
2560
2561 })
2562 },
2563 _ => {
2564 Err(DecodeError::InvalidOpcode(op).into())
2565 },
2566 }
2567 }
2568}
2569#[derive(Copy, Clone, Debug, Eq, PartialEq)]
2570#[repr(u32)]
2571pub enum Error {
2572 /// tried to grab after being mapped,
2573 InvalidGrab = 0,
2574}
2575
2576impl Error {
2577 pub fn from_bits(v: u32) -> Option<Self> {
2578 match v {
2579 0 => Some(Error::InvalidGrab),
2580 _ => None,
2581 }
2582 }
2583
2584 pub fn bits(&self) -> u32 {
2585 *self as u32
2586 }
2587}
2588impl Into<Arg> for Error {
2589 fn into(self) -> Arg {
2590 Arg::Uint(self.bits())
2591 }
2592}
2593} // mod xdg_popup
2594
2595pub use crate::xdg_popup::XdgPopup;
2596pub use crate::xdg_popup::Request as XdgPopupRequest;
2597pub use crate::xdg_popup::Event as XdgPopupEvent;