From 1274a5947276d02d4072e70702f06c16fb233236 Mon Sep 17 00:00:00 2001 From: Vivienne Watermeier Date: Tue, 15 Mar 2022 14:18:08 +0100 Subject: [PATCH] video: update navigation API for recent changes Add support for the new send_event_simple and event_get/set_coordinates functions, as well as touchscreen events and modifier state. See: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1633 https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2010 --- ci/4580.patch | 135 ------ ci/install-gtk4.sh | 1 - gstreamer-video/Gir.toml | 103 ++++- gstreamer-video/src/auto/flags.rs | 94 +++++ gstreamer-video/src/auto/mod.rs | 3 + gstreamer-video/src/auto/navigation.rs | 153 ------- gstreamer-video/src/navigation.rs | 13 + gstreamer-video/src/subclass/navigation.rs | 65 ++- gstreamer-video/src/video_event.rs | 465 ++++++++++++++++++--- 9 files changed, 674 insertions(+), 358 deletions(-) delete mode 100644 ci/4580.patch diff --git a/ci/4580.patch b/ci/4580.patch deleted file mode 100644 index fffbbc82b..000000000 --- a/ci/4580.patch +++ /dev/null @@ -1,135 +0,0 @@ -From e2873bc614e50d19f1b8aa939514c83933b10136 Mon Sep 17 00:00:00 2001 -From: Eli Schwartz -Date: Thu, 10 Mar 2022 00:08:36 -0500 -Subject: [PATCH 1/2] meson: use proper handling of wayland-protocols - dependency - -Ensure that resolution of the subproject occurs via the dependency -interface, not the "poke at subprojects manually" interface, and make -that actually work via --wrap-mode=forcefallback. - -There's no need to mark it as not-required and then manually invoke -subproject(), since fallback should work correctly and it is always -needed. - -However, if fallback was performed (or forced) it would error out since -get_variable() was instructed to only use pkg-config while the relevant -variable was exported by the subproject as an internal fallback -dependency. ---- - meson.build | 8 ++------ - 1 file changed, 2 insertions(+), 6 deletions(-) - -diff --git a/meson.build b/meson.build -index 63b4d73bfe..17fdb1cfe7 100644 ---- a/meson.build -+++ b/meson.build -@@ -517,15 +517,11 @@ if wayland_enabled - wlclientdep = dependency('wayland-client', version: wayland_req, - fallback: 'wayland', - default_options: ['documentation=false']) -- wlprotocolsdep = dependency('wayland-protocols', version: wayland_proto_req, required: false) -+ wlprotocolsdep = dependency('wayland-protocols', version: wayland_proto_req) - wlegldep = dependency('wayland-egl', - fallback: 'wayland') - -- if not wlprotocolsdep.found() -- wlproto_dir = subproject('wayland-protocols').get_variable('wayland_protocols_srcdir') -- else -- wlproto_dir = wlprotocolsdep.get_variable(pkgconfig: 'pkgdatadir') -- endif -+ wlproto_dir = wlprotocolsdep.get_variable('pkgdatadir') - - wayland_pkgs = [ - 'wayland-client @0@'.format(wayland_req), --- -GitLab - - -From dc875b6af9311f3b5275961618ad867bf1f57a1e Mon Sep 17 00:00:00 2001 -From: Jordan Petridis -Date: Wed, 16 Mar 2022 09:53:16 +0200 -Subject: [PATCH 2/2] meson: switch some .wrap files to stable branches - -To avoid random failures if one of the projects starts -depending on new things or has incompatible changes. ---- - subprojects/glib.wrap | 2 +- - subprojects/graphene.wrap | 2 +- - subprojects/libepoxy.wrap | 2 +- - subprojects/sysprof.wrap | 2 +- - subprojects/wayland-protocols.wrap | 2 +- - subprojects/wayland.wrap | 2 +- - 6 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/subprojects/glib.wrap b/subprojects/glib.wrap -index c785910d9f..ec5febde86 100644 ---- a/subprojects/glib.wrap -+++ b/subprojects/glib.wrap -@@ -2,5 +2,5 @@ - directory=glib - url=https://gitlab.gnome.org/GNOME/glib.git - push-url=ssh://git@gitlab.gnome.org:GNOME/glib.git --revision=main -+revision=glib-2-68 - depth=1 -diff --git a/subprojects/graphene.wrap b/subprojects/graphene.wrap -index 902095dbd7..d9503ab978 100644 ---- a/subprojects/graphene.wrap -+++ b/subprojects/graphene.wrap -@@ -1,5 +1,5 @@ - [wrap-git] - directory=graphene - url=https://github.com/ebassi/graphene.git --revision=master -+revision=1.10.6 - depth=1 -diff --git a/subprojects/libepoxy.wrap b/subprojects/libepoxy.wrap -index fc5147a22b..0ab256ef26 100644 ---- a/subprojects/libepoxy.wrap -+++ b/subprojects/libepoxy.wrap -@@ -1,5 +1,5 @@ - [wrap-git] - directory=libepoxy - url=https://github.com/anholt/libepoxy.git --revision=master -+revision=1.5.9 - depth=1 -diff --git a/subprojects/sysprof.wrap b/subprojects/sysprof.wrap -index 99aa36ce87..41fb7c6ee2 100644 ---- a/subprojects/sysprof.wrap -+++ b/subprojects/sysprof.wrap -@@ -1,5 +1,5 @@ - [wrap-git] - directory=sysprof - url=https://gitlab.gnome.org/GNOME/sysprof.git --revision=master -+revision=sysprof-3-38 - depth=1 -diff --git a/subprojects/wayland-protocols.wrap b/subprojects/wayland-protocols.wrap -index 065651db63..5361f0c540 100644 ---- a/subprojects/wayland-protocols.wrap -+++ b/subprojects/wayland-protocols.wrap -@@ -1,5 +1,5 @@ - [wrap-git] - directory=wayland-protocols - url=https://gitlab.freedesktop.org/wayland/wayland-protocols.git --revision=main -+revision=1.23 - depth=1 -diff --git a/subprojects/wayland.wrap b/subprojects/wayland.wrap -index 5be67bf491..bdb12d3aa7 100644 ---- a/subprojects/wayland.wrap -+++ b/subprojects/wayland.wrap -@@ -1,7 +1,7 @@ - [wrap-git] - directory=wayland - url=https://gitlab.freedesktop.org/wayland/wayland.git --revision=main -+revision=1.20.0 - depth=1 - - [provide] --- -GitLab - diff --git a/ci/install-gtk4.sh b/ci/install-gtk4.sh index d92a5c6c7..76a1d5c4e 100644 --- a/ci/install-gtk4.sh +++ b/ci/install-gtk4.sh @@ -4,7 +4,6 @@ BRANCH=gtk-4-6 git clone https://gitlab.gnome.org/GNOME/gtk.git --branch $BRANCH --depth=1 cd gtk -git apply ../ci/4580.patch meson build -D prefix=/usr/local -Dbuild-tests=false ninja -C build ninja -C build install diff --git a/gstreamer-video/Gir.toml b/gstreamer-video/Gir.toml index cfe647aa2..d0e9c7ebf 100644 --- a/gstreamer-video/Gir.toml +++ b/gstreamer-video/Gir.toml @@ -112,10 +112,6 @@ status = "generate" name = "event_parse_key_event" manual = true - [[object.function]] - name = "send_event" - manual = true - [[object.function]] name = "event_parse_mouse_button_event" manual = true @@ -129,21 +125,21 @@ status = "generate" manual = true [[object.function]] - name = "message_parse_event" + name = "event_parse_touch_event" manual = true [[object.function]] - name = "message_get_type" - manual = true - - [[object.function]] - name = "message_new_event" + name = "event_parse_touch_up_event" manual = true [[object.function]] name = "event_parse_mouse_scroll_event" manual = true + [[object.function]] + name = "event_parse_modifier_state" + manual = true + [[object.function]] name = "event_get_type" manual = true @@ -176,6 +172,68 @@ status = "generate" name = "event_new_mouse_scroll" manual = true + [[object.function]] + name = "event_new_touch_down" + manual = true + + [[object.function]] + name = "event_new_touch_motion" + manual = true + + [[object.function]] + name = "event_new_touch_up" + manual = true + + [[object.function]] + name = "event_new_touch_frame" + manual = true + + [[object.function]] + name = "event_new_touch_cancel" + manual = true + + [[object.function]] + name = "event_get_coordinates" + manual = true + + [[object.function]] + name = "event_set_coordinates" + manual = true + + [[object.function]] + name = "send_event" + manual = true + + [[object.function]] + name = "send_event_simple" + manual = true + + [[object.function]] + name = "send_key_event" + + [[object.function]] + name = "send_mouse_event" + + [[object.function]] + name = "send_mouse_scroll_event" + + [[object.function]] + name = "send_command" + + + [[object.function]] + name = "message_parse_event" + manual = true + + [[object.function]] + name = "message_get_type" + manual = true + + [[object.function]] + name = "message_new_event" + manual = true + + [[object.function]] name = "message_new_commands_changed" ignore = true @@ -239,6 +297,31 @@ status = "generate" [[object.member]] name = "mouse_scroll" version = "1.18" + [[object.member]] + name = "touch_down" + version = "1.22" + [[object.member]] + name = "touch_motion" + version = "1.22" + [[object.member]] + name = "touch_up" + version = "1.22" + [[object.member]] + name = "touch_frame" + version = "1.22" + [[object.member]] + name = "touch_cancel" + version = "1.22" + +[[object]] +name = "GstVideo.NavigationModifierType" +status = "generate" + [[object.member]] + name = "none" + ignore = true + [[object.member]] + name = "mask" + ignore = true [[object]] name = "GstVideo.VideoAggregatorConvertPad" diff --git a/gstreamer-video/src/auto/flags.rs b/gstreamer-video/src/auto/flags.rs index e8aec7db2..861670a6d 100644 --- a/gstreamer-video/src/auto/flags.rs +++ b/gstreamer-video/src/auto/flags.rs @@ -11,6 +11,100 @@ use glib::StaticType; use glib::Type; use std::fmt; +#[cfg(any(feature = "v1_22", feature = "dox"))] +bitflags! { + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + #[doc(alias = "GstNavigationModifierType")] + pub struct NavigationModifierType: u32 { + #[doc(alias = "GST_NAVIGATION_MODIFIER_SHIFT_MASK")] + const SHIFT_MASK = ffi::GST_NAVIGATION_MODIFIER_SHIFT_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_LOCK_MASK")] + const LOCK_MASK = ffi::GST_NAVIGATION_MODIFIER_LOCK_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_CONTROL_MASK")] + const CONTROL_MASK = ffi::GST_NAVIGATION_MODIFIER_CONTROL_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_ALT_MASK")] + const ALT_MASK = ffi::GST_NAVIGATION_MODIFIER_ALT_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_BUTTON1_MASK")] + const BUTTON1_MASK = ffi::GST_NAVIGATION_MODIFIER_BUTTON1_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_BUTTON2_MASK")] + const BUTTON2_MASK = ffi::GST_NAVIGATION_MODIFIER_BUTTON2_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_BUTTON3_MASK")] + const BUTTON3_MASK = ffi::GST_NAVIGATION_MODIFIER_BUTTON3_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_BUTTON4_MASK")] + const BUTTON4_MASK = ffi::GST_NAVIGATION_MODIFIER_BUTTON4_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_BUTTON5_MASK")] + const BUTTON5_MASK = ffi::GST_NAVIGATION_MODIFIER_BUTTON5_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_SUPER_MASK")] + const SUPER_MASK = ffi::GST_NAVIGATION_MODIFIER_SUPER_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_HYPER_MASK")] + const HYPER_MASK = ffi::GST_NAVIGATION_MODIFIER_HYPER_MASK as u32; + #[doc(alias = "GST_NAVIGATION_MODIFIER_META_MASK")] + const META_MASK = ffi::GST_NAVIGATION_MODIFIER_META_MASK as u32; + } +} + +#[cfg(any(feature = "v1_22", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] +#[doc(hidden)] +impl IntoGlib for NavigationModifierType { + type GlibType = ffi::GstNavigationModifierType; + + fn into_glib(self) -> ffi::GstNavigationModifierType { + self.bits() + } +} + +#[cfg(any(feature = "v1_22", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] +#[doc(hidden)] +impl FromGlib for NavigationModifierType { + unsafe fn from_glib(value: ffi::GstNavigationModifierType) -> Self { + skip_assert_initialized!(); + Self::from_bits_truncate(value) + } +} + +#[cfg(any(feature = "v1_22", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] +impl StaticType for NavigationModifierType { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_navigation_modifier_type_get_type()) } + } +} + +#[cfg(any(feature = "v1_22", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] +impl glib::value::ValueType for NavigationModifierType { + type Type = Self; +} + +#[cfg(any(feature = "v1_22", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] +unsafe impl<'a> FromValue<'a> for NavigationModifierType { + type Checker = glib::value::GenericValueTypeChecker; + + unsafe fn from_value(value: &'a glib::Value) -> Self { + skip_assert_initialized!(); + from_glib(glib::gobject_ffi::g_value_get_flags(value.to_glib_none().0)) + } +} + +#[cfg(any(feature = "v1_22", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] +impl ToValue for NavigationModifierType { + fn to_value(&self) -> glib::Value { + let mut value = glib::Value::for_value_type::(); + unsafe { + glib::gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, self.into_glib()); + } + value + } + + fn value_type(&self) -> glib::Type { + Self::static_type() + } +} + bitflags! { #[doc(alias = "GstVideoBufferFlags")] pub struct VideoBufferFlags: u32 { diff --git a/gstreamer-video/src/auto/mod.rs b/gstreamer-video/src/auto/mod.rs index d5d7a761b..200d8ab48 100644 --- a/gstreamer-video/src/auto/mod.rs +++ b/gstreamer-video/src/auto/mod.rs @@ -99,6 +99,9 @@ pub use self::enums::VideoTileMode; pub use self::enums::VideoTransferFunction; mod flags; +#[cfg(any(feature = "v1_22", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] +pub use self::flags::NavigationModifierType; pub use self::flags::VideoBufferFlags; pub use self::flags::VideoChromaSite; pub use self::flags::VideoCodecFrameFlags; diff --git a/gstreamer-video/src/auto/navigation.rs b/gstreamer-video/src/auto/navigation.rs index b9a5f64dc..9eb56210b 100644 --- a/gstreamer-video/src/auto/navigation.rs +++ b/gstreamer-video/src/auto/navigation.rs @@ -6,9 +6,6 @@ use crate::NavigationCommand; use glib::object::IsA; use glib::translate::*; -#[cfg(any(feature = "v1_22", feature = "dox"))] -#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] -use std::mem; glib::wrapper! { #[doc(alias = "GstNavigation")] @@ -22,140 +19,6 @@ glib::wrapper! { impl Navigation { pub const NONE: Option<&'static Navigation> = None; - #[cfg(any(feature = "v1_22", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - #[doc(alias = "gst_navigation_event_get_coordinates")] - pub fn event_get_coordinates(event: &gst::Event) -> Option<(f64, f64)> { - assert_initialized_main_thread!(); - unsafe { - let mut x = mem::MaybeUninit::uninit(); - let mut y = mem::MaybeUninit::uninit(); - let ret = from_glib(ffi::gst_navigation_event_get_coordinates( - event.to_glib_none().0, - x.as_mut_ptr(), - y.as_mut_ptr(), - )); - let x = x.assume_init(); - let y = y.assume_init(); - if ret { - Some((x, y)) - } else { - None - } - } - } - - //#[cfg(any(feature = "v1_22", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - //#[doc(alias = "gst_navigation_event_new_touch_cancel")] - //pub fn event_new_touch_cancel(state: /*Ignored*/NavigationModifierType) -> Option { - // unsafe { TODO: call ffi:gst_navigation_event_new_touch_cancel() } - //} - - //#[cfg(any(feature = "v1_22", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - //#[doc(alias = "gst_navigation_event_new_touch_down")] - //pub fn event_new_touch_down(identifier: u32, x: f64, y: f64, pressure: f64, state: /*Ignored*/NavigationModifierType) -> Option { - // unsafe { TODO: call ffi:gst_navigation_event_new_touch_down() } - //} - - //#[cfg(any(feature = "v1_22", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - //#[doc(alias = "gst_navigation_event_new_touch_frame")] - //pub fn event_new_touch_frame(state: /*Ignored*/NavigationModifierType) -> Option { - // unsafe { TODO: call ffi:gst_navigation_event_new_touch_frame() } - //} - - //#[cfg(any(feature = "v1_22", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - //#[doc(alias = "gst_navigation_event_new_touch_motion")] - //pub fn event_new_touch_motion(identifier: u32, x: f64, y: f64, pressure: f64, state: /*Ignored*/NavigationModifierType) -> Option { - // unsafe { TODO: call ffi:gst_navigation_event_new_touch_motion() } - //} - - //#[cfg(any(feature = "v1_22", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - //#[doc(alias = "gst_navigation_event_new_touch_up")] - //pub fn event_new_touch_up(identifier: u32, x: f64, y: f64, state: /*Ignored*/NavigationModifierType) -> Option { - // unsafe { TODO: call ffi:gst_navigation_event_new_touch_up() } - //} - - //#[cfg(any(feature = "v1_22", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - //#[doc(alias = "gst_navigation_event_parse_modifier_state")] - //pub fn event_parse_modifier_state(event: &gst::Event, state: /*Ignored*/NavigationModifierType) -> bool { - // unsafe { TODO: call ffi:gst_navigation_event_parse_modifier_state() } - //} - - #[cfg(any(feature = "v1_22", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - #[doc(alias = "gst_navigation_event_parse_touch_event")] - pub fn event_parse_touch_event(event: &gst::Event) -> Option<(u32, f64, f64, f64)> { - assert_initialized_main_thread!(); - unsafe { - let mut identifier = mem::MaybeUninit::uninit(); - let mut x = mem::MaybeUninit::uninit(); - let mut y = mem::MaybeUninit::uninit(); - let mut pressure = mem::MaybeUninit::uninit(); - let ret = from_glib(ffi::gst_navigation_event_parse_touch_event( - event.to_glib_none().0, - identifier.as_mut_ptr(), - x.as_mut_ptr(), - y.as_mut_ptr(), - pressure.as_mut_ptr(), - )); - let identifier = identifier.assume_init(); - let x = x.assume_init(); - let y = y.assume_init(); - let pressure = pressure.assume_init(); - if ret { - Some((identifier, x, y, pressure)) - } else { - None - } - } - } - - #[cfg(any(feature = "v1_22", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - #[doc(alias = "gst_navigation_event_parse_touch_up_event")] - pub fn event_parse_touch_up_event(event: &gst::Event) -> Option<(u32, f64, f64)> { - assert_initialized_main_thread!(); - unsafe { - let mut identifier = mem::MaybeUninit::uninit(); - let mut x = mem::MaybeUninit::uninit(); - let mut y = mem::MaybeUninit::uninit(); - let ret = from_glib(ffi::gst_navigation_event_parse_touch_up_event( - event.to_glib_none().0, - identifier.as_mut_ptr(), - x.as_mut_ptr(), - y.as_mut_ptr(), - )); - let identifier = identifier.assume_init(); - let x = x.assume_init(); - let y = y.assume_init(); - if ret { - Some((identifier, x, y)) - } else { - None - } - } - } - - #[cfg(any(feature = "v1_22", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - #[doc(alias = "gst_navigation_event_set_coordinates")] - pub fn event_set_coordinates(event: &gst::Event, x: f64, y: f64) -> bool { - assert_initialized_main_thread!(); - unsafe { - from_glib(ffi::gst_navigation_event_set_coordinates( - event.to_glib_none().0, - x, - y, - )) - } - } - //#[doc(alias = "gst_navigation_query_set_commands")] //pub fn query_set_commands(query: &gst::Query, n_cmds: i32, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) { // unsafe { TODO: call ffi:gst_navigation_query_set_commands() } @@ -174,11 +37,6 @@ pub trait NavigationExt: 'static { #[doc(alias = "gst_navigation_send_command")] fn send_command(&self, command: NavigationCommand); - #[cfg(any(feature = "v1_22", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - #[doc(alias = "gst_navigation_send_event_simple")] - fn send_event_simple(&self, event: &gst::Event); - #[doc(alias = "gst_navigation_send_key_event")] fn send_key_event(&self, event: &str, key: &str); @@ -198,17 +56,6 @@ impl> NavigationExt for O { } } - #[cfg(any(feature = "v1_22", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] - fn send_event_simple(&self, event: &gst::Event) { - unsafe { - ffi::gst_navigation_send_event_simple( - self.as_ref().to_glib_none().0, - event.to_glib_full(), - ); - } - } - fn send_key_event(&self, event: &str, key: &str) { unsafe { ffi::gst_navigation_send_key_event( diff --git a/gstreamer-video/src/navigation.rs b/gstreamer-video/src/navigation.rs index 95ff530d7..97e223988 100644 --- a/gstreamer-video/src/navigation.rs +++ b/gstreamer-video/src/navigation.rs @@ -5,6 +5,11 @@ use glib::translate::ToGlibPtr; pub trait NavigationExtManual: 'static { #[doc(alias = "gst_navigation_send_event")] fn send_event(&self, structure: gst::Structure); + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + #[doc(alias = "gst_navigation_send_event_simple")] + fn send_event_simple(&self, event: gst::Event); } impl> NavigationExtManual for O { @@ -13,4 +18,12 @@ impl> NavigationExtManual for O { ffi::gst_navigation_send_event(self.as_ref().to_glib_none().0, structure.into_ptr()); } } + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + fn send_event_simple(&self, event: gst::Event) { + unsafe { + ffi::gst_navigation_send_event_simple(self.as_ref().to_glib_none().0, event.into_ptr()); + } + } } diff --git a/gstreamer-video/src/subclass/navigation.rs b/gstreamer-video/src/subclass/navigation.rs index 66dc1c646..58fb56bb9 100644 --- a/gstreamer-video/src/subclass/navigation.rs +++ b/gstreamer-video/src/subclass/navigation.rs @@ -5,16 +5,30 @@ use glib::translate::*; use glib::subclass::prelude::*; -use gst::ffi::GstStructure; - use crate::Navigation; pub trait NavigationImpl: ObjectImpl { fn send_event(&self, nav: &Self::Type, structure: gst::Structure); + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + fn send_event_simple(&self, nav: &Self::Type, event: gst::Event) { + if let Some(structure) = event.structure() { + self.send_event(nav, structure.to_owned()); + } + } } pub trait NavigationImplExt: ObjectSubclass { fn parent_send_event(&self, nav: &Self::Type, structure: gst::Structure); + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + fn parent_send_event_simple(&self, nav: &Self::Type, event: gst::Event) { + if let Some(structure) = event.structure() { + self.parent_send_event(nav, structure.to_owned()); + } + } } impl NavigationImplExt for T { @@ -35,19 +49,49 @@ impl NavigationImplExt for T { ); } } + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + fn parent_send_event_simple(&self, nav: &Self::Type, event: gst::Event) { + unsafe { + let type_data = Self::type_data(); + let parent_iface = type_data.as_ref().parent_interface::() + as *const ffi::GstNavigationInterface; + + let func = match (*parent_iface).send_event_simple { + Some(func) => func, + None => return, + }; + + func( + nav.unsafe_cast_ref::().to_glib_none().0, + event.into_ptr(), + ); + } + } } unsafe impl IsImplementable for Navigation { + #[cfg(not(feature = "v1_22"))] fn interface_init(iface: &mut glib::Interface) { let iface = iface.as_mut(); iface.send_event = Some(navigation_send_event::); } + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + fn interface_init(iface: &mut glib::Interface) { + let iface = iface.as_mut(); + + iface.send_event = Some(navigation_send_event::); + iface.send_event_simple = Some(navigation_send_event_simple::); + } } unsafe extern "C" fn navigation_send_event( nav: *mut ffi::GstNavigation, - structure: *mut GstStructure, + structure: *mut gst::ffi::GstStructure, ) { let instance = &*(nav as *mut T::Instance); let imp = instance.imp(); @@ -57,3 +101,18 @@ unsafe extern "C" fn navigation_send_event( from_glib_full(structure), ); } + +#[cfg(any(feature = "v1_22", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] +unsafe extern "C" fn navigation_send_event_simple( + nav: *mut ffi::GstNavigation, + event: *mut gst::ffi::GstEvent, +) { + let instance = &*(nav as *mut T::Instance); + let imp = instance.imp(); + + imp.send_event_simple( + from_glib_borrow::<_, Navigation>(nav).unsafe_cast_ref(), + from_glib_full(event), + ); +} diff --git a/gstreamer-video/src/video_event.rs b/gstreamer-video/src/video_event.rs index f6629fd95..6775ff89d 100644 --- a/gstreamer-video/src/video_event.rs +++ b/gstreamer-video/src/video_event.rs @@ -2,8 +2,13 @@ use crate::{NavigationCommand, NavigationEventType}; use glib::translate::{from_glib, from_glib_full, IntoGlib}; use glib::ToSendValue; +use gst::EventType; use std::mem; +#[cfg(any(feature = "v1_22", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] +use crate::NavigationModifierType; + // FIXME: Copy from gstreamer/src/event.rs macro_rules! event_builder_generic_impl { ($new_fn:expr) => { @@ -357,26 +362,44 @@ const NAVIGATION_EVENT_NAME: &str = "application/x-gst-navigation"; pub enum NavigationEvent { KeyPress { key: String, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType, }, KeyRelease { key: String, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType, }, MouseMove { x: f64, y: f64, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType, }, MouseButtonPress { button: i32, x: f64, y: f64, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType, }, MouseButtonRelease { button: i32, x: f64, y: f64, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType, }, Command { command: NavigationCommand, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType, }, #[cfg(any(feature = "v1_18", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] @@ -385,6 +408,45 @@ pub enum NavigationEvent { y: f64, delta_x: f64, delta_y: f64, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType, + }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + TouchDown { + identifier: u32, + x: f64, + y: f64, + pressure: f64, + modifier_state: NavigationModifierType, + }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + TouchMotion { + identifier: u32, + x: f64, + y: f64, + pressure: f64, + modifier_state: NavigationModifierType, + }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + TouchUp { + identifier: u32, + x: f64, + y: f64, + modifier_state: NavigationModifierType, + }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + TouchFrame { + modifier_state: NavigationModifierType, + }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + TouchCancel { + modifier_state: NavigationModifierType, }, } @@ -394,6 +456,9 @@ impl NavigationEvent { assert_initialized_main_thread!(); Self::KeyPress { key: key.to_string(), + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), } } @@ -402,25 +467,48 @@ impl NavigationEvent { assert_initialized_main_thread!(); Self::KeyRelease { key: key.to_string(), + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), } } #[doc(alias = "gst_navigation_event_new_mouse_move")] pub fn new_mouse_move(x: f64, y: f64) -> NavigationEvent { assert_initialized_main_thread!(); - Self::MouseMove { x, y } + Self::MouseMove { + x, + y, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), + } } #[doc(alias = "gst_navigation_event_new_mouse_button_press")] pub fn new_mouse_button_press(button: i32, x: f64, y: f64) -> NavigationEvent { assert_initialized_main_thread!(); - Self::MouseButtonPress { button, x, y } + Self::MouseButtonPress { + button, + x, + y, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), + } } #[doc(alias = "gst_navigation_event_new_mouse_button_release")] pub fn new_mouse_button_release(button: i32, x: f64, y: f64) -> NavigationEvent { assert_initialized_main_thread!(); - Self::MouseButtonRelease { button, x, y } + Self::MouseButtonRelease { + button, + x, + y, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), + } } #[cfg(any(feature = "v1_18", feature = "dox"))] @@ -433,13 +521,92 @@ impl NavigationEvent { y, delta_x, delta_y, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), } } #[doc(alias = "gst_navigation_event_new_command")] pub fn new_command(command: NavigationCommand) -> NavigationEvent { assert_initialized_main_thread!(); - Self::Command { command } + Self::Command { + command, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), + } + } + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + #[doc(alias = "gst_navigation_event_new_touch_down")] + pub fn new_touch_down(identifier: u32, x: f64, y: f64, pressure: f64) -> NavigationEvent { + assert_initialized_main_thread!(); + Self::TouchDown { + identifier, + x, + y, + pressure, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), + } + } + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + #[doc(alias = "gst_navigation_event_new_touch_motion")] + pub fn new_touch_motion(identifier: u32, x: f64, y: f64, pressure: f64) -> NavigationEvent { + assert_initialized_main_thread!(); + Self::TouchMotion { + identifier, + x, + y, + pressure, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), + } + } + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + #[doc(alias = "gst_navigation_event_new_touch_up")] + pub fn new_touch_up(identifier: u32, x: f64, y: f64) -> NavigationEvent { + assert_initialized_main_thread!(); + Self::TouchUp { + identifier, + x, + y, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), + } + } + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + #[doc(alias = "gst_navigation_event_new_touch_frame")] + pub fn new_touch_frame() -> NavigationEvent { + assert_initialized_main_thread!(); + Self::TouchFrame { + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), + } + } + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + #[doc(alias = "gst_navigation_event_new_touch_cancel")] + pub fn new_touch_cancel() -> NavigationEvent { + assert_initialized_main_thread!(); + Self::TouchCancel { + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state: NavigationModifierType::empty(), + } } #[doc(alias = "gst_navigation_event_get_type")] @@ -448,107 +615,196 @@ impl NavigationEvent { unsafe { from_glib(ffi::gst_navigation_event_get_type(event.as_mut_ptr())) } } + #[doc(alias = "gst_navigation_event_parse_key_event")] #[doc(alias = "gst_navigation_event_parse_mouse_button_event")] - #[doc(alias = "gst_navigation_event_parse_mouse_command")] #[doc(alias = "gst_navigation_event_parse_mouse_scroll_event")] #[doc(alias = "gst_navigation_event_parse_mouse_move_event")] + #[doc(alias = "gst_navigation_event_parse_touch_event")] + #[doc(alias = "gst_navigation_event_parse_touch_up_event")] + #[doc(alias = "gst_navigation_event_parse_command")] pub fn parse(event: &gst::EventRef) -> Result { skip_assert_initialized!(); + if event.type_() != EventType::Navigation { + return Err(glib::bool_error!("Invalid navigation event")); + } let structure = event .structure() - .ok_or_else(|| glib::bool_error!("Invalid mouse event"))?; - Ok(match Self::type_(event) { - NavigationEventType::MouseMove => Self::new_mouse_move( - structure + .ok_or_else(|| glib::bool_error!("Invalid navigation event"))?; + if structure.name() != NAVIGATION_EVENT_NAME { + return Err(glib::bool_error!("Invalid navigation event")); + } + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + let modifier_state = structure + .get("state") + .unwrap_or(NavigationModifierType::empty()); + let event = match Self::type_(event) { + NavigationEventType::MouseMove => NavigationEvent::MouseMove { + x: structure .get("pointer_x") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - structure + y: structure .get("pointer_y") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - ), - NavigationEventType::MouseButtonPress => Self::new_mouse_button_press( - structure + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state, + }, + NavigationEventType::MouseButtonPress => NavigationEvent::MouseButtonPress { + button: structure .get("button") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - structure + x: structure .get("pointer_x") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - structure + y: structure .get("pointer_y") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - ), - NavigationEventType::MouseButtonRelease => Self::new_mouse_button_press( - structure + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state, + }, + NavigationEventType::MouseButtonRelease => NavigationEvent::MouseButtonRelease { + button: structure .get("button") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - structure + x: structure .get("pointer_x") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - structure + y: structure .get("pointer_y") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - ), + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state, + }, #[cfg(any(feature = "v1_18", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] - NavigationEventType::MouseScroll => Self::new_mouse_scroll( - structure + NavigationEventType::MouseScroll => NavigationEvent::MouseScroll { + x: structure .get("pointer_x") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - structure + y: structure .get("pointer_y") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - structure + delta_x: structure .get("delta_pointer_x") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - structure + delta_y: structure .get("delta_pointer_y") .map_err(|_| glib::bool_error!("Invalid mouse event"))?, - ), - NavigationEventType::KeyPress => Self::new_key_press( - structure + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state, + }, + NavigationEventType::KeyPress => NavigationEvent::KeyPress { + key: structure .get("key") .map_err(|_| glib::bool_error!("Invalid key press event"))?, - ), - NavigationEventType::KeyRelease => Self::new_key_release( - structure + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state, + }, + NavigationEventType::KeyRelease => NavigationEvent::KeyRelease { + key: structure .get("key") .map_err(|_| glib::bool_error!("Invalid key press event"))?, - ), - NavigationEventType::Command => Self::new_command( - structure + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state, + }, + NavigationEventType::Command => NavigationEvent::Command { + command: structure .get("command-code") .map_err(|_| glib::bool_error!("Invalid key press event"))?, - ), + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + modifier_state, + }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + NavigationEventType::TouchDown => NavigationEvent::TouchDown { + identifier: structure + .get("identifier") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + x: structure + .get("pointer_x") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + y: structure + .get("pointer_y") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + pressure: structure + .get("pressure") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + modifier_state, + }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + NavigationEventType::TouchMotion => NavigationEvent::TouchMotion { + identifier: structure + .get("identifier") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + x: structure + .get("pointer_x") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + y: structure + .get("pointer_y") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + pressure: structure + .get("pressure") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + modifier_state, + }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + NavigationEventType::TouchUp => NavigationEvent::TouchUp { + identifier: structure + .get("identifier") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + x: structure + .get("pointer_x") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + y: structure + .get("pointer_y") + .map_err(|_| glib::bool_error!("Invalid touch event"))?, + modifier_state, + }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + NavigationEventType::TouchFrame => NavigationEvent::TouchFrame { modifier_state }, + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + NavigationEventType::TouchCancel => NavigationEvent::TouchCancel { modifier_state }, NavigationEventType::Invalid | NavigationEventType::__Unknown(_) => { return Err(glib::bool_error!("Invalid navigation event")) } - }) + }; + Ok(event) } pub fn structure(&self) -> gst::Structure { skip_assert_initialized!(); - match self { - Self::MouseMove { x, y } => gst::Structure::builder(NAVIGATION_EVENT_NAME) + #[allow(unused_mut)] + let mut structure = match self { + Self::MouseMove { x, y, .. } => gst::Structure::builder(NAVIGATION_EVENT_NAME) .field("event", "mouse-move") .field("pointer_x", x) - .field("pointer_y", y) - .build(), - Self::MouseButtonPress { button, x, y } => { + .field("pointer_y", y), + Self::MouseButtonPress { button, x, y, .. } => { gst::Structure::builder(NAVIGATION_EVENT_NAME) .field("event", "mouse-button-press") .field("button", button) .field("pointer_x", x) .field("pointer_y", y) - .build() } - Self::MouseButtonRelease { button, x, y } => { + Self::MouseButtonRelease { button, x, y, .. } => { gst::Structure::builder(NAVIGATION_EVENT_NAME) .field("event", "mouse-button-release") .field("button", button) .field("pointer_x", x) .field("pointer_y", y) - .build() } #[cfg(any(feature = "v1_18", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] @@ -557,26 +813,101 @@ impl NavigationEvent { y, delta_x, delta_y, + .. } => gst::Structure::builder(NAVIGATION_EVENT_NAME) .field("event", "mouse-scroll") .field("pointer_x", x) .field("pointer_y", y) .field("delta_pointer_x", delta_x) - .field("delta_pointer_y", delta_y) - .build(), - Self::KeyPress { key } => gst::Structure::builder(NAVIGATION_EVENT_NAME) + .field("delta_pointer_y", delta_y), + Self::KeyPress { key, .. } => gst::Structure::builder(NAVIGATION_EVENT_NAME) .field("event", "key-press") - .field("key", key) - .build(), - Self::KeyRelease { key } => gst::Structure::builder(NAVIGATION_EVENT_NAME) + .field("key", key), + Self::KeyRelease { key, .. } => gst::Structure::builder(NAVIGATION_EVENT_NAME) .field("event", "key-release") - .field("key", key) - .build(), - Self::Command { command } => gst::Structure::builder(NAVIGATION_EVENT_NAME) + .field("key", key), + Self::Command { command, .. } => gst::Structure::builder(NAVIGATION_EVENT_NAME) .field("event", "command") - .field("command-code", command) - .build(), + .field("command-code", command), + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + Self::TouchDown { + identifier, + x, + y, + pressure, + .. + } => gst::Structure::builder(NAVIGATION_EVENT_NAME) + .field("event", "touch-down") + .field("identifier", identifier) + .field("pointer_x", x) + .field("pointer_y", y) + .field("pressure", pressure), + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + Self::TouchMotion { + identifier, + x, + y, + pressure, + .. + } => gst::Structure::builder(NAVIGATION_EVENT_NAME) + .field("event", "touch-motion") + .field("identifier", identifier) + .field("pointer_x", x) + .field("pointer_y", y) + .field("pressure", pressure), + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + Self::TouchUp { + identifier, x, y, .. + } => gst::Structure::builder(NAVIGATION_EVENT_NAME) + .field("event", "touch-up") + .field("identifier", identifier) + .field("pointer_x", x) + .field("pointer_y", y), + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + Self::TouchFrame { .. } => { + gst::Structure::builder(NAVIGATION_EVENT_NAME).field("event", "touch-frame") + } + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + Self::TouchCancel { .. } => { + gst::Structure::builder(NAVIGATION_EVENT_NAME).field("event", "touch-cancel") + } + }; + + #[cfg(any(feature = "v1_22", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_22")))] + if true { + structure = match self { + Self::MouseMove { modifier_state, .. } => structure.field("state", modifier_state), + Self::MouseButtonPress { modifier_state, .. } => { + structure.field("state", modifier_state) + } + Self::MouseButtonRelease { modifier_state, .. } => { + structure.field("state", modifier_state) + } + Self::MouseScroll { modifier_state, .. } => { + structure.field("state", modifier_state) + } + Self::KeyPress { modifier_state, .. } => structure.field("state", modifier_state), + Self::KeyRelease { modifier_state, .. } => structure.field("state", modifier_state), + Self::Command { modifier_state, .. } => structure.field("state", modifier_state), + Self::TouchDown { modifier_state, .. } => structure.field("state", modifier_state), + Self::TouchMotion { modifier_state, .. } => { + structure.field("state", modifier_state) + } + Self::TouchUp { modifier_state, .. } => structure.field("state", modifier_state), + Self::TouchFrame { modifier_state, .. } => structure.field("state", modifier_state), + Self::TouchCancel { modifier_state, .. } => { + structure.field("state", modifier_state) + } + }; } + + structure.build() } pub fn build(&self) -> gst::Event { @@ -653,5 +984,27 @@ mod tests { let json_event = serde_json::to_string(&navigation_event).unwrap(); assert_eq!(json_event, r#"{"event":"KeyRelease","key":"a"}"#); + + let ev = NavigationEvent::new_touch_motion(0, 1.0, 2.0, 0.5).build(); + let navigation_event = NavigationEvent::parse(&ev).unwrap(); + match &navigation_event { + NavigationEvent::TouchMotion { id, x, y, pressure } => { + assert!(*id == 0 && *x = 1.0 && *y == 2.0 && *pressure == 0.5); + } + _ => unreachable!(), + } + + let json_event = serde_json::to_string(&navigation_event).unwrap(); + assert_eq!( + json_event, + r#"{"event":"TouchMotion","identifier":0,"x":1.0,"y":2.0,"pressure":0.5}"# + ); + + let ev = NavigationEvent::new_touch_cancel().build(); + let navigation_event = NavigationEvent::parse(&ev).unwrap(); + assert!(matches!(&navigation_event, NavigationEvent::TouchCancel {})); + + let json_event = serde_json::to_string(&navigation_event).unwrap(); + assert_eq!(json_event, r#"{"event":"TouchCancel"}"#); } }