poll_integration/common/protocols/wayland/wl_touch.rs
1//! touchscreen input device
2//!
3//! The wl_touch interface represents a touchscreen
4//! associated with a seat.
5//!
6//! Touch interactions can consist of one or more contacts.
7//! For each contact, a series of events is generated, starting
8//! with a down event, followed by zero or more motion events,
9//! and ending with an up event. Events relating to the same
10//! contact point can be identified by the ID of the sequence.
11
12use {super::super::all_types::*, ::wl_client::builder::prelude::*};
13
14static INTERFACE: wl_interface = wl_interface {
15 name: c"wl_touch".as_ptr(),
16 version: 10,
17 method_count: 1,
18 methods: {
19 static MESSAGES: [wl_message; 1] = [wl_message {
20 name: c"release".as_ptr(),
21 signature: c"".as_ptr(),
22 types: {
23 static TYPES: [Option<&'static wl_interface>; 0] = [];
24 TYPES.as_ptr().cast()
25 },
26 }];
27 MESSAGES.as_ptr()
28 },
29 event_count: 7,
30 events: {
31 static MESSAGES: [wl_message; 7] = [
32 wl_message {
33 name: c"down".as_ptr(),
34 signature: c"uuoiff".as_ptr(),
35 types: {
36 static TYPES: [Option<&'static wl_interface>; 6] =
37 [None, None, Some(WlSurface::WL_INTERFACE), None, None, None];
38 TYPES.as_ptr().cast()
39 },
40 },
41 wl_message {
42 name: c"up".as_ptr(),
43 signature: c"uui".as_ptr(),
44 types: {
45 static TYPES: [Option<&'static wl_interface>; 3] = [None, None, None];
46 TYPES.as_ptr().cast()
47 },
48 },
49 wl_message {
50 name: c"motion".as_ptr(),
51 signature: c"uiff".as_ptr(),
52 types: {
53 static TYPES: [Option<&'static wl_interface>; 4] = [None, None, None, None];
54 TYPES.as_ptr().cast()
55 },
56 },
57 wl_message {
58 name: c"frame".as_ptr(),
59 signature: c"".as_ptr(),
60 types: {
61 static TYPES: [Option<&'static wl_interface>; 0] = [];
62 TYPES.as_ptr().cast()
63 },
64 },
65 wl_message {
66 name: c"cancel".as_ptr(),
67 signature: c"".as_ptr(),
68 types: {
69 static TYPES: [Option<&'static wl_interface>; 0] = [];
70 TYPES.as_ptr().cast()
71 },
72 },
73 wl_message {
74 name: c"shape".as_ptr(),
75 signature: c"iff".as_ptr(),
76 types: {
77 static TYPES: [Option<&'static wl_interface>; 3] = [None, None, None];
78 TYPES.as_ptr().cast()
79 },
80 },
81 wl_message {
82 name: c"orientation".as_ptr(),
83 signature: c"if".as_ptr(),
84 types: {
85 static TYPES: [Option<&'static wl_interface>; 2] = [None, None];
86 TYPES.as_ptr().cast()
87 },
88 },
89 ];
90 MESSAGES.as_ptr()
91 },
92};
93
94/// An owned wl_touch proxy.
95///
96/// See the documentation of [the module][self] for the interface description.
97#[derive(Clone, Eq, PartialEq)]
98#[repr(transparent)]
99pub struct WlTouch {
100 /// This proxy has the interface INTERFACE.
101 proxy: UntypedOwnedProxy,
102}
103
104/// A borrowed wl_touch proxy.
105///
106/// See the documentation of [the module][self] for the interface description.
107#[derive(Eq, PartialEq)]
108#[repr(transparent)]
109pub struct WlTouchRef {
110 /// This proxy has the interface INTERFACE.
111 proxy: UntypedBorrowedProxy,
112}
113
114// SAFETY: WlTouch is a transparent wrapper around UntypedOwnedProxy
115unsafe impl UntypedOwnedProxyWrapper for WlTouch {}
116
117// SAFETY: - INTERFACE is a valid wl_interface
118// - The only invariant is that self.proxy has a compatible interface
119unsafe impl OwnedProxy for WlTouch {
120 const INTERFACE: &'static str = "wl_touch";
121 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
122 const NO_OP_EVENT_HANDLER: Self::NoOpEventHandler =
123 private::EventHandler(private::NoOpEventHandler);
124 const MAX_VERSION: u32 = 10;
125
126 type Borrowed = WlTouchRef;
127 type Api = private::ProxyApi;
128 type NoOpEventHandler = private::EventHandler<private::NoOpEventHandler>;
129}
130
131// SAFETY: WlTouchRef is a transparent wrapper around UntypedBorrowedProxy
132unsafe impl UntypedBorrowedProxyWrapper for WlTouchRef {}
133
134// SAFETY: - The only invariant is that self.proxy has a compatible interface
135unsafe impl BorrowedProxy for WlTouchRef {
136 type Owned = WlTouch;
137}
138
139impl Deref for WlTouch {
140 type Target = WlTouchRef;
141
142 fn deref(&self) -> &Self::Target {
143 proxy::low_level::deref(self)
144 }
145}
146
147mod private {
148 pub struct ProxyApi;
149
150 #[allow(dead_code)]
151 pub struct EventHandler<H>(pub(super) H);
152
153 #[allow(dead_code)]
154 pub struct NoOpEventHandler;
155}
156
157impl Debug for WlTouch {
158 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
159 write!(f, "wl_touch#{}", self.proxy.id())
160 }
161}
162
163impl Debug for WlTouchRef {
164 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
165 write!(f, "wl_touch#{}", self.proxy.id())
166 }
167}
168
169impl PartialEq<WlTouchRef> for WlTouch {
170 fn eq(&self, other: &WlTouchRef) -> bool {
171 self.proxy == other.proxy
172 }
173}
174
175impl PartialEq<WlTouch> for WlTouchRef {
176 fn eq(&self, other: &WlTouch) -> bool {
177 self.proxy == other.proxy
178 }
179}
180
181#[allow(dead_code)]
182impl WlTouch {
183 /// Since when the release request is available.
184 #[allow(dead_code)]
185 pub const REQ__RELEASE__SINCE: u32 = 3;
186
187 /// release the touch object
188 #[inline]
189 pub fn release(&self) {
190 let mut args = [];
191 // SAFETY: - self.proxy has the interface INTERFACE
192 // - 0 < INTERFACE.method_count = 1
193 // - the request signature is ``
194 unsafe {
195 self.proxy.send_destructor(0, &mut args);
196 }
197 }
198}
199
200impl WlTouch {
201 /// Since when the down event is available.
202 #[allow(dead_code)]
203 pub const EVT__DOWN__SINCE: u32 = 1;
204
205 /// Since when the up event is available.
206 #[allow(dead_code)]
207 pub const EVT__UP__SINCE: u32 = 1;
208
209 /// Since when the motion event is available.
210 #[allow(dead_code)]
211 pub const EVT__MOTION__SINCE: u32 = 1;
212
213 /// Since when the frame event is available.
214 #[allow(dead_code)]
215 pub const EVT__FRAME__SINCE: u32 = 1;
216
217 /// Since when the cancel event is available.
218 #[allow(dead_code)]
219 pub const EVT__CANCEL__SINCE: u32 = 1;
220
221 /// Since when the shape event is available.
222 #[allow(dead_code)]
223 pub const EVT__SHAPE__SINCE: u32 = 6;
224
225 /// Since when the orientation event is available.
226 #[allow(dead_code)]
227 pub const EVT__ORIENTATION__SINCE: u32 = 6;
228}
229
230/// An event handler for [WlTouch] proxies.
231#[allow(dead_code)]
232pub trait WlTouchEventHandler {
233 /// touch down event and beginning of a touch sequence
234 ///
235 /// A new touch point has appeared on the surface. This touch point is
236 /// assigned a unique ID. Future events from this touch point reference
237 /// this ID. The ID ceases to be valid after a touch up event and may be
238 /// reused in the future.
239 ///
240 /// # Arguments
241 ///
242 /// - `serial`: serial number of the touch down event
243 /// - `time`: timestamp with millisecond granularity
244 /// - `surface`: surface touched
245 /// - `id`: the unique ID of this touch point
246 /// - `x`: surface-local x coordinate
247 /// - `y`: surface-local y coordinate
248 ///
249 /// All borrowed proxies passed to this function are guaranteed to be
250 /// immutable and non-null.
251 #[inline]
252 fn down(
253 &self,
254 _slf: &WlTouchRef,
255 serial: u32,
256 time: u32,
257 surface: Option<&WlSurfaceRef>,
258 id: i32,
259 x: Fixed,
260 y: Fixed,
261 ) {
262 let _ = serial;
263 let _ = time;
264 let _ = surface;
265 let _ = id;
266 let _ = x;
267 let _ = y;
268 }
269
270 /// end of a touch event sequence
271 ///
272 /// The touch point has disappeared. No further events will be sent for
273 /// this touch point and the touch point's ID is released and may be
274 /// reused in a future touch down event.
275 ///
276 /// # Arguments
277 ///
278 /// - `serial`: serial number of the touch up event
279 /// - `time`: timestamp with millisecond granularity
280 /// - `id`: the unique ID of this touch point
281 #[inline]
282 fn up(&self, _slf: &WlTouchRef, serial: u32, time: u32, id: i32) {
283 let _ = serial;
284 let _ = time;
285 let _ = id;
286 }
287
288 /// update of touch point coordinates
289 ///
290 /// A touch point has changed coordinates.
291 ///
292 /// # Arguments
293 ///
294 /// - `time`: timestamp with millisecond granularity
295 /// - `id`: the unique ID of this touch point
296 /// - `x`: surface-local x coordinate
297 /// - `y`: surface-local y coordinate
298 #[inline]
299 fn motion(&self, _slf: &WlTouchRef, time: u32, id: i32, x: Fixed, y: Fixed) {
300 let _ = time;
301 let _ = id;
302 let _ = x;
303 let _ = y;
304 }
305
306 /// end of touch frame event
307 ///
308 /// Indicates the end of a set of events that logically belong together.
309 /// A client is expected to accumulate the data in all events within the
310 /// frame before proceeding.
311 ///
312 /// A wl_touch.frame terminates at least one event but otherwise no
313 /// guarantee is provided about the set of events within a frame. A client
314 /// must assume that any state not updated in a frame is unchanged from the
315 /// previously known state.
316 #[inline]
317 fn frame(&self, _slf: &WlTouchRef) {}
318
319 /// touch session cancelled
320 ///
321 /// Sent if the compositor decides the touch stream is a global
322 /// gesture. No further events are sent to the clients from that
323 /// particular gesture. Touch cancellation applies to all touch points
324 /// currently active on this client's surface. The client is
325 /// responsible for finalizing the touch points, future touch points on
326 /// this surface may reuse the touch point ID.
327 ///
328 /// No frame event is required after the cancel event.
329 #[inline]
330 fn cancel(&self, _slf: &WlTouchRef) {}
331
332 /// update shape of touch point
333 ///
334 /// Sent when a touchpoint has changed its shape.
335 ///
336 /// This event does not occur on its own. It is sent before a
337 /// wl_touch.frame event and carries the new shape information for
338 /// any previously reported, or new touch points of that frame.
339 ///
340 /// Other events describing the touch point such as wl_touch.down,
341 /// wl_touch.motion or wl_touch.orientation may be sent within the
342 /// same wl_touch.frame. A client should treat these events as a single
343 /// logical touch point update. The order of wl_touch.shape,
344 /// wl_touch.orientation and wl_touch.motion is not guaranteed.
345 /// A wl_touch.down event is guaranteed to occur before the first
346 /// wl_touch.shape event for this touch ID but both events may occur within
347 /// the same wl_touch.frame.
348 ///
349 /// A touchpoint shape is approximated by an ellipse through the major and
350 /// minor axis length. The major axis length describes the longer diameter
351 /// of the ellipse, while the minor axis length describes the shorter
352 /// diameter. Major and minor are orthogonal and both are specified in
353 /// surface-local coordinates. The center of the ellipse is always at the
354 /// touchpoint location as reported by wl_touch.down or wl_touch.move.
355 ///
356 /// This event is only sent by the compositor if the touch device supports
357 /// shape reports. The client has to make reasonable assumptions about the
358 /// shape if it did not receive this event.
359 ///
360 /// # Arguments
361 ///
362 /// - `id`: the unique ID of this touch point
363 /// - `major`: length of the major axis in surface-local coordinates
364 /// - `minor`: length of the minor axis in surface-local coordinates
365 #[inline]
366 fn shape(&self, _slf: &WlTouchRef, id: i32, major: Fixed, minor: Fixed) {
367 let _ = id;
368 let _ = major;
369 let _ = minor;
370 }
371
372 /// update orientation of touch point
373 ///
374 /// Sent when a touchpoint has changed its orientation.
375 ///
376 /// This event does not occur on its own. It is sent before a
377 /// wl_touch.frame event and carries the new shape information for
378 /// any previously reported, or new touch points of that frame.
379 ///
380 /// Other events describing the touch point such as wl_touch.down,
381 /// wl_touch.motion or wl_touch.shape may be sent within the
382 /// same wl_touch.frame. A client should treat these events as a single
383 /// logical touch point update. The order of wl_touch.shape,
384 /// wl_touch.orientation and wl_touch.motion is not guaranteed.
385 /// A wl_touch.down event is guaranteed to occur before the first
386 /// wl_touch.orientation event for this touch ID but both events may occur
387 /// within the same wl_touch.frame.
388 ///
389 /// The orientation describes the clockwise angle of a touchpoint's major
390 /// axis to the positive surface y-axis and is normalized to the -180 to
391 /// +180 degree range. The granularity of orientation depends on the touch
392 /// device, some devices only support binary rotation values between 0 and
393 /// 90 degrees.
394 ///
395 /// This event is only sent by the compositor if the touch device supports
396 /// orientation reports.
397 ///
398 /// # Arguments
399 ///
400 /// - `id`: the unique ID of this touch point
401 /// - `orientation`: angle between major axis and positive surface y-axis in degrees
402 #[inline]
403 fn orientation(&self, _slf: &WlTouchRef, id: i32, orientation: Fixed) {
404 let _ = id;
405 let _ = orientation;
406 }
407}
408
409impl WlTouchEventHandler for private::NoOpEventHandler {}
410
411// SAFETY: INTERFACE is a valid wl_interface
412unsafe impl<H> EventHandler for private::EventHandler<H>
413where
414 H: WlTouchEventHandler,
415{
416 const WL_INTERFACE: &'static wl_interface = &INTERFACE;
417
418 #[allow(unused_variables)]
419 unsafe fn handle_event(
420 &self,
421 queue: &Queue,
422 slf: &UntypedBorrowedProxy,
423 opcode: u32,
424 args: *mut wl_argument,
425 ) {
426 // SAFETY: This function required that slf has the interface INTERFACE
427 let slf = unsafe { proxy::low_level::from_untyped_borrowed::<WlTouchRef>(slf) };
428 match opcode {
429 0 => {
430 // SAFETY: INTERFACE requires that there are 6 arguments
431 let args = unsafe { &*args.cast::<[wl_argument; 6]>() };
432 // SAFETY: - INTERFACE requires that args[0] contains a uint
433 let arg0 = unsafe { args[0].u };
434 // SAFETY: - INTERFACE requires that args[1] contains a uint
435 let arg1 = unsafe { args[1].u };
436 // SAFETY: - INTERFACE requires that args[2] contains an object
437 let arg2 = unsafe {
438 if let Some(p) = NonNull::new(args[2].o.cast()) {
439 Some(UntypedBorrowedProxy::new_immutable(queue.libwayland(), p))
440 } else {
441 None
442 }
443 };
444 // SAFETY: - INTERFACE requires that the object has the interface WlSurface::WL_INTERFACE
445 let arg2 = arg2.as_ref().map(|arg2| unsafe {
446 proxy::low_level::from_untyped_borrowed::<WlSurfaceRef>(arg2)
447 });
448 // SAFETY: - INTERFACE requires that args[3] contains an int
449 let arg3 = unsafe { args[3].i };
450 // SAFETY: - INTERFACE requires that args[4] contains a fixed
451 let arg4 = unsafe { Fixed::from_wire(args[4].f) };
452 // SAFETY: - INTERFACE requires that args[5] contains a fixed
453 let arg5 = unsafe { Fixed::from_wire(args[5].f) };
454 self.0.down(slf, arg0, arg1, arg2, arg3, arg4, arg5);
455 }
456 1 => {
457 // SAFETY: INTERFACE requires that there are 3 arguments
458 let args = unsafe { &*args.cast::<[wl_argument; 3]>() };
459 // SAFETY: - INTERFACE requires that args[0] contains a uint
460 let arg0 = unsafe { args[0].u };
461 // SAFETY: - INTERFACE requires that args[1] contains a uint
462 let arg1 = unsafe { args[1].u };
463 // SAFETY: - INTERFACE requires that args[2] contains an int
464 let arg2 = unsafe { args[2].i };
465 self.0.up(slf, arg0, arg1, arg2);
466 }
467 2 => {
468 // SAFETY: INTERFACE requires that there are 4 arguments
469 let args = unsafe { &*args.cast::<[wl_argument; 4]>() };
470 // SAFETY: - INTERFACE requires that args[0] contains a uint
471 let arg0 = unsafe { args[0].u };
472 // SAFETY: - INTERFACE requires that args[1] contains an int
473 let arg1 = unsafe { args[1].i };
474 // SAFETY: - INTERFACE requires that args[2] contains a fixed
475 let arg2 = unsafe { Fixed::from_wire(args[2].f) };
476 // SAFETY: - INTERFACE requires that args[3] contains a fixed
477 let arg3 = unsafe { Fixed::from_wire(args[3].f) };
478 self.0.motion(slf, arg0, arg1, arg2, arg3);
479 }
480 3 => {
481 self.0.frame(slf);
482 }
483 4 => {
484 self.0.cancel(slf);
485 }
486 5 => {
487 // SAFETY: INTERFACE requires that there are 3 arguments
488 let args = unsafe { &*args.cast::<[wl_argument; 3]>() };
489 // SAFETY: - INTERFACE requires that args[0] contains an int
490 let arg0 = unsafe { args[0].i };
491 // SAFETY: - INTERFACE requires that args[1] contains a fixed
492 let arg1 = unsafe { Fixed::from_wire(args[1].f) };
493 // SAFETY: - INTERFACE requires that args[2] contains a fixed
494 let arg2 = unsafe { Fixed::from_wire(args[2].f) };
495 self.0.shape(slf, arg0, arg1, arg2);
496 }
497 6 => {
498 // SAFETY: INTERFACE requires that there are 2 arguments
499 let args = unsafe { &*args.cast::<[wl_argument; 2]>() };
500 // SAFETY: - INTERFACE requires that args[0] contains an int
501 let arg0 = unsafe { args[0].i };
502 // SAFETY: - INTERFACE requires that args[1] contains a fixed
503 let arg1 = unsafe { Fixed::from_wire(args[1].f) };
504 self.0.orientation(slf, arg0, arg1);
505 }
506 _ => {
507 invalid_opcode("wl_touch", opcode);
508 }
509 }
510 }
511}
512
513impl<H> CreateEventHandler<H> for private::ProxyApi
514where
515 H: WlTouchEventHandler,
516{
517 type EventHandler = private::EventHandler<H>;
518
519 #[inline]
520 fn create_event_handler(handler: H) -> Self::EventHandler {
521 private::EventHandler(handler)
522 }
523}
524
525/// Functional event handlers.
526pub mod event_handlers {
527 use super::*;
528
529 /// Event handler for down events.
530 pub struct Down<F>(F);
531 impl<F> WlTouchEventHandler for Down<F>
532 where
533 F: Fn(&WlTouchRef, u32, u32, Option<&WlSurfaceRef>, i32, Fixed, Fixed),
534 {
535 #[inline]
536 fn down(
537 &self,
538 _slf: &WlTouchRef,
539 serial: u32,
540 time: u32,
541 surface: Option<&WlSurfaceRef>,
542 id: i32,
543 x: Fixed,
544 y: Fixed,
545 ) {
546 self.0(_slf, serial, time, surface, id, x, y)
547 }
548 }
549
550 /// Event handler for up events.
551 pub struct Up<F>(F);
552 impl<F> WlTouchEventHandler for Up<F>
553 where
554 F: Fn(&WlTouchRef, u32, u32, i32),
555 {
556 #[inline]
557 fn up(&self, _slf: &WlTouchRef, serial: u32, time: u32, id: i32) {
558 self.0(_slf, serial, time, id)
559 }
560 }
561
562 /// Event handler for motion events.
563 pub struct Motion<F>(F);
564 impl<F> WlTouchEventHandler for Motion<F>
565 where
566 F: Fn(&WlTouchRef, u32, i32, Fixed, Fixed),
567 {
568 #[inline]
569 fn motion(&self, _slf: &WlTouchRef, time: u32, id: i32, x: Fixed, y: Fixed) {
570 self.0(_slf, time, id, x, y)
571 }
572 }
573
574 /// Event handler for frame events.
575 pub struct Frame<F>(F);
576 impl<F> WlTouchEventHandler for Frame<F>
577 where
578 F: Fn(&WlTouchRef),
579 {
580 #[inline]
581 fn frame(&self, _slf: &WlTouchRef) {
582 self.0(_slf)
583 }
584 }
585
586 /// Event handler for cancel events.
587 pub struct Cancel<F>(F);
588 impl<F> WlTouchEventHandler for Cancel<F>
589 where
590 F: Fn(&WlTouchRef),
591 {
592 #[inline]
593 fn cancel(&self, _slf: &WlTouchRef) {
594 self.0(_slf)
595 }
596 }
597
598 /// Event handler for shape events.
599 pub struct Shape<F>(F);
600 impl<F> WlTouchEventHandler for Shape<F>
601 where
602 F: Fn(&WlTouchRef, i32, Fixed, Fixed),
603 {
604 #[inline]
605 fn shape(&self, _slf: &WlTouchRef, id: i32, major: Fixed, minor: Fixed) {
606 self.0(_slf, id, major, minor)
607 }
608 }
609
610 /// Event handler for orientation events.
611 pub struct Orientation<F>(F);
612 impl<F> WlTouchEventHandler for Orientation<F>
613 where
614 F: Fn(&WlTouchRef, i32, Fixed),
615 {
616 #[inline]
617 fn orientation(&self, _slf: &WlTouchRef, id: i32, orientation: Fixed) {
618 self.0(_slf, id, orientation)
619 }
620 }
621
622 impl WlTouch {
623 /// Creates an event handler for down events.
624 ///
625 /// The event handler ignores all other events.
626 #[allow(dead_code)]
627 pub fn on_down<F>(f: F) -> Down<F>
628 where
629 F: Fn(&WlTouchRef, u32, u32, Option<&WlSurfaceRef>, i32, Fixed, Fixed),
630 {
631 Down(f)
632 }
633
634 /// Creates an event handler for up events.
635 ///
636 /// The event handler ignores all other events.
637 #[allow(dead_code)]
638 pub fn on_up<F>(f: F) -> Up<F>
639 where
640 F: Fn(&WlTouchRef, u32, u32, i32),
641 {
642 Up(f)
643 }
644
645 /// Creates an event handler for motion events.
646 ///
647 /// The event handler ignores all other events.
648 #[allow(dead_code)]
649 pub fn on_motion<F>(f: F) -> Motion<F>
650 where
651 F: Fn(&WlTouchRef, u32, i32, Fixed, Fixed),
652 {
653 Motion(f)
654 }
655
656 /// Creates an event handler for frame events.
657 ///
658 /// The event handler ignores all other events.
659 #[allow(dead_code)]
660 pub fn on_frame<F>(f: F) -> Frame<F>
661 where
662 F: Fn(&WlTouchRef),
663 {
664 Frame(f)
665 }
666
667 /// Creates an event handler for cancel events.
668 ///
669 /// The event handler ignores all other events.
670 #[allow(dead_code)]
671 pub fn on_cancel<F>(f: F) -> Cancel<F>
672 where
673 F: Fn(&WlTouchRef),
674 {
675 Cancel(f)
676 }
677
678 /// Creates an event handler for shape events.
679 ///
680 /// The event handler ignores all other events.
681 #[allow(dead_code)]
682 pub fn on_shape<F>(f: F) -> Shape<F>
683 where
684 F: Fn(&WlTouchRef, i32, Fixed, Fixed),
685 {
686 Shape(f)
687 }
688
689 /// Creates an event handler for orientation events.
690 ///
691 /// The event handler ignores all other events.
692 #[allow(dead_code)]
693 pub fn on_orientation<F>(f: F) -> Orientation<F>
694 where
695 F: Fn(&WlTouchRef, i32, Fixed),
696 {
697 Orientation(f)
698 }
699 }
700}