vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Tue May 29 21:52:25 2018 +0300| [6db9ffab45b9dac2026ce88c32f5db8591236e2d] | committer: Rémi Denis-Courmont
xcb/window: implement XKeyboard using xkbcommon > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=6db9ffab45b9dac2026ce88c32f5db8591236e2d --- configure.ac | 14 +- modules/gui/qt/util/customwidgets.cpp | 3 + modules/video_output/Makefile.am | 10 +- modules/video_output/xcb/window.c | 233 +++++++++++++++++++++++++--------- 4 files changed, 196 insertions(+), 64 deletions(-) diff --git a/configure.ac b/configure.ac index 078a588aca..40d78663d5 100644 --- a/configure.ac +++ b/configure.ac @@ -3077,6 +3077,7 @@ have_xcb="no" have_xcb_keysyms="no" have_xcb_randr="no" have_xcb_xvideo="no" +have_xcb_xkb="no" AS_IF([test "${enable_xcb}" != "no"], [ dnl libxcb PKG_CHECK_MODULES(XCB, [xcb >= 1.6]) @@ -3091,15 +3092,26 @@ AS_IF([test "${enable_xcb}" != "no"], [ PKG_CHECK_MODULES(XCB_RANDR, [xcb-randr >= 1.3], [have_xcb_randr="yes"]) + PKG_CHECK_MODULES([XCB_XKB], [xcb-xkb], [ + PKG_CHECK_MODULES([XKBCOMMON_X11], [xkbcommon-x11], [ + have_xcb_xkb="yes" + ], [ + AC_MSG_WARN([${XKBCOMMON_X11_PKG_ERRORS}. Hotkeys will not work.]) + ]) + ], [ + AC_MSG_WARN([${XCB_XKB_PKG_ERRORS}. Hotkeys will not work.]) + ]) + dnl xcb-utils PKG_CHECK_MODULES(XCB_KEYSYMS, [xcb-keysyms >= 0.3.4], [have_xcb_keysyms="yes"], [ - AC_MSG_WARN([${XCB_KEYSYMS_PKG_ERRORS}. Hotkeys will not work.]) + AC_MSG_WARN([${XCB_KEYSYMS_PKG_ERRORS}]) ]) ]) AM_CONDITIONAL([HAVE_XCB], [test "${have_xcb}" = "yes"]) AM_CONDITIONAL([HAVE_XCB_KEYSYMS], [test "${have_xcb_keysyms}" = "yes"]) AM_CONDITIONAL([HAVE_XCB_RANDR], [test "${have_xcb_randr}" = "yes"]) AM_CONDITIONAL([HAVE_XCB_XVIDEO], [test "${have_xcb_xvideo}" = "yes"]) +AM_CONDITIONAL([HAVE_XCB_XKB], [test "${have_xcb_xkb}" = "yes"]) dnl diff --git a/modules/gui/qt/util/customwidgets.cpp b/modules/gui/qt/util/customwidgets.cpp index 3879cc350b..254f8e27c0 100644 --- a/modules/gui/qt/util/customwidgets.cpp +++ b/modules/gui/qt/util/customwidgets.cpp @@ -290,8 +290,11 @@ int qtEventToVLCKey( QKeyEvent *e ) i_vlck = map->vlc; } + fprintf(stderr, "key %08x (%08x)\n", i_vlck, qtk); + /* Handle modifiers */ i_vlck |= qtKeyModifiersToVLC( e ); + fprintf(stderr, "key event %08x\n", i_vlck); return i_vlck; } diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am index a6ad7fba02..2f27c27735 100644 --- a/modules/video_output/Makefile.am +++ b/modules/video_output/Makefile.am @@ -150,8 +150,10 @@ libxcb_xv_plugin_la_LIBADD = libvlc_xcb_events.la \ libxcb_window_plugin_la_SOURCES = video_output/xcb/window.c libxcb_window_plugin_la_CFLAGS = $(AM_CFLAGS) \ $(CFLAGS_xcb_window) \ - $(XPROTO_CFLAGS) $(XCB_CFLAGS) $(XCB_KEYSYMS_CFLAGS) -libxcb_window_plugin_la_LIBADD = $(XPROTO_LIBS) $(XCB_LIBS) $(XCB_KEYSYMS_LIBS) + $(XPROTO_CFLAGS) $(XCB_CFLAGS) \ + $(XCB_XKB_CFLAGS) $(XKBCOMMON_X11_CFLAGS) +libxcb_window_plugin_la_LIBADD = $(XPROTO_LIBS) $(XCB_LIBS) \ + $(XCB_XKB_LIBS) $(XKBCOMMON_X11_LIBS) libegl_x11_plugin_la_SOURCES = video_output/opengl/egl.c libegl_x11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) -DUSE_PLATFORM_X11=1 @@ -165,11 +167,11 @@ libglx_plugin_la_LIBADD = $(GL_LIBS) $(X_LIBS) $(X_PRE_LIBS) -lX11 if HAVE_XCB pkglib_LTLIBRARIES += libvlc_xcb_events.la vout_LTLIBRARIES += libxcb_x11_plugin.la libxcb_window_plugin.la -if HAVE_XCB_KEYSYMS +if HAVE_XCB_XKB libxcb_window_plugin_la_SOURCES += \ video_output/xcb/keysym.h video_output/xcb/xcb_keysym.h \ video_output/xcb/vlc_xkb.h video_output/xcb/xkb.c -libxcb_window_plugin_la_CFLAGS += -DHAVE_XCB_KEYSYMS +libxcb_window_plugin_la_CFLAGS += -DHAVE_XCB_XKB -DHAVE_XKBCOMMON endif if HAVE_XCB_XVIDEO vout_LTLIBRARIES += libxcb_xv_plugin.la diff --git a/modules/video_output/xcb/window.c b/modules/video_output/xcb/window.c index 1e4eae8a06..28caeafc32 100644 --- a/modules/video_output/xcb/window.c +++ b/modules/video_output/xcb/window.c @@ -31,8 +31,9 @@ #include <limits.h> /* _POSIX_HOST_NAME_MAX */ #include <xcb/xcb.h> -#ifdef HAVE_XCB_KEYSYMS -# include <xcb/xcb_keysyms.h> +#ifdef HAVE_XCB_XKB +# include <xcb/xkb.h> +# include <xkbcommon/xkbcommon-x11.h> # include "vlc_xkb.h" #endif typedef xcb_atom_t Atom; @@ -47,9 +48,6 @@ typedef xcb_atom_t Atom; struct vout_window_sys_t { xcb_connection_t *conn; -#ifdef HAVE_XCB_KEYSYMS - xcb_key_symbols_t *keys; -#endif vlc_thread_t thread; xcb_window_t root; @@ -58,9 +56,162 @@ struct vout_window_sys_t xcb_atom_t wm_state_below; xcb_atom_t wm_state_fullscreen; +#ifdef HAVE_XCB_XKB + struct + { + struct xkb_context *ctx; + struct xkb_keymap *map; + struct xkb_state *state; + uint8_t base; + } xkb; +#endif + bool embedded; }; +#ifdef HAVE_XCB_XKB +static int InitKeyboard(vout_window_t *wnd) +{ + vout_window_sys_t *sys = wnd->sys; + xcb_connection_t *conn = sys->conn; + + int32_t core = xkb_x11_get_core_keyboard_device_id(conn); + if (core == -1) + return -1; + + sys->xkb.map = xkb_x11_keymap_new_from_device(sys->xkb.ctx, conn, core, + XKB_KEYMAP_COMPILE_NO_FLAGS); + if (unlikely(sys->xkb.map == NULL)) + return -1; + + sys->xkb.state = xkb_x11_state_new_from_device(sys->xkb.map, conn, core); + if (unlikely(sys->xkb.state == NULL)) + { + xkb_keymap_unref(sys->xkb.map); + sys->xkb.map = NULL; + return -1; + } + return 0; +} + +static void DeinitKeyboard(vout_window_t *wnd) +{ + vout_window_sys_t *sys = wnd->sys; + + if (sys->xkb.map == NULL) + return; + + xkb_state_unref(sys->xkb.state); + xkb_keymap_unref(sys->xkb.map); + sys->xkb.map = NULL; +} + +static void ProcessKeyboardEvent(vout_window_t *wnd, + const xcb_generic_event_t *ev) +{ + vout_window_sys_t *sys = wnd->sys; + + switch (ev->pad0) + { + case XCB_XKB_NEW_KEYBOARD_NOTIFY: + case XCB_XKB_MAP_NOTIFY: + msg_Dbg(wnd, "refreshing keyboard mapping"); + DeinitKeyboard(wnd); + InitKeyboard(wnd); + break; + + case XCB_XKB_STATE_NOTIFY: + if (sys->xkb.map != NULL) + { + const xcb_xkb_state_notify_event_t *ne = (void *)ev; + + xkb_state_update_mask(sys->xkb.state, ne->baseMods, + ne->latchedMods, ne->lockedMods, + ne->baseGroup, ne->latchedGroup, + ne->lockedGroup); + } + break; + } +} + +static int InitKeyboardExtension(vout_window_t *wnd) +{ + vout_window_sys_t *sys = wnd->sys; + xcb_connection_t *conn = sys->conn; + uint16_t maj, min; + + if (!xkb_x11_setup_xkb_extension(conn, XKB_X11_MIN_MAJOR_XKB_VERSION, + XKB_X11_MIN_MINOR_XKB_VERSION, + XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, + &maj, &min, &sys->xkb.base, NULL)) + { + msg_Err(wnd, "XKeyboard initialization error"); + return 0; + } + + msg_Dbg(wnd, "XKeyboard v%"PRIu16".%"PRIu16" initialized", maj, min); + sys->xkb.ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + if (unlikely(sys->xkb.ctx == NULL)) + return -1; + + /* Events: new KB, keymap change, state (modifiers) change */ + const uint16_t affect = XCB_XKB_EVENT_TYPE_NEW_KEYBOARD_NOTIFY + | XCB_XKB_EVENT_TYPE_MAP_NOTIFY + | XCB_XKB_EVENT_TYPE_STATE_NOTIFY; + /* Map event sub-types: everything except key behaviours */ + const uint16_t map_parts = XCB_XKB_MAP_PART_KEY_TYPES + | XCB_XKB_MAP_PART_KEY_SYMS + | XCB_XKB_MAP_PART_MODIFIER_MAP + | XCB_XKB_MAP_PART_EXPLICIT_COMPONENTS + | XCB_XKB_MAP_PART_KEY_ACTIONS + | XCB_XKB_MAP_PART_VIRTUAL_MODS + | XCB_XKB_MAP_PART_VIRTUAL_MOD_MAP; + static const xcb_xkb_select_events_details_t details = + { + /* New keyboard details */ + .affectNewKeyboard = XCB_XKB_NKN_DETAIL_KEYCODES, + .newKeyboardDetails = XCB_XKB_NKN_DETAIL_KEYCODES, + /* State event sub-types: as per xkb_state_update_mask() */ +#define STATE_PARTS XCB_XKB_STATE_PART_MODIFIER_BASE \ + | XCB_XKB_STATE_PART_MODIFIER_LATCH \ + | XCB_XKB_STATE_PART_MODIFIER_LOCK \ + | XCB_XKB_STATE_PART_GROUP_BASE \ + | XCB_XKB_STATE_PART_GROUP_LATCH \ + | XCB_XKB_STATE_PART_GROUP_LOCK + .affectState = STATE_PARTS, + .stateDetails = STATE_PARTS, + }; + + int32_t core = xkb_x11_get_core_keyboard_device_id(conn); + if (core == -1) + { + xkb_context_unref(sys->xkb.ctx); + sys->xkb.ctx = NULL; + return -1; + } + + xcb_xkb_select_events_aux(conn, core, affect, 0, 0, map_parts, map_parts, + &details); + + InitKeyboard(wnd); + return 0; +} + +static void DeinitKeyboardExtension(vout_window_t *wnd) +{ + vout_window_sys_t *sys = wnd->sys; + + if (sys->xkb.ctx == NULL) + return; + + DeinitKeyboard(wnd); + xkb_context_unref(sys->xkb.ctx); +} +#else +# define InitKeyboardExtension(w) (w, -1) +# define DeinitKeyboardExtension(w) ((void)(w)) +#endif + static xcb_cursor_t CursorCreate(xcb_connection_t *conn, xcb_window_t root) { xcb_cursor_t cur = xcb_generate_id(conn); @@ -80,29 +231,14 @@ static int ProcessEvent(vout_window_t *wnd, xcb_generic_event_t *ev) { case XCB_KEY_PRESS: { -#ifdef HAVE_XCB_KEYSYMS +#ifdef HAVE_XCB_XKB xcb_key_press_event_t *e = (xcb_key_press_event_t *)ev; - xcb_keysym_t sym = xcb_key_press_lookup_keysym(sys->keys, e, 0); - uint_fast32_t vk = vlc_xkb_convert_keysym(sym); + uint_fast32_t vk = vlc_xkb_get_one(sys->xkb.state, e->detail - 8); msg_Dbg(wnd, "key: 0x%08"PRIxFAST32" (X11: 0x%04"PRIx32")", - vk, sym); + vk, e->detail); if (vk == KEY_UNSET) break; - if (e->state & XCB_MOD_MASK_SHIFT) /* Shift */ - vk |= KEY_MODIFIER_SHIFT; - /* XCB_MOD_MASK_LOCK */ /* Caps Lock */ - if (e->state & XCB_MOD_MASK_CONTROL) /* Control */ - vk |= KEY_MODIFIER_CTRL; - if (e->state & XCB_MOD_MASK_1) /* Alternate */ - vk |= KEY_MODIFIER_ALT; - /* XCB_MOD_MASK_2 */ /* Numeric Pad Lock */ - if (e->state & XCB_MOD_MASK_3) /* Super */ - vk |= KEY_MODIFIER_META; - if (e->state & XCB_MOD_MASK_4) /* Meta */ - vk |= KEY_MODIFIER_META; - if (e->state & XCB_MOD_MASK_5) /* Alternate Graphic */ - vk |= KEY_MODIFIER_ALT; vout_window_ReportKeyPress(wnd, vk); #endif @@ -151,17 +287,16 @@ static int ProcessEvent(vout_window_t *wnd, xcb_generic_event_t *ev) break; case XCB_MAPPING_NOTIFY: - { -#ifdef HAVE_XCB_KEYSYMS - xcb_mapping_notify_event_t *e = (xcb_mapping_notify_event_t *)ev; - - msg_Dbg(wnd, "refreshing keyboard mapping"); - xcb_refresh_keyboard_mapping(sys->keys, e); -#endif break; - } default: +#ifdef HAVE_XCB_XKB + if (sys->xkb.ctx != NULL && ev->response_type == sys->xkb.base) + { + ProcessKeyboardEvent(wnd, ev); + break; + } +#endif msg_Dbg (wnd, "unhandled event %"PRIu8, ev->response_type); } @@ -488,12 +623,8 @@ static int Open (vout_window_t *wnd, const vout_window_cfg_t *cfg) wnd->sys = p_sys; p_sys->conn = conn; -#ifdef HAVE_XCB_KEYSYMS - if (var_InheritBool (wnd, "keyboard-events")) - p_sys->keys = xcb_key_symbols_alloc(conn); - else - p_sys->keys = NULL; -#endif + if (var_InheritBool(wnd, "keyboard-events")) + InitKeyboardExtension(wnd); p_sys->root = scr->root; /* ICCCM @@ -565,10 +696,7 @@ static int Open (vout_window_t *wnd, const vout_window_cfg_t *cfg) * request from this thread must be completed at this point. */ if (vlc_clone (&p_sys->thread, Thread, wnd, VLC_THREAD_PRIORITY_LOW)) { -#ifdef HAVE_XCB_KEYSYMS - if (p_sys->keys != NULL) - xcb_key_symbols_free(p_sys->keys); -#endif + DeinitKeyboardExtension(wnd); goto error; } @@ -593,11 +721,8 @@ static void Close (vout_window_t *wnd) vlc_cancel (p_sys->thread); vlc_join (p_sys->thread, NULL); -#ifdef HAVE_XCB_KEYSYMS - if (p_sys->keys != NULL) - xcb_key_symbols_free(p_sys->keys); -#endif + DeinitKeyboardExtension(wnd); xcb_disconnect (conn); free (wnd->display.x11); free (p_sys); @@ -724,18 +849,11 @@ static int EmOpen (vout_window_t *wnd, const vout_window_cfg_t *cfg) vout_window_ReportSize(wnd, geo->width, geo->height); free (geo); -#ifdef HAVE_XCB_KEYSYMS /* Try to subscribe to keyboard and mouse events (only one X11 client can * subscribe to input events, so this can fail). */ - if (var_InheritBool (wnd, "keyboard-events")) - { - p_sys->keys = xcb_key_symbols_alloc(conn); - if (p_sys->keys != NULL) - value |= XCB_EVENT_MASK_KEY_PRESS; - } - else - p_sys->keys = NULL; -#endif + if (var_InheritBool(wnd, "keyboard-events") + && InitKeyboardExtension(wnd) == 0) + value |= XCB_EVENT_MASK_KEY_PRESS; if (var_InheritBool(wnd, "mouse-events")) value |= XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE; @@ -746,10 +864,7 @@ static int EmOpen (vout_window_t *wnd, const vout_window_cfg_t *cfg) CacheAtoms (p_sys); if (vlc_clone (&p_sys->thread, Thread, wnd, VLC_THREAD_PRIORITY_LOW)) { -#ifdef HAVE_XCB_KEYSYMS - if (p_sys->keys != NULL) - xcb_key_symbols_free(p_sys->keys); -#endif + DeinitKeyboardExtension(wnd); goto error; } _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
