]> git.sesse.net Git - vlc/commitdiff
XCB window hoykeys support
authorRémi Denis-Courmont <rdenis@simphalempin.com>
Thu, 5 Feb 2009 19:23:57 +0000 (21:23 +0200)
committerRémi Denis-Courmont <rdenis@simphalempin.com>
Thu, 5 Feb 2009 19:23:57 +0000 (21:23 +0200)
It kinda suck to have to duplicate this though. Qt4 embedded X video
exhibits the same problem. One ugly "fix" could involve the video
output listening for the parent window event - not sure if this would
work. Another option would be to now create a window in the video
output at all, but then we loose reparenting (useless?). In either
cases, handling of hotkeys in fullscreen mode would seem problematic,
unless we handle fullscreen via the window provider too
(control request?).

modules/video_output/Modules.am
modules/video_output/xcb/window.c

index 5f68727e8425254ad21b81283af8eb678cf7f075..e8209b6994efb8ac00400b97f6eeb8aa4b7e6913 100644 (file)
@@ -42,11 +42,13 @@ libxcb_plugin_la_LIBADD = $(AM_LIBADD) \
        $(XCB_AUX_LIBS) $(XCB_IMAGE_LIBS) $(XCB_KEYSYMS_LIBS)
 libxcb_plugin_la_DEPENDENCIES =
 
-libxcb_window_plugin_la_SOURCES = xcb/window.c
+libxcb_window_plugin_la_SOURCES = xcb/window.c xcb/keys.c
 libxcb_window_plugin_la_CFLAGS = $(AM_CFLAGS) \
-       $(XCB_CFLAGS) $(XCB_AUX_CFLAGS)
+       $(XCB_CFLAGS) \
+       $(XCB_AUX_CFLAGS) $(XCB_KEYSYMS_CFLAGS)
 libxcb_window_plugin_la_LIBADD = $(AM_LIBADD) \
-       $(XCB_LIBS) $(XCB_AUX_LIBS)
+       $(XCB_LIBS) \
+       $(XCB_AUX_LIBS) $(XCB_KEYSYMS_LIBS)
 libxcb_window_plugin_la_DEPENDENCIES =
 
 EXTRA_LTLIBRARIES += libxcb_plugin.la libxcb_window_plugin.la
index 50cef9ef97fb4eca3017a1658fcad49486d63b73..f31690a0227f5d7466c2280c8104e3f3dda2b081 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <stdarg.h>
 #include <assert.h>
+#include <poll.h>
 
 #include <xcb/xcb.h>
 #include <xcb/xcb_aux.h>
@@ -34,6 +35,8 @@
 #include <vlc_plugin.h>
 #include <vlc_window.h>
 
+#include "xcb_vlc.h"
+
 #define DISPLAY_TEXT N_("X11 display")
 #define DISPLAY_LONGTEXT N_( \
     "X11 hardware display to use. By default VLC will " \
@@ -58,6 +61,14 @@ vlc_module_begin ()
 vlc_module_end ()
 
 static int Control (vout_window_t *, int, va_list ap);
+static void *Thread (void *);
+
+struct vout_window_sys_t
+{
+    xcb_connection_t *conn;
+    key_handler_t *keys;
+    vlc_thread_t thread;
+};
 
 /**
  * Create an X11 window.
@@ -65,9 +76,13 @@ static int Control (vout_window_t *, int, va_list ap);
 static int Open (vlc_object_t *obj)
 {
     vout_window_t *wnd = (vout_window_t *)obj;
+    vout_window_sys_t *p_sys = malloc (sizeof (*p_sys));
     xcb_generic_error_t *err;
     xcb_void_cookie_t ck;
 
+    if (p_sys == NULL)
+        return VLC_ENOMEM;
+
     /* Connect to X */
     char *display = var_CreateGetNonEmptyString (wnd, "x11-display");
     int snum;
@@ -79,10 +94,12 @@ static int Open (vlc_object_t *obj)
 
     /* Create window */
     xcb_screen_t *scr = xcb_aux_get_screen (conn, snum);
-    const uint32_t mask = XCB_CW_BACK_PIXEL;
-    uint32_t values[1] = {
+    const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
+    uint32_t values[2] = {
         /* XCB_CW_BACK_PIXEL */
         scr->black_pixel,
+        /* XCB_CW_EVENT_MASK */
+        XCB_EVENT_MASK_KEY_PRESS,
     };
 
     xcb_window_t window = xcb_generate_id (conn);
@@ -97,17 +114,26 @@ static int Open (vlc_object_t *obj)
         goto error;
     }
 
+    wnd->handle.xid = window;
+    wnd->p_sys = p_sys;
+    wnd->control = Control;
+
+    p_sys->conn = conn;
+    p_sys->keys = CreateKeyHandler (obj, conn);
+
+    if ((p_sys->keys != NULL)
+     && vlc_clone (&p_sys->thread, Thread, wnd, VLC_THREAD_PRIORITY_LOW))
+        DestroyKeyHandler (p_sys->keys);
+
     /* Make sure the window is ready */
     xcb_map_window (conn, window);
     xcb_flush (conn);
 
-    wnd->handle.xid = window;
-    wnd->p_sys = conn;
-    wnd->control = Control;
     return VLC_SUCCESS;
 
 error:
     xcb_disconnect (conn);
+    free (p_sys);
     return VLC_EGENERIC;
 }
 
@@ -118,12 +144,56 @@ error:
 static void Close (vlc_object_t *obj)
 {
     vout_window_t *wnd = (vout_window_t *)obj;
-    xcb_connection_t *conn = wnd->p_sys;
+    vout_window_sys_t *p_sys = wnd->p_sys;
+    xcb_connection_t *conn = p_sys->conn;
     xcb_window_t window = wnd->handle.xid;
 
+    if (p_sys->keys)
+    {
+        vlc_cancel (p_sys->thread);
+        vlc_join (p_sys->thread, NULL);
+        DestroyKeyHandler (p_sys->keys);
+    }
     xcb_unmap_window (conn, window);
     xcb_destroy_window (conn, window);
     xcb_disconnect (conn);
+    free (p_sys);
+}
+
+
+static void *Thread (void *data)
+{
+    vout_window_t *wnd = data;
+    vout_window_sys_t *p_sys = wnd->p_sys;
+    xcb_connection_t *conn = p_sys->conn;
+
+    int fd = xcb_get_file_descriptor (conn);
+    if (fd == -1)
+        return NULL;
+
+    for (;;)
+    {
+        xcb_generic_event_t *ev;
+        struct pollfd ufd = { .fd = fd, .events = POLLIN, };
+
+        poll (&ufd, 1, -1);
+
+        int canc = vlc_savecancel ();
+        while ((ev = xcb_poll_for_event (conn)) != NULL)
+        {
+            if (ProcessKeyEvent (p_sys->keys, ev) == 0)
+                continue;
+            free (ev);
+        }
+        vlc_restorecancel (canc);
+
+        if (xcb_connection_has_error (conn))
+        {
+            msg_Err (wnd, "X server failure");
+            break;
+        }
+    }
+    return NULL;
 }