static void gst_gl_window_default_send_message (GstGLWindow * window,
GstGLWindowCB callback, gpointer data);
+static gpointer gst_gl_window_navigation_thread (GstGLWindow * window);
+void gst_gl_window_run_navigation (GstGLWindow * window);
+void gst_gl_window_open_navigation (GstGLWindow * window);
+void gst_gl_window_close_navigation (GstGLWindow * window);
+void gst_gl_window_quit_navigation (GstGLWindow * window);
struct _GstGLWindowPrivate
{
GThread *gl_thread;
+ GThread *navigation_thread;
gboolean alive;
};
window->priv = GST_GL_WINDOW_GET_PRIVATE (window);
g_mutex_init (&window->lock);
+ g_mutex_init (&window->nav_lock);
+ g_cond_init (&window->nav_create_cond);
+ g_cond_init (&window->nav_destroy_cond);
+ window->nav_created = FALSE;
+ window->nav_alive = FALSE;
window->is_drawing = FALSE;
g_weak_ref_init (&window->context_ref, NULL);
window->display = gst_object_ref (display);
+ g_mutex_lock (&window->nav_lock);
+
+ if (!window->nav_created) {
+ window->priv->navigation_thread = g_thread_new ("gstglnavigation",
+ (GThreadFunc) gst_gl_window_navigation_thread, window);
+
+ g_cond_wait (&window->nav_create_cond, &window->nav_lock);
+ window->nav_created = TRUE;
+ }
+ g_mutex_unlock (&window->nav_lock);
+
return window;
}
{
GstGLWindow *window = GST_GL_WINDOW (object);
+ if (window->nav_alive) {
+ g_mutex_lock (&window->nav_lock);
+ GST_INFO ("send quit navigation loop");
+ gst_gl_window_quit_navigation (window);
+ while (window->nav_alive) {
+ g_cond_wait (&window->nav_destroy_cond, &window->nav_lock);
+ }
+ g_mutex_unlock (&window->nav_lock);
+ }
+
g_weak_ref_clear (&window->context_ref);
g_mutex_clear (&window->lock);
+ g_mutex_clear (&window->nav_lock);
+ g_cond_clear (&window->nav_create_cond);
+ g_cond_clear (&window->nav_destroy_cond);
gst_object_unref (window->display);
G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object);
}
/**
+ * gst_gl_window_run_navigation:
+ * @window: a #GstGLWindow
+ *
+ * Start the execution of the navigation runloop.
+ */
+void
+gst_gl_window_run_navigation (GstGLWindow * window)
+{
+ g_return_if_fail (GST_GL_IS_WINDOW (window));
+ g_return_if_fail (window->navigation_context != NULL);
+ g_return_if_fail (window->navigation_loop != NULL);
+ g_main_loop_run (window->navigation_loop);
+}
+
+/**
* gst_gl_window_quit:
* @window: a #GstGLWindow
*
guint * height)
{
GstGLWindowClass *window_class;
-
g_return_if_fail (GST_GL_IS_WINDOW (window));
window_class = GST_GL_WINDOW_GET_CLASS (window);
g_return_if_fail (window_class->get_surface_dimensions != NULL);
g_main_loop_run (dummy->loop);
}
+void
+gst_gl_window_open_navigation (GstGLWindow * window)
+{
+ g_return_if_fail (GST_GL_IS_WINDOW (window));
+ g_mutex_lock (&window->nav_lock);
+ 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->nav_alive = TRUE;
+ g_cond_signal (&window->nav_create_cond);
+ g_mutex_unlock (&window->nav_lock);
+}
+
+void
+gst_gl_window_close_navigation (GstGLWindow * window)
+{
+ g_return_if_fail (GST_GL_IS_WINDOW (window));
+ g_return_if_fail (window->navigation_context != NULL);
+ g_return_if_fail (window->navigation_loop != NULL);
+
+ g_mutex_lock (&window->nav_lock);
+ window->nav_alive = FALSE;
+ g_main_context_pop_thread_default (window->navigation_context);
+ g_main_loop_unref (window->navigation_loop);
+ g_main_context_unref (window->navigation_context);
+ g_cond_signal (&window->nav_destroy_cond);
+ g_mutex_unlock (&window->nav_lock);
+}
+
+void
+gst_gl_window_quit_navigation (GstGLWindow * window)
+{
+ g_return_if_fail (GST_GL_IS_WINDOW (window));
+
+ g_main_loop_quit (window->navigation_loop);
+}
+
+static gpointer
+gst_gl_window_navigation_thread (GstGLWindow * window)
+{
+ gst_gl_window_open_navigation (window);
+ gst_gl_window_run_navigation (window);
+ GST_INFO ("navigation loop exited\n");
+ gst_gl_window_close_navigation (window);
+
+ return NULL;
+}
+
typedef struct _GstGLMessage
{
GstGLWindowCB callback;
return g_object_new (gst_gl_dummy_window_get_type (), NULL);
}
+gboolean
+gst_gl_window_key_event_cb (gpointer data)
+{
+ struct key_event *key_data = (struct key_event *) 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)
event_type, key_str);
}
+gboolean
+gst_gl_window_mouse_event_cb (gpointer data)
+{
+ struct mouse_event *mouse_data = (struct mouse_event *) 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)
gboolean ret = TRUE;
const char *key_str = NULL;
KeySym keysym;
+ struct mouse_event *mouse_data;
+ struct key_event *key_data;
+ XWindowAttributes attr;
window = GST_GL_WINDOW (window_x11);
/* XSendEvent (which are called in other threads) are done from another display structure */
XNextEvent (window_x11->device, &event);
+ XGetWindowAttributes (window_x11->device, window_x11->internal_win_id,
+ &attr);
+ window_x11->current_width = attr.width;
+ window_x11->current_height = attr.height;
window_x11->allow_extra_expose_events = XPending (window_x11->device) <= 2;
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);
- gst_gl_window_send_key_event (window,
- event.type == KeyPress ? "key-press" : "key-release", key_str);
+ g_main_context_invoke (window->navigation_context,
+ (GSourceFunc) gst_gl_window_key_event_cb, key_data);
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);
- gst_gl_window_send_mouse_event (window,
+ mouse_data = g_slice_new (struct mouse_event);
+ mouse_data->window = window;
+ mouse_data->event_type =
event.type ==
- ButtonPress ? "mouse-button-press" : "mouse-button-release",
- event.xbutton.button, (double) event.xbutton.x,
- (double) event.xbutton.y);
+ 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);
break;
case MotionNotify:
GST_DEBUG ("input event pointer moved over window at %d,%d",
event.xmotion.x, event.xmotion.y);
- gst_gl_window_send_mouse_event (window, "mouse-move", 0,
- (double) event.xmotion.x, (double) 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);
break;
default:
GST_DEBUG ("unknown XEvent type: %u", event.type);
guint * height)
{
GstGLWindowX11 *window_x11 = GST_GL_WINDOW_X11 (window);
- XWindowAttributes attr;
- XGetWindowAttributes (window_x11->device, window_x11->internal_win_id, &attr);
if (width != NULL)
- *width = attr.width;
+ *width = window_x11->current_width;
if (height != NULL)
- *height = attr.height;
+ *height = window_x11->current_height;
}