glwindow/win32: Fix possible deadlock around key/mouse event handling

Calling gst_gl_window_send_{key,mouse}_event() from GstGLContext
thread might cause a deadlock. Instead, use the dedicated event handling
thread in GstGLDisplay.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/721>
This commit is contained in:
Seungha Yang 2020-07-02 22:33:44 +09:00 committed by GStreamer Merge Bot
parent 595ca46301
commit 55f10f31d4

View file

@ -407,27 +407,74 @@ gst_gl_window_win32_draw (GstGLWindow * window)
RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE); RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE);
} }
typedef struct
{
GstGLWindow *window;
const gchar *event_type;
gchar *key_string;
} GstGLWindowWin32KeyEvent;
static gboolean
gst_gl_window_win32_handle_key_event_func (GstGLWindowWin32KeyEvent * event)
{
gst_gl_window_send_key_event (event->window,
event->event_type, event->key_string);
return G_SOURCE_REMOVE;
}
static void
gst_gl_window_win32_key_event_free (GstGLWindowWin32KeyEvent * event)
{
g_free (event->key_string);
g_free (event);
}
static void static void
gst_gl_window_win32_handle_key_event (GstGLWindow * window, UINT uMsg, gst_gl_window_win32_handle_key_event (GstGLWindow * window, UINT uMsg,
LPARAM lParam) LPARAM lParam)
{ {
gunichar2 wcrep[128]; gunichar2 wcrep[128];
const gchar *event;
if (GetKeyNameTextW (lParam, (LPWSTR) wcrep, 128)) { if (GetKeyNameTextW (lParam, (LPWSTR) wcrep, 128)) {
gchar *utfrep = g_utf16_to_utf8 (wcrep, 128, NULL, NULL, NULL); gchar *utfrep = g_utf16_to_utf8 (wcrep, 128, NULL, NULL, NULL);
if (utfrep) { if (utfrep) {
if (uMsg == WM_KEYDOWN) GstGLDisplay *display = window->display;
event = "key-press"; GstGLWindowWin32KeyEvent *key_event;
else
event = "key-release";
gst_gl_window_send_key_event (window, event, utfrep); key_event = g_new0 (GstGLWindowWin32KeyEvent, 1);
g_free (utfrep); key_event->window = window;
if (uMsg == WM_KEYDOWN)
key_event->event_type = "key-press";
else
key_event->event_type = "key-release";
key_event->key_string = utfrep;
g_main_context_invoke_full (display->main_context, G_PRIORITY_DEFAULT,
(GSourceFunc) gst_gl_window_win32_handle_key_event_func,
key_event, (GDestroyNotify) gst_gl_window_win32_key_event_free);
} }
} }
} }
typedef struct
{
GstGLWindow *window;
const gchar *event_type;
gint button;
gdouble pos_x;
gdouble pos_y;
} GstGLWindowWin32MouseEvent;
static gboolean
gst_gl_window_win32_handle_mouse_event_func (GstGLWindowWin32MouseEvent * event)
{
gst_gl_window_send_mouse_event (event->window,
event->event_type, event->button, event->pos_x, event->pos_y);
return G_SOURCE_REMOVE;
}
static void static void
gst_gl_window_win32_handle_mouse_event (GstGLWindow * window, UINT uMsg, gst_gl_window_win32_handle_mouse_event (GstGLWindow * window, UINT uMsg,
LPARAM lParam) LPARAM lParam)
@ -468,9 +515,21 @@ gst_gl_window_win32_handle_mouse_event (GstGLWindow * window, UINT uMsg,
break; break;
} }
if (event) if (event) {
gst_gl_window_send_mouse_event (window, event, button, GstGLDisplay *display = window->display;
(double) LOWORD (lParam), (double) HIWORD (lParam)); GstGLWindowWin32MouseEvent *mouse_event;
mouse_event = g_new0 (GstGLWindowWin32MouseEvent, 1);
mouse_event->window = window;
mouse_event->event_type = event;
mouse_event->button = button;
mouse_event->pos_x = (gdouble) LOWORD (lParam);
mouse_event->pos_y = (gdouble) HIWORD (lParam);
g_main_context_invoke_full (display->main_context, G_PRIORITY_DEFAULT,
(GSourceFunc) gst_gl_window_win32_handle_mouse_event_func,
mouse_event, (GDestroyNotify) g_free);
}
} }
/* PRIVATE */ /* PRIVATE */