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