From 25819c41fbe61f6a7b03b787b54331981ccc5326 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Fri, 18 Mar 2022 16:59:32 +0000 Subject: [PATCH] navigation: Add support for key Modifiers in all relevant events Part-of: --- .../ext/directfb/dfbvideosink.c | 10 +- .../ext/opencv/gsthanddetect.cpp | 4 +- .../gst-plugins-bad/ext/vulkan/vksink.c | 22 ++- .../sys/d3d11/gstd3d11videosink.cpp | 10 +- .../sys/d3dvideosink/d3dhelpers.c | 27 ++- .../tests/check/pipelines/ipcpipeline.c | 6 +- .../gst-plugins-base/ext/gl/gstglimagesink.c | 41 +++-- .../gst-libs/gst/video/navigation.c | 154 +++++++++++++----- .../gst-libs/gst/video/navigation.h | 95 +++++++++-- .../gst-plugins-base/sys/ximage/ximagesink.c | 27 +-- .../sys/xvimage/xvimagesink.c | 23 +-- .../tests/check/libs/navigation.c | 13 +- .../tests/examples/playback/playback-test.c | 12 +- .../ext/gtk/gtkgstbasewidget.c | 23 ++- subprojects/gst-plugins-good/ext/qt/qtitem.cc | 46 +++++- .../tests/check/elements/vaapipostproc.c | 6 +- 16 files changed, 378 insertions(+), 141 deletions(-) diff --git a/subprojects/gst-plugins-bad/ext/directfb/dfbvideosink.c b/subprojects/gst-plugins-bad/ext/directfb/dfbvideosink.c index 6c60f9772a..7b88930c63 100644 --- a/subprojects/gst-plugins-bad/ext/directfb/dfbvideosink.c +++ b/subprojects/gst-plugins-bad/ext/directfb/dfbvideosink.c @@ -606,7 +606,8 @@ gst_dfbvideosink_event_thread (GstDfbVideoSink * dfbvideosink) GST_DEBUG_OBJECT (dfbvideosink, "key press event %c !", event.input.key_symbol); gst_dfbvideosink_navigation_send_event - (gst_navigation_event_new_key_press ("prout")); + (gst_navigation_event_new_key_press ("prout", + GST_NAVIGATION_MODIFIER_NONE)); } } else if (event.input.type == DIET_BUTTONPRESS) { gint x, y; @@ -618,7 +619,7 @@ gst_dfbvideosink_event_thread (GstDfbVideoSink * dfbvideosink) gst_dfbvideosink_navigation_send_event (gst_navigation_event_new_mouse_button_press (event.input.button, - x, y)); + x, y, GST_NAVIGATION_MODIFIER_NONE)); } else if (event.input.type == DIET_BUTTONRELEASE) { gint x, y; @@ -629,13 +630,14 @@ gst_dfbvideosink_event_thread (GstDfbVideoSink * dfbvideosink) gst_dfbvideosink_navigation_send_event (gst_navigation_event_new_mouse_button_release - (event.input.button, x, y)); + (event.input.button, x, y, GST_NAVIGATION_MODIFIER_NONE)); } else if (event.input.type == DIET_AXISMOTION) { gint x, y; dfbvideosink->layer->GetCursorPosition (dfbvideosink->layer, &x, &y); gst_dfbvideosink_navigation_send_event - (gst_navigation_event_new_mouse_move (x, y)); + (gst_navigation_event_new_mouse_move (x, y, + GST_NAVIGATION_MODIFIER_NONE)); } else { GST_WARNING_OBJECT (dfbvideosink, "unhandled event type %d", event.input.type); diff --git a/subprojects/gst-plugins-bad/ext/opencv/gsthanddetect.cpp b/subprojects/gst-plugins-bad/ext/opencv/gsthanddetect.cpp index fa2bfecd42..373c92e4b4 100644 --- a/subprojects/gst-plugins-bad/ext/opencv/gsthanddetect.cpp +++ b/subprojects/gst-plugins-bad/ext/opencv/gsthanddetect.cpp @@ -482,7 +482,7 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, gst_handdetect_navigation_send_event (GST_NAVIGATION (filter), gst_navigation_event_new_mouse_move ( (double) (filter->best_r->x + filter->best_r->width * 0.5), - (double) (filter->best_r->y + filter->best_r->height * 0.5))); + (double) (filter->best_r->y + filter->best_r->height * 0.5), GST_NAVIGATION_MODIFIER_NONE)); #endif } @@ -571,7 +571,7 @@ gst_handdetect_transform_ip (GstOpencvVideoFilter * transform, gst_handdetect_navigation_send_event (GST_NAVIGATION (filter), gst_navigation_event_new_mouse_move ( (double) (filter->best_r->x + filter->best_r->width * 0.5), - (double) (filter->best_r->y + filter->best_r->height * 0.5))); + (double) (filter->best_r->y + filter->best_r->height * 0.5), GST_NAVIGATION_MODIFIER_NONE)); /* or use another way to send upstream navigation event for debug * diff --git a/subprojects/gst-plugins-bad/ext/vulkan/vksink.c b/subprojects/gst-plugins-bad/ext/vulkan/vksink.c index 9be1d5bd8b..ec523a0d22 100644 --- a/subprojects/gst-plugins-bad/ext/vulkan/vksink.c +++ b/subprojects/gst-plugins-bad/ext/vulkan/vksink.c @@ -682,10 +682,15 @@ gst_vulkan_sink_key_event_cb (GstVulkanWindow * window, char *event_name, char GstEvent *event = NULL; GST_DEBUG_OBJECT (vk_sink, "event %s key %s pressed", event_name, key_string); + /* FIXME: Add support for modifiers */ if (0 == g_strcmp0 ("key-press", event_name)) - event = gst_navigation_event_new_key_press (key_string); + event = + gst_navigation_event_new_key_press (key_string, + GST_NAVIGATION_MODIFIER_NONE); else if (0 == g_strcmp0 ("key-release", event_name)) - event = gst_navigation_event_new_key_release (key_string); + event = + gst_navigation_event_new_key_release (key_string, + GST_NAVIGATION_MODIFIER_NONE); if (event) gst_navigation_send_event_simple (GST_NAVIGATION (vk_sink), event); @@ -697,13 +702,20 @@ gst_vulkan_sink_mouse_event_cb (GstVulkanWindow * window, char *event_name, { GstEvent *event = NULL; + /* FIXME: Add support for modifiers */ GST_DEBUG_OBJECT (vk_sink, "event %s at %g, %g", event_name, posx, posy); if (0 == g_strcmp0 ("mouse-button-press", event_name)) - event = gst_navigation_event_new_mouse_button_press (button, posx, posy); + event = + gst_navigation_event_new_mouse_button_press (button, posx, posy, + GST_NAVIGATION_MODIFIER_NONE); else if (0 == g_strcmp0 ("mouse-button-release", event_name)) - event = gst_navigation_event_new_mouse_button_release (button, posx, posy); + event = + gst_navigation_event_new_mouse_button_release (button, posx, posy, + GST_NAVIGATION_MODIFIER_NONE); else if (0 == g_strcmp0 ("mouse-move", event_name)) - event = gst_navigation_event_new_mouse_move (posx, posy); + event = + gst_navigation_event_new_mouse_move (posx, posy, + GST_NAVIGATION_MODIFIER_NONE); if (event) gst_navigation_send_event_simple (GST_NAVIGATION (vk_sink), event); diff --git a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp index e9d4aac2a9..02ea4f0ccc 100644 --- a/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp +++ b/subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp @@ -692,9 +692,9 @@ gst_d3d11_video_sink_key_event (GstD3D11Window * window, const gchar * event, if (self->enable_navigation_events) { GST_LOG_OBJECT (self, "send key event %s, key %s", event, key); if (0 == g_strcmp0 ("key-press", event)) - key_event = gst_navigation_event_new_key_press (key); + key_event = gst_navigation_event_new_key_press (key, GST_NAVIGATION_MODIFIER_NONE); else if (0 == g_strcmp0 ("key-release", event)) - key_event = gst_navigation_event_new_key_release (key); + key_event = gst_navigation_event_new_key_release (key, GST_NAVIGATION_MODIFIER_NONE); if (event) gst_navigation_send_event_simple (GST_NAVIGATION (self), key_event); @@ -711,11 +711,11 @@ gst_d3d11_video_mouse_key_event (GstD3D11Window * window, const gchar * event, GST_LOG_OBJECT (self, "send mouse event %s, button %d (%.1f, %.1f)", event, button, x, y); if (0 == g_strcmp0 ("mouse-button-press", event)) - mouse_event = gst_navigation_event_new_mouse_button_press (button, x, y); + mouse_event = gst_navigation_event_new_mouse_button_press (button, x, y, GST_NAVIGATION_MODIFIER_NONE); else if (0 == g_strcmp0 ("mouse-button-release", event)) - mouse_event = gst_navigation_event_new_mouse_button_release (button, x, y); + mouse_event = gst_navigation_event_new_mouse_button_release (button, x, y, GST_NAVIGATION_MODIFIER_NONE); else if (0 == g_strcmp0 ("mouse-move", event)) - mouse_event = gst_navigation_event_new_mouse_move (x, y); + mouse_event = gst_navigation_event_new_mouse_move (x, y, GST_NAVIGATION_MODIFIER_NONE); if (event) gst_navigation_send_event_simple (GST_NAVIGATION (self), mouse_event); diff --git a/subprojects/gst-plugins-bad/sys/d3dvideosink/d3dhelpers.c b/subprojects/gst-plugins-bad/sys/d3dvideosink/d3dhelpers.c index 960023a5ad..99e8408882 100644 --- a/subprojects/gst-plugins-bad/sys/d3dvideosink/d3dhelpers.c +++ b/subprojects/gst-plugins-bad/sys/d3dvideosink/d3dhelpers.c @@ -2141,10 +2141,12 @@ d3d_wnd_proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (utfrep) { if (message == WM_KEYDOWN) gst_navigation_send_event_simple (GST_NAVIGATION (sink), - gst_navigation_event_new_key_press (utfrep)); + gst_navigation_event_new_key_press (utfrep, + GST_NAVIGATION_MODIFIER_NONE)); else if (message == WM_KEYUP) gst_navigation_send_event_simple (GST_NAVIGATION (sink), - gst_navigation_event_new_key_release (utfrep)); + gst_navigation_event_new_key_release (utfrep, + GST_NAVIGATION_MODIFIER_NONE)); g_free (utfrep); } } @@ -2164,31 +2166,38 @@ d3d_wnd_proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) switch (message) { case WM_MOUSEMOVE: gst_navigation_send_event_simple (GST_NAVIGATION (sink), - gst_navigation_event_new_mouse_move (x, y)); + gst_navigation_event_new_mouse_move (x, y, + GST_NAVIGATION_MODIFIER_NONE)); break; case WM_LBUTTONDOWN: gst_navigation_send_event_simple (GST_NAVIGATION (sink), - gst_navigation_event_new_mouse_button_press (1, x, y)); + gst_navigation_event_new_mouse_button_press (1, x, y, + GST_NAVIGATION_MODIFIER_NONE)); break; case WM_LBUTTONUP: gst_navigation_send_event_simple (GST_NAVIGATION (sink), - gst_navigation_event_new_mouse_button_release (1, x, y)); + gst_navigation_event_new_mouse_button_release (1, x, y, + GST_NAVIGATION_MODIFIER_NONE)); break; case WM_RBUTTONDOWN: gst_navigation_send_event_simple (GST_NAVIGATION (sink), - gst_navigation_event_new_mouse_button_press (2, x, y)); + gst_navigation_event_new_mouse_button_press (2, x, y, + GST_NAVIGATION_MODIFIER_NONE)); break; case WM_RBUTTONUP: gst_navigation_send_event_simple (GST_NAVIGATION (sink), - gst_navigation_event_new_mouse_button_release (2, x, y)); + gst_navigation_event_new_mouse_button_release (2, x, y, + GST_NAVIGATION_MODIFIER_NONE)); break; case WM_MBUTTONDOWN: gst_navigation_send_event_simple (GST_NAVIGATION (sink), - gst_navigation_event_new_mouse_button_press (3, x, y)); + gst_navigation_event_new_mouse_button_press (3, x, y, + GST_NAVIGATION_MODIFIER_NONE)); break; case WM_MBUTTONUP: gst_navigation_send_event_simple (GST_NAVIGATION (sink), - gst_navigation_event_new_mouse_button_release (3, x, y)); + gst_navigation_event_new_mouse_button_release (3, x, y, + GST_NAVIGATION_MODIFIER_NONE)); break; default: break; diff --git a/subprojects/gst-plugins-bad/tests/check/pipelines/ipcpipeline.c b/subprojects/gst-plugins-bad/tests/check/pipelines/ipcpipeline.c index d28735df74..ed2c8b9fa7 100644 --- a/subprojects/gst-plugins-bad/tests/check/pipelines/ipcpipeline.c +++ b/subprojects/gst-plugins-bad/tests/check/pipelines/ipcpipeline.c @@ -3077,10 +3077,12 @@ send_navigation_event (const GValue * v, gpointer user_data) switch (d->step) { case TEST_NAV_MOUSE_MOVE: - e = gst_navigation_event_new_mouse_move (4.7, 0.1); + e = gst_navigation_event_new_mouse_move (4.7, 0.1, + GST_NAVIGATION_MODIFIER_NONE); break; case TEST_NAV_KEY_PRESS: - e = gst_navigation_event_new_key_press ("Left"); + e = gst_navigation_event_new_key_press ("Left", + GST_NAVIGATION_MODIFIER_NONE); break; } diff --git a/subprojects/gst-plugins-base/ext/gl/gstglimagesink.c b/subprojects/gst-plugins-base/ext/gl/gstglimagesink.c index 99fe170656..f0d1fabd62 100644 --- a/subprojects/gst-plugins-base/ext/gl/gstglimagesink.c +++ b/subprojects/gst-plugins-base/ext/gl/gstglimagesink.c @@ -637,8 +637,10 @@ gst_glimage_sink_navigation_send_event (GstNavigation * navigation, _display_scroll_value_to_stream_scroll_value (sink, dx, dy, &stream_dx, &stream_dy); + /* FIXME: Add support for NavigationModifier */ gst_event_replace (&event, - gst_navigation_event_new_mouse_scroll (x, y, stream_dx, stream_dy)); + gst_navigation_event_new_mouse_scroll (x, y, stream_dx, stream_dy, + GST_NAVIGATION_MODIFIER_NONE)); } gst_event_ref (event); @@ -946,10 +948,16 @@ gst_glimage_sink_key_event_cb (GstGLWindow * window, char *event_name, char GstEvent *event = NULL; GST_DEBUG_OBJECT (gl_sink, "event %s key %s pressed", event_name, key_string); - if (0 == g_strcmp0 ("key-press", event_name)) - event = gst_navigation_event_new_key_press (key_string); - else if (0 == g_strcmp0 ("key-release", event_name)) - event = gst_navigation_event_new_key_release (key_string); + // FIXME: Add support for modifiers + if (0 == g_strcmp0 ("key-press", event_name)) { + event = + gst_navigation_event_new_key_press (key_string, + GST_NAVIGATION_MODIFIER_NONE); + } else if (0 == g_strcmp0 ("key-release", event_name)) { + event = + gst_navigation_event_new_key_release (key_string, + GST_NAVIGATION_MODIFIER_NONE); + } if (event) gst_navigation_send_event_simple (GST_NAVIGATION (gl_sink), event); @@ -962,12 +970,20 @@ gst_glimage_sink_mouse_event_cb (GstGLWindow * window, char *event_name, GstEvent *event = NULL; GST_DEBUG_OBJECT (gl_sink, "event %s at %g, %g", event_name, posx, posy); - if (0 == g_strcmp0 ("mouse-button-press", event_name)) - event = gst_navigation_event_new_mouse_button_press (button, posx, posy); - else if (0 == g_strcmp0 ("mouse-button-release", event_name)) - event = gst_navigation_event_new_mouse_button_release (button, posx, posy); - else if (0 == g_strcmp0 ("mouse-move", event_name)) - event = gst_navigation_event_new_mouse_move (posx, posy); + // FIXME: Add support for modifiers + if (0 == g_strcmp0 ("mouse-button-press", event_name)) { + event = + gst_navigation_event_new_mouse_button_press (button, posx, posy, + GST_NAVIGATION_MODIFIER_NONE); + } else if (0 == g_strcmp0 ("mouse-button-release", event_name)) { + event = + gst_navigation_event_new_mouse_button_release (button, posx, posy, + GST_NAVIGATION_MODIFIER_NONE); + } else if (0 == g_strcmp0 ("mouse-move", event_name)) { + event = + gst_navigation_event_new_mouse_move (posx, posy, + GST_NAVIGATION_MODIFIER_NONE); + } if (event) gst_navigation_send_event_simple (GST_NAVIGATION (gl_sink), event); @@ -981,7 +997,8 @@ gst_glimage_sink_mouse_scroll_event_cb (GstGLWindow * window, { GST_DEBUG_OBJECT (gl_sink, "event scroll at %g, %g", posx, posy); gst_navigation_send_event_simple (GST_NAVIGATION (gl_sink), - gst_navigation_event_new_mouse_scroll (posx, posy, delta_x, delta_y)); + gst_navigation_event_new_mouse_scroll (posx, posy, delta_x, delta_y, + GST_NAVIGATION_MODIFIER_NONE)); } static void diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/navigation.c b/subprojects/gst-plugins-base/gst-libs/gst/video/navigation.c index a187186353..12fc638bf2 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/navigation.c +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/navigation.c @@ -26,27 +26,29 @@ * @short_description: Interface for creating, sending and parsing navigation * events. * - * The Navigation interface is used for creating and injecting navigation related - * events such as mouse button presses, cursor motion and key presses. The associated - * library also provides methods for parsing received events, and for sending and - * receiving navigation related bus events. One main usecase is DVD menu navigation. + * The Navigation interface is used for creating and injecting navigation + * related events such as mouse button presses, cursor motion and key presses. + * The associated library also provides methods for parsing received events, and + * for sending and receiving navigation related bus events. One main usecase is + * DVD menu navigation. * * The main parts of the API are: * - * * The GstNavigation interface, implemented by elements which provide an application - * with the ability to create and inject navigation events into the pipeline. - * * GstNavigation event handling API. GstNavigation events are created in response to - * calls on a GstNavigation interface implementation, and sent in the pipeline. Upstream - * elements can use the navigation event API functions to parse the contents of received - * messages. + * * The GstNavigation interface, implemented by elements which provide an + * application with the ability to create and inject navigation events into + * the pipeline. + * * GstNavigation event handling API. GstNavigation events are created in + * response to calls on a GstNavigation interface implementation, and sent in + * the pipeline. Upstream elements can use the navigation event API functions + * to parse the contents of received messages. * - * * GstNavigation message handling API. GstNavigation messages may be sent on the message - * bus to inform applications of navigation related changes in the pipeline, such as the - * mouse moving over a clickable region, or the set of available angles changing. - * - * The GstNavigation message functions provide functions for creating and parsing - * custom bus messages for signaling GstNavigation changes. + * * GstNavigation message handling API. GstNavigation messages may be sent on + * the message bus to inform applications of navigation related changes in the + * pipeline, such as the mouse moving over a clickable region, or the set of + * available angles changing. * + * The GstNavigation message functions provide functions for creating and + * parsing custom bus messages for signaling GstNavigation changes. */ #ifdef HAVE_CONFIG_H @@ -801,6 +803,8 @@ gst_navigation_event_get_type (GstEvent * event) /** * gst_navigation_event_new_key_press: * @key: A string identifying the key press. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event for the given key press. * @@ -809,16 +813,19 @@ gst_navigation_event_get_type (GstEvent * event) * Since: 1.22 */ GstEvent * -gst_navigation_event_new_key_press (const gchar * key) +gst_navigation_event_new_key_press (const gchar * key, + GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, "key-press", "key", G_TYPE_STRING, key, - NULL)); + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** * gst_navigation_event_new_key_release: * @key: A string identifying the released key. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event for the given key release. * @@ -827,11 +834,12 @@ gst_navigation_event_new_key_press (const gchar * key) * Since: 1.22 */ GstEvent * -gst_navigation_event_new_key_release (const gchar * key) +gst_navigation_event_new_key_release (const gchar * key, + GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, "key-release", "key", G_TYPE_STRING, key, - NULL)); + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** @@ -839,6 +847,8 @@ gst_navigation_event_new_key_release (const gchar * key) * @button: The number of the pressed mouse button. * @x: The x coordinate of the mouse cursor. * @y: The y coordinate of the mouse cursor. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event for the given key mouse button press. * @@ -847,12 +857,14 @@ gst_navigation_event_new_key_release (const gchar * key) * Since: 1.22 */ GstEvent * -gst_navigation_event_new_mouse_button_press (gint button, gdouble x, gdouble y) +gst_navigation_event_new_mouse_button_press (gint button, gdouble x, gdouble y, + GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, "mouse-button-press", "button", G_TYPE_INT, button, "pointer_x", G_TYPE_DOUBLE, x, - "pointer_y", G_TYPE_DOUBLE, y, NULL)); + "pointer_y", G_TYPE_DOUBLE, y, + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** @@ -860,6 +872,8 @@ gst_navigation_event_new_mouse_button_press (gint button, gdouble x, gdouble y) * @button: The number of the released mouse button. * @x: The x coordinate of the mouse cursor. * @y: The y coordinate of the mouse cursor. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event for the given key mouse button release. * @@ -869,18 +883,21 @@ gst_navigation_event_new_mouse_button_press (gint button, gdouble x, gdouble y) */ GstEvent * gst_navigation_event_new_mouse_button_release (gint button, gdouble x, - gdouble y) + gdouble y, GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, "mouse-button-release", "button", G_TYPE_INT, button, "pointer_x", G_TYPE_DOUBLE, x, - "pointer_y", G_TYPE_DOUBLE, y, NULL)); + "pointer_y", G_TYPE_DOUBLE, y, + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** * gst_navigation_event_new_mouse_move: * @x: The x coordinate of the mouse cursor. * @y: The y coordinate of the mouse cursor. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event for the new mouse location. * @@ -889,11 +906,14 @@ gst_navigation_event_new_mouse_button_release (gint button, gdouble x, * Since: 1.22 */ GstEvent * -gst_navigation_event_new_mouse_move (gdouble x, gdouble y) +gst_navigation_event_new_mouse_move (gdouble x, gdouble y, + GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, "mouse-move", - "pointer_x", G_TYPE_DOUBLE, x, "pointer_y", G_TYPE_DOUBLE, y, NULL)); + "pointer_x", G_TYPE_DOUBLE, x, + "pointer_y", G_TYPE_DOUBLE, y, + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** @@ -902,6 +922,8 @@ gst_navigation_event_new_mouse_move (gdouble x, gdouble y) * @y: The y coordinate of the mouse cursor. * @delta_x: The x component of the scroll movement. * @delta_y: The y component of the scroll movement. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event for the mouse scroll. * @@ -911,13 +933,14 @@ gst_navigation_event_new_mouse_move (gdouble x, gdouble y) */ GstEvent * gst_navigation_event_new_mouse_scroll (gdouble x, gdouble y, gdouble delta_x, - gdouble delta_y) + gdouble delta_y, GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, "mouse-scroll", "pointer_x", G_TYPE_DOUBLE, x, "pointer_y", G_TYPE_DOUBLE, y, "delta_pointer_x", G_TYPE_DOUBLE, delta_x, - "delta_pointer_y", G_TYPE_DOUBLE, delta_y, NULL)); + "delta_pointer_y", G_TYPE_DOUBLE, delta_y, + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** @@ -947,6 +970,8 @@ gst_navigation_event_new_command (GstNavigationCommand command) * @y: The y coordinate of the new touch point. * @pressure: Pressure data of the touch point, from 0.0 to 1.0, or NaN if no * data is available. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event for an added touch point. * @@ -956,14 +981,15 @@ gst_navigation_event_new_command (GstNavigationCommand command) */ GstEvent * gst_navigation_event_new_touch_down (guint identifier, gdouble x, gdouble y, - gdouble pressure) + gdouble pressure, GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, "touch-down", "identifier", G_TYPE_UINT, identifier, "pointer_x", G_TYPE_DOUBLE, x, "pointer_y", G_TYPE_DOUBLE, y, - "pressure", G_TYPE_DOUBLE, pressure, NULL)); + "pressure", G_TYPE_DOUBLE, pressure, + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** @@ -974,6 +1000,8 @@ gst_navigation_event_new_touch_down (guint identifier, gdouble x, gdouble y, * @y: The y coordinate of the touch point. * @pressure: Pressure data of the touch point, from 0.0 to 1.0, or NaN if no * data is available. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event for a moved touch point. * @@ -983,14 +1011,15 @@ gst_navigation_event_new_touch_down (guint identifier, gdouble x, gdouble y, */ GstEvent * gst_navigation_event_new_touch_motion (guint identifier, gdouble x, gdouble y, - gdouble pressure) + gdouble pressure, GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, "touch-motion", "identifier", G_TYPE_UINT, identifier, "pointer_x", G_TYPE_DOUBLE, x, "pointer_y", G_TYPE_DOUBLE, y, - "pressure", G_TYPE_DOUBLE, pressure, NULL)); + "pressure", G_TYPE_DOUBLE, pressure, + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** @@ -1000,6 +1029,8 @@ gst_navigation_event_new_touch_motion (guint identifier, gdouble x, gdouble y, * after sending this event. * @x: The x coordinate of the touch point. * @y: The y coordinate of the touch point. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event for a removed touch point. * @@ -1008,16 +1039,20 @@ gst_navigation_event_new_touch_motion (guint identifier, gdouble x, gdouble y, * Since: 1.22 */ GstEvent * -gst_navigation_event_new_touch_up (guint identifier, gdouble x, gdouble y) +gst_navigation_event_new_touch_up (guint identifier, gdouble x, gdouble y, + GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, "touch-up", "identifier", G_TYPE_UINT, identifier, - "pointer_x", G_TYPE_DOUBLE, x, "pointer_y", G_TYPE_DOUBLE, y, NULL)); + "pointer_x", G_TYPE_DOUBLE, x, "pointer_y", G_TYPE_DOUBLE, y, + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** * gst_navigation_event_new_touch_frame: + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event signalling the end of a touch frame. Touch * frames signal that all previous down, motion and up events not followed by @@ -1028,15 +1063,18 @@ gst_navigation_event_new_touch_up (guint identifier, gdouble x, gdouble y) * Since: 1.22 */ GstEvent * -gst_navigation_event_new_touch_frame (void) +gst_navigation_event_new_touch_frame (GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, - "event", G_TYPE_STRING, "touch-frame", NULL)); + "event", G_TYPE_STRING, "touch-frame", + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** * gst_navigation_event_new_touch_cancel: + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). * * Create a new navigation event signalling that all currently active touch * points are cancelled and should be discarded. For example, under Wayland @@ -1048,10 +1086,11 @@ gst_navigation_event_new_touch_frame (void) * Since: 1.22 */ GstEvent * -gst_navigation_event_new_touch_cancel (void) +gst_navigation_event_new_touch_cancel (GstNavigationModifierType state) { return gst_event_new_navigation (gst_structure_new (GST_NAVIGATION_EVENT_NAME, - "event", G_TYPE_STRING, "touch-cancel", NULL)); + "event", G_TYPE_STRING, "touch-cancel", + "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, NULL)); } /** @@ -1060,6 +1099,11 @@ gst_navigation_event_new_touch_cancel (void) * @key: (out) (optional) (transfer none): A pointer to a location to receive * the string identifying the key press. The returned string is owned by the * event, and valid only until the event is unreffed. + * + * Note: Modifier keys (as defined in #GstNavigationModifierType) + * [press](GST_NAVIGATION_EVENT_KEY_PRESS) and + * [release](GST_NAVIGATION_KEY_PRESS) events are generated even if those states are + * present on all other related events */ gboolean gst_navigation_event_parse_key_event (GstEvent * event, const gchar ** key) @@ -1396,3 +1440,37 @@ gst_navigation_event_set_coordinates (GstEvent * event, gdouble x, gdouble y) return TRUE; } + + +/** + * gst_navigation_event_parse_state: + * @event: The #GstEvent to modify. + * @state: a bit-mask representing the state of the modifier keys (e.g. Control, + * Shift and Alt). + * + * Returns: TRUE if the event is a #GstNavigation event with associated + * modifiers state, otherwise FALSE. + * + * Since: 1.22 + */ +gboolean +gst_navigation_event_parse_state (GstEvent * event, + GstNavigationModifierType * state) +{ + GstNavigationEventType e_type; + const GstStructure *s; + + g_return_val_if_fail (GST_IS_EVENT (event), FALSE); + + e_type = gst_navigation_event_get_type (event); + if (e_type == GST_NAVIGATION_EVENT_COMMAND) { + return FALSE; + } + + s = gst_event_get_structure (event); + if (!gst_structure_get (s, "state", GST_TYPE_NAVIGATION_MODIFIER_TYPE, state, + NULL)) + *state = GST_NAVIGATION_MODIFIER_NONE; + + return TRUE; +} diff --git a/subprojects/gst-plugins-base/gst-libs/gst/video/navigation.h b/subprojects/gst-plugins-base/gst-libs/gst/video/navigation.h index e789c25a32..bb922f3b58 100644 --- a/subprojects/gst-plugins-base/gst-libs/gst/video/navigation.h +++ b/subprojects/gst-plugins-base/gst-libs/gst/video/navigation.h @@ -40,6 +40,65 @@ G_BEGIN_DECLS typedef struct _GstNavigation GstNavigation; typedef struct _GstNavigationInterface GstNavigationInterface; +/** + * GstNavigationModifierType: + * @GST_NAVIGATION_MODIFIER_SHIFT_MASK: the Shift key. + * @GST_NAVIGATION_MODIFIER_CONTROL_MASK: the Control key. + * @GST_NAVIGATION_MODIFIER_ALT_MASK: the fourth modifier key + * @GST_NAVIGATION_MODIFIER_BUTTON1_MASK: the first mouse button (usually the left button). + * @GST_NAVIGATION_MODIFIER_BUTTON2_MASK: the second mouse button (usually the right button). + * @GST_NAVIGATION_MODIFIER_BUTTON3_MASK: the third mouse button (usually the mouse wheel button or middle button). + * @GST_NAVIGATION_MODIFIER_BUTTON4_MASK: the fourth mouse button (typically the "Back" button). + * @GST_NAVIGATION_MODIFIER_BUTTON5_MASK: the fifth mouse button (typically the "forward" button). + * @GST_NAVIGATION_MODIFIER_SUPER_MASK: the Super modifier + * @GST_NAVIGATION_MODIFIER_HYPER_MASK: the Hyper modifier + * @GST_NAVIGATION_MODIFIER_META_MASK: the Meta modifier + * @GST_NAVIGATION_MODIFIER_MASK: A mask covering all entries in #GdkModifierType. + * + * Flags to indicate the state of modifier keys and mouse buttons + * in events. + * + * Typical modifier keys are Shift, Control, Meta, Super, Hyper, Alt, Compose, + * Apple, CapsLock or ShiftLock. + * + * Since: 1.22 + */ +typedef enum +{ + GST_NAVIGATION_MODIFIER_NONE = 0, + GST_NAVIGATION_MODIFIER_SHIFT_MASK = 1 << 0, + GST_NAVIGATION_MODIFIER_LOCK_MASK = 1 << 1, + GST_NAVIGATION_MODIFIER_CONTROL_MASK = 1 << 2, + GST_NAVIGATION_MODIFIER_ALT_MASK = 1 << 3, + + GST_NAVIGATION_MODIFIER_BUTTON1_MASK = 1 << 8, + GST_NAVIGATION_MODIFIER_BUTTON2_MASK = 1 << 9, + GST_NAVIGATION_MODIFIER_BUTTON3_MASK = 1 << 10, + GST_NAVIGATION_MODIFIER_BUTTON4_MASK = 1 << 11, + GST_NAVIGATION_MODIFIER_BUTTON5_MASK = 1 << 12, + + GST_NAVIGATION_MODIFIER_SUPER_MASK = 1 << 26, + GST_NAVIGATION_MODIFIER_HYPER_MASK = 1 << 27, + GST_NAVIGATION_MODIFIER_META_MASK = 1 << 28, + + GST_NAVIGATION_MODIFIER_MASK = ( + GST_NAVIGATION_MODIFIER_NONE | + GST_NAVIGATION_MODIFIER_SHIFT_MASK | + GST_NAVIGATION_MODIFIER_LOCK_MASK | + GST_NAVIGATION_MODIFIER_CONTROL_MASK | + GST_NAVIGATION_MODIFIER_ALT_MASK | + GST_NAVIGATION_MODIFIER_BUTTON1_MASK | + GST_NAVIGATION_MODIFIER_BUTTON2_MASK | + GST_NAVIGATION_MODIFIER_BUTTON3_MASK | + GST_NAVIGATION_MODIFIER_BUTTON4_MASK | + GST_NAVIGATION_MODIFIER_BUTTON5_MASK | + GST_NAVIGATION_MODIFIER_SUPER_MASK | + GST_NAVIGATION_MODIFIER_HYPER_MASK | + GST_NAVIGATION_MODIFIER_META_MASK + ) + +} GstNavigationModifierType; + /** * GstNavigationInterface: * @iface: the parent interface @@ -381,25 +440,32 @@ GST_VIDEO_API GstNavigationEventType gst_navigation_event_get_type (GstEvent *event); GST_VIDEO_API -GstEvent* gst_navigation_event_new_key_press (const gchar * key) G_GNUC_MALLOC; +GstEvent* gst_navigation_event_new_key_press (const gchar * key, + GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API -GstEvent* gst_navigation_event_new_key_release (const gchar * key) G_GNUC_MALLOC; +GstEvent* gst_navigation_event_new_key_release (const gchar * key, + GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API GstEvent* gst_navigation_event_new_mouse_button_press (gint button, gdouble x, - gdouble y) G_GNUC_MALLOC; + gdouble y, + GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API GstEvent* gst_navigation_event_new_mouse_button_release (gint button, gdouble x, - gdouble y) G_GNUC_MALLOC; + gdouble y, + GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API -GstEvent* gst_navigation_event_new_mouse_move (gdouble x, gdouble y) G_GNUC_MALLOC; +GstEvent* gst_navigation_event_new_mouse_move (gdouble x, + gdouble y, + GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API GstEvent* gst_navigation_event_new_mouse_scroll (gdouble x, gdouble y, - gdouble delta_x, gdouble delta_y) G_GNUC_MALLOC; + gdouble delta_x, gdouble delta_y, + GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API GstEvent* gst_navigation_event_new_command (GstNavigationCommand command) G_GNUC_MALLOC; @@ -407,22 +473,25 @@ GstEvent* gst_navigation_event_new_command (GstNavigationComm GST_VIDEO_API GstEvent* gst_navigation_event_new_touch_down (guint identifier, gdouble x, gdouble y, - gdouble pressure) G_GNUC_MALLOC; + gdouble pressure, + GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API GstEvent* gst_navigation_event_new_touch_motion (guint identifier, gdouble x, gdouble y, - gdouble pressure) G_GNUC_MALLOC; + gdouble pressure, + GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API GstEvent* gst_navigation_event_new_touch_up (guint identifier, - gdouble x, gdouble y) G_GNUC_MALLOC; + gdouble x, gdouble y, + GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API -GstEvent* gst_navigation_event_new_touch_frame (void) G_GNUC_MALLOC; +GstEvent* gst_navigation_event_new_touch_frame (GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API -GstEvent* gst_navigation_event_new_touch_cancel (void) G_GNUC_MALLOC; +GstEvent* gst_navigation_event_new_touch_cancel (GstNavigationModifierType state) G_GNUC_MALLOC; GST_VIDEO_API gboolean gst_navigation_event_parse_key_event (GstEvent *event, @@ -490,6 +559,10 @@ GST_VIDEO_API void gst_navigation_send_event_simple (GstNavigation *navigation, GstEvent *event); +GST_VIDEO_API +gboolean gst_navigation_event_parse_state (GstEvent *event, + GstNavigationModifierType *state); + G_END_DECLS #endif /* __GST_NAVIGATION_H__ */ diff --git a/subprojects/gst-plugins-base/sys/ximage/ximagesink.c b/subprojects/gst-plugins-base/sys/ximage/ximagesink.c index f983a3c989..a72e3071fe 100644 --- a/subprojects/gst-plugins-base/sys/ximage/ximagesink.c +++ b/subprojects/gst-plugins-base/sys/ximage/ximagesink.c @@ -551,7 +551,7 @@ gst_x_image_sink_xwindow_new (GstXImageSink * ximagesink, gint width, ximagesink->xcontext->root, 0, 0, width, height, 0, 0, ximagesink->xcontext->black); - /* We have to do that to prevent X from redrawing the background on + /* We have to do that to prevent X from redrawing the background on ConfigureNotify. This takes away flickering of video when resizing. */ XSetWindowBackgroundPixmap (ximagesink->xcontext->disp, xwindow->win, None); @@ -693,6 +693,7 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) gint pointer_x = 0, pointer_y = 0; gboolean pointer_moved = FALSE, touch_frame_open = FALSE; gboolean exposed = FALSE, configured = FALSE; + GstNavigationModifierType state = GST_NAVIGATION_MODIFIER_NONE; g_return_if_fail (GST_IS_X_IMAGE_SINK (ximagesink)); @@ -725,7 +726,8 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) GST_DEBUG ("ximagesink pointer moved over window at %d,%d", pointer_x, pointer_y); gst_navigation_send_event_simple (GST_NAVIGATION (ximagesink), - gst_navigation_event_new_mouse_move (pointer_x, pointer_y)); + gst_navigation_event_new_mouse_move (pointer_x, pointer_y, + e.xmotion.state)); g_mutex_lock (&ximagesink->flow_lock); g_mutex_lock (&ximagesink->x_lock); @@ -751,14 +753,14 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) e.xbutton.button, e.xbutton.x, e.xbutton.x); gst_navigation_send_event_simple (GST_NAVIGATION (ximagesink), gst_navigation_event_new_mouse_button_press (e.xbutton.button, - e.xbutton.x, e.xbutton.y)); + e.xbutton.x, e.xbutton.y, e.xbutton.state)); break; case ButtonRelease: GST_DEBUG ("ximagesink button %d release over window at %d,%d", e.xbutton.button, e.xbutton.x, e.xbutton.x); gst_navigation_send_event_simple (GST_NAVIGATION (ximagesink), gst_navigation_event_new_mouse_button_release (e.xbutton.button, - e.xbutton.x, e.xbutton.y)); + e.xbutton.x, e.xbutton.y, e.xbutton.state)); break; case KeyPress: case KeyRelease: @@ -783,8 +785,8 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) e.xkey.keycode, e.xkey.x, e.xkey.y, key_str); gst_navigation_send_event_simple (GST_NAVIGATION (ximagesink), (e.type == KeyPress) ? - gst_navigation_event_new_key_press (key_str) : - gst_navigation_event_new_key_release (key_str)); + gst_navigation_event_new_key_press (key_str, e.xkey.state) : + gst_navigation_event_new_key_release (key_str, e.xkey.state)); break; default: GST_DEBUG_OBJECT (ximagesink, "ximagesink unhandled X event (%d)", @@ -906,6 +908,7 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) g_mutex_unlock (&ximagesink->x_lock); g_mutex_unlock (&ximagesink->flow_lock); + state = touch->mods.effective; /* assume the event queue is ordered chronologically, and end */ /* the previous touch event frame when the timestamp increases */ if (touch->time != ximagesink->last_touch && touch_frame_open) { @@ -916,7 +919,7 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) GST_DEBUG ("ximagesink ending touch frame for %lu", ximagesink->last_touch); gst_navigation_send_event_simple (GST_NAVIGATION (ximagesink), - gst_navigation_event_new_touch_frame ()); + gst_navigation_event_new_touch_frame (state)); } } @@ -926,7 +929,7 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) "at %.0f,%.0f", touch->detail, touch->deviceid, touch->event_x, touch->event_y); nav = gst_navigation_event_new_touch_down (ev_id, touch->event_x, - touch->event_y, pressure); + touch->event_y, pressure, state); break; } case XI_TouchEnd:{ @@ -934,7 +937,7 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) "at %.0f,%.0f", touch->detail, touch->deviceid, touch->event_x, touch->event_y); nav = gst_navigation_event_new_touch_up (ev_id, touch->event_x, - touch->event_y); + touch->event_y, state); break; } case XI_TouchUpdate:{ @@ -942,7 +945,7 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) "to %.0f,%.0f", touch->detail, touch->deviceid, touch->event_x, touch->event_y); nav = gst_navigation_event_new_touch_motion (ev_id, - touch->event_x, touch->event_y, pressure); + touch->event_x, touch->event_y, pressure, state); break; } default: @@ -972,7 +975,7 @@ gst_x_image_sink_handle_xevents (GstXImageSink * ximagesink) if (touch_frame_open) { GST_DEBUG ("ximagesink ending touch frame for %lu", ximagesink->last_touch); gst_navigation_send_event_simple (GST_NAVIGATION (ximagesink), - gst_navigation_event_new_touch_frame ()); + gst_navigation_event_new_touch_frame (state)); } #endif } @@ -1276,7 +1279,7 @@ gst_x_image_sink_xcontext_clear (GstXImageSink * ximagesink) } /* Take the xcontext reference and NULL it while we - * clean it up, so that any buffer-alloced buffers + * clean it up, so that any buffer-alloced buffers * arriving after this will be freed correctly */ xcontext = ximagesink->xcontext; ximagesink->xcontext = NULL; diff --git a/subprojects/gst-plugins-base/sys/xvimage/xvimagesink.c b/subprojects/gst-plugins-base/sys/xvimage/xvimagesink.c index 325a82897a..68b8fb7222 100644 --- a/subprojects/gst-plugins-base/sys/xvimage/xvimagesink.c +++ b/subprojects/gst-plugins-base/sys/xvimage/xvimagesink.c @@ -423,6 +423,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) { XEvent e; gint pointer_x = 0, pointer_y = 0; + GstNavigationModifierType state = GST_NAVIGATION_MODIFIER_NONE; gboolean pointer_moved = FALSE, touch_frame_open = FALSE; gboolean exposed = FALSE, configured = FALSE; @@ -459,7 +460,8 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) GST_DEBUG ("xvimagesink pointer moved over window at %d,%d", pointer_x, pointer_y); gst_navigation_send_event_simple (GST_NAVIGATION (xvimagesink), - gst_navigation_event_new_mouse_move (e.xbutton.x, e.xbutton.y)); + gst_navigation_event_new_mouse_move (e.xbutton.x, e.xbutton.y, + e.xbutton.state)); g_mutex_lock (&xvimagesink->flow_lock); g_mutex_lock (&xvimagesink->context->lock); @@ -485,7 +487,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) e.xbutton.button, e.xbutton.x, e.xbutton.y); gst_navigation_send_event_simple (GST_NAVIGATION (xvimagesink), gst_navigation_event_new_mouse_button_press (e.xbutton.button, - e.xbutton.x, e.xbutton.y)); + e.xbutton.x, e.xbutton.y, e.xbutton.state)); break; case ButtonRelease: /* Mouse button released over our window. We send upstream @@ -494,7 +496,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) e.xbutton.button, e.xbutton.x, e.xbutton.y); gst_navigation_send_event_simple (GST_NAVIGATION (xvimagesink), gst_navigation_event_new_mouse_button_release (e.xbutton.button, - e.xbutton.x, e.xbutton.y)); + e.xbutton.x, e.xbutton.y, e.xbutton.state)); break; case KeyPress: case KeyRelease: @@ -519,8 +521,8 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) e.xkey.keycode, e.xkey.x, e.xkey.y, key_str); gst_navigation_send_event_simple (GST_NAVIGATION (xvimagesink), (e.type == KeyPress) ? - gst_navigation_event_new_key_press (key_str) : - gst_navigation_event_new_key_release (key_str)); + gst_navigation_event_new_key_press (key_str, e.xkey.state) : + gst_navigation_event_new_key_release (key_str, e.xkey.state)); break; default: GST_DEBUG_OBJECT (xvimagesink, "xvimagesink unhandled X event (%d)", @@ -647,6 +649,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) g_mutex_unlock (&xvimagesink->context->lock); g_mutex_unlock (&xvimagesink->flow_lock); + state = touch->mods.effective; /* assume the event queue is ordered chronologically, and end */ /* the previous touch event frame when the timestamp increases */ if (touch->time != xwindow->last_touch && touch_frame_open) { @@ -657,7 +660,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) GST_DEBUG ("ximagesink ending touch frame for %lu", xwindow->last_touch); gst_navigation_send_event_simple (GST_NAVIGATION (xvimagesink), - gst_navigation_event_new_touch_frame ()); + gst_navigation_event_new_touch_frame (state)); } } @@ -667,7 +670,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) "at %.0f,%.0f", touch->detail, touch->deviceid, touch->event_x, touch->event_y); nav = gst_navigation_event_new_touch_down (ev_id, - touch->event_x, touch->event_y, pressure); + touch->event_x, touch->event_y, pressure, state); break; } case XI_TouchEnd:{ @@ -675,7 +678,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) "at %.0f,%.0f", touch->detail, touch->deviceid, touch->event_x, touch->event_y); nav = gst_navigation_event_new_touch_up (ev_id, - touch->event_x, touch->event_y); + touch->event_x, touch->event_y, state); break; } case XI_TouchUpdate:{ @@ -683,7 +686,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) "to %.0f,%.0f", touch->detail, touch->deviceid, touch->event_x, touch->event_y); nav = gst_navigation_event_new_touch_motion (ev_id, - touch->event_x, touch->event_y, pressure); + touch->event_x, touch->event_y, pressure, state); break; } default: @@ -714,7 +717,7 @@ gst_xv_image_sink_handle_xevents (GstXvImageSink * xvimagesink) GST_DEBUG ("xvimagesink ending touch frame for %lu", xvimagesink->xwindow->last_touch); gst_navigation_send_event_simple (GST_NAVIGATION (xvimagesink), - gst_navigation_event_new_touch_frame ()); + gst_navigation_event_new_touch_frame (state)); } #endif } diff --git a/subprojects/gst-plugins-base/tests/check/libs/navigation.c b/subprojects/gst-plugins-base/tests/check/libs/navigation.c index ff8b0a1f12..f589f57a11 100644 --- a/subprojects/gst-plugins-base/tests/check/libs/navigation.c +++ b/subprojects/gst-plugins-base/tests/check/libs/navigation.c @@ -170,14 +170,14 @@ GST_START_TEST (test_events) gst_navigation_send_key_event (GST_NAVIGATION (test_element), "key-press", "1"); gst_navigation_send_event_simple (GST_NAVIGATION (test_element), - gst_navigation_event_new_key_press ("1")); + gst_navigation_event_new_key_press ("1", GST_NAVIGATION_MODIFIER_NONE)); test_element->sent_type = GST_NAVIGATION_EVENT_KEY_RELEASE; test_element->sent_key = "2"; gst_navigation_send_key_event (GST_NAVIGATION (test_element), "key-release", "2"); gst_navigation_send_event_simple (GST_NAVIGATION (test_element), - gst_navigation_event_new_key_release ("2")); + gst_navigation_event_new_key_release ("2", GST_NAVIGATION_MODIFIER_NONE)); test_element->sent_type = GST_NAVIGATION_EVENT_MOUSE_MOVE; test_element->sent_x = 50; @@ -185,7 +185,8 @@ GST_START_TEST (test_events) gst_navigation_send_mouse_event (GST_NAVIGATION (test_element), "mouse-move", 0, 50, 100); gst_navigation_send_event_simple (GST_NAVIGATION (test_element), - gst_navigation_event_new_mouse_move (50, 100)); + gst_navigation_event_new_mouse_move (50, 100, + GST_NAVIGATION_MODIFIER_NONE)); test_element->sent_type = GST_NAVIGATION_EVENT_MOUSE_SCROLL; test_element->sent_x = 60; @@ -195,7 +196,8 @@ GST_START_TEST (test_events) gst_navigation_send_mouse_scroll_event (GST_NAVIGATION (test_element), 60, 120, 2, 3); gst_navigation_send_event_simple (GST_NAVIGATION (test_element), - gst_navigation_event_new_mouse_scroll (60, 120, 2, 3)); + gst_navigation_event_new_mouse_scroll (60, 120, 2, 3, + GST_NAVIGATION_MODIFIER_NONE)); test_element->sent_type = GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS; test_element->sent_x = 10; @@ -204,7 +206,8 @@ GST_START_TEST (test_events) gst_navigation_send_mouse_event (GST_NAVIGATION (test_element), "mouse-button-press", 1, 10, 20); gst_navigation_send_event_simple (GST_NAVIGATION (test_element), - gst_navigation_event_new_mouse_button_press (1, 10, 20)); + gst_navigation_event_new_mouse_button_press (1, 10, 20, + GST_NAVIGATION_MODIFIER_NONE)); for (i = 0; i < G_N_ELEMENTS (cmds); i++) { test_element->sent_type = GST_NAVIGATION_EVENT_COMMAND; diff --git a/subprojects/gst-plugins-base/tests/examples/playback/playback-test.c b/subprojects/gst-plugins-base/tests/examples/playback/playback-test.c index bb72f09473..7da042eb20 100644 --- a/subprojects/gst-plugins-base/tests/examples/playback/playback-test.c +++ b/subprojects/gst-plugins-base/tests/examples/playback/playback-test.c @@ -2274,7 +2274,7 @@ button_press_cb (GtkWidget * widget, GdkEventButton * event, PlaybackApp * app) if (app->navigation_element) gst_navigation_send_event_simple (GST_NAVIGATION (app->navigation_element), gst_navigation_event_new_mouse_button_press (event->button, event->x, - event->y)); + event->y, event->state)); return FALSE; } @@ -2286,7 +2286,7 @@ button_release_cb (GtkWidget * widget, GdkEventButton * event, if (app->navigation_element) gst_navigation_send_event_simple (GST_NAVIGATION (app->navigation_element), gst_navigation_event_new_mouse_button_release (event->button, event->x, - event->y)); + event->y, event->state)); return FALSE; } @@ -2296,7 +2296,8 @@ key_press_cb (GtkWidget * widget, GdkEventKey * event, PlaybackApp * app) { if (app->navigation_element) gst_navigation_send_event_simple (GST_NAVIGATION (app->navigation_element), - gst_navigation_event_new_key_press (gdk_keyval_name (event->keyval))); + gst_navigation_event_new_key_press (gdk_keyval_name (event->keyval), + event->state)); return FALSE; } @@ -2306,7 +2307,8 @@ key_release_cb (GtkWidget * widget, GdkEventKey * event, PlaybackApp * app) { if (app->navigation_element) gst_navigation_send_event_simple (GST_NAVIGATION (app->navigation_element), - gst_navigation_event_new_key_release (gdk_keyval_name (event->keyval))); + gst_navigation_event_new_key_release (gdk_keyval_name (event->keyval), + event->state)); return FALSE; } @@ -2316,7 +2318,7 @@ motion_notify_cb (GtkWidget * widget, GdkEventMotion * event, PlaybackApp * app) { if (app->navigation_element) gst_navigation_send_event_simple (GST_NAVIGATION (app->navigation_element), - gst_navigation_event_new_mouse_move (event->x, event->y)); + gst_navigation_event_new_mouse_move (event->x, event->y, event->state)); return FALSE; } diff --git a/subprojects/gst-plugins-good/ext/gtk/gtkgstbasewidget.c b/subprojects/gst-plugins-good/ext/gtk/gtkgstbasewidget.c index 611018e80a..ed7cfa6609 100644 --- a/subprojects/gst-plugins-good/ext/gtk/gtkgstbasewidget.c +++ b/subprojects/gst-plugins-good/ext/gtk/gtkgstbasewidget.c @@ -297,8 +297,8 @@ gtk_gst_base_widget_key_event (GtkWidget * widget, GdkEventKey * event) gst_navigation_send_event_simple (GST_NAVIGATION (element), (event->type == GDK_KEY_PRESS) ? - gst_navigation_event_new_key_press (str) : - gst_navigation_event_new_key_release (str)); + gst_navigation_event_new_key_press (str, event->state) : + gst_navigation_event_new_key_release (str, event->state)); } g_object_unref (element); } @@ -383,9 +383,9 @@ gtk_gst_base_widget_button_event (GtkWidget * widget, GdkEventButton * event) gst_navigation_send_event_simple (GST_NAVIGATION (element), (event->type == GDK_BUTTON_PRESS) ? gst_navigation_event_new_mouse_button_press (event->button, - event->x, event->y) : + event->x, event->y, event->state) : gst_navigation_event_new_mouse_button_release (event->button, - event->x, event->y)); + event->x, event->y, event->state)); } g_object_unref (element); } @@ -402,7 +402,8 @@ gtk_gst_base_widget_motion_event (GtkWidget * widget, GdkEventMotion * event) if ((element = g_weak_ref_get (&base_widget->element))) { if (GST_IS_NAVIGATION (element)) { gst_navigation_send_event_simple (GST_NAVIGATION (element), - gst_navigation_event_new_mouse_move (event->x, event->y)); + gst_navigation_event_new_mouse_move (event->x, event->y, + event->state)); } g_object_unref (element); } @@ -447,7 +448,8 @@ gtk_gst_base_widget_scroll_event (GtkWidget * widget, GdkEventScroll * event) } } gst_navigation_send_event_simple (GST_NAVIGATION (element), - gst_navigation_event_new_mouse_scroll (x, y, delta_x, delta_y)); + gst_navigation_event_new_mouse_scroll (x, y, delta_x, delta_y, + event->state)); } g_object_unref (element); } @@ -480,14 +482,17 @@ gtk_gst_base_widget_touch_event (GtkWidget * widget, GdkEventTouch * event) switch (event->type) { case GDK_TOUCH_BEGIN: - nav_event = gst_navigation_event_new_touch_down (id, x, y, p); + nav_event = + gst_navigation_event_new_touch_down (id, x, y, p, event->state); break; case GDK_TOUCH_UPDATE: - nav_event = gst_navigation_event_new_touch_motion (id, x, y, p); + nav_event = + gst_navigation_event_new_touch_motion (id, x, y, p, event->state); break; case GDK_TOUCH_END: case GDK_TOUCH_CANCEL: - nav_event = gst_navigation_event_new_touch_up (id, x, y); + nav_event = + gst_navigation_event_new_touch_up (id, x, y, event->state); break; default: nav_event = NULL; diff --git a/subprojects/gst-plugins-good/ext/qt/qtitem.cc b/subprojects/gst-plugins-good/ext/qt/qtitem.cc index 2ffd5d3d72..a8a3aca703 100644 --- a/subprojects/gst-plugins-good/ext/qt/qtitem.cc +++ b/subprojects/gst-plugins-good/ext/qt/qtitem.cc @@ -430,6 +430,27 @@ QtGLVideoItem::mapPointToStreamSize(QPointF pos) return QPointF(stream_x, stream_y); } +static GstNavigationModifierType +translateModifiers(Qt::KeyboardModifiers modifiers) +{ + return (GstNavigationModifierType)( + ((modifiers & Qt::KeyboardModifier::ShiftModifier) ? GST_NAVIGATION_MODIFIER_SHIFT_MASK : 0) | + ((modifiers & Qt::KeyboardModifier::ControlModifier) ? GST_NAVIGATION_MODIFIER_CONTROL_MASK : 0) | + ((modifiers & Qt::KeyboardModifier::AltModifier) ? GST_NAVIGATION_MODIFIER_ALT_MASK : 0) | + ((modifiers & Qt::KeyboardModifier::MetaModifier) ? GST_NAVIGATION_MODIFIER_META_MASK : 0)); +} + +static GstNavigationModifierType +translateMouseButtons(Qt::MouseButtons buttons) +{ + return (GstNavigationModifierType)( + ((buttons & Qt::LeftButton) ? GST_NAVIGATION_MODIFIER_BUTTON1_MASK : 0) | + ((buttons & Qt::RightButton) ? GST_NAVIGATION_MODIFIER_BUTTON2_MASK : 0) | + ((buttons & Qt::MiddleButton) ? GST_NAVIGATION_MODIFIER_BUTTON3_MASK : 0) | + ((buttons & Qt::BackButton) ? GST_NAVIGATION_MODIFIER_BUTTON4_MASK : 0) | + ((buttons & Qt::ForwardButton) ? GST_NAVIGATION_MODIFIER_BUTTON5_MASK : 0)); +} + void QtGLVideoItem::wheelEvent(QWheelEvent * event) { @@ -445,7 +466,9 @@ QtGLVideoItem::wheelEvent(QWheelEvent * event) #endif gst_navigation_send_event_simple (GST_NAVIGATION (element), gst_navigation_event_new_mouse_scroll (position.x(), position.y(), - delta.x(), delta.y())); + delta.x(), delta.y(), + (GstNavigationModifierType) ( + translateModifiers(event->modifiers()) | translateMouseButtons(event->buttons())))); g_object_unref (element); } g_mutex_unlock (&this->priv->lock); @@ -483,7 +506,8 @@ QtGLVideoItem::hoverMoveEvent(QHoverEvent * event) if (element != NULL) { gst_navigation_send_event_simple (GST_NAVIGATION (element), - gst_navigation_event_new_mouse_move (pos.x(), pos.y())); + gst_navigation_event_new_mouse_move (pos.x(), pos.y(), + translateModifiers(event->modifiers()))); g_object_unref (element); } } @@ -507,7 +531,7 @@ QtGLVideoItem::touchEvent(QTouchEvent * event) if (event->type() == QEvent::TouchCancel) { gst_navigation_send_event_simple (GST_NAVIGATION (element), - gst_navigation_event_new_touch_cancel ()); + gst_navigation_event_new_touch_cancel (translateModifiers(event->modifiers()))); } else { const QList points = event->touchPoints(); gboolean sent_event = FALSE; @@ -519,15 +543,15 @@ QtGLVideoItem::touchEvent(QTouchEvent * event) switch (points[i].state()) { case Qt::TouchPointPressed: nav_event = gst_navigation_event_new_touch_down ((guint) points[i].id(), - pos.x(), pos.y(), (gdouble) points[i].pressure()); + pos.x(), pos.y(), (gdouble) points[i].pressure(), translateModifiers(event->modifiers())); break; case Qt::TouchPointMoved: nav_event = gst_navigation_event_new_touch_motion ((guint) points[i].id(), - pos.x(), pos.y(), (gdouble) points[i].pressure()); + pos.x(), pos.y(), (gdouble) points[i].pressure(), translateModifiers(event->modifiers())); break; case Qt::TouchPointReleased: nav_event = gst_navigation_event_new_touch_up ((guint) points[i].id(), - pos.x(), pos.y()); + pos.x(), pos.y(), translateModifiers(event->modifiers())); break; /* Don't send an event if the point did not change */ default: @@ -544,7 +568,7 @@ QtGLVideoItem::touchEvent(QTouchEvent * event) /* Group simultaneos touch events with a frame event */ if (sent_event) { gst_navigation_send_event_simple (GST_NAVIGATION (element), - gst_navigation_event_new_touch_frame ()); + gst_navigation_event_new_touch_frame (translateModifiers(event->modifiers()))); } } @@ -584,9 +608,13 @@ QtGLVideoItem::sendMouseEvent(QMouseEvent * event, gboolean is_press) if (element != NULL) { gst_navigation_send_event_simple (GST_NAVIGATION (element), (is_press) ? gst_navigation_event_new_mouse_button_press (button, - pos.x(), pos.y()) : + pos.x(), pos.y(), + (GstNavigationModifierType) ( + translateModifiers(event->modifiers()) | translateMouseButtons(event->buttons()))) : gst_navigation_event_new_mouse_button_release (button, pos.x(), - pos.y())); + pos.y(), + (GstNavigationModifierType) ( + translateModifiers(event->modifiers()) | translateMouseButtons(event->buttons())))); g_object_unref (element); } diff --git a/subprojects/gstreamer-vaapi/tests/check/elements/vaapipostproc.c b/subprojects/gstreamer-vaapi/tests/check/elements/vaapipostproc.c index 4e362219c4..d4bf6caba5 100644 --- a/subprojects/gstreamer-vaapi/tests/check/elements/vaapipostproc.c +++ b/subprojects/gstreamer-vaapi/tests/check/elements/vaapipostproc.c @@ -182,15 +182,15 @@ vpp_test_mouse_events (VppTestContext * ctx, switch (j) { case 0: event = gst_navigation_event_new_mouse_move (params[i].send.x, - params[i].send.y); + params[i].send.y, GST_NAVIGATION_MODIFIER_NONE); break; case 1: event = gst_navigation_event_new_mouse_button_press (0, - params[i].send.x, params[i].send.y); + params[i].send.x, params[i].send.y, GST_NAVIGATION_MODIFIER_NONE); break; case 2: event = gst_navigation_event_new_mouse_button_release (0, - params[i].send.x, params[i].send.y); + params[i].send.x, params[i].send.y, GST_NAVIGATION_MODIFIER_NONE); break; }