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