navigation: Add support for key Modifiers in all relevant events
authorThibault Saunier <tsaunier@igalia.com>
Fri, 18 Mar 2022 16:59:32 +0000 (16:59 +0000)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Fri, 25 Mar 2022 15:16:03 +0000 (15:16 +0000)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/2010>

16 files changed:
subprojects/gst-plugins-bad/ext/directfb/dfbvideosink.c
subprojects/gst-plugins-bad/ext/opencv/gsthanddetect.cpp
subprojects/gst-plugins-bad/ext/vulkan/vksink.c
subprojects/gst-plugins-bad/sys/d3d11/gstd3d11videosink.cpp
subprojects/gst-plugins-bad/sys/d3dvideosink/d3dhelpers.c
subprojects/gst-plugins-bad/tests/check/pipelines/ipcpipeline.c
subprojects/gst-plugins-base/ext/gl/gstglimagesink.c
subprojects/gst-plugins-base/gst-libs/gst/video/navigation.c
subprojects/gst-plugins-base/gst-libs/gst/video/navigation.h
subprojects/gst-plugins-base/sys/ximage/ximagesink.c
subprojects/gst-plugins-base/sys/xvimage/xvimagesink.c
subprojects/gst-plugins-base/tests/check/libs/navigation.c
subprojects/gst-plugins-base/tests/examples/playback/playback-test.c
subprojects/gst-plugins-good/ext/gtk/gtkgstbasewidget.c
subprojects/gst-plugins-good/ext/qt/qtitem.cc
subprojects/gstreamer-vaapi/tests/check/elements/vaapipostproc.c

index 6c60f97..7b88930 100644 (file)
@@ -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);
index fa2bfec..373c92e 100644 (file)
@@ -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
            *
index 9be1d5b..ec523a0 100644 (file)
@@ -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);
index e9d4aac..02ea4f0 100644 (file)
@@ -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);
index 960023a..99e8408 100644 (file)
@@ -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;
index d28735d..ed2c8b9 100644 (file)
@@ -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;
   }
 
index 99fe170..f0d1fab 100644 (file)
@@ -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
index a187186..12fc638 100644 (file)
  * @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.
- *
- * * 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.
- *
+ * * 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.
  */
 
 #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;
+}
index e789c25..bb922f3 100644 (file)
@@ -41,6 +41,65 @@ 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
  * @send_event: sending a navigation event
@@ -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__ */
index f983a3c..a72e307 100644 (file)
@@ -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;
index 325a828..68b8fb7 100644 (file)
@@ -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
 }
index ff8b0a1..f589f57 100644 (file)
@@ -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;
index bb72f09..7da042e 100644 (file)
@@ -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;
 }
index 611018e..ed7cfa6 100644 (file)
@@ -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;
index 2ffd5d3..a8a3aca 100644 (file)
@@ -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<QTouchEvent::TouchPoint> 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);
   }
 
index 4e36221..d4bf6ca 100644 (file)
@@ -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;
       }