$(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
#include <stdarg.h>
#include <assert.h>
+#include <poll.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#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 " \
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.
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;
/* 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);
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;
}
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;
}