1use std::mem;
3
4use glib::{prelude::*, translate::*};
5use gst::EventType;
6
7#[cfg(feature = "v1_22")]
8#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
9use crate::NavigationModifierType;
10use crate::{ffi, NavigationCommand, NavigationEventType};
11
12macro_rules! event_builder_generic_impl {
14 ($new_fn:expr) => {
15 pub fn seqnum(self, seqnum: gst::Seqnum) -> Self {
16 Self {
17 seqnum: Some(seqnum),
18 ..self
19 }
20 }
21
22 pub fn seqnum_if(self, seqnum: gst::Seqnum, predicate: bool) -> Self {
23 if predicate {
24 self.seqnum(seqnum)
25 } else {
26 self
27 }
28 }
29
30 pub fn seqnum_if_some(self, seqnum: Option<gst::Seqnum>) -> Self {
31 if let Some(seqnum) = seqnum {
32 self.seqnum(seqnum)
33 } else {
34 self
35 }
36 }
37
38 pub fn running_time_offset(self, running_time_offset: i64) -> Self {
39 Self {
40 running_time_offset: Some(running_time_offset),
41 ..self
42 }
43 }
44
45 pub fn running_time_offset_if(self, running_time_offset: i64, predicate: bool) -> Self {
46 if predicate {
47 self.running_time_offset(running_time_offset)
48 } else {
49 self
50 }
51 }
52
53 pub fn running_time_offset_if_some(self, running_time_offset: Option<i64>) -> Self {
54 if let Some(running_time_offset) = running_time_offset {
55 self.running_time_offset(running_time_offset)
56 } else {
57 self
58 }
59 }
60
61 pub fn other_field(self, name: &'a str, value: impl ToSendValue) -> Self {
62 let mut other_fields = self.other_fields;
63 other_fields.push((name, value.to_send_value()));
64
65 Self {
66 other_fields,
67 ..self
68 }
69 }
70
71 gst::impl_builder_gvalue_extra_setters!(other_field);
72
73 #[must_use = "Building the event without using it has no effect"]
74 #[allow(clippy::redundant_closure_call)]
75 pub fn build(mut self) -> gst::Event {
76 skip_assert_initialized!();
77 unsafe {
78 let event = $new_fn(&mut self);
79 if let Some(seqnum) = self.seqnum {
80 gst::ffi::gst_event_set_seqnum(event, seqnum.into_glib());
81 }
82
83 if let Some(running_time_offset) = self.running_time_offset {
84 gst::ffi::gst_event_set_running_time_offset(event, running_time_offset);
85 }
86
87 {
88 let s = gst::StructureRef::from_glib_borrow_mut(
89 gst::ffi::gst_event_writable_structure(event),
90 );
91
92 for (k, v) in self.other_fields {
93 s.set_value(k, v);
94 }
95 }
96
97 from_glib_full(event)
98 }
99 }
100 };
101}
102
103#[must_use = "The builder must be built to be used"]
104pub struct DownstreamForceKeyUnitEventBuilder<'a> {
105 seqnum: Option<gst::Seqnum>,
106 running_time_offset: Option<i64>,
107 other_fields: Vec<(&'a str, glib::SendValue)>,
108 timestamp: Option<gst::ClockTime>,
109 stream_time: Option<gst::ClockTime>,
110 running_time: Option<gst::ClockTime>,
111 all_headers: bool,
112 count: u32,
113}
114
115impl<'a> DownstreamForceKeyUnitEventBuilder<'a> {
116 fn new() -> Self {
117 skip_assert_initialized!();
118 Self {
119 seqnum: None,
120 running_time_offset: None,
121 other_fields: Vec::new(),
122 timestamp: gst::ClockTime::NONE,
123 stream_time: gst::ClockTime::NONE,
124 running_time: gst::ClockTime::NONE,
125 all_headers: true,
126 count: 0,
127 }
128 }
129
130 pub fn timestamp(self, timestamp: impl Into<Option<gst::ClockTime>>) -> Self {
131 Self {
132 timestamp: timestamp.into(),
133 ..self
134 }
135 }
136
137 pub fn timestamp_if(self, timestamp: gst::ClockTime, predicate: bool) -> Self {
138 if predicate {
139 self.timestamp(timestamp)
140 } else {
141 self
142 }
143 }
144
145 pub fn timestamp_if_some(self, timestamp: Option<gst::ClockTime>) -> Self {
146 if let Some(timestamp) = timestamp {
147 self.timestamp(timestamp)
148 } else {
149 self
150 }
151 }
152
153 pub fn stream_time(self, stream_time: impl Into<Option<gst::ClockTime>>) -> Self {
154 Self {
155 stream_time: stream_time.into(),
156 ..self
157 }
158 }
159
160 pub fn stream_time_if(self, stream_time: gst::ClockTime, predicate: bool) -> Self {
161 if predicate {
162 self.stream_time(stream_time)
163 } else {
164 self
165 }
166 }
167
168 pub fn stream_time_if_some(self, stream_time: Option<gst::ClockTime>) -> Self {
169 if let Some(stream_time) = stream_time {
170 self.stream_time(stream_time)
171 } else {
172 self
173 }
174 }
175
176 pub fn running_time(self, running_time: impl Into<Option<gst::ClockTime>>) -> Self {
177 Self {
178 running_time: running_time.into(),
179 ..self
180 }
181 }
182
183 pub fn running_time_if(self, running_time: gst::ClockTime, predicate: bool) -> Self {
184 if predicate {
185 self.running_time(running_time)
186 } else {
187 self
188 }
189 }
190
191 pub fn running_time_if_some(self, running_time: Option<gst::ClockTime>) -> Self {
192 if let Some(running_time) = running_time {
193 self.running_time(running_time)
194 } else {
195 self
196 }
197 }
198
199 pub fn all_headers(self, all_headers: bool) -> Self {
200 Self {
201 all_headers,
202 ..self
203 }
204 }
205
206 pub fn all_headers_if_some(self, all_headers: Option<bool>) -> Self {
207 if let Some(all_headers) = all_headers {
208 self.all_headers(all_headers)
209 } else {
210 self
211 }
212 }
213
214 pub fn count(self, count: u32) -> Self {
215 Self { count, ..self }
216 }
217
218 pub fn count_if(self, count: u32, predicate: bool) -> Self {
219 if predicate {
220 self.count(count)
221 } else {
222 self
223 }
224 }
225
226 pub fn count_if_some(self, count: Option<u32>) -> Self {
227 if let Some(count) = count {
228 self.count(count)
229 } else {
230 self
231 }
232 }
233
234 event_builder_generic_impl!(|s: &mut Self| {
235 ffi::gst_video_event_new_downstream_force_key_unit(
236 s.timestamp.into_glib(),
237 s.stream_time.into_glib(),
238 s.running_time.into_glib(),
239 s.all_headers.into_glib(),
240 s.count,
241 )
242 });
243}
244
245#[derive(Clone, PartialEq, Eq, Debug)]
246pub struct DownstreamForceKeyUnitEvent {
247 pub timestamp: Option<gst::ClockTime>,
248 pub stream_time: Option<gst::ClockTime>,
249 pub running_time: Option<gst::ClockTime>,
250 pub all_headers: bool,
251 pub count: u32,
252}
253
254impl DownstreamForceKeyUnitEvent {
255 pub fn builder<'a>() -> DownstreamForceKeyUnitEventBuilder<'a> {
256 assert_initialized_main_thread!();
257 DownstreamForceKeyUnitEventBuilder::new()
258 }
259
260 #[doc(alias = "gst_video_event_parse_downstream_force_key_unit")]
261 pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
262 skip_assert_initialized!();
263 unsafe {
264 let mut timestamp = mem::MaybeUninit::uninit();
265 let mut stream_time = mem::MaybeUninit::uninit();
266 let mut running_time = mem::MaybeUninit::uninit();
267 let mut all_headers = mem::MaybeUninit::uninit();
268 let mut count = mem::MaybeUninit::uninit();
269
270 let res: bool = from_glib(ffi::gst_video_event_parse_downstream_force_key_unit(
271 event.as_mut_ptr(),
272 timestamp.as_mut_ptr(),
273 stream_time.as_mut_ptr(),
274 running_time.as_mut_ptr(),
275 all_headers.as_mut_ptr(),
276 count.as_mut_ptr(),
277 ));
278 if res {
279 Ok(Self {
280 timestamp: from_glib(timestamp.assume_init()),
281 stream_time: from_glib(stream_time.assume_init()),
282 running_time: from_glib(running_time.assume_init()),
283 all_headers: from_glib(all_headers.assume_init()),
284 count: count.assume_init(),
285 })
286 } else {
287 Err(glib::bool_error!("Failed to parse GstEvent"))
288 }
289 }
290 }
291}
292
293#[must_use = "The builder must be built to be used"]
294pub struct UpstreamForceKeyUnitEventBuilder<'a> {
295 seqnum: Option<gst::Seqnum>,
296 running_time_offset: Option<i64>,
297 other_fields: Vec<(&'a str, glib::SendValue)>,
298 running_time: Option<gst::ClockTime>,
299 all_headers: bool,
300 count: u32,
301}
302
303impl<'a> UpstreamForceKeyUnitEventBuilder<'a> {
304 fn new() -> Self {
305 skip_assert_initialized!();
306 Self {
307 seqnum: None,
308 running_time_offset: None,
309 other_fields: Vec::new(),
310 running_time: gst::ClockTime::NONE,
311 all_headers: true,
312 count: 0,
313 }
314 }
315
316 pub fn running_time(self, running_time: impl Into<Option<gst::ClockTime>>) -> Self {
317 Self {
318 running_time: running_time.into(),
319 ..self
320 }
321 }
322
323 pub fn running_time_if(self, running_time: gst::ClockTime, predicate: bool) -> Self {
324 if predicate {
325 self.running_time(running_time)
326 } else {
327 self
328 }
329 }
330
331 pub fn running_time_if_some(self, running_time: Option<gst::ClockTime>) -> Self {
332 if let Some(running_time) = running_time {
333 self.running_time(running_time)
334 } else {
335 self
336 }
337 }
338
339 pub fn all_headers(self, all_headers: bool) -> Self {
340 Self {
341 all_headers,
342 ..self
343 }
344 }
345
346 pub fn all_headers_if_some(self, all_headers: Option<bool>) -> Self {
347 if let Some(all_headers) = all_headers {
348 self.all_headers(all_headers)
349 } else {
350 self
351 }
352 }
353
354 pub fn count(self, count: u32) -> Self {
355 Self { count, ..self }
356 }
357
358 pub fn count_if(self, count: u32, predicate: bool) -> Self {
359 if predicate {
360 self.count(count)
361 } else {
362 self
363 }
364 }
365
366 pub fn count_if_some(self, count: Option<u32>) -> Self {
367 if let Some(count) = count {
368 self.count(count)
369 } else {
370 self
371 }
372 }
373
374 event_builder_generic_impl!(|s: &mut Self| {
375 ffi::gst_video_event_new_upstream_force_key_unit(
376 s.running_time.into_glib(),
377 s.all_headers.into_glib(),
378 s.count,
379 )
380 });
381}
382
383#[derive(Clone, PartialEq, Eq, Debug)]
384pub struct UpstreamForceKeyUnitEvent {
385 pub running_time: Option<gst::ClockTime>,
386 pub all_headers: bool,
387 pub count: u32,
388}
389
390impl UpstreamForceKeyUnitEvent {
391 pub fn builder<'a>() -> UpstreamForceKeyUnitEventBuilder<'a> {
392 assert_initialized_main_thread!();
393 UpstreamForceKeyUnitEventBuilder::new()
394 }
395
396 #[doc(alias = "gst_video_event_parse_upstream_force_key_unit")]
397 pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
398 skip_assert_initialized!();
399 unsafe {
400 let mut running_time = mem::MaybeUninit::uninit();
401 let mut all_headers = mem::MaybeUninit::uninit();
402 let mut count = mem::MaybeUninit::uninit();
403
404 let res: bool = from_glib(ffi::gst_video_event_parse_upstream_force_key_unit(
405 event.as_mut_ptr(),
406 running_time.as_mut_ptr(),
407 all_headers.as_mut_ptr(),
408 count.as_mut_ptr(),
409 ));
410 if res {
411 Ok(Self {
412 running_time: from_glib(running_time.assume_init()),
413 all_headers: from_glib(all_headers.assume_init()),
414 count: count.assume_init(),
415 })
416 } else {
417 Err(glib::bool_error!("Failed to parse GstEvent"))
418 }
419 }
420 }
421}
422
423#[derive(Clone, PartialEq, Eq, Debug)]
424pub enum ForceKeyUnitEvent {
425 Downstream(DownstreamForceKeyUnitEvent),
426 Upstream(UpstreamForceKeyUnitEvent),
427}
428
429impl ForceKeyUnitEvent {
430 #[doc(alias = "gst_video_event_is_force_key_unit")]
431 pub fn is(event: &gst::EventRef) -> bool {
432 skip_assert_initialized!();
433 unsafe { from_glib(ffi::gst_video_event_is_force_key_unit(event.as_mut_ptr())) }
434 }
435
436 pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
437 skip_assert_initialized!();
438 if event.is_upstream() {
439 UpstreamForceKeyUnitEvent::parse(event).map(Self::Upstream)
440 } else {
441 DownstreamForceKeyUnitEvent::parse(event).map(Self::Downstream)
442 }
443 }
444}
445
446#[must_use = "The builder must be built to be used"]
447pub struct StillFrameEventBuilder<'a> {
448 seqnum: Option<gst::Seqnum>,
449 running_time_offset: Option<i64>,
450 other_fields: Vec<(&'a str, glib::SendValue)>,
451 in_still: bool,
452}
453
454impl<'a> StillFrameEventBuilder<'a> {
455 fn new(in_still: bool) -> Self {
456 skip_assert_initialized!();
457 Self {
458 seqnum: None,
459 running_time_offset: None,
460 other_fields: Vec::new(),
461 in_still,
462 }
463 }
464
465 event_builder_generic_impl!(|s: &mut Self| ffi::gst_video_event_new_still_frame(
466 s.in_still.into_glib()
467 ));
468}
469
470#[derive(Clone, PartialEq, Eq, Debug)]
471pub struct StillFrameEvent {
472 pub in_still: bool,
473}
474
475impl StillFrameEvent {
476 pub fn builder<'a>(in_still: bool) -> StillFrameEventBuilder<'a> {
477 assert_initialized_main_thread!();
478 StillFrameEventBuilder::new(in_still)
479 }
480
481 #[doc(alias = "gst_video_event_parse_still_frame")]
482 pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
483 skip_assert_initialized!();
484 unsafe {
485 let mut in_still = mem::MaybeUninit::uninit();
486
487 let res: bool = from_glib(ffi::gst_video_event_parse_still_frame(
488 event.as_mut_ptr(),
489 in_still.as_mut_ptr(),
490 ));
491 if res {
492 Ok(Self {
493 in_still: from_glib(in_still.assume_init()),
494 })
495 } else {
496 Err(glib::bool_error!("Invalid still-frame event"))
497 }
498 }
499 }
500}
501
502macro_rules! nav_event_builder {
503 ($builder:ident, $($event_field:ident: $event_type:ty,)? [$( $field_names:ident : $field_types:ty),*], $new_fn: expr) => {
504 #[must_use = "The builder must be built to be used"]
505 pub struct $builder<'a> {
506 seqnum: Option<gst::Seqnum>,
507 running_time_offset: Option<i64>,
508 other_fields: Vec<(&'a str, glib::SendValue)>,
509 $($field_names: $field_types,)*
510 #[cfg(feature = "v1_22")]
511 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
512 modifier_state: NavigationModifierType,
513 $($event_field: $event_type,)?
514 }
515
516 impl<'a> $builder<'a> {
517 fn new($($event_field: $event_type)?) -> Self {
518 skip_assert_initialized!();
519 Self {
520 seqnum: None,
521 running_time_offset: None,
522 other_fields: Vec::new(),
523 $($field_names: <$field_types>::default(),)*
524 #[cfg(feature = "v1_22")]
525 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
526 modifier_state: NavigationModifierType::empty(),
527 $($event_field,)?
528 }
529 }
530
531 $(pub fn $field_names(self, $field_names: $field_types) -> Self {
532 Self { $field_names, ..self }
533 })*
534
535 #[cfg(feature = "v1_22")]
536 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
537 pub fn modifier_state(self, modifier_state: NavigationModifierType) -> Self {
538 Self { modifier_state, ..self }
539 }
540
541 event_builder_generic_impl!($new_fn);
542 }
543 };
544}
545
546pub enum KeyEventType<'a> {
547 Press { key: &'a str },
548 Release { key: &'a str },
549}
550
551nav_event_builder!(
552 KeyEventBuilder,
553 kind: KeyEventType<'a>,
554 [],
555 |s: &mut Self| {
556 let event = match s.kind {
557 KeyEventType::Press { key } => NavigationEvent::KeyPress {
558 key: key.to_owned(),
559 #[cfg(feature = "v1_22")]
560 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
561 modifier_state: s.modifier_state,
562 },
563 KeyEventType::Release { key } => NavigationEvent::KeyRelease {
564 key: key.to_owned(),
565 #[cfg(feature = "v1_22")]
566 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
567 modifier_state: s.modifier_state,
568 },
569 };
570 gst::ffi::gst_event_new_navigation(event.structure().into_glib_ptr())
571 }
572);
573
574pub enum MouseEventType {
575 Move,
576 Press {
577 button: i32,
578 },
579 Release {
580 button: i32,
581 },
582 #[cfg(feature = "v1_18")]
583 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
584 Scroll {
585 delta_x: f64,
586 delta_y: f64,
587 },
588 #[cfg(feature = "v1_26")]
589 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
590 DoubleClick {
591 button: i32,
592 },
593}
594
595nav_event_builder!(
596 MouseEventBuilder,
597 kind: MouseEventType,
598 [x: f64, y: f64],
599 |s: &mut Self| {
600 let event = match s.kind {
601 MouseEventType::Move => NavigationEvent::MouseMove {
602 x: s.x,
603 y: s.y,
604 #[cfg(feature = "v1_22")]
605 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
606 modifier_state: s.modifier_state,
607 },
608 MouseEventType::Press { button } => NavigationEvent::MouseButtonPress {
609 button,
610 x: s.x,
611 y: s.y,
612 #[cfg(feature = "v1_22")]
613 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
614 modifier_state: s.modifier_state,
615 },
616 MouseEventType::Release { button } => NavigationEvent::MouseButtonRelease {
617 button,
618 x: s.x,
619 y: s.y,
620 #[cfg(feature = "v1_22")]
621 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
622 modifier_state: s.modifier_state,
623 },
624 #[cfg(feature = "v1_18")]
625 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
626 MouseEventType::Scroll { delta_x, delta_y } => NavigationEvent::MouseScroll {
627 x: s.x,
628 y: s.y,
629 delta_x,
630 delta_y,
631 #[cfg(feature = "v1_22")]
632 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
633 modifier_state: s.modifier_state,
634 },
635 #[cfg(feature = "v1_26")]
636 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
637 MouseEventType::DoubleClick { button } => NavigationEvent::MouseDoubleClick {
638 button,
639 x: s.x,
640 y: s.y,
641 modifier_state: s.modifier_state,
642 },
643 };
644 gst::ffi::gst_event_new_navigation(event.structure().into_glib_ptr())
645 }
646);
647
648#[must_use = "The builder must be built to be used"]
649pub struct CommandEventBuilder<'a> {
650 seqnum: Option<gst::Seqnum>,
651 running_time_offset: Option<i64>,
652 other_fields: Vec<(&'a str, glib::SendValue)>,
653 command: NavigationCommand,
654 #[cfg(feature = "v1_22")]
655 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
656 modifier_state: NavigationModifierType,
657}
658
659impl<'a> CommandEventBuilder<'a> {
660 fn new(command: NavigationCommand) -> Self {
661 skip_assert_initialized!();
662 Self {
663 seqnum: None,
664 running_time_offset: None,
665 other_fields: Vec::new(),
666 command,
667 #[cfg(feature = "v1_22")]
668 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
669 modifier_state: NavigationModifierType::empty(),
670 }
671 }
672
673 #[cfg(feature = "v1_22")]
674 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
675 pub fn modifier_state(self, modifier_state: NavigationModifierType) -> Self {
676 Self {
677 modifier_state,
678 ..self
679 }
680 }
681
682 event_builder_generic_impl!(|s: &mut Self| {
683 let event = NavigationEvent::Command {
684 command: s.command,
685 #[cfg(feature = "v1_22")]
686 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
687 modifier_state: s.modifier_state,
688 };
689 gst::ffi::gst_event_new_navigation(event.structure().into_glib_ptr())
690 });
691}
692
693#[cfg(feature = "v1_22")]
694#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
695pub enum TouchEventType {
696 Down { pressure: f64 },
697 Motion { pressure: f64 },
698 Up,
699}
700
701#[cfg(feature = "v1_22")]
702#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
703nav_event_builder!(
704 TouchEventBuilder,
705 kind: TouchEventType,
706 [identifier: u32, x: f64, y: f64],
707 |s: &mut Self| {
708 let event = match s.kind {
709 TouchEventType::Down { pressure } => NavigationEvent::TouchDown {
710 identifier: s.identifier,
711 x: s.x,
712 y: s.y,
713 modifier_state: s.modifier_state,
714 pressure,
715 },
716 TouchEventType::Motion { pressure } => NavigationEvent::TouchMotion {
717 identifier: s.identifier,
718 x: s.x,
719 y: s.y,
720 modifier_state: s.modifier_state,
721 pressure,
722 },
723 TouchEventType::Up => NavigationEvent::TouchUp {
724 identifier: s.identifier,
725 x: s.x,
726 y: s.y,
727 modifier_state: s.modifier_state,
728 },
729 };
730 gst::ffi::gst_event_new_navigation(event.structure().into_glib_ptr())
731 }
732);
733
734#[cfg(feature = "v1_22")]
735#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
736pub enum TouchMetaEventType {
737 Frame,
738 Cancel,
739}
740
741#[cfg(feature = "v1_22")]
742#[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
743nav_event_builder!(
744 TouchMetaEventBuilder,
745 kind: TouchMetaEventType,
746 [],
747 |s: &mut Self| {
748 let event = match s.kind {
749 TouchMetaEventType::Frame => NavigationEvent::TouchFrame {
750 modifier_state: s.modifier_state,
751 },
752 TouchMetaEventType::Cancel => NavigationEvent::TouchCancel {
753 modifier_state: s.modifier_state,
754 },
755 };
756 gst::ffi::gst_event_new_navigation(event.structure().into_glib_ptr())
757 }
758);
759
760const NAVIGATION_EVENT_NAME: &str = "application/x-gst-navigation";
761#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
762#[cfg_attr(feature = "serde", serde(tag = "event"))]
763#[derive(Clone, PartialEq, Debug)]
764pub enum NavigationEvent {
765 KeyPress {
766 key: String,
767 #[cfg(feature = "v1_22")]
768 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
769 modifier_state: NavigationModifierType,
770 },
771 KeyRelease {
772 key: String,
773 #[cfg(feature = "v1_22")]
774 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
775 modifier_state: NavigationModifierType,
776 },
777 MouseMove {
778 x: f64,
779 y: f64,
780 #[cfg(feature = "v1_22")]
781 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
782 modifier_state: NavigationModifierType,
783 },
784 MouseButtonPress {
785 button: i32,
786 x: f64,
787 y: f64,
788 #[cfg(feature = "v1_22")]
789 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
790 modifier_state: NavigationModifierType,
791 },
792 MouseButtonRelease {
793 button: i32,
794 x: f64,
795 y: f64,
796 #[cfg(feature = "v1_22")]
797 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
798 modifier_state: NavigationModifierType,
799 },
800 Command {
801 command: NavigationCommand,
802 #[cfg(feature = "v1_22")]
803 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
804 modifier_state: NavigationModifierType,
805 },
806 #[cfg(feature = "v1_18")]
807 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
808 MouseScroll {
809 x: f64,
810 y: f64,
811 delta_x: f64,
812 delta_y: f64,
813 #[cfg(feature = "v1_22")]
814 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
815 modifier_state: NavigationModifierType,
816 },
817 #[cfg(feature = "v1_22")]
818 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
819 TouchDown {
820 identifier: u32,
821 x: f64,
822 y: f64,
823 pressure: f64,
824 modifier_state: NavigationModifierType,
825 },
826 #[cfg(feature = "v1_22")]
827 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
828 TouchMotion {
829 identifier: u32,
830 x: f64,
831 y: f64,
832 pressure: f64,
833 modifier_state: NavigationModifierType,
834 },
835 #[cfg(feature = "v1_22")]
836 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
837 TouchUp {
838 identifier: u32,
839 x: f64,
840 y: f64,
841 modifier_state: NavigationModifierType,
842 },
843 #[cfg(feature = "v1_22")]
844 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
845 TouchFrame {
846 modifier_state: NavigationModifierType,
847 },
848 #[cfg(feature = "v1_22")]
849 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
850 TouchCancel {
851 modifier_state: NavigationModifierType,
852 },
853 #[cfg(feature = "v1_26")]
854 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
855 MouseDoubleClick {
856 button: i32,
857 x: f64,
858 y: f64,
859 modifier_state: NavigationModifierType,
860 },
861}
862
863impl NavigationEvent {
864 #[doc(alias = "gst_navigation_event_new_key_press")]
865 pub fn new_key_press(key: &str) -> NavigationEvent {
866 assert_initialized_main_thread!();
867 Self::KeyPress {
868 key: key.to_string(),
869 #[cfg(feature = "v1_22")]
870 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
871 modifier_state: NavigationModifierType::empty(),
872 }
873 }
874
875 #[doc(alias = "gst_navigation_event_new_key_release")]
876 pub fn new_key_release(key: &str) -> NavigationEvent {
877 assert_initialized_main_thread!();
878 Self::KeyRelease {
879 key: key.to_string(),
880 #[cfg(feature = "v1_22")]
881 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
882 modifier_state: NavigationModifierType::empty(),
883 }
884 }
885
886 #[doc(alias = "gst_navigation_event_new_mouse_move")]
887 pub fn new_mouse_move(x: f64, y: f64) -> NavigationEvent {
888 assert_initialized_main_thread!();
889 Self::MouseMove {
890 x,
891 y,
892 #[cfg(feature = "v1_22")]
893 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
894 modifier_state: NavigationModifierType::empty(),
895 }
896 }
897
898 #[doc(alias = "gst_navigation_event_new_mouse_button_press")]
899 pub fn new_mouse_button_press(button: i32, x: f64, y: f64) -> NavigationEvent {
900 assert_initialized_main_thread!();
901 Self::MouseButtonPress {
902 button,
903 x,
904 y,
905 #[cfg(feature = "v1_22")]
906 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
907 modifier_state: NavigationModifierType::empty(),
908 }
909 }
910
911 #[doc(alias = "gst_navigation_event_new_mouse_button_release")]
912 pub fn new_mouse_button_release(button: i32, x: f64, y: f64) -> NavigationEvent {
913 assert_initialized_main_thread!();
914 Self::MouseButtonRelease {
915 button,
916 x,
917 y,
918 #[cfg(feature = "v1_22")]
919 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
920 modifier_state: NavigationModifierType::empty(),
921 }
922 }
923
924 #[cfg(feature = "v1_18")]
925 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
926 #[doc(alias = "gst_navigation_event_new_mouse_scroll")]
927 pub fn new_mouse_scroll(x: f64, y: f64, delta_x: f64, delta_y: f64) -> NavigationEvent {
928 assert_initialized_main_thread!();
929 Self::MouseScroll {
930 x,
931 y,
932 delta_x,
933 delta_y,
934 #[cfg(feature = "v1_22")]
935 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
936 modifier_state: NavigationModifierType::empty(),
937 }
938 }
939
940 #[doc(alias = "gst_navigation_event_new_command")]
941 pub fn new_command(command: NavigationCommand) -> NavigationEvent {
942 assert_initialized_main_thread!();
943 Self::Command {
944 command,
945 #[cfg(feature = "v1_22")]
946 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
947 modifier_state: NavigationModifierType::empty(),
948 }
949 }
950
951 #[cfg(feature = "v1_22")]
952 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
953 #[doc(alias = "gst_navigation_event_new_touch_down")]
954 pub fn new_touch_down(identifier: u32, x: f64, y: f64, pressure: f64) -> NavigationEvent {
955 assert_initialized_main_thread!();
956 Self::TouchDown {
957 identifier,
958 x,
959 y,
960 pressure,
961 modifier_state: NavigationModifierType::empty(),
962 }
963 }
964
965 #[cfg(feature = "v1_22")]
966 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
967 #[doc(alias = "gst_navigation_event_new_touch_motion")]
968 pub fn new_touch_motion(identifier: u32, x: f64, y: f64, pressure: f64) -> NavigationEvent {
969 assert_initialized_main_thread!();
970 Self::TouchMotion {
971 identifier,
972 x,
973 y,
974 pressure,
975 modifier_state: NavigationModifierType::empty(),
976 }
977 }
978
979 #[cfg(feature = "v1_22")]
980 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
981 #[doc(alias = "gst_navigation_event_new_touch_up")]
982 pub fn new_touch_up(identifier: u32, x: f64, y: f64) -> NavigationEvent {
983 assert_initialized_main_thread!();
984 Self::TouchUp {
985 identifier,
986 x,
987 y,
988 modifier_state: NavigationModifierType::empty(),
989 }
990 }
991
992 #[cfg(feature = "v1_22")]
993 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
994 #[doc(alias = "gst_navigation_event_new_touch_frame")]
995 pub fn new_touch_frame() -> NavigationEvent {
996 assert_initialized_main_thread!();
997 Self::TouchFrame {
998 modifier_state: NavigationModifierType::empty(),
999 }
1000 }
1001
1002 #[cfg(feature = "v1_22")]
1003 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1004 #[doc(alias = "gst_navigation_event_new_touch_cancel")]
1005 pub fn new_touch_cancel() -> NavigationEvent {
1006 assert_initialized_main_thread!();
1007 Self::TouchCancel {
1008 modifier_state: NavigationModifierType::empty(),
1009 }
1010 }
1011
1012 #[cfg(feature = "v1_26")]
1013 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
1014 #[doc(alias = "gst_navigation_event_new_mouse_double_click")]
1015 pub fn new_mouse_double_click(button: i32, x: f64, y: f64) -> NavigationEvent {
1016 assert_initialized_main_thread!();
1017 Self::MouseDoubleClick {
1018 button,
1019 x,
1020 y,
1021 modifier_state: NavigationModifierType::empty(),
1022 }
1023 }
1024 pub fn key_press_builder(key: &str) -> KeyEventBuilder {
1025 assert_initialized_main_thread!();
1026 KeyEventBuilder::new(KeyEventType::Press { key })
1027 }
1028
1029 pub fn key_release_builder(key: &str) -> KeyEventBuilder {
1030 assert_initialized_main_thread!();
1031 KeyEventBuilder::new(KeyEventType::Release { key })
1032 }
1033
1034 pub fn mouse_move_builder(x: f64, y: f64) -> MouseEventBuilder<'static> {
1035 assert_initialized_main_thread!();
1036 MouseEventBuilder::new(MouseEventType::Move {}).x(x).y(y)
1037 }
1038
1039 pub fn mouse_button_press_builder(button: i32, x: f64, y: f64) -> MouseEventBuilder<'static> {
1040 assert_initialized_main_thread!();
1041 MouseEventBuilder::new(MouseEventType::Press { button })
1042 .x(x)
1043 .y(y)
1044 }
1045
1046 pub fn mouse_button_release_builder(button: i32, x: f64, y: f64) -> MouseEventBuilder<'static> {
1047 assert_initialized_main_thread!();
1048 MouseEventBuilder::new(MouseEventType::Press { button })
1049 .x(x)
1050 .y(y)
1051 }
1052
1053 #[cfg(feature = "v1_18")]
1054 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1055 pub fn mouse_scroll_builder(
1056 x: f64,
1057 y: f64,
1058 delta_x: f64,
1059 delta_y: f64,
1060 ) -> MouseEventBuilder<'static> {
1061 assert_initialized_main_thread!();
1062 MouseEventBuilder::new(MouseEventType::Scroll { delta_x, delta_y })
1063 .x(x)
1064 .y(y)
1065 }
1066
1067 pub fn command_builder(command: NavigationCommand) -> CommandEventBuilder<'static> {
1068 assert_initialized_main_thread!();
1069 CommandEventBuilder::new(command)
1070 }
1071
1072 #[cfg(feature = "v1_22")]
1073 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1074 pub fn touch_down_builder(
1075 identifier: u32,
1076 x: f64,
1077 y: f64,
1078 pressure: f64,
1079 ) -> TouchEventBuilder<'static> {
1080 assert_initialized_main_thread!();
1081 TouchEventBuilder::new(TouchEventType::Down { pressure })
1082 .identifier(identifier)
1083 .x(x)
1084 .y(y)
1085 }
1086
1087 #[cfg(feature = "v1_22")]
1088 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1089 pub fn touch_motion_builder(
1090 identifier: u32,
1091 x: f64,
1092 y: f64,
1093 pressure: f64,
1094 ) -> TouchEventBuilder<'static> {
1095 assert_initialized_main_thread!();
1096 TouchEventBuilder::new(TouchEventType::Motion { pressure })
1097 .identifier(identifier)
1098 .x(x)
1099 .y(y)
1100 }
1101
1102 #[cfg(feature = "v1_22")]
1103 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1104 pub fn touch_up_builder(identifier: u32, x: f64, y: f64) -> TouchEventBuilder<'static> {
1105 assert_initialized_main_thread!();
1106 TouchEventBuilder::new(TouchEventType::Up)
1107 .identifier(identifier)
1108 .x(x)
1109 .y(y)
1110 }
1111
1112 #[cfg(feature = "v1_22")]
1113 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1114 pub fn touch_frame_builder() -> TouchMetaEventBuilder<'static> {
1115 assert_initialized_main_thread!();
1116 TouchMetaEventBuilder::new(TouchMetaEventType::Frame)
1117 }
1118
1119 #[cfg(feature = "v1_22")]
1120 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1121 pub fn touch_cancel_builder() -> TouchMetaEventBuilder<'static> {
1122 assert_initialized_main_thread!();
1123 TouchMetaEventBuilder::new(TouchMetaEventType::Cancel)
1124 }
1125
1126 #[cfg(feature = "v1_26")]
1127 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
1128 pub fn mouse_double_click_builder(button: i32, x: f64, y: f64) -> MouseEventBuilder<'static> {
1129 assert_initialized_main_thread!();
1130 MouseEventBuilder::new(MouseEventType::DoubleClick { button })
1131 .x(x)
1132 .y(y)
1133 }
1134
1135 #[doc(alias = "gst_navigation_event_get_type")]
1136 pub fn type_(event: &gst::EventRef) -> NavigationEventType {
1137 skip_assert_initialized!();
1138 unsafe { from_glib(ffi::gst_navigation_event_get_type(event.as_mut_ptr())) }
1139 }
1140
1141 #[doc(alias = "gst_navigation_event_parse_key_event")]
1142 #[doc(alias = "gst_navigation_event_parse_mouse_button_event")]
1143 #[doc(alias = "gst_navigation_event_parse_mouse_scroll_event")]
1144 #[doc(alias = "gst_navigation_event_parse_mouse_move_event")]
1145 #[doc(alias = "gst_navigation_event_parse_touch_event")]
1146 #[doc(alias = "gst_navigation_event_parse_touch_up_event")]
1147 #[doc(alias = "gst_navigation_event_parse_command")]
1148 pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
1149 skip_assert_initialized!();
1150 if event.type_() != EventType::Navigation {
1151 return Err(glib::bool_error!("Invalid navigation event"));
1152 }
1153
1154 let structure = event
1155 .structure()
1156 .ok_or_else(|| glib::bool_error!("Invalid navigation event"))?;
1157 if structure.name() != NAVIGATION_EVENT_NAME {
1158 return Err(glib::bool_error!("Invalid navigation event"));
1159 }
1160
1161 #[cfg(feature = "v1_22")]
1162 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1163 let modifier_state = structure
1164 .get("state")
1165 .unwrap_or(NavigationModifierType::empty());
1166 let event = match Self::type_(event) {
1167 NavigationEventType::MouseMove => NavigationEvent::MouseMove {
1168 x: structure
1169 .get("pointer_x")
1170 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1171 y: structure
1172 .get("pointer_y")
1173 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1174 #[cfg(feature = "v1_22")]
1175 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1176 modifier_state,
1177 },
1178 NavigationEventType::MouseButtonPress => NavigationEvent::MouseButtonPress {
1179 button: structure
1180 .get("button")
1181 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1182 x: structure
1183 .get("pointer_x")
1184 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1185 y: structure
1186 .get("pointer_y")
1187 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1188 #[cfg(feature = "v1_22")]
1189 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1190 modifier_state,
1191 },
1192 NavigationEventType::MouseButtonRelease => NavigationEvent::MouseButtonRelease {
1193 button: structure
1194 .get("button")
1195 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1196 x: structure
1197 .get("pointer_x")
1198 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1199 y: structure
1200 .get("pointer_y")
1201 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1202 #[cfg(feature = "v1_22")]
1203 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1204 modifier_state,
1205 },
1206 #[cfg(feature = "v1_18")]
1207 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1208 NavigationEventType::MouseScroll => NavigationEvent::MouseScroll {
1209 x: structure
1210 .get("pointer_x")
1211 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1212 y: structure
1213 .get("pointer_y")
1214 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1215 delta_x: structure
1216 .get("delta_pointer_x")
1217 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1218 delta_y: structure
1219 .get("delta_pointer_y")
1220 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1221 #[cfg(feature = "v1_22")]
1222 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1223 modifier_state,
1224 },
1225 NavigationEventType::KeyPress => NavigationEvent::KeyPress {
1226 key: structure
1227 .get("key")
1228 .map_err(|_| glib::bool_error!("Invalid key press event"))?,
1229 #[cfg(feature = "v1_22")]
1230 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1231 modifier_state,
1232 },
1233 NavigationEventType::KeyRelease => NavigationEvent::KeyRelease {
1234 key: structure
1235 .get("key")
1236 .map_err(|_| glib::bool_error!("Invalid key press event"))?,
1237 #[cfg(feature = "v1_22")]
1238 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1239 modifier_state,
1240 },
1241 NavigationEventType::Command => NavigationEvent::Command {
1242 command: structure
1243 .get("command-code")
1244 .map_err(|_| glib::bool_error!("Invalid key press event"))?,
1245 #[cfg(feature = "v1_22")]
1246 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1247 modifier_state,
1248 },
1249 #[cfg(feature = "v1_22")]
1250 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1251 NavigationEventType::TouchDown => NavigationEvent::TouchDown {
1252 identifier: structure
1253 .get("identifier")
1254 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1255 x: structure
1256 .get("pointer_x")
1257 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1258 y: structure
1259 .get("pointer_y")
1260 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1261 pressure: structure
1262 .get("pressure")
1263 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1264 modifier_state,
1265 },
1266 #[cfg(feature = "v1_22")]
1267 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1268 NavigationEventType::TouchMotion => NavigationEvent::TouchMotion {
1269 identifier: structure
1270 .get("identifier")
1271 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1272 x: structure
1273 .get("pointer_x")
1274 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1275 y: structure
1276 .get("pointer_y")
1277 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1278 pressure: structure
1279 .get("pressure")
1280 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1281 modifier_state,
1282 },
1283 #[cfg(feature = "v1_22")]
1284 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1285 NavigationEventType::TouchUp => NavigationEvent::TouchUp {
1286 identifier: structure
1287 .get("identifier")
1288 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1289 x: structure
1290 .get("pointer_x")
1291 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1292 y: structure
1293 .get("pointer_y")
1294 .map_err(|_| glib::bool_error!("Invalid touch event"))?,
1295 modifier_state,
1296 },
1297 #[cfg(feature = "v1_22")]
1298 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1299 NavigationEventType::TouchFrame => NavigationEvent::TouchFrame { modifier_state },
1300 #[cfg(feature = "v1_22")]
1301 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1302 NavigationEventType::TouchCancel => NavigationEvent::TouchCancel { modifier_state },
1303 #[cfg(feature = "v1_26")]
1304 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
1305 NavigationEventType::MouseDoubleClick => NavigationEvent::MouseDoubleClick {
1306 button: structure
1307 .get("button")
1308 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1309 x: structure
1310 .get("pointer_x")
1311 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1312 y: structure
1313 .get("pointer_y")
1314 .map_err(|_| glib::bool_error!("Invalid mouse event"))?,
1315 modifier_state,
1316 },
1317
1318 NavigationEventType::Invalid | NavigationEventType::__Unknown(_) => {
1319 return Err(glib::bool_error!("Invalid navigation event"))
1320 }
1321 };
1322 Ok(event)
1323 }
1324
1325 pub fn structure(&self) -> gst::Structure {
1326 skip_assert_initialized!();
1327 #[allow(unused_mut)]
1328 let mut structure = match self {
1329 Self::MouseMove { x, y, .. } => gst::Structure::builder(NAVIGATION_EVENT_NAME)
1330 .field("event", "mouse-move")
1331 .field("pointer_x", x)
1332 .field("pointer_y", y),
1333 Self::MouseButtonPress { button, x, y, .. } => {
1334 gst::Structure::builder(NAVIGATION_EVENT_NAME)
1335 .field("event", "mouse-button-press")
1336 .field("button", button)
1337 .field("pointer_x", x)
1338 .field("pointer_y", y)
1339 }
1340 Self::MouseButtonRelease { button, x, y, .. } => {
1341 gst::Structure::builder(NAVIGATION_EVENT_NAME)
1342 .field("event", "mouse-button-release")
1343 .field("button", button)
1344 .field("pointer_x", x)
1345 .field("pointer_y", y)
1346 }
1347 #[cfg(feature = "v1_18")]
1348 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
1349 Self::MouseScroll {
1350 x,
1351 y,
1352 delta_x,
1353 delta_y,
1354 ..
1355 } => gst::Structure::builder(NAVIGATION_EVENT_NAME)
1356 .field("event", "mouse-scroll")
1357 .field("pointer_x", x)
1358 .field("pointer_y", y)
1359 .field("delta_pointer_x", delta_x)
1360 .field("delta_pointer_y", delta_y),
1361 Self::KeyPress { key, .. } => gst::Structure::builder(NAVIGATION_EVENT_NAME)
1362 .field("event", "key-press")
1363 .field("key", key),
1364 Self::KeyRelease { key, .. } => gst::Structure::builder(NAVIGATION_EVENT_NAME)
1365 .field("event", "key-release")
1366 .field("key", key),
1367 Self::Command { command, .. } => gst::Structure::builder(NAVIGATION_EVENT_NAME)
1368 .field("event", "command")
1369 .field("command-code", command),
1370 #[cfg(feature = "v1_22")]
1371 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1372 Self::TouchDown {
1373 identifier,
1374 x,
1375 y,
1376 pressure,
1377 ..
1378 } => gst::Structure::builder(NAVIGATION_EVENT_NAME)
1379 .field("event", "touch-down")
1380 .field("identifier", identifier)
1381 .field("pointer_x", x)
1382 .field("pointer_y", y)
1383 .field("pressure", pressure),
1384 #[cfg(feature = "v1_22")]
1385 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1386 Self::TouchMotion {
1387 identifier,
1388 x,
1389 y,
1390 pressure,
1391 ..
1392 } => gst::Structure::builder(NAVIGATION_EVENT_NAME)
1393 .field("event", "touch-motion")
1394 .field("identifier", identifier)
1395 .field("pointer_x", x)
1396 .field("pointer_y", y)
1397 .field("pressure", pressure),
1398 #[cfg(feature = "v1_22")]
1399 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1400 Self::TouchUp {
1401 identifier, x, y, ..
1402 } => gst::Structure::builder(NAVIGATION_EVENT_NAME)
1403 .field("event", "touch-up")
1404 .field("identifier", identifier)
1405 .field("pointer_x", x)
1406 .field("pointer_y", y),
1407 #[cfg(feature = "v1_22")]
1408 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1409 Self::TouchFrame { .. } => {
1410 gst::Structure::builder(NAVIGATION_EVENT_NAME).field("event", "touch-frame")
1411 }
1412 #[cfg(feature = "v1_22")]
1413 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1414 Self::TouchCancel { .. } => {
1415 gst::Structure::builder(NAVIGATION_EVENT_NAME).field("event", "touch-cancel")
1416 }
1417 #[cfg(feature = "v1_26")]
1418 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
1419 Self::MouseDoubleClick { button, x, y, .. } => {
1420 gst::Structure::builder(NAVIGATION_EVENT_NAME)
1421 .field("event", "mouse-double-click")
1422 .field("button", button)
1423 .field("pointer_x", x)
1424 .field("pointer_y", y)
1425 }
1426 };
1427
1428 #[cfg(feature = "v1_22")]
1429 {
1430 structure = match self {
1431 Self::MouseMove { modifier_state, .. } => structure.field("state", modifier_state),
1432 Self::MouseButtonPress { modifier_state, .. } => {
1433 structure.field("state", modifier_state)
1434 }
1435 Self::MouseButtonRelease { modifier_state, .. } => {
1436 structure.field("state", modifier_state)
1437 }
1438 Self::MouseScroll { modifier_state, .. } => {
1439 structure.field("state", modifier_state)
1440 }
1441 Self::KeyPress { modifier_state, .. } => structure.field("state", modifier_state),
1442 Self::KeyRelease { modifier_state, .. } => structure.field("state", modifier_state),
1443 Self::Command { modifier_state, .. } => structure.field("state", modifier_state),
1444 Self::TouchDown { modifier_state, .. } => structure.field("state", modifier_state),
1445 Self::TouchMotion { modifier_state, .. } => {
1446 structure.field("state", modifier_state)
1447 }
1448 Self::TouchUp { modifier_state, .. } => structure.field("state", modifier_state),
1449 Self::TouchFrame { modifier_state, .. } => structure.field("state", modifier_state),
1450 Self::TouchCancel { modifier_state, .. } => {
1451 structure.field("state", modifier_state)
1452 }
1453 #[cfg(feature = "v1_26")]
1454 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
1455 Self::MouseDoubleClick { modifier_state, .. } => {
1456 structure.field("state", modifier_state)
1457 }
1458 };
1459 }
1460
1461 structure.build()
1462 }
1463
1464 pub fn build(&self) -> gst::Event {
1465 skip_assert_initialized!();
1466
1467 gst::event::Navigation::new(self.structure())
1468 }
1469}
1470
1471#[cfg(test)]
1472mod tests {
1473 #[test]
1474 #[cfg(feature = "serde")]
1475 #[cfg(feature = "v1_22")]
1476 #[cfg_attr(docsrs, doc(cfg(feature = "v1_22")))]
1477 fn serialize_navigation_events() {
1478 use crate::{NavigationEvent, NavigationModifierType};
1479
1480 gst::init().unwrap();
1481
1482 let mods = NavigationModifierType::SHIFT_MASK | NavigationModifierType::CONTROL_MASK;
1483 let ev = NavigationEvent::mouse_scroll_builder(1.0, 2.0, 3.0, 4.0)
1484 .modifier_state(mods)
1485 .build();
1486 let navigation_event = NavigationEvent::parse(&ev).unwrap();
1487 match &navigation_event {
1488 NavigationEvent::MouseScroll {
1489 x,
1490 y,
1491 delta_x,
1492 delta_y,
1493 modifier_state,
1494 } => {
1495 assert!(
1496 *x == 1.0
1497 && *y == 2.0
1498 && *delta_x == 3.0
1499 && *delta_y == 4.0
1500 && *modifier_state == mods
1501 );
1502 }
1503 _ => unreachable!(),
1504 }
1505
1506 let json_event = serde_json::to_string(&navigation_event).unwrap();
1507 assert_eq!(
1508 json_event,
1509 r#"{"event":"MouseScroll","x":1.0,"y":2.0,"delta_x":3.0,"delta_y":4.0,"modifier_state":"shift-mask+control-mask"}"#
1510 );
1511 let navigation_event: NavigationEvent = serde_json::from_str(&json_event).unwrap();
1512 match &navigation_event {
1513 NavigationEvent::MouseScroll {
1514 x,
1515 y,
1516 delta_x,
1517 delta_y,
1518 modifier_state,
1519 } => {
1520 assert!(
1521 *x == 1.0
1522 && *y == 2.0
1523 && *delta_x == 3.0
1524 && *delta_y == 4.0
1525 && *modifier_state == mods
1526 );
1527 }
1528 _ => unreachable!(),
1529 }
1530
1531 let ev = NavigationEvent::new_mouse_button_press(1, 1.0, 2.0).build();
1532 let navigation_event = NavigationEvent::parse(&ev).unwrap();
1533 match &navigation_event {
1534 NavigationEvent::MouseButtonPress {
1535 button,
1536 x,
1537 y,
1538 modifier_state,
1539 } => {
1540 assert!(
1541 *button == 1
1542 && *x == 1.0
1543 && *y == 2.0
1544 && *modifier_state == NavigationModifierType::empty()
1545 );
1546 }
1547 _ => unreachable!(),
1548 }
1549 let json_event = serde_json::to_string(&navigation_event).unwrap();
1550 assert_eq!(
1551 json_event,
1552 r#"{"event":"MouseButtonPress","button":1,"x":1.0,"y":2.0,"modifier_state":""}"#
1553 );
1554 let navigation_event: NavigationEvent = serde_json::from_str(&json_event).unwrap();
1555 match &navigation_event {
1556 NavigationEvent::MouseButtonPress {
1557 button,
1558 x,
1559 y,
1560 modifier_state,
1561 } => {
1562 assert!(
1563 *button == 1
1564 && *x == 1.0
1565 && *y == 2.0
1566 && *modifier_state == NavigationModifierType::empty()
1567 );
1568 }
1569 _ => unreachable!(),
1570 }
1571
1572 let mods = NavigationModifierType::META_MASK;
1573 let ev = NavigationEvent::key_release_builder("a")
1574 .modifier_state(mods)
1575 .build();
1576 let navigation_event = NavigationEvent::parse(&ev).unwrap();
1577 match &navigation_event {
1578 NavigationEvent::KeyRelease {
1579 key,
1580 modifier_state,
1581 } => {
1582 assert!(*key == "a" && *modifier_state == mods);
1583 }
1584 _ => unreachable!(),
1585 }
1586
1587 let json_event = serde_json::to_string(&navigation_event).unwrap();
1588 assert_eq!(
1589 json_event,
1590 r#"{"event":"KeyRelease","key":"a","modifier_state":"meta-mask"}"#
1591 );
1592 let navigation_event: NavigationEvent = serde_json::from_str(&json_event).unwrap();
1593 match &navigation_event {
1594 NavigationEvent::KeyRelease {
1595 key,
1596 modifier_state,
1597 } => {
1598 assert!(*key == "a" && *modifier_state == mods);
1599 }
1600 _ => unreachable!(),
1601 }
1602
1603 let ev = NavigationEvent::new_touch_motion(0, 1.0, 2.0, 0.5).build();
1604 let navigation_event = NavigationEvent::parse(&ev).unwrap();
1605 match &navigation_event {
1606 NavigationEvent::TouchMotion {
1607 identifier,
1608 x,
1609 y,
1610 pressure,
1611 modifier_state,
1612 } => {
1613 assert!(
1614 *identifier == 0
1615 && *x == 1.0
1616 && *y == 2.0
1617 && *pressure == 0.5
1618 && *modifier_state == NavigationModifierType::empty()
1619 );
1620 }
1621 _ => unreachable!(),
1622 }
1623
1624 let json_event = serde_json::to_string(&navigation_event).unwrap();
1625 assert_eq!(
1626 json_event,
1627 r#"{"event":"TouchMotion","identifier":0,"x":1.0,"y":2.0,"pressure":0.5,"modifier_state":""}"#
1628 );
1629 let navigation_event: NavigationEvent = serde_json::from_str(&json_event).unwrap();
1630 match &navigation_event {
1631 NavigationEvent::TouchMotion {
1632 identifier,
1633 x,
1634 y,
1635 pressure,
1636 modifier_state,
1637 } => {
1638 assert!(
1639 *identifier == 0
1640 && *x == 1.0
1641 && *y == 2.0
1642 && *pressure == 0.5
1643 && *modifier_state == NavigationModifierType::empty()
1644 );
1645 }
1646 _ => unreachable!(),
1647 }
1648
1649 let ev = NavigationEvent::touch_cancel_builder().build();
1650 let navigation_event = NavigationEvent::parse(&ev).unwrap();
1651 match &navigation_event {
1652 NavigationEvent::TouchCancel { modifier_state } => {
1653 assert!(*modifier_state == NavigationModifierType::empty());
1654 }
1655 _ => unreachable!(),
1656 }
1657
1658 let json_event = serde_json::to_string(&navigation_event).unwrap();
1659 assert_eq!(json_event, r#"{"event":"TouchCancel","modifier_state":""}"#);
1660 let navigation_event: NavigationEvent = serde_json::from_str(&json_event).unwrap();
1661 match &navigation_event {
1662 NavigationEvent::TouchCancel { modifier_state } => {
1663 assert!(*modifier_state == NavigationModifierType::empty());
1664 }
1665 _ => unreachable!(),
1666 }
1667 }
1668}