diff options
-rw-r--r-- | src/client.h | 4 | ||||
-rw-r--r-- | src/input.c | 63 | ||||
-rw-r--r-- | src/xlibclient.c | 66 |
3 files changed, 125 insertions, 8 deletions
diff --git a/src/client.h b/src/client.h index 6a652f1..4c73b3c 100644 --- a/src/client.h +++ b/src/client.h @@ -33,6 +33,8 @@ #include <misc.h> #include "xf86Cursor.h" +#include <X11/extensions/XKBstr.h> + struct NestedClientPrivate; typedef struct NestedClientPrivate *NestedClientPrivatePtr; @@ -69,3 +71,5 @@ void NestedClientCloseScreen(NestedClientPrivatePtr pPriv); void NestedClientSetDevicePtr(NestedClientPrivatePtr pPriv, DeviceIntPtr dev); int NestedClientGetFileDescriptor(NestedClientPrivatePtr pPriv); + +Bool NestedClientGetKeyboardMappings(NestedClientPrivatePtr pPriv, KeySymsPtr keySyms, CARD8 *modmap, XkbControlsPtr ctrls); diff --git a/src/input.c b/src/input.c index 7168764..66c05f5 100644 --- a/src/input.c +++ b/src/input.c @@ -45,6 +45,7 @@ #include <xf86Module.h> #include <xf86str.h> #include <xf86_OSproc.h> +#include <xkbsrv.h> #ifdef HAVE_CONFIG_H #include "config.h" @@ -131,10 +132,53 @@ static void NestedInputUnplug(pointer p) { } +static void +NestedInputUpdateKeymap(DeviceIntPtr device) { + InputInfoPtr pInfo = device->public.devicePrivate; + NestedInputDevicePtr pNestedInput = pInfo->private; + KeySymsRec keySyms; + XkbControlsRec ctrls; + CARD8 modmap[MAP_LENGTH]; + + if(!NestedClientGetKeyboardMappings(pNestedInput->clientData, &keySyms, modmap, &ctrls)) { + xf86Msg(X_ERROR, "%s: Failed to get keyboard mappings.\n", pInfo->name); + return; + } + +#ifdef _XSERVER64 + { + unsigned long *keymap64 = keySyms.map; + size_t len = (keySyms.maxKeyCode - keySyms.minKeyCode + 1) * keySyms.mapWidth; + size_t i; + + keySyms.map = malloc(len * sizeof(KeySym)); + if (!keySyms.map) { + xf86Msg(X_ERROR, "%s: Failed to get keyboard mappings.\n", pInfo->name); + free(keymap64); + return; + } + + for(i = 0; i < len; ++i) + keySyms.map[i] = keymap64[i]; + free(keymap64); + } +#endif + + XkbApplyMappingChange(device, &keySyms, keySyms.minKeyCode, + keySyms.maxKeyCode - keySyms.minKeyCode + 1, + modmap, serverClient); + XkbDDXChangeControls(device, &ctrls, &ctrls); + + free(keySyms.map); + + if (inputInfo.keyboard != device) + XkbCopyDeviceKeymap(inputInfo.keyboard, device); +} + static int _nested_input_init_keyboard(DeviceIntPtr device) { InputInfoPtr pInfo = device->public.devicePrivate; - + if (!InitKeyboardDeviceStruct(device, NULL, NULL, NULL)) { xf86Msg(X_ERROR, "%s: Failed to register keyboard.\n", pInfo->name); return BadAlloc; @@ -260,7 +304,10 @@ NestedInputReadInput(InputInfoPtr pInfo) { void NestedInputLoadDriver(NestedClientPrivatePtr clientData) { - + DeviceIntPtr dev; + InputInfoPtr pInfo; + NestedInputDevicePtr pNestedInput; + // Create input options for our invocation to NewInputDeviceRequest. InputOption* options = (InputOption*)malloc(sizeof(InputOption)); @@ -275,20 +322,22 @@ NestedInputLoadDriver(NestedClientPrivatePtr clientData) { // Invoke NewInputDeviceRequest to call the PreInit function of // the driver. - DeviceIntPtr dev; int ret = NewInputDeviceRequest(options, NULL, &dev); if (ret != Success) { FatalError("Failed to load input driver.\n"); } + pInfo = dev->public.devicePrivate; + pNestedInput = pInfo->private; + pNestedInput->clientData = clientData; + + // Set our keymap to be the same as the server's + NestedInputUpdateKeymap(dev); + // Send the device to the client so that the client can send the // device back to the input driver when events are being posted. NestedClientSetDevicePtr(clientData, dev); - - InputInfoPtr pInfo = dev->public.devicePrivate; - NestedInputDevicePtr pNestedInput = pInfo->private; - pNestedInput->clientData = clientData; } void diff --git a/src/xlibclient.c b/src/xlibclient.c index 337a9cb..0ef3d84 100644 --- a/src/xlibclient.c +++ b/src/xlibclient.c @@ -36,6 +36,7 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> +#include <X11/XKBlib.h> #include <X11/extensions/XShm.h> #include <xf86.h> @@ -64,6 +65,14 @@ struct NestedClientPrivate { XColor color1; DeviceIntPtr dev; // The pointer to the input device. Passed back to the // input driver when posting input events. + + struct { + int op; + int event; + int error; + int major; + int minor; + } xkb; }; /* Checks if a display is open */ @@ -161,7 +170,7 @@ NestedClientCreateScreen(int scrnIndex, Pixel *retBlueMask) { NestedClientPrivatePtr pPriv; XSizeHints sizeHints; - + Bool supported; char windowTitle[32]; pPriv = malloc(sizeof(struct NestedClientPrivate)); @@ -171,6 +180,14 @@ NestedClientCreateScreen(int scrnIndex, if (!pPriv->display) return NULL; + supported = XkbQueryExtension(pPriv->display, &pPriv->xkb.op, &pPriv->xkb.event, + &pPriv->xkb.error, &pPriv->xkb.major, &pPriv->xkb.minor); + if (!supported) { + xf86DrvMsg(pPriv->scrnIndex, X_ERROR, "The remote server does not support the XKEYBOARD extension.\n"); + XCloseDisplay(pPriv->display); + return NULL; + } + pPriv->screenNumber = DefaultScreen(pPriv->display); pPriv->screen = ScreenOfDisplay(pPriv->display, pPriv->screenNumber); pPriv->rootWindow = RootWindow(pPriv->display, pPriv->screenNumber); @@ -354,3 +371,50 @@ int NestedClientGetFileDescriptor(NestedClientPrivatePtr pPriv) { return ConnectionNumber(pPriv->display); } + +Bool NestedClientGetKeyboardMappings(NestedClientPrivatePtr pPriv, KeySymsPtr keySyms, CARD8 *modmap, XkbControlsPtr ctrls) { + XModifierKeymap *modifier_keymap; + KeySym *keymap; + int mapWidth; + int min_keycode, max_keycode; + int i, j; + XkbDescPtr xkb; + + XDisplayKeycodes(pPriv->display, &min_keycode, &max_keycode); + keymap = XGetKeyboardMapping(pPriv->display, + min_keycode, + max_keycode - min_keycode + 1, + &mapWidth); + + memset(modmap, 0, sizeof(CARD8) * MAP_LENGTH); + modifier_keymap = XGetModifierMapping(pPriv->display); + for (j = 0; j < 8; j++) + for(i = 0; i < modifier_keymap->max_keypermod; i++) { + CARD8 keycode; + if ((keycode = modifier_keymap->modifiermap[j * modifier_keymap->max_keypermod + i])) + modmap[keycode] |= 1<<j; + } + XFreeModifiermap(modifier_keymap); + + keySyms->minKeyCode = min_keycode; + keySyms->maxKeyCode = max_keycode; + keySyms->mapWidth = mapWidth; + keySyms->map = keymap; + + xkb = XkbGetKeyboard(pPriv->display, XkbGBN_AllComponentsMask, XkbUseCoreKbd); + if (xkb == NULL || xkb->geom == NULL) { + xf86DrvMsg(pPriv->scrnIndex, X_ERROR, "Couldn't get XKB keyboard.\n"); + free(keymap); + return FALSE; + } + + if(XkbGetControls(pPriv->display, XkbAllControlsMask, xkb) != Success) { + xf86DrvMsg(pPriv->scrnIndex, X_ERROR, "Couldn't get XKB keyboard controls.\n"); + free(keymap); + return FALSE; + } + + memcpy(ctrls, xkb->ctrls, sizeof(XkbControlsRec)); + XkbFreeKeyboard(xkb, 0, False); + return TRUE; +} |