Analogous to Xnest implementation at 83fef4235db86343477b4ec9858c6ba35e1aa7d9.
v4 changes: - Just a last-minute simplification in EphyrKeyboardInit(): there's no need to test explicitely if keySyms.map is NULL anymore, because hostx_load_keymap() now returns FALSE if that one can't be allocated. v3 changes: - Several changes in XCB code following Uli Schlachter's advices. v2 changes: - Keep struct KdKeyboardInfo untouched. - Move XkbApplyMappingChange()+XkbDDXChangeControls() call to EphyrKeyboardInit(), since it doesn't apply for e.g. kdrive evdev driver. - Call kdrive keyboard driver's Init() after InitKeyboardDeviceStruct(), so we can apply keymap change within EphyrKeyboardInit(), as described above. Signed-off-by: Laércio de Sousa <laercioso...@sme-mogidascruzes.sp.gov.br> --- configure.ac | 2 +- hw/kdrive/ephyr/ephyr.c | 30 ++++++++--- hw/kdrive/ephyr/hostx.c | 131 +++++++++++++++++++++++++++++++++++++++++++++--- hw/kdrive/ephyr/hostx.h | 9 +--- hw/kdrive/src/kinput.c | 8 +-- 5 files changed, 155 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index 2e38efa..933addc 100644 --- a/configure.ac +++ b/configure.ac @@ -2391,7 +2391,7 @@ if test "$KDRIVE" = yes; then AC_DEFINE(KDRIVE_MOUSE, 1, [Enable KDrive mouse driver]) fi - XEPHYR_REQUIRED_LIBS="xau xdmcp xcb xcb-shape xcb-render xcb-renderutil xcb-aux xcb-image xcb-icccm xcb-shm xcb-keysyms xcb-randr" + XEPHYR_REQUIRED_LIBS="xau xdmcp xcb xcb-shape xcb-render xcb-renderutil xcb-aux xcb-image xcb-icccm xcb-shm xcb-keysyms xcb-randr xcb-xkb" if test "x$XV" = xyes; then XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS xcb-xv" fi diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index 896bac5..0973b2b 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -54,7 +54,6 @@ extern Bool ephyr_glamor; KdKeyboardInfo *ephyrKbd; KdPointerInfo *ephyrMouse; -EphyrKeySyms ephyrKeySyms; Bool ephyrNoDRI = FALSE; Bool ephyrNoXV = FALSE; @@ -1367,16 +1366,35 @@ KdPointerDriver EphyrMouseDriver = { static Status EphyrKeyboardInit(KdKeyboardInfo * ki) { + int i; + KeySymsRec keySyms; + CARD8 modmap[MAP_LENGTH]; + XkbControlsRec controls; + ki->driverPrivate = (EphyrKbdPrivate *) calloc(sizeof(EphyrKbdPrivate), 1); - hostx_load_keymap(); - if (!ephyrKeySyms.minKeyCode) { + + if (hostx_load_keymap(&keySyms, modmap, &controls)) { + XkbApplyMappingChange(ki->dixdev, &keySyms, + keySyms.minKeyCode, + keySyms.maxKeyCode - keySyms.minKeyCode + 1, + modmap, serverClient); + XkbDDXChangeControls(ki->dixdev, &controls, &controls); + free(keySyms.map); + } + + if (!keySyms.minKeyCode) { ErrorF("Couldn't load keymap from host\n"); return BadAlloc; } - ki->minScanCode = ephyrKeySyms.minKeyCode; - ki->maxScanCode = ephyrKeySyms.maxKeyCode; - free(ki->name); + + ki->minScanCode = keySyms.minKeyCode; + ki->maxScanCode = keySyms.maxKeyCode; + + if (ki->name != NULL) { + free(ki->name); + } + ki->name = strdup("Xephyr virtual keyboard"); ephyrKbd = ki; return Success; diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index 49516bb..47cb97c 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -52,6 +52,7 @@ #include <xcb/shape.h> #include <xcb/xcb_keysyms.h> #include <xcb/randr.h> +#include <xcb/xkb.h> #ifdef XF86DRI #include <xcb/xf86dri.h> #include <xcb/glx.h> @@ -90,8 +91,6 @@ static EphyrHostXVars HostX; static int HostXWantDamageDebug = 0; -extern EphyrKeySyms ephyrKeySyms; - extern Bool EphyrWantResize; char *ephyrResName = NULL; @@ -1086,18 +1085,136 @@ hostx_paint_debug_rect(KdScreenInfo *screen, nanosleep(&tspec, NULL); } -void -hostx_load_keymap(void) +Bool +hostx_load_keymap(KeySymsPtr keySyms, CARD8 *modmap, XkbControlsPtr controls) { int min_keycode, max_keycode; - + int map_width; + size_t i, j; + int keymap_len; + xcb_keysym_t *keymap; + xcb_keycode_t *modifier_map; + xcb_get_keyboard_mapping_cookie_t mapping_c; + xcb_get_keyboard_mapping_reply_t *mapping_r; + xcb_get_modifier_mapping_cookie_t modifier_c; + xcb_get_modifier_mapping_reply_t *modifier_r; + xcb_xkb_use_extension_cookie_t use_c; + xcb_xkb_use_extension_reply_t *use_r; + xcb_xkb_get_controls_cookie_t controls_c; + xcb_xkb_get_controls_reply_t *controls_r; + + /* First of all, collect host X server's + * min_keycode and max_keycode, which are + * independent from XKB support. */ min_keycode = xcb_get_setup(HostX.conn)->min_keycode; max_keycode = xcb_get_setup(HostX.conn)->max_keycode; EPHYR_DBG("min: %d, max: %d", min_keycode, max_keycode); - ephyrKeySyms.minKeyCode = min_keycode; - ephyrKeySyms.maxKeyCode = max_keycode; + keySyms->minKeyCode = min_keycode; + keySyms->maxKeyCode = max_keycode; + + /* Check for XKB availabitity in host X server */ + if (!hostx_has_extension(&xcb_xkb_id)) { + EPHYR_LOG_ERROR("XKB extension is not supported in host X server."); + return FALSE; + } + + use_c = xcb_xkb_use_extension(HostX.conn, + XCB_XKB_MAJOR_VERSION, + XCB_XKB_MINOR_VERSION); + use_r = xcb_xkb_use_extension_reply(HostX.conn, use_c, NULL); + + if (!use_r) { + EPHYR_LOG_ERROR("Couldn't use XKB extension."); + return FALSE; + } else if (!use_r->supported) { + EPHYR_LOG_ERROR("XKB extension is not supported in host X server."); + free(use_r); + return FALSE; + } + + free(use_r); + + /* Send all needed XCB requests at once, + * and process the replies as needed. */ + mapping_c = xcb_get_keyboard_mapping(HostX.conn, + min_keycode, + max_keycode - min_keycode + 1); + modifier_c = xcb_get_modifier_mapping(HostX.conn); + controls_c = xcb_xkb_get_controls(HostX.conn, + XCB_XKB_ID_USE_CORE_KBD); + + mapping_r = xcb_get_keyboard_mapping_reply(HostX.conn, + mapping_c, + NULL); + + if (!mapping_r) { + EPHYR_LOG_ERROR("xcb_get_keyboard_mapping_reply() failed."); + return FALSE; + } + + map_width = mapping_r->keysyms_per_keycode; + keymap = xcb_get_keyboard_mapping_keysyms(mapping_r); + keymap_len = xcb_get_keyboard_mapping_keysyms_length(mapping_r); + + keySyms->mapWidth = map_width; + keySyms->map = calloc(keymap_len, sizeof(KeySym)); + + if (!keySyms->map) { + EPHYR_LOG_ERROR("Failed to allocate KeySym map."); + free(mapping_r); + return FALSE; + } + + for (i = 0; i < keymap_len; i++) { + keySyms->map[i] = keymap[i]; + } + + free(mapping_r); + + modifier_r = xcb_get_modifier_mapping_reply(HostX.conn, + modifier_c, + NULL); + + if (!modifier_r) { + EPHYR_LOG_ERROR("xcb_get_modifier_mapping_reply() failed."); + return FALSE; + } + + modifier_map = xcb_get_modifier_mapping_keycodes(modifier_r); + memset(modmap, 0, sizeof(CARD8) * MAP_LENGTH); + + for (j = 0; j < 8; j++) { + for (i = 0; i < modifier_r->keycodes_per_modifier; i++) { + CARD8 keycode; + + if ((keycode = modifier_map[j * modifier_r->keycodes_per_modifier + i])) { + modmap[keycode] |= 1 << j; + } + } + } + + free(modifier_r); + + controls_r = xcb_xkb_get_controls_reply(HostX.conn, + controls_c, + NULL); + + if (!controls_r) { + EPHYR_LOG_ERROR("xcb_xkb_get_controls_reply() failed."); + return FALSE; + } + + controls->enabled_ctrls = controls_r->enabledControls; + + for (i = 0; i < XkbPerKeyBitArraySize; i++) { + controls->per_key_repeat[i] = controls_r->perKeyRepeat[i]; + } + + free(controls_r); + + return TRUE; } xcb_connection_t * diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index d416dae..c907274 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -44,11 +44,6 @@ typedef struct EphyrHostXVars EphyrHostXVars; typedef struct { - int minKeyCode; - int maxKeyCode; -} EphyrKeySyms; - -typedef struct { VisualID visualid; int screen; int depth; @@ -153,8 +148,8 @@ void hostx_paint_rect(KdScreenInfo *screen, int sx, int sy, int dx, int dy, int width, int height); -void - hostx_load_keymap(void); +Bool +hostx_load_keymap(KeySymsPtr keySyms, CARD8 *modmap, XkbControlsPtr controls); xcb_connection_t * hostx_get_xcbconn(void); diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c index 1fdaa52..d46c2e1 100644 --- a/hw/kdrive/src/kinput.c +++ b/hw/kdrive/src/kinput.c @@ -742,10 +742,6 @@ KdKeyboardProc(DeviceIntPtr pDevice, int onoff) return BadImplementation; } - if ((*ki->driver->Init) (ki) != Success) { - return !Success; - } - memset(&rmlvo, 0, sizeof(rmlvo)); rmlvo.rules = ki->xkbRules; rmlvo.model = ki->xkbModel; @@ -758,6 +754,10 @@ KdKeyboardProc(DeviceIntPtr pDevice, int onoff) return BadImplementation; } + if ((*ki->driver->Init) (ki) != Success) { + return !Success; + } + xiclass = AtomFromName(XI_KEYBOARD); AssignTypeAndName(pDevice, xiclass, ki->name ? ki->name : "Generic KDrive Keyboard"); -- 2.1.4 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel