glwindow: Hide navigation specific internal API and add API to asynchronously send...
authorSebastian Dröge <sebastian@centricular.com>
Mon, 21 Dec 2015 10:27:09 +0000 (11:27 +0100)
committerSebastian Dröge <sebastian@centricular.com>
Mon, 21 Dec 2015 10:27:09 +0000 (11:27 +0100)
Exposing the navigation thread's main context, GSourceFuncs and structs called
key_event and mouse_event is exposing a bit too much of the internals. Let's
just go with two functions to asynchronously send navigation events on the
window with the same API as the synchronous ones.

gst-libs/gst/gl/gstglwindow.c
gst-libs/gst/gl/gstglwindow.h
gst-libs/gst/gl/x11/gstglwindow_x11.c

index 3c12d1c..b5175f9 100644 (file)
@@ -90,13 +90,15 @@ struct _GstGLWindowPrivate
 {
   GMainContext *main_context;
   GMainLoop *loop;
-  GThread *navigation_thread;
 
   guint surface_width;
   guint surface_height;
 
   gboolean alive;
 
+  GThread *navigation_thread;
+  GMainContext *navigation_context;
+  GMainLoop *navigation_loop;
   GMutex nav_lock;
   GCond nav_create_cond;
   gboolean nav_alive;
@@ -327,7 +329,7 @@ gst_gl_window_finalize (GObject * object)
   GstGLWindowPrivate *priv = window->priv;
 
   GST_INFO ("quit navigation loop");
-  g_main_loop_quit (window->navigation_loop);
+  g_main_loop_quit (window->priv->navigation_loop);
   /* wait until navigation thread finished */
   g_thread_join (window->priv->navigation_thread);
   window->priv->navigation_thread = NULL;
@@ -920,24 +922,25 @@ gst_gl_window_navigation_thread (GstGLWindow * window)
 
   g_return_val_if_fail (GST_IS_GL_WINDOW (window), NULL);
 
-  window->navigation_context = g_main_context_new ();
-  window->navigation_loop = g_main_loop_new (window->navigation_context, FALSE);
-  g_main_context_push_thread_default (window->navigation_context);
+  window->priv->navigation_context = g_main_context_new ();
+  window->priv->navigation_loop =
+      g_main_loop_new (window->priv->navigation_context, FALSE);
+  g_main_context_push_thread_default (window->priv->navigation_context);
 
   source = g_idle_source_new ();
   g_source_set_callback (source, (GSourceFunc) gst_gl_window_navigation_started,
       window, NULL);
-  g_source_attach (source, window->navigation_context);
+  g_source_attach (source, window->priv->navigation_context);
   g_source_unref (source);
 
-  g_main_loop_run (window->navigation_loop);
+  g_main_loop_run (window->priv->navigation_loop);
 
-  g_main_context_pop_thread_default (window->navigation_context);
+  g_main_context_pop_thread_default (window->priv->navigation_context);
 
-  g_main_loop_unref (window->navigation_loop);
-  g_main_context_unref (window->navigation_context);
-  window->navigation_loop = NULL;
-  window->navigation_context = NULL;
+  g_main_loop_unref (window->priv->navigation_loop);
+  g_main_context_unref (window->priv->navigation_context);
+  window->priv->navigation_loop = NULL;
+  window->priv->navigation_context = NULL;
 
   GST_INFO ("navigation loop exited\n");
 
@@ -991,48 +994,100 @@ gst_gl_dummy_window_new (void)
   return g_object_new (gst_gl_dummy_window_get_type (), NULL);
 }
 
-gboolean
+void
+gst_gl_window_send_key_event (GstGLWindow * window, const char *event_type,
+    const char *key_str)
+{
+  g_signal_emit (window, gst_gl_window_signals[EVENT_KEY_SIGNAL], 0,
+      event_type, key_str);
+}
+
+typedef struct
+{
+  GstGLWindow *window;
+  const char *event_type;
+  const char *key_str;
+} KeyEventData;
+
+static gboolean
 gst_gl_window_key_event_cb (gpointer data)
 {
-  struct key_event *key_data = (struct key_event *) data;
+  KeyEventData *key_data = data;
+
   GST_DEBUG
       ("%s called data struct %p window %p key %s event %s ",
       __func__, key_data, key_data->window, key_data->key_str,
       key_data->event_type);
+
   gst_gl_window_send_key_event (GST_GL_WINDOW (key_data->window),
       key_data->event_type, key_data->key_str);
-  g_slice_free (struct key_event, key_data);
+
   return G_SOURCE_REMOVE;
 }
 
 void
-gst_gl_window_send_key_event (GstGLWindow * window, const char *event_type,
-    const char *key_str)
+gst_gl_window_send_key_event_async (GstGLWindow * window,
+    const char *event_type, const char *key_str)
 {
-  g_signal_emit (window, gst_gl_window_signals[EVENT_KEY_SIGNAL], 0,
-      event_type, key_str);
+  KeyEventData *key_data = g_new0 (KeyEventData, 1);
+
+  key_data->window = window;
+  key_data->key_str = key_str;
+  key_data->event_type = event_type;
+
+  g_main_context_invoke_full (window->priv->navigation_context,
+      G_PRIORITY_DEFAULT, (GSourceFunc) gst_gl_window_key_event_cb, key_data,
+      (GDestroyNotify) g_free);
 }
 
-gboolean
+void
+gst_gl_window_send_mouse_event (GstGLWindow * window, const char *event_type,
+    int button, double posx, double posy)
+{
+  g_signal_emit (window, gst_gl_window_signals[EVENT_MOUSE_SIGNAL], 0,
+      event_type, button, posx, posy);
+}
+
+typedef struct
+{
+  GstGLWindow *window;
+  const char *event_type;
+  int button;
+  double posx;
+  double posy;
+} MouseEventData;
+
+static gboolean
 gst_gl_window_mouse_event_cb (gpointer data)
 {
-  struct mouse_event *mouse_data = (struct mouse_event *) data;
+  MouseEventData *mouse_data = data;
+
   GST_DEBUG ("%s called data struct %p mouse event %s button %d at %g, %g",
       __func__, mouse_data, mouse_data->event_type, mouse_data->button,
       mouse_data->posx, mouse_data->posy);
+
   gst_gl_window_send_mouse_event (GST_GL_WINDOW (mouse_data->window),
       mouse_data->event_type, mouse_data->button, mouse_data->posx,
       mouse_data->posy);
-  g_slice_free (struct mouse_event, mouse_data);
+
   return G_SOURCE_REMOVE;
 }
 
 void
-gst_gl_window_send_mouse_event (GstGLWindow * window, const char *event_type,
-    int button, double posx, double posy)
+gst_gl_window_send_mouse_event_async (GstGLWindow * window,
+    const char *event_type, int button, double posx, double posy)
 {
-  g_signal_emit (window, gst_gl_window_signals[EVENT_MOUSE_SIGNAL], 0,
-      event_type, button, posx, posy);
+  MouseEventData *mouse_data = g_new0 (MouseEventData, 1);
+
+  mouse_data->window = window;
+  mouse_data->event_type = event_type;
+  mouse_data->button = button;
+  mouse_data->posx = posx;
+  mouse_data->posy = posy;
+
+  g_main_context_invoke_full (window->priv->navigation_context,
+      G_PRIORITY_DEFAULT, (GSourceFunc) gst_gl_window_mouse_event_cb,
+      mouse_data, (GDestroyNotify) g_free);
 }
 
 /**
index 3e3782a..1cf5c3e 100644 (file)
@@ -88,9 +88,6 @@ struct _GstGLWindow {
   gboolean              queue_resize;
 
   /*< private >*/
-  GMainContext *navigation_context;
-  GMainLoop *navigation_loop;
-
   GstGLWindowPrivate *priv;
 
   gpointer _reserved[GST_PADDING];
@@ -143,22 +140,6 @@ struct _GstGLWindowClass {
   gpointer _reserved[GST_PADDING];
 };
 
-struct key_event
-{
-  GstGLWindow *window;
-  const char *event_type;
-  const char *key_str;
-};
-
-struct mouse_event
-{
-  GstGLWindow *window;
-  const char *event_type;
-  int button;
-  double posx;
-  double posy;
-};
-
 GQuark gst_gl_window_error_quark (void);
 GType gst_gl_window_get_type     (void);
 
@@ -196,16 +177,23 @@ void     gst_gl_window_send_message_async   (GstGLWindow *window,
 /* navigation */
 void     gst_gl_window_handle_events        (GstGLWindow * window,
                                              gboolean handle_events);
-gboolean gst_gl_window_key_event_cb         (gpointer data);
-gboolean gst_gl_window_mouse_event_cb       (gpointer data);
+
 void     gst_gl_window_send_key_event       (GstGLWindow * window,
                                              const char * event_type,
                                              const char * key_str);
+void     gst_gl_window_send_key_event_async (GstGLWindow * window,
+                                             const char * event_type,
+                                             const char * key_str);
 void     gst_gl_window_send_mouse_event     (GstGLWindow * window,
                                              const char * event_type,
                                              int button,
                                              double posx,
                                              double posy);
+void     gst_gl_window_send_mouse_event_async (GstGLWindow * window,
+                                             const char * event_type,
+                                             int button,
+                                             double posx,
+                                             double posy);
 
 /* surfaces/rendering */
 void     gst_gl_window_queue_resize         (GstGLWindow *window);
index f9fc4da..43387ac 100644 (file)
@@ -515,10 +515,6 @@ gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11)
   GstGLContextClass *context_class;
   GstGLWindow *window;
   gboolean ret = TRUE;
-  const char *key_str = NULL;
-  KeySym keysym;
-  struct mouse_event *mouse_data;
-  struct key_event *key_data;
 
   window = GST_GL_WINDOW (window_x11);
 
@@ -591,47 +587,39 @@ gst_gl_window_x11_handle_event (GstGLWindowX11 * window_x11)
         break;
       case KeyPress:
       case KeyRelease:
+      {
+        const char *key_str = NULL, *key_type = NULL;
+        KeySym keysym;
+
         keysym = XkbKeycodeToKeysym (window_x11->device,
             event.xkey.keycode, 0, 0);
         key_str = XKeysymToString (keysym);
-        key_data = g_slice_new (struct key_event);
-        key_data->window = window;
-        key_data->key_str = XKeysymToString (keysym);
-        key_data->event_type =
-            event.type == KeyPress ? "key-press" : "key-release";
-        GST_DEBUG ("input event key %d pressed over window at %d,%d (%s)",
-            event.xkey.keycode, event.xkey.x, event.xkey.y, key_str);
-        g_main_context_invoke (window->navigation_context,
-            (GSourceFunc) gst_gl_window_key_event_cb, key_data);
+        key_type = event.type == KeyPress ? "key-press" : "key-release";
+        GST_DEBUG ("input event key %d %s over window at %d,%d (%s)",
+            event.xkey.keycode, key_type, event.xkey.x, event.xkey.y, key_str);
+        gst_gl_window_send_key_event_async (window, key_type, key_str);
         break;
+      }
       case ButtonPress:
-      case ButtonRelease:
-        GST_DEBUG ("input event mouse button %d pressed over window at %d,%d",
-            event.xbutton.button, event.xbutton.x, event.xbutton.y);
-        mouse_data = g_slice_new (struct mouse_event);
-        mouse_data->window = window;
-        mouse_data->event_type =
-            event.type ==
+      case ButtonRelease:{
+        const char *mouse_type = NULL;
+
+        mouse_type = event.type ==
             ButtonPress ? "mouse-button-press" : "mouse-button-release";
-        mouse_data->button = event.xbutton.button;
-        mouse_data->posx = (double) event.xbutton.x;
-        mouse_data->posy = (double) event.xbutton.y;
 
-        g_main_context_invoke (window->navigation_context,
-            (GSourceFunc) gst_gl_window_mouse_event_cb, mouse_data);
+        GST_DEBUG ("input event mouse button %d %s over window at %d,%d",
+            event.xbutton.button, mouse_type, event.xbutton.x, event.xbutton.y);
+
+        gst_gl_window_send_mouse_event_async (window, mouse_type,
+            event.xbutton.button, event.xbutton.x, event.xbutton.y);
         break;
+      }
       case MotionNotify:
         GST_DEBUG ("input event pointer moved over window at %d,%d",
             event.xmotion.x, event.xmotion.y);
-        mouse_data = g_slice_new (struct mouse_event);
-        mouse_data->window = window;
-        mouse_data->event_type = "mouse-move";
-        mouse_data->button = 0;
-        mouse_data->posx = (double) event.xbutton.x;
-        mouse_data->posy = (double) event.xbutton.y;
-
-        g_main_context_invoke (window->navigation_context, (GSourceFunc)
-            gst_gl_window_mouse_event_cb, mouse_data);
+
+        gst_gl_window_send_mouse_event_async (window, "mouse-move", 0,
+            event.xbutton.x, event.xbutton.y);
         break;
       default:
         GST_DEBUG ("unknown XEvent type: %u", event.type);