summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/client.h4
-rw-r--r--src/input.c63
-rw-r--r--src/xlibclient.c66
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;
+}