|
|
1448d9 |
diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.cc.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.cc
|
|
|
1448d9 |
--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.cc.input 2012-08-29 09:56:37.000000000 +0100
|
|
|
1448d9 |
+++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.cc 2014-01-17 16:01:13.140109450 +0000
|
|
|
1448d9 |
@@ -1,5 +1,6 @@
|
|
|
1448d9 |
/* Copyright (C) 2009 TightVNC Team
|
|
|
1448d9 |
* Copyright (C) 2009 Red Hat, Inc.
|
|
|
1448d9 |
+ * Copyright 2013 Pierre Ossman for Cendio AB
|
|
|
1448d9 |
*
|
|
|
1448d9 |
* This is free software; you can redistribute it and/or modify
|
|
|
1448d9 |
* it under the terms of the GNU General Public License as published by
|
|
|
1448d9 |
@@ -34,16 +35,6 @@ extern "C" {
|
|
|
1448d9 |
#include "inpututils.h"
|
|
|
1448d9 |
#endif
|
|
|
1448d9 |
#include "mi.h"
|
|
|
1448d9 |
-#ifndef XKB_IN_SERVER
|
|
|
1448d9 |
-#define XKB_IN_SERVER
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
-#ifdef XKB
|
|
|
1448d9 |
-/*
|
|
|
1448d9 |
- * This include is needed to use XkbConvertCase instead of XConvertCase even if
|
|
|
1448d9 |
- * we don't use XKB extension.
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
-#include <xkbsrv.h>
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
#if XORG >= 16
|
|
|
1448d9 |
#include "exevents.h"
|
|
|
1448d9 |
#endif
|
|
|
1448d9 |
@@ -58,6 +49,7 @@ CopyKeyClass(DeviceIntPtr device, Device
|
|
|
1448d9 |
extern _X_EXPORT DevPrivateKey CoreDevicePrivateKey;
|
|
|
1448d9 |
#endif
|
|
|
1448d9 |
#include <X11/keysym.h>
|
|
|
1448d9 |
+#include <X11/Xlib.h>
|
|
|
1448d9 |
#include <X11/Xutil.h>
|
|
|
1448d9 |
#undef public
|
|
|
1448d9 |
#undef class
|
|
|
1448d9 |
@@ -72,12 +64,9 @@ using namespace rfb;
|
|
|
1448d9 |
|
|
|
1448d9 |
static LogWriter vlog("Input");
|
|
|
1448d9 |
|
|
|
1448d9 |
-#define BUTTONS 7
|
|
|
1448d9 |
-static int pointerProc(DeviceIntPtr pDevice, int onoff);
|
|
|
1448d9 |
+rfb::BoolParameter avoidShiftNumLock("AvoidShiftNumLock", "Avoid fake Shift presses for keys affected by NumLock.", true);
|
|
|
1448d9 |
|
|
|
1448d9 |
-static int keyboardProc(DeviceIntPtr pDevice, int onoff);
|
|
|
1448d9 |
-static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col);
|
|
|
1448d9 |
-static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col);
|
|
|
1448d9 |
+#define BUTTONS 7
|
|
|
1448d9 |
|
|
|
1448d9 |
/* Event queue is shared between all devices. */
|
|
|
1448d9 |
#if XORG == 15
|
|
|
1448d9 |
@@ -128,26 +117,16 @@ static void enqueueEvents(DeviceIntPtr d
|
|
|
1448d9 |
#endif /* XORG < 111 */
|
|
|
1448d9 |
|
|
|
1448d9 |
InputDevice::InputDevice(rfb::VNCServerST *_server)
|
|
|
1448d9 |
- : server(_server), oldButtonMask(0)
|
|
|
1448d9 |
+ : server(_server), initialized(false), oldButtonMask(0)
|
|
|
1448d9 |
{
|
|
|
1448d9 |
-#if XORG < 17
|
|
|
1448d9 |
- pointerDev = AddInputDevice(
|
|
|
1448d9 |
-#if XORG >= 16
|
|
|
1448d9 |
- serverClient,
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- pointerProc, TRUE);
|
|
|
1448d9 |
- RegisterPointerDevice(pointerDev);
|
|
|
1448d9 |
+ int i;
|
|
|
1448d9 |
|
|
|
1448d9 |
- keyboardDev = AddInputDevice(
|
|
|
1448d9 |
-#if XORG >= 16
|
|
|
1448d9 |
- serverClient,
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- keyboardProc, TRUE);
|
|
|
1448d9 |
- RegisterKeyboardDevice(keyboardDev);
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
#if XORG < 111
|
|
|
1448d9 |
initEventq();
|
|
|
1448d9 |
#endif
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (i = 0;i < 256;i++)
|
|
|
1448d9 |
+ pressedKeys[i] = NoSymbol;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
|
|
|
1448d9 |
void InputDevice::PointerButtonAction(int buttonMask)
|
|
|
1448d9 |
@@ -160,8 +139,6 @@ void InputDevice::PointerButtonAction(in
|
|
|
1448d9 |
ValuatorMask mask;
|
|
|
1448d9 |
#endif
|
|
|
1448d9 |
|
|
|
1448d9 |
- initInputDevice();
|
|
|
1448d9 |
-
|
|
|
1448d9 |
for (i = 0; i < BUTTONS; i++) {
|
|
|
1448d9 |
if ((buttonMask ^ oldButtonMask) & (1 << i)) {
|
|
|
1448d9 |
int action = (buttonMask & (1<
|
|
|
1448d9 |
@@ -199,8 +176,6 @@ void InputDevice::PointerMove(const rfb:
|
|
|
1448d9 |
if (pos.equals(cursorPos))
|
|
|
1448d9 |
return;
|
|
|
1448d9 |
|
|
|
1448d9 |
- initInputDevice();
|
|
|
1448d9 |
-
|
|
|
1448d9 |
valuators[0] = pos.x;
|
|
|
1448d9 |
valuators[1] = pos.y;
|
|
|
1448d9 |
#if XORG < 110
|
|
|
1448d9 |
@@ -287,16 +262,78 @@ static int pointerProc(DeviceIntPtr pDev
|
|
|
1448d9 |
return Success;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
|
|
|
1448d9 |
-void InputDevice::initInputDevice(void)
|
|
|
1448d9 |
+static void keyboardBell(int percent, DeviceIntPtr device, pointer ctrl,
|
|
|
1448d9 |
+ int class_)
|
|
|
1448d9 |
{
|
|
|
1448d9 |
+ if (percent > 0)
|
|
|
1448d9 |
+ vncBell();
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+extern void GetInitKeyboardMap(KeySymsPtr keysyms, CARD8 *modmap);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+static int keyboardProc(DeviceIntPtr pDevice, int onoff)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+#if XORG < 17
|
|
|
1448d9 |
+ KeySymsRec keySyms;
|
|
|
1448d9 |
+ CARD8 modMap[MAP_LENGTH];
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+ DevicePtr pDev = (DevicePtr)pDevice;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ switch (onoff) {
|
|
|
1448d9 |
+ case DEVICE_INIT:
|
|
|
1448d9 |
+#if XORG < 17
|
|
|
1448d9 |
+ GetInitKeyboardMap(&keySyms, modMap);
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+ InitKeyboardDeviceStruct(
|
|
|
1448d9 |
#if XORG >= 17
|
|
|
1448d9 |
- int ret;
|
|
|
1448d9 |
- static int initialized = 0;
|
|
|
1448d9 |
+ pDevice, NULL,
|
|
|
1448d9 |
+#else
|
|
|
1448d9 |
+ pDev, &keySyms, modMap,
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+ keyboardBell, (KbdCtrlProcPtr)NoopDDA);
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case DEVICE_ON:
|
|
|
1448d9 |
+ pDev->on = TRUE;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case DEVICE_OFF:
|
|
|
1448d9 |
+ pDev->on = FALSE;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
|
|
|
1448d9 |
- if (initialized != 0)
|
|
|
1448d9 |
+ return Success;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+void InputDevice::InitInputDevice(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ if (initialized)
|
|
|
1448d9 |
return;
|
|
|
1448d9 |
|
|
|
1448d9 |
- initialized = 1;
|
|
|
1448d9 |
+ initialized = true;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#if XORG < 17
|
|
|
1448d9 |
+ pointerDev = AddInputDevice(
|
|
|
1448d9 |
+#if XORG >= 16
|
|
|
1448d9 |
+ serverClient,
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+ pointerProc, TRUE);
|
|
|
1448d9 |
+ RegisterPointerDevice(pointerDev);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keyboardDev = AddInputDevice(
|
|
|
1448d9 |
+#if XORG >= 16
|
|
|
1448d9 |
+ serverClient,
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+ keyboardProc, TRUE);
|
|
|
1448d9 |
+ RegisterKeyboardDevice(keyboardDev);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (ActivateDevice(pointerDev) != Success ||
|
|
|
1448d9 |
+ ActivateDevice(keyboardDev) != Success)
|
|
|
1448d9 |
+ FatalError("Failed to activate TigerVNC devices\n");
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (!EnableDevice(pointerDev) ||
|
|
|
1448d9 |
+ !EnableDevice(keyboardDev))
|
|
|
1448d9 |
+ FatalError("Failed to enable TigerVNC devices\n");
|
|
|
1448d9 |
+#else /* < 17 */
|
|
|
1448d9 |
+ int ret;
|
|
|
1448d9 |
|
|
|
1448d9 |
ret = AllocDevicePair(serverClient, "TigerVNC", &pointerDev,
|
|
|
1448d9 |
&keyboardDev, pointerProc, keyboardProc,
|
|
|
1448d9 |
@@ -312,7 +349,9 @@ void InputDevice::initInputDevice(void)
|
|
|
1448d9 |
if (!EnableDevice(pointerDev, TRUE) ||
|
|
|
1448d9 |
!EnableDevice(keyboardDev, TRUE))
|
|
|
1448d9 |
FatalError("Failed to activate TigerVNC devices\n");
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
+#endif /* 17 */
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ PrepareInputDevices();
|
|
|
1448d9 |
}
|
|
|
1448d9 |
|
|
|
1448d9 |
static inline void pressKey(DeviceIntPtr dev, int kc, bool down, const char *msg)
|
|
|
1448d9 |
@@ -334,143 +373,6 @@ static inline void pressKey(DeviceIntPtr
|
|
|
1448d9 |
#endif
|
|
|
1448d9 |
}
|
|
|
1448d9 |
|
|
|
1448d9 |
-#define IS_PRESSED(keyc, keycode) \
|
|
|
1448d9 |
- ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-/*
|
|
|
1448d9 |
- * ModifierState is a class which helps simplify generating a "fake" press or
|
|
|
1448d9 |
- * release of shift, ctrl, alt, etc. An instance of the class is created for
|
|
|
1448d9 |
- * every modifier which may need to be pressed or released. Then either
|
|
|
1448d9 |
- * press() or release() may be called to make sure that the corresponding keys
|
|
|
1448d9 |
- * are in the right state. The destructor of the class automatically reverts
|
|
|
1448d9 |
- * to the previous state. Each modifier may have multiple keys associated with
|
|
|
1448d9 |
- * it, so in the case of a fake release, this may involve releasing more than
|
|
|
1448d9 |
- * one key.
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-class ModifierState {
|
|
|
1448d9 |
-public:
|
|
|
1448d9 |
- ModifierState(DeviceIntPtr _dev, int _modIndex)
|
|
|
1448d9 |
- : modIndex(_modIndex), nKeys(0), keys(0), pressed(false),
|
|
|
1448d9 |
- dev(_dev) {}
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- ~ModifierState()
|
|
|
1448d9 |
- {
|
|
|
1448d9 |
- for (int i = 0; i < nKeys; i++)
|
|
|
1448d9 |
- pressKey(dev, keys[i], !pressed, "fake keycode");
|
|
|
1448d9 |
- delete [] keys;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- void press()
|
|
|
1448d9 |
- {
|
|
|
1448d9 |
- int state, maxKeysPerMod, keycode;
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- KeyCode *modmap = NULL;
|
|
|
1448d9 |
-#if XORG >= 111
|
|
|
1448d9 |
- state = XkbStateFieldFromRec(&dev->master->key->xkbInfo->state);
|
|
|
1448d9 |
-#else /* XORG >= 111 */
|
|
|
1448d9 |
- state = XkbStateFieldFromRec(&dev->u.master->key->xkbInfo->state);
|
|
|
1448d9 |
-#endif /* XORG >= 111 */
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- KeyClassPtr keyc = dev->key;
|
|
|
1448d9 |
- state = keyc->state;
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- if ((state & (1 << modIndex)) != 0)
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- if (generate_modkeymap(serverClient, dev, &modmap,
|
|
|
1448d9 |
- &maxKeysPerMod) != Success) {
|
|
|
1448d9 |
- vlog.error("generate_modkeymap failed");
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- if (maxKeysPerMod == 0) {
|
|
|
1448d9 |
- vlog.debug("Keyboard has no modifiers");
|
|
|
1448d9 |
- xfree(modmap);
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- keycode = modmap[modIndex * maxKeysPerMod];
|
|
|
1448d9 |
- xfree(modmap);
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- maxKeysPerMod = keyc->maxKeysPerModifier;
|
|
|
1448d9 |
- keycode = keyc->modifierKeyMap[modIndex * maxKeysPerMod];
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- tempKeyEvent(keycode, true, maxKeysPerMod);
|
|
|
1448d9 |
- pressed = true;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- void release()
|
|
|
1448d9 |
- {
|
|
|
1448d9 |
- int state, maxKeysPerMod;
|
|
|
1448d9 |
- KeyClassPtr keyc;
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- KeyCode *modmap = NULL;
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-#if XORG >= 111
|
|
|
1448d9 |
- keyc = dev->master->key;
|
|
|
1448d9 |
-#else /* XORG >= 111 */
|
|
|
1448d9 |
- keyc = dev->u.master->key;
|
|
|
1448d9 |
-#endif /* XORG >= 111 */
|
|
|
1448d9 |
- state = XkbStateFieldFromRec(&keyc->xkbInfo->state);
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- keyc = dev->key;
|
|
|
1448d9 |
- state = keyc->state;
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- if ((state & (1 << modIndex)) == 0)
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- if (generate_modkeymap(serverClient, dev, &modmap,
|
|
|
1448d9 |
- &maxKeysPerMod) != Success) {
|
|
|
1448d9 |
- vlog.error("generate_modkeymap failed");
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- if (maxKeysPerMod == 0) {
|
|
|
1448d9 |
- vlog.debug("Keyboard has no modifiers");
|
|
|
1448d9 |
- xfree(modmap);
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- maxKeysPerMod = keyc->maxKeysPerModifier;
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- for (int k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
- int keycode;
|
|
|
1448d9 |
- int index = modIndex * maxKeysPerMod + k;
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- keycode = modmap[index];
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- keycode = keyc->modifierKeyMap[index];
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- if (keycode && IS_PRESSED(keyc, keycode))
|
|
|
1448d9 |
- tempKeyEvent(keycode, false, maxKeysPerMod);
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- xfree(modmap);
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-private:
|
|
|
1448d9 |
- void tempKeyEvent(int keycode, bool down, int maxKeysPerMod)
|
|
|
1448d9 |
- {
|
|
|
1448d9 |
- if (keycode) {
|
|
|
1448d9 |
- if (!keys) keys = new int[maxKeysPerMod];
|
|
|
1448d9 |
- keys[nKeys++] = keycode;
|
|
|
1448d9 |
- pressKey(dev, keycode, down, "fake keycode");
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- int modIndex;
|
|
|
1448d9 |
- int nKeys;
|
|
|
1448d9 |
- int *keys;
|
|
|
1448d9 |
- bool pressed;
|
|
|
1448d9 |
- DeviceIntPtr dev;
|
|
|
1448d9 |
-};
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-
|
|
|
1448d9 |
/* altKeysym is a table of alternative keysyms which have the same meaning. */
|
|
|
1448d9 |
|
|
|
1448d9 |
static struct altKeysym_t {
|
|
|
1448d9 |
@@ -517,102 +419,48 @@ static struct altKeysym_t {
|
|
|
1448d9 |
{ XK_KP_7, XK_7 },
|
|
|
1448d9 |
{ XK_KP_8, XK_8 },
|
|
|
1448d9 |
{ XK_KP_9, XK_9 },
|
|
|
1448d9 |
+ { XK_ISO_Level3_Shift, XK_Mode_switch },
|
|
|
1448d9 |
};
|
|
|
1448d9 |
|
|
|
1448d9 |
/*
|
|
|
1448d9 |
* keyEvent() - work out the best keycode corresponding to the keysym sent by
|
|
|
1448d9 |
- * the viewer. This is non-trivial because we can't assume much about the
|
|
|
1448d9 |
- * local keyboard layout. We must also find out which column of the keyboard
|
|
|
1448d9 |
- * mapping the keysym is in, and alter the shift state appropriately. Column 0
|
|
|
1448d9 |
- * means both shift and "mode_switch" (AltGr) must be released, column 1 means
|
|
|
1448d9 |
- * shift must be pressed and mode_switch released, column 2 means shift must be
|
|
|
1448d9 |
- * released and mode_switch pressed, and column 3 means both shift and
|
|
|
1448d9 |
- * mode_switch must be pressed.
|
|
|
1448d9 |
- *
|
|
|
1448d9 |
- * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org
|
|
|
1448d9 |
- * version. Quick explanation of that "magic":
|
|
|
1448d9 |
- *
|
|
|
1448d9 |
- * 1.5
|
|
|
1448d9 |
- * - has only one core keyboard so we have to keep core keyboard mapping
|
|
|
1448d9 |
- * synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard()
|
|
|
1448d9 |
- *
|
|
|
1448d9 |
- * 1.6 (aka MPX - Multi pointer X)
|
|
|
1448d9 |
- * - multiple master devices (= core devices) exists, keep vncKeyboardDevice
|
|
|
1448d9 |
- * synchronized with proper master device
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
-#define FREE_MAPS \
|
|
|
1448d9 |
- do { \
|
|
|
1448d9 |
- xfree(modmap); \
|
|
|
1448d9 |
- xfree(keymap->map); \
|
|
|
1448d9 |
- xfree(keymap); \
|
|
|
1448d9 |
- } while (0);
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
-#define FREE_MAPS
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
-/*
|
|
|
1448d9 |
- * Modifier keysyms must be handled differently. Instead of finding
|
|
|
1448d9 |
- * the right row and collumn in the keymap, directly press/release
|
|
|
1448d9 |
- * the keycode which is mapped as modifier with the same keysym.
|
|
|
1448d9 |
- *
|
|
|
1448d9 |
- * This will avoid issues when there are multiple modifier keysyms
|
|
|
1448d9 |
- * in the keymap but only some of them are mapped as modifiers in
|
|
|
1448d9 |
- * the modmap.
|
|
|
1448d9 |
- *
|
|
|
1448d9 |
- * Returns keycode of the modifier key.
|
|
|
1448d9 |
+ * the viewer. This is basically impossible in the general case, but we make
|
|
|
1448d9 |
+ * a best effort by assuming that all useful keysyms can be reached using
|
|
|
1448d9 |
+ * just the Shift and Level 3 (AltGr) modifiers. For core keyboards this is
|
|
|
1448d9 |
+ * basically always true, and should be true for most sane, western XKB
|
|
|
1448d9 |
+ * layouts.
|
|
|
1448d9 |
*/
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-static inline int isModifier(KeySymsPtr keymap, KeyCode *modmap,
|
|
|
1448d9 |
- int maxKeysPerMod, rdr::U32 keysym)
|
|
|
1448d9 |
+void InputDevice::keyEvent(rdr::U32 keysym, bool down)
|
|
|
1448d9 |
{
|
|
|
1448d9 |
- KeySym *map = keymap->map;
|
|
|
1448d9 |
- KeyCode minKeyCode = keymap->minKeyCode;
|
|
|
1448d9 |
- int mapWidth = keymap->mapWidth;
|
|
|
1448d9 |
- int i, j, k;
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- /* Find modifier index in the modmap */
|
|
|
1448d9 |
- for (i = 0; i < 8; i++) {
|
|
|
1448d9 |
- for (k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
- int index = i * maxKeysPerMod + k;
|
|
|
1448d9 |
- int keycode = modmap[index];
|
|
|
1448d9 |
+ int i;
|
|
|
1448d9 |
+ unsigned state, new_state;
|
|
|
1448d9 |
+ KeyCode keycode;
|
|
|
1448d9 |
|
|
|
1448d9 |
- if (keycode == 0)
|
|
|
1448d9 |
- continue;
|
|
|
1448d9 |
+ unsigned level_three_mask;
|
|
|
1448d9 |
+ KeyCode shift_press, level_three_press;
|
|
|
1448d9 |
+ std::list<KeyCode> shift_release, level_three_release;
|
|
|
1448d9 |
|
|
|
1448d9 |
- for (j = 0; j < mapWidth; j++) {
|
|
|
1448d9 |
- if (map[(keycode - minKeyCode) * mapWidth + j]
|
|
|
1448d9 |
- == keysym) {
|
|
|
1448d9 |
- return keycode;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * Release events must match the press event, so look up what
|
|
|
1448d9 |
+ * keycode we sent for the press.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ if (!down) {
|
|
|
1448d9 |
+ for (i = 0;i < 256;i++) {
|
|
|
1448d9 |
+ if (pressedKeys[i] == keysym) {
|
|
|
1448d9 |
+ pressedKeys[i] = NoSymbol;
|
|
|
1448d9 |
+ pressKey(keyboardDev, i, false, "keycode");
|
|
|
1448d9 |
+ mieqProcessInputEvents();
|
|
|
1448d9 |
+ return;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
}
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- return -1; /* Not a modifier */
|
|
|
1448d9 |
-}
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
|
|
|
1448d9 |
-void InputDevice::keyEvent(rdr::U32 keysym, bool down)
|
|
|
1448d9 |
-{
|
|
|
1448d9 |
-#if XORG < 17
|
|
|
1448d9 |
- DeviceIntPtr master;
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- KeyClassPtr keyc;
|
|
|
1448d9 |
- KeySymsPtr keymap = NULL;
|
|
|
1448d9 |
- KeySym *map = NULL;
|
|
|
1448d9 |
- KeyCode minKeyCode, maxKeyCode;
|
|
|
1448d9 |
- KeyCode *modmap = NULL;
|
|
|
1448d9 |
- int mapWidth;
|
|
|
1448d9 |
- unsigned int i;
|
|
|
1448d9 |
- int j, k, state, maxKeysPerMod;
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- KeybdCtrl ctrl;
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- initInputDevice();
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * This can happen quite often as we ignore some
|
|
|
1448d9 |
+ * key presses.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ vlog.debug("Unexpected release of keysym 0x%x", keysym);
|
|
|
1448d9 |
+ return;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
|
|
|
1448d9 |
/*
|
|
|
1448d9 |
* Since we are checking the current state to determine if we need
|
|
|
1448d9 |
@@ -622,543 +470,214 @@ void InputDevice::keyEvent(rdr::U32 keys
|
|
|
1448d9 |
*/
|
|
|
1448d9 |
mieqProcessInputEvents();
|
|
|
1448d9 |
|
|
|
1448d9 |
- if (keysym == XK_Caps_Lock) {
|
|
|
1448d9 |
- vlog.debug("Ignoring caps lock");
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
+ state = getKeyboardState();
|
|
|
1448d9 |
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
-#if XORG >= 111
|
|
|
1448d9 |
- keyc = keyboardDev->master->key;
|
|
|
1448d9 |
-#else /* XORG >= 111 */
|
|
|
1448d9 |
- keyc = keyboardDev->u.master->key;
|
|
|
1448d9 |
-#endif /* XORG >= 111 */
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- keymap = XkbGetCoreMap(keyboardDev);
|
|
|
1448d9 |
- if (!keymap) {
|
|
|
1448d9 |
- vlog.error("VNC keyboard device has no map");
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
+ keycode = keysymToKeycode(keysym, state, &new_state);
|
|
|
1448d9 |
|
|
|
1448d9 |
- if (generate_modkeymap(serverClient, keyboardDev, &modmap,
|
|
|
1448d9 |
- &maxKeysPerMod) != Success) {
|
|
|
1448d9 |
- vlog.error("generate_modkeymap failed");
|
|
|
1448d9 |
- xfree(keymap->map);
|
|
|
1448d9 |
- xfree(keymap);
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- if (maxKeysPerMod == 0)
|
|
|
1448d9 |
- vlog.debug("Keyboard has no modifiers");
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- state = XkbStateFieldFromRec(&keyc->xkbInfo->state);
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- keyc = keyboardDev->key;
|
|
|
1448d9 |
- state = keyc->state;
|
|
|
1448d9 |
- maxKeysPerMod = keyc->maxKeysPerModifier;
|
|
|
1448d9 |
- keymap = &keyc->curKeySyms;
|
|
|
1448d9 |
- modmap = keyc->modifierKeyMap;
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- map = keymap->map;
|
|
|
1448d9 |
- minKeyCode = keymap->minKeyCode;
|
|
|
1448d9 |
- maxKeyCode = keymap->maxKeyCode;
|
|
|
1448d9 |
- mapWidth = keymap->mapWidth;
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- /*
|
|
|
1448d9 |
- * No server-side key repeating, please. Some clients won't work well,
|
|
|
1448d9 |
- * check https://bugzilla.redhat.com/show_bug.cgi?id=607866.
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
- ctrl = keyboardDev->kbdfeed->ctrl;
|
|
|
1448d9 |
- if (ctrl.autoRepeat != FALSE) {
|
|
|
1448d9 |
- ctrl.autoRepeat = FALSE;
|
|
|
1448d9 |
- XkbSetRepeatKeys(keyboardDev, -1, ctrl.autoRepeat);
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- /* find which modifier Mode_switch is on. */
|
|
|
1448d9 |
- int modeSwitchMapIndex = 0;
|
|
|
1448d9 |
- for (i = 3; i < 8; i++) {
|
|
|
1448d9 |
- for (k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
- int index = i * maxKeysPerMod + k;
|
|
|
1448d9 |
- int keycode = modmap[index];
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- if (keycode == 0)
|
|
|
1448d9 |
+ /* Try some equivalent keysyms if we couldn't find a perfect match */
|
|
|
1448d9 |
+ if (keycode == 0) {
|
|
|
1448d9 |
+ for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {
|
|
|
1448d9 |
+ KeySym altsym;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (altKeysym[i].a == keysym)
|
|
|
1448d9 |
+ altsym = altKeysym[i].b;
|
|
|
1448d9 |
+ else if (altKeysym[i].b == keysym)
|
|
|
1448d9 |
+ altsym = altKeysym[i].a;
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
continue;
|
|
|
1448d9 |
|
|
|
1448d9 |
- for (j = 0; j < mapWidth; j++) {
|
|
|
1448d9 |
- if (map[(keycode - minKeyCode) * mapWidth + j]
|
|
|
1448d9 |
- == XK_Mode_switch) {
|
|
|
1448d9 |
- modeSwitchMapIndex = i;
|
|
|
1448d9 |
- goto ModeSwitchFound;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
+ keycode = keysymToKeycode(altsym, state, &new_state);
|
|
|
1448d9 |
+ if (keycode != 0)
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
}
|
|
|
1448d9 |
-ModeSwitchFound:
|
|
|
1448d9 |
|
|
|
1448d9 |
- int kc;
|
|
|
1448d9 |
- int col = 0;
|
|
|
1448d9 |
+ /* We don't have lock synchronisation... */
|
|
|
1448d9 |
+ if (isLockModifier(keycode, new_state)) {
|
|
|
1448d9 |
+ vlog.debug("Ignoring lock key (e.g. caps lock)");
|
|
|
1448d9 |
+ return;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- if ((kc = isModifier(keymap, modmap, maxKeysPerMod, keysym)) != -1) {
|
|
|
1448d9 |
- /*
|
|
|
1448d9 |
- * It is a modifier key event.
|
|
|
1448d9 |
- *
|
|
|
1448d9 |
- * Don't do any auto-repeat because the X server will translate
|
|
|
1448d9 |
- * each press into a release followed by a press.
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
- if (IS_PRESSED(keyc, kc) && down) {
|
|
|
1448d9 |
- FREE_MAPS;
|
|
|
1448d9 |
+ /* No matches. Will have to add a new entry... */
|
|
|
1448d9 |
+ if (keycode == 0) {
|
|
|
1448d9 |
+ keycode = addKeysym(keysym, state);
|
|
|
1448d9 |
+ if (keycode == 0) {
|
|
|
1448d9 |
+ vlog.error("Failure adding new keysym 0x%x", keysym);
|
|
|
1448d9 |
return;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
|
|
|
1448d9 |
- goto press;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- if (maxKeysPerMod != 0) {
|
|
|
1448d9 |
- if ((state & (1 << ShiftMapIndex)) != 0)
|
|
|
1448d9 |
- col |= 1;
|
|
|
1448d9 |
- if (modeSwitchMapIndex != 0 &&
|
|
|
1448d9 |
- ((state & (1 << modeSwitchMapIndex))) != 0)
|
|
|
1448d9 |
- col |= 2;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- kc = KeysymToKeycode(keymap, keysym, &col);
|
|
|
1448d9 |
+ vlog.info("Added unknown keysym 0x%x to keycode %d",
|
|
|
1448d9 |
+ keysym, keycode);
|
|
|
1448d9 |
|
|
|
1448d9 |
- /*
|
|
|
1448d9 |
- * Sort out the "shifted Tab" mess. If we are sent a shifted Tab,
|
|
|
1448d9 |
- * generate a local shifted Tab regardless of what the "shifted Tab"
|
|
|
1448d9 |
- * keysym is on the local keyboard (it might be Tab, ISO_Left_Tab or
|
|
|
1448d9 |
- * HP's private BackTab keysym, and quite possibly some others too).
|
|
|
1448d9 |
- * We never get ISO_Left_Tab here because it's already been translated
|
|
|
1448d9 |
- * in VNCSConnectionST.
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
- if (maxKeysPerMod != 0 && keysym == XK_Tab &&
|
|
|
1448d9 |
- ((state & (1 << ShiftMapIndex))) != 0)
|
|
|
1448d9 |
- col |= 1;
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- if (kc == 0) {
|
|
|
1448d9 |
/*
|
|
|
1448d9 |
- * Not a direct match in the local keyboard mapping. Check for
|
|
|
1448d9 |
- * alternative keysyms with the same meaning.
|
|
|
1448d9 |
+ * The state given to addKeysym() is just a hint and
|
|
|
1448d9 |
+ * the actual result might still require some state
|
|
|
1448d9 |
+ * changes.
|
|
|
1448d9 |
*/
|
|
|
1448d9 |
- for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) {
|
|
|
1448d9 |
- if (keysym == altKeysym[i].a)
|
|
|
1448d9 |
- kc = KeysymToKeycode(keymap, altKeysym[i].b,
|
|
|
1448d9 |
- &col);
|
|
|
1448d9 |
- else if (keysym == altKeysym[i].b)
|
|
|
1448d9 |
- kc = KeysymToKeycode(keymap, altKeysym[i].a,
|
|
|
1448d9 |
- &col);
|
|
|
1448d9 |
- if (kc)
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
+ keycode = keysymToKeycode(keysym, state, &new_state);
|
|
|
1448d9 |
+ if (keycode == 0) {
|
|
|
1448d9 |
+ vlog.error("Newly added keysym 0x%x cannot be generated", keysym);
|
|
|
1448d9 |
+ return;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
}
|
|
|
1448d9 |
|
|
|
1448d9 |
- if (kc == 0) {
|
|
|
1448d9 |
- /* Dynamically add a new key to the keyboard mapping. */
|
|
|
1448d9 |
- for (kc = maxKeyCode; kc >= minKeyCode; kc--) {
|
|
|
1448d9 |
- if (map[(kc - minKeyCode) * mapWidth] != 0)
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * X11 generally lets shift toggle the keys on the numeric pad
|
|
|
1448d9 |
+ * the same way NumLock does. This is however not the case on
|
|
|
1448d9 |
+ * other systems like Windows. As a result, some applications
|
|
|
1448d9 |
+ * get confused when we do a fake shift to get the same effect
|
|
|
1448d9 |
+ * that having NumLock active would produce.
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * Until we have proper NumLock synchronisation (so we can
|
|
|
1448d9 |
+ * avoid faking shift), we try to avoid the fake shifts if we
|
|
|
1448d9 |
+ * can use an alternative keysym.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ if (((state & ShiftMask) != (new_state & ShiftMask)) &&
|
|
|
1448d9 |
+ avoidShiftNumLock && isAffectedByNumLock(keycode)) {
|
|
|
1448d9 |
+ KeyCode keycode2;
|
|
|
1448d9 |
+ unsigned new_state2;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ vlog.debug("Finding alternative to keysym 0x%x to avoid fake shift for numpad", keysym);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {
|
|
|
1448d9 |
+ KeySym altsym;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (altKeysym[i].a == keysym)
|
|
|
1448d9 |
+ altsym = altKeysym[i].b;
|
|
|
1448d9 |
+ else if (altKeysym[i].b == keysym)
|
|
|
1448d9 |
+ altsym = altKeysym[i].a;
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
continue;
|
|
|
1448d9 |
|
|
|
1448d9 |
- map[(kc - minKeyCode) * mapWidth] = keysym;
|
|
|
1448d9 |
- col = 0;
|
|
|
1448d9 |
+ keycode2 = keysymToKeycode(altsym, state, &new_state2);
|
|
|
1448d9 |
+ if (keycode2 == 0)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
|
|
|
1448d9 |
- vlog.info("Added unknown keysym 0x%x to keycode %d",
|
|
|
1448d9 |
- keysym, kc);
|
|
|
1448d9 |
+ if (((state & ShiftMask) != (new_state2 & ShiftMask)) &&
|
|
|
1448d9 |
+ isAffectedByNumLock(keycode2))
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
|
|
|
1448d9 |
-#if XORG < 17
|
|
|
1448d9 |
-#if XORG == 15
|
|
|
1448d9 |
- master = inputInfo.keyboard;
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- master = keyboardDev->u.master;
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- void *slave = dixLookupPrivate(&master->devPrivates,
|
|
|
1448d9 |
- CoreDevicePrivateKey);
|
|
|
1448d9 |
- if (keyboardDev == slave) {
|
|
|
1448d9 |
- dixSetPrivate(&master->devPrivates,
|
|
|
1448d9 |
- CoreDevicePrivateKey, NULL);
|
|
|
1448d9 |
-#if XORG == 15
|
|
|
1448d9 |
- SwitchCoreKeyboard(keyboardDev);
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- CopyKeyClass(keyboardDev, master);
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-#else /* XORG < 17 */
|
|
|
1448d9 |
- XkbApplyMappingChange(keyboardDev, keymap, minKeyCode,
|
|
|
1448d9 |
- maxKeyCode - minKeyCode + 1,
|
|
|
1448d9 |
- NULL, serverClient);
|
|
|
1448d9 |
-#if XORG >= 111
|
|
|
1448d9 |
- XkbCopyDeviceKeymap(keyboardDev->master, keyboardDev);
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- XkbCopyDeviceKeymap(keyboardDev->u.master, keyboardDev);
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
-#endif /* XORG < 17 */
|
|
|
1448d9 |
break;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
|
|
|
1448d9 |
- if (kc < minKeyCode) {
|
|
|
1448d9 |
- vlog.info("Keyboard mapping full - ignoring unknown keysym "
|
|
|
1448d9 |
- "0x%x",keysym);
|
|
|
1448d9 |
- FREE_MAPS;
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-#if XORG < 17
|
|
|
1448d9 |
- /*
|
|
|
1448d9 |
- * See if it's a modifier key. If so, then don't do any auto-repeat,
|
|
|
1448d9 |
- * because the X server will translate each press into a release
|
|
|
1448d9 |
- * followed by a press.
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
- for (i = 0; i < 8; i++) {
|
|
|
1448d9 |
- for (k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
- int index = i * maxKeysPerMod + k;
|
|
|
1448d9 |
- if (kc == modmap[index] && IS_PRESSED(keyc,kc) && down) {
|
|
|
1448d9 |
- FREE_MAPS;
|
|
|
1448d9 |
- return;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
+ if (i == sizeof(altKeysym)/sizeof(altKeysym[0]))
|
|
|
1448d9 |
+ vlog.debug("No alternative keysym found");
|
|
|
1448d9 |
+ else {
|
|
|
1448d9 |
+ keycode = keycode2;
|
|
|
1448d9 |
+ new_state = new_state2;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
}
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
+
|
|
|
1448d9 |
/*
|
|
|
1448d9 |
- * If you would like to press a key which is already pressed then
|
|
|
1448d9 |
- * viewer didn't send the "release" event. In this case release it
|
|
|
1448d9 |
- * before the press.
|
|
|
1448d9 |
+ * "Shifted Tab" is a bit of a mess. Some systems have varying,
|
|
|
1448d9 |
+ * special keysyms for this symbol. VNC mandates that clients
|
|
|
1448d9 |
+ * should always send the plain XK_Tab keysym and the server
|
|
|
1448d9 |
+ * should deduce the meaning based on current Shift state.
|
|
|
1448d9 |
+ * To comply with this, we will find the keycode that sends
|
|
|
1448d9 |
+ * XK_Tab, and make sure that Shift isn't cleared. This can
|
|
|
1448d9 |
+ * possibly result in a different keysym than XK_Tab, but that
|
|
|
1448d9 |
+ * is the desired behaviour.
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * Note: We never get ISO_Left_Tab here because it's already
|
|
|
1448d9 |
+ * been translated in VNCSConnectionST.
|
|
|
1448d9 |
*/
|
|
|
1448d9 |
- if (IS_PRESSED(keyc, kc) && down) {
|
|
|
1448d9 |
- vlog.debug("KeyRelease for %d wasn't sent, releasing", kc);
|
|
|
1448d9 |
- pressKey(keyboardDev, kc, false, "fixing keycode");
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
+ if (keysym == XK_Tab && (state & ShiftMask))
|
|
|
1448d9 |
+ new_state |= ShiftMask;
|
|
|
1448d9 |
|
|
|
1448d9 |
- if (maxKeysPerMod != 0) {
|
|
|
1448d9 |
- ModifierState shift(keyboardDev, ShiftMapIndex);
|
|
|
1448d9 |
- ModifierState modeSwitch(keyboardDev, modeSwitchMapIndex);
|
|
|
1448d9 |
- if (down) {
|
|
|
1448d9 |
- if (col & 1)
|
|
|
1448d9 |
- shift.press();
|
|
|
1448d9 |
- else
|
|
|
1448d9 |
- shift.release();
|
|
|
1448d9 |
- if (modeSwitchMapIndex) {
|
|
|
1448d9 |
- if (col & 2)
|
|
|
1448d9 |
- modeSwitch.press();
|
|
|
1448d9 |
- else
|
|
|
1448d9 |
- modeSwitch.release();
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
- /*
|
|
|
1448d9 |
- * Ensure ModifierState objects are not destroyed before
|
|
|
1448d9 |
- * pressKey call, otherwise fake modifier keypress can be lost.
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
- pressKey(keyboardDev, kc, down, "keycode");
|
|
|
1448d9 |
- } else {
|
|
|
1448d9 |
-press:
|
|
|
1448d9 |
- pressKey(keyboardDev, kc, down, "keycode");
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- FREE_MAPS;
|
|
|
1448d9 |
-
|
|
|
1448d9 |
/*
|
|
|
1448d9 |
- * When faking a modifier we are putting a keycode (which can
|
|
|
1448d9 |
- * currently activate the desired modifier) on the input
|
|
|
1448d9 |
- * queue. A future modmap change can change the mapping so
|
|
|
1448d9 |
- * that this keycode means something else entirely. Guard
|
|
|
1448d9 |
- * against this by processing the queue now.
|
|
|
1448d9 |
+ * We need a bigger state change than just shift,
|
|
|
1448d9 |
+ * so we need to know what the mask is for level 3 shifts.
|
|
|
1448d9 |
*/
|
|
|
1448d9 |
- mieqProcessInputEvents();
|
|
|
1448d9 |
-}
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
|
|
|
1448d9 |
-{
|
|
|
1448d9 |
- int per = keymap->mapWidth;
|
|
|
1448d9 |
- KeySym *syms;
|
|
|
1448d9 |
- KeySym lsym, usym;
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- if ((col < 0) || ((col >= per) && (col > 3)) ||
|
|
|
1448d9 |
- (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
|
|
|
1448d9 |
- return NoSymbol;
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
|
|
|
1448d9 |
- if (col >= 4)
|
|
|
1448d9 |
- return syms[col];
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- if (col > 1) {
|
|
|
1448d9 |
- while ((per > 2) && (syms[per - 1] == NoSymbol))
|
|
|
1448d9 |
- per--;
|
|
|
1448d9 |
- if (per < 3)
|
|
|
1448d9 |
- col -= 2;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
|
|
|
1448d9 |
- XkbConvertCase
|
|
|
1448d9 |
- (syms[col&~1], &lsym, &usym);
|
|
|
1448d9 |
- if (!(col & 1))
|
|
|
1448d9 |
- return lsym;
|
|
|
1448d9 |
- /*
|
|
|
1448d9 |
- * I'm commenting out this logic because it's incorrect even
|
|
|
1448d9 |
- * though it was copied from the Xlib sources. The X protocol
|
|
|
1448d9 |
- * book quite clearly states that where a group consists of
|
|
|
1448d9 |
- * element 1 being a non-alphabetic keysym and element 2 being
|
|
|
1448d9 |
- * NoSymbol that you treat the second element as being the
|
|
|
1448d9 |
- * same as the first. This also tallies with the behaviour
|
|
|
1448d9 |
- * produced by the installed Xlib on my linux box (I believe
|
|
|
1448d9 |
- * this is because it uses some XKB code rather than the
|
|
|
1448d9 |
- * original Xlib code - compare XKBBind.c with KeyBind.c in
|
|
|
1448d9 |
- * lib/X11).
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
-#if 0
|
|
|
1448d9 |
- else if (usym == lsym)
|
|
|
1448d9 |
- return NoSymbol;
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- else
|
|
|
1448d9 |
- return usym;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
-
|
|
|
1448d9 |
- return syms[col];
|
|
|
1448d9 |
-}
|
|
|
1448d9 |
+ if ((new_state & ~ShiftMask) != (state & ~ShiftMask))
|
|
|
1448d9 |
+ level_three_mask = getLevelThreeMask();
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
+ level_three_mask = 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ shift_press = level_three_press = 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* Need a fake press or release of shift? */
|
|
|
1448d9 |
+ if (!(state & ShiftMask) && (new_state & ShiftMask)) {
|
|
|
1448d9 |
+ shift_press = pressShift();
|
|
|
1448d9 |
+ if (shift_press == 0) {
|
|
|
1448d9 |
+ vlog.error("Unable to find a modifier key for Shift");
|
|
|
1448d9 |
+ return;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
|
|
|
1448d9 |
-/*
|
|
|
1448d9 |
- * KeysymToKeycode() - find the keycode and column corresponding to the given
|
|
|
1448d9 |
- * keysym. The value of col passed in should be the column determined from the
|
|
|
1448d9 |
- * current shift state. If the keysym can be found in that column we prefer
|
|
|
1448d9 |
- * that to finding it in a different column (which would require fake events to
|
|
|
1448d9 |
- * alter the shift state).
|
|
|
1448d9 |
- */
|
|
|
1448d9 |
-static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col)
|
|
|
1448d9 |
-{
|
|
|
1448d9 |
- int i, j;
|
|
|
1448d9 |
+ pressKey(keyboardDev, shift_press, true, "temp shift");
|
|
|
1448d9 |
+ } else if ((state & ShiftMask) && !(new_state & ShiftMask)) {
|
|
|
1448d9 |
+ std::list<KeyCode>::const_iterator iter;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ shift_release = releaseShift();
|
|
|
1448d9 |
+ if (shift_release.empty()) {
|
|
|
1448d9 |
+ vlog.error("Unable to find the modifier key(s) for releasing Shift");
|
|
|
1448d9 |
+ return;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
|
|
|
1448d9 |
- j = *col;
|
|
|
1448d9 |
- for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
|
|
|
1448d9 |
- if (KeyCodetoKeySym(keymap, i, j) == ks)
|
|
|
1448d9 |
- return i;
|
|
|
1448d9 |
+ for (iter = shift_release.begin();iter != shift_release.end();++iter)
|
|
|
1448d9 |
+ pressKey(keyboardDev, *iter, false, "temp shift");
|
|
|
1448d9 |
}
|
|
|
1448d9 |
|
|
|
1448d9 |
- for (j = 0; j < keymap->mapWidth; j++) {
|
|
|
1448d9 |
- for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
|
|
|
1448d9 |
- if (KeyCodetoKeySym(keymap, i, j) == ks) {
|
|
|
1448d9 |
- *col = j;
|
|
|
1448d9 |
- return i;
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
+ /* Need a fake press or release of level three shift? */
|
|
|
1448d9 |
+ if (!(state & level_three_mask) && (new_state & level_three_mask)) {
|
|
|
1448d9 |
+ level_three_press = pressLevelThree();
|
|
|
1448d9 |
+ if (level_three_press == 0) {
|
|
|
1448d9 |
+ vlog.error("Unable to find a modifier key for ISO_Level3_Shift/Mode_Switch");
|
|
|
1448d9 |
+ return;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
- }
|
|
|
1448d9 |
|
|
|
1448d9 |
- return 0;
|
|
|
1448d9 |
-}
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-#if XORG < 17
|
|
|
1448d9 |
-/* Fairly standard US PC Keyboard */
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-#define MIN_KEY 8
|
|
|
1448d9 |
-#define MAX_KEY 255
|
|
|
1448d9 |
-#define MAP_LEN (MAX_KEY - MIN_KEY + 1)
|
|
|
1448d9 |
-#define KEYSYMS_PER_KEY 2
|
|
|
1448d9 |
-KeySym keyboardMap[MAP_LEN * KEYSYMS_PER_KEY] = {
|
|
|
1448d9 |
- NoSymbol, NoSymbol,
|
|
|
1448d9 |
- XK_Escape, NoSymbol,
|
|
|
1448d9 |
- XK_1, XK_exclam,
|
|
|
1448d9 |
- XK_2, XK_at,
|
|
|
1448d9 |
- XK_3, XK_numbersign,
|
|
|
1448d9 |
- XK_4, XK_dollar,
|
|
|
1448d9 |
- XK_5, XK_percent,
|
|
|
1448d9 |
- XK_6, XK_asciicircum,
|
|
|
1448d9 |
- XK_7, XK_ampersand,
|
|
|
1448d9 |
- XK_8, XK_asterisk,
|
|
|
1448d9 |
- XK_9, XK_parenleft,
|
|
|
1448d9 |
- XK_0, XK_parenright,
|
|
|
1448d9 |
- XK_minus, XK_underscore,
|
|
|
1448d9 |
- XK_equal, XK_plus,
|
|
|
1448d9 |
- XK_BackSpace, NoSymbol,
|
|
|
1448d9 |
- XK_Tab, NoSymbol,
|
|
|
1448d9 |
- XK_q, XK_Q,
|
|
|
1448d9 |
- XK_w, XK_W,
|
|
|
1448d9 |
- XK_e, XK_E,
|
|
|
1448d9 |
- XK_r, XK_R,
|
|
|
1448d9 |
- XK_t, XK_T,
|
|
|
1448d9 |
- XK_y, XK_Y,
|
|
|
1448d9 |
- XK_u, XK_U,
|
|
|
1448d9 |
- XK_i, XK_I,
|
|
|
1448d9 |
- XK_o, XK_O,
|
|
|
1448d9 |
- XK_p, XK_P,
|
|
|
1448d9 |
- XK_bracketleft, XK_braceleft,
|
|
|
1448d9 |
- XK_bracketright, XK_braceright,
|
|
|
1448d9 |
- XK_Return, NoSymbol,
|
|
|
1448d9 |
- XK_Control_L, NoSymbol,
|
|
|
1448d9 |
- XK_a, XK_A,
|
|
|
1448d9 |
- XK_s, XK_S,
|
|
|
1448d9 |
- XK_d, XK_D,
|
|
|
1448d9 |
- XK_f, XK_F,
|
|
|
1448d9 |
- XK_g, XK_G,
|
|
|
1448d9 |
- XK_h, XK_H,
|
|
|
1448d9 |
- XK_j, XK_J,
|
|
|
1448d9 |
- XK_k, XK_K,
|
|
|
1448d9 |
- XK_l, XK_L,
|
|
|
1448d9 |
- XK_semicolon, XK_colon,
|
|
|
1448d9 |
- XK_apostrophe, XK_quotedbl,
|
|
|
1448d9 |
- XK_grave, XK_asciitilde,
|
|
|
1448d9 |
- XK_Shift_L, NoSymbol,
|
|
|
1448d9 |
- XK_backslash, XK_bar,
|
|
|
1448d9 |
- XK_z, XK_Z,
|
|
|
1448d9 |
- XK_x, XK_X,
|
|
|
1448d9 |
- XK_c, XK_C,
|
|
|
1448d9 |
- XK_v, XK_V,
|
|
|
1448d9 |
- XK_b, XK_B,
|
|
|
1448d9 |
- XK_n, XK_N,
|
|
|
1448d9 |
- XK_m, XK_M,
|
|
|
1448d9 |
- XK_comma, XK_less,
|
|
|
1448d9 |
- XK_period, XK_greater,
|
|
|
1448d9 |
- XK_slash, XK_question,
|
|
|
1448d9 |
- XK_Shift_R, NoSymbol,
|
|
|
1448d9 |
- XK_KP_Multiply, NoSymbol,
|
|
|
1448d9 |
- XK_Alt_L, XK_Meta_L,
|
|
|
1448d9 |
- XK_space, NoSymbol,
|
|
|
1448d9 |
- XK_Caps_Lock, NoSymbol,
|
|
|
1448d9 |
- XK_F1, NoSymbol,
|
|
|
1448d9 |
- XK_F2, NoSymbol,
|
|
|
1448d9 |
- XK_F3, NoSymbol,
|
|
|
1448d9 |
- XK_F4, NoSymbol,
|
|
|
1448d9 |
- XK_F5, NoSymbol,
|
|
|
1448d9 |
- XK_F6, NoSymbol,
|
|
|
1448d9 |
- XK_F7, NoSymbol,
|
|
|
1448d9 |
- XK_F8, NoSymbol,
|
|
|
1448d9 |
- XK_F9, NoSymbol,
|
|
|
1448d9 |
- XK_F10, NoSymbol,
|
|
|
1448d9 |
- XK_Num_Lock, XK_Pointer_EnableKeys,
|
|
|
1448d9 |
- XK_Scroll_Lock, NoSymbol,
|
|
|
1448d9 |
- XK_KP_Home, XK_KP_7,
|
|
|
1448d9 |
- XK_KP_Up, XK_KP_8,
|
|
|
1448d9 |
- XK_KP_Prior, XK_KP_9,
|
|
|
1448d9 |
- XK_KP_Subtract, NoSymbol,
|
|
|
1448d9 |
- XK_KP_Left, XK_KP_4,
|
|
|
1448d9 |
- XK_KP_Begin, XK_KP_5,
|
|
|
1448d9 |
- XK_KP_Right, XK_KP_6,
|
|
|
1448d9 |
- XK_KP_Add, NoSymbol,
|
|
|
1448d9 |
- XK_KP_End, XK_KP_1,
|
|
|
1448d9 |
- XK_KP_Down, XK_KP_2,
|
|
|
1448d9 |
- XK_KP_Next, XK_KP_3,
|
|
|
1448d9 |
- XK_KP_Insert, XK_KP_0,
|
|
|
1448d9 |
- XK_KP_Delete, XK_KP_Decimal,
|
|
|
1448d9 |
- NoSymbol, NoSymbol,
|
|
|
1448d9 |
- NoSymbol, NoSymbol,
|
|
|
1448d9 |
- NoSymbol, NoSymbol,
|
|
|
1448d9 |
- XK_F11, NoSymbol,
|
|
|
1448d9 |
- XK_F12, NoSymbol,
|
|
|
1448d9 |
- XK_Home, NoSymbol,
|
|
|
1448d9 |
- XK_Up, NoSymbol,
|
|
|
1448d9 |
- XK_Prior, NoSymbol,
|
|
|
1448d9 |
- XK_Left, NoSymbol,
|
|
|
1448d9 |
- NoSymbol, NoSymbol,
|
|
|
1448d9 |
- XK_Right, NoSymbol,
|
|
|
1448d9 |
- XK_End, NoSymbol,
|
|
|
1448d9 |
- XK_Down, NoSymbol,
|
|
|
1448d9 |
- XK_Next, NoSymbol,
|
|
|
1448d9 |
- XK_Insert, NoSymbol,
|
|
|
1448d9 |
- XK_Delete, NoSymbol,
|
|
|
1448d9 |
- XK_KP_Enter, NoSymbol,
|
|
|
1448d9 |
- XK_Control_R, NoSymbol,
|
|
|
1448d9 |
- XK_Pause, XK_Break,
|
|
|
1448d9 |
- XK_Print, XK_Execute,
|
|
|
1448d9 |
- XK_KP_Divide, NoSymbol,
|
|
|
1448d9 |
- XK_Alt_R, XK_Meta_R,
|
|
|
1448d9 |
- NoSymbol, NoSymbol,
|
|
|
1448d9 |
- XK_Super_L, NoSymbol,
|
|
|
1448d9 |
- XK_Super_R, NoSymbol,
|
|
|
1448d9 |
- XK_Menu, NoSymbol,
|
|
|
1448d9 |
-};
|
|
|
1448d9 |
+ pressKey(keyboardDev, level_three_press, true, "temp level 3 shift");
|
|
|
1448d9 |
+ } else if ((state & level_three_mask) && !(new_state & level_three_mask)) {
|
|
|
1448d9 |
+ std::list<KeyCode>::const_iterator iter;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ level_three_release = releaseLevelThree();
|
|
|
1448d9 |
+ if (level_three_release.empty()) {
|
|
|
1448d9 |
+ vlog.error("Unable to find the modifier key(s) for releasing ISO_Level3_Shift/Mode_Switch");
|
|
|
1448d9 |
+ return;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
|
|
|
1448d9 |
-static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap)
|
|
|
1448d9 |
-{
|
|
|
1448d9 |
- int i;
|
|
|
1448d9 |
+ for (iter = level_three_release.begin();iter != level_three_release.end();++iter)
|
|
|
1448d9 |
+ pressKey(keyboardDev, *iter, false, "temp level 3 shift");
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
|
|
|
1448d9 |
- for (i = 0; i < MAP_LENGTH; i++)
|
|
|
1448d9 |
- pModMap[i] = NoSymbol;
|
|
|
1448d9 |
+ /* Now press the actual key */
|
|
|
1448d9 |
+ pressKey(keyboardDev, keycode, true, "keycode");
|
|
|
1448d9 |
|
|
|
1448d9 |
- for (i = 0; i < MAP_LEN; i++) {
|
|
|
1448d9 |
- switch (keyboardMap[i * KEYSYMS_PER_KEY]) {
|
|
|
1448d9 |
- case XK_Shift_L:
|
|
|
1448d9 |
- case XK_Shift_R:
|
|
|
1448d9 |
- pModMap[i + MIN_KEY] = ShiftMask;
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
- case XK_Caps_Lock:
|
|
|
1448d9 |
- pModMap[i + MIN_KEY] = LockMask;
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
- case XK_Control_L:
|
|
|
1448d9 |
- case XK_Control_R:
|
|
|
1448d9 |
- pModMap[i + MIN_KEY] = ControlMask;
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
- case XK_Alt_L:
|
|
|
1448d9 |
- case XK_Alt_R:
|
|
|
1448d9 |
- pModMap[i + MIN_KEY] = Mod1Mask;
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
- case XK_Num_Lock:
|
|
|
1448d9 |
- pModMap[i + MIN_KEY] = Mod2Mask;
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
- /* No defaults for Mod3Mask yet */
|
|
|
1448d9 |
- case XK_Super_L:
|
|
|
1448d9 |
- case XK_Super_R:
|
|
|
1448d9 |
- case XK_Hyper_L:
|
|
|
1448d9 |
- case XK_Hyper_R:
|
|
|
1448d9 |
- pModMap[i + MIN_KEY] = Mod4Mask;
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
- case XK_ISO_Level3_Shift:
|
|
|
1448d9 |
- case XK_Mode_switch:
|
|
|
1448d9 |
- pModMap[i + MIN_KEY] = Mod5Mask;
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
+ /* And store the mapping so that we can do a proper release later */
|
|
|
1448d9 |
+ for (i = 0;i < 256;i++) {
|
|
|
1448d9 |
+ if (i == keycode)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+ if (pressedKeys[i] == keysym) {
|
|
|
1448d9 |
+ vlog.error("Keysym 0x%x generated by both keys %d and %d", keysym, i, keycode);
|
|
|
1448d9 |
+ pressedKeys[i] = NoSymbol;
|
|
|
1448d9 |
}
|
|
|
1448d9 |
}
|
|
|
1448d9 |
|
|
|
1448d9 |
- pKeySyms->minKeyCode = MIN_KEY;
|
|
|
1448d9 |
- pKeySyms->maxKeyCode = MAX_KEY;
|
|
|
1448d9 |
- pKeySyms->mapWidth = KEYSYMS_PER_KEY;
|
|
|
1448d9 |
- pKeySyms->map = keyboardMap;
|
|
|
1448d9 |
+ pressedKeys[keycode] = keysym;
|
|
|
1448d9 |
|
|
|
1448d9 |
- return TRUE;
|
|
|
1448d9 |
-}
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-static void keyboardBell(int percent, DeviceIntPtr device, pointer ctrl,
|
|
|
1448d9 |
- int class_)
|
|
|
1448d9 |
-{
|
|
|
1448d9 |
- if (percent > 0)
|
|
|
1448d9 |
- vncBell();
|
|
|
1448d9 |
-}
|
|
|
1448d9 |
-
|
|
|
1448d9 |
-static int keyboardProc(DeviceIntPtr pDevice, int onoff)
|
|
|
1448d9 |
-{
|
|
|
1448d9 |
-#if XORG < 17
|
|
|
1448d9 |
- KeySymsRec keySyms;
|
|
|
1448d9 |
- CARD8 modMap[MAP_LENGTH];
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- DevicePtr pDev = (DevicePtr)pDevice;
|
|
|
1448d9 |
+ /* Undo any fake level three shift */
|
|
|
1448d9 |
+ if (level_three_press != 0)
|
|
|
1448d9 |
+ pressKey(keyboardDev, level_three_press, false, "temp level 3 shift");
|
|
|
1448d9 |
+ else if (!level_three_release.empty()) {
|
|
|
1448d9 |
+ std::list<KeyCode>::const_iterator iter;
|
|
|
1448d9 |
+ for (iter = level_three_release.begin();iter != level_three_release.end();++iter)
|
|
|
1448d9 |
+ pressKey(keyboardDev, *iter, true, "temp level 3 shift");
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
|
|
|
1448d9 |
- switch (onoff) {
|
|
|
1448d9 |
- case DEVICE_INIT:
|
|
|
1448d9 |
-#if XORG < 17
|
|
|
1448d9 |
- GetMappings(&keySyms, modMap);
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- InitKeyboardDeviceStruct(
|
|
|
1448d9 |
-#if XORG >= 17
|
|
|
1448d9 |
- pDevice, NULL,
|
|
|
1448d9 |
-#else
|
|
|
1448d9 |
- pDev, &keySyms, modMap,
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
- keyboardBell, (KbdCtrlProcPtr)NoopDDA);
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
- case DEVICE_ON:
|
|
|
1448d9 |
- pDev->on = TRUE;
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
- case DEVICE_OFF:
|
|
|
1448d9 |
- pDev->on = FALSE;
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
-#if 0
|
|
|
1448d9 |
- case DEVICE_CLOSE:
|
|
|
1448d9 |
- break;
|
|
|
1448d9 |
-#endif
|
|
|
1448d9 |
+ /* Undo any fake shift */
|
|
|
1448d9 |
+ if (shift_press != 0)
|
|
|
1448d9 |
+ pressKey(keyboardDev, shift_press, false, "temp shift");
|
|
|
1448d9 |
+ else if (!shift_release.empty()) {
|
|
|
1448d9 |
+ std::list<KeyCode>::const_iterator iter;
|
|
|
1448d9 |
+ for (iter = shift_release.begin();iter != shift_release.end();++iter)
|
|
|
1448d9 |
+ pressKey(keyboardDev, *iter, true, "temp shift");
|
|
|
1448d9 |
}
|
|
|
1448d9 |
|
|
|
1448d9 |
- return Success;
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * When faking a modifier we are putting a keycode (which can
|
|
|
1448d9 |
+ * currently activate the desired modifier) on the input
|
|
|
1448d9 |
+ * queue. A future modmap change can change the mapping so
|
|
|
1448d9 |
+ * that this keycode means something else entirely. Guard
|
|
|
1448d9 |
+ * against this by processing the queue now.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ mieqProcessInputEvents();
|
|
|
1448d9 |
}
|
|
|
1448d9 |
-
|
|
|
1448d9 |
diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputCore.cc.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputCore.cc
|
|
|
1448d9 |
--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputCore.cc.input 2014-01-17 16:01:13.141109454 +0000
|
|
|
1448d9 |
+++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputCore.cc 2014-01-17 16:01:13.141109454 +0000
|
|
|
1448d9 |
@@ -0,0 +1,594 @@
|
|
|
1448d9 |
+/* Copyright (C) 2009 TightVNC Team
|
|
|
1448d9 |
+ * Copyright (C) 2009 Red Hat, Inc.
|
|
|
1448d9 |
+ * Copyright 2013 Pierre Ossman for Cendio AB
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * This is free software; you can redistribute it and/or modify
|
|
|
1448d9 |
+ * it under the terms of the GNU General Public License as published by
|
|
|
1448d9 |
+ * the Free Software Foundation; either version 2 of the License, or
|
|
|
1448d9 |
+ * (at your option) any later version.
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * This software is distributed in the hope that it will be useful,
|
|
|
1448d9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
1448d9 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
1448d9 |
+ * GNU General Public License for more details.
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * You should have received a copy of the GNU General Public License
|
|
|
1448d9 |
+ * along with this software; if not, write to the Free Software
|
|
|
1448d9 |
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
|
1448d9 |
+ * USA.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#ifdef HAVE_DIX_CONFIG_H
|
|
|
1448d9 |
+#include <dix-config.h>
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#include "Input.h"
|
|
|
1448d9 |
+#include "xorg-version.h"
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+extern "C" {
|
|
|
1448d9 |
+#define public c_public
|
|
|
1448d9 |
+#define class c_class
|
|
|
1448d9 |
+#include "inputstr.h"
|
|
|
1448d9 |
+#ifndef XKB_IN_SERVER
|
|
|
1448d9 |
+#define XKB_IN_SERVER
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+#ifdef XKB
|
|
|
1448d9 |
+/*
|
|
|
1448d9 |
+ * This include is needed to use XkbConvertCase instead of XConvertCase even if
|
|
|
1448d9 |
+ * we don't use XKB extension.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+#include <xkbsrv.h>
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+/* These defines give us access to all keysyms we need */
|
|
|
1448d9 |
+#define XK_PUBLISHING
|
|
|
1448d9 |
+#define XK_TECHNICAL
|
|
|
1448d9 |
+#include <X11/keysym.h>
|
|
|
1448d9 |
+#include <X11/XF86keysym.h>
|
|
|
1448d9 |
+#include <X11/Xlib.h>
|
|
|
1448d9 |
+#include <X11/Xutil.h>
|
|
|
1448d9 |
+#undef public
|
|
|
1448d9 |
+#undef class
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#if XORG < 17
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#define IS_PRESSED(dev, keycode) \
|
|
|
1448d9 |
+ ((dev)->key->down[(keycode) >> 3] & (1 << ((keycode) & 7)))
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+/* Fairly standard US PC Keyboard */
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#define MIN_KEY 8
|
|
|
1448d9 |
+#define MAX_KEY 255
|
|
|
1448d9 |
+#define MAP_LEN (MAX_KEY - MIN_KEY + 1)
|
|
|
1448d9 |
+#define KEYSYMS_PER_KEY 2
|
|
|
1448d9 |
+KeySym keyboardMap[MAP_LEN * KEYSYMS_PER_KEY] = {
|
|
|
1448d9 |
+ NoSymbol, NoSymbol,
|
|
|
1448d9 |
+ XK_Escape, NoSymbol,
|
|
|
1448d9 |
+ XK_1, XK_exclam,
|
|
|
1448d9 |
+ XK_2, XK_at,
|
|
|
1448d9 |
+ XK_3, XK_numbersign,
|
|
|
1448d9 |
+ XK_4, XK_dollar,
|
|
|
1448d9 |
+ XK_5, XK_percent,
|
|
|
1448d9 |
+ XK_6, XK_asciicircum,
|
|
|
1448d9 |
+ XK_7, XK_ampersand,
|
|
|
1448d9 |
+ XK_8, XK_asterisk,
|
|
|
1448d9 |
+ XK_9, XK_parenleft,
|
|
|
1448d9 |
+ XK_0, XK_parenright,
|
|
|
1448d9 |
+ XK_minus, XK_underscore,
|
|
|
1448d9 |
+ XK_equal, XK_plus,
|
|
|
1448d9 |
+ XK_BackSpace, NoSymbol,
|
|
|
1448d9 |
+ XK_Tab, NoSymbol,
|
|
|
1448d9 |
+ XK_q, XK_Q,
|
|
|
1448d9 |
+ XK_w, XK_W,
|
|
|
1448d9 |
+ XK_e, XK_E,
|
|
|
1448d9 |
+ XK_r, XK_R,
|
|
|
1448d9 |
+ XK_t, XK_T,
|
|
|
1448d9 |
+ XK_y, XK_Y,
|
|
|
1448d9 |
+ XK_u, XK_U,
|
|
|
1448d9 |
+ XK_i, XK_I,
|
|
|
1448d9 |
+ XK_o, XK_O,
|
|
|
1448d9 |
+ XK_p, XK_P,
|
|
|
1448d9 |
+ XK_bracketleft, XK_braceleft,
|
|
|
1448d9 |
+ XK_bracketright, XK_braceright,
|
|
|
1448d9 |
+ XK_Return, NoSymbol,
|
|
|
1448d9 |
+ XK_Control_L, NoSymbol,
|
|
|
1448d9 |
+ XK_a, XK_A,
|
|
|
1448d9 |
+ XK_s, XK_S,
|
|
|
1448d9 |
+ XK_d, XK_D,
|
|
|
1448d9 |
+ XK_f, XK_F,
|
|
|
1448d9 |
+ XK_g, XK_G,
|
|
|
1448d9 |
+ XK_h, XK_H,
|
|
|
1448d9 |
+ XK_j, XK_J,
|
|
|
1448d9 |
+ XK_k, XK_K,
|
|
|
1448d9 |
+ XK_l, XK_L,
|
|
|
1448d9 |
+ XK_semicolon, XK_colon,
|
|
|
1448d9 |
+ XK_apostrophe, XK_quotedbl,
|
|
|
1448d9 |
+ XK_grave, XK_asciitilde,
|
|
|
1448d9 |
+ XK_Shift_L, NoSymbol,
|
|
|
1448d9 |
+ XK_backslash, XK_bar,
|
|
|
1448d9 |
+ XK_z, XK_Z,
|
|
|
1448d9 |
+ XK_x, XK_X,
|
|
|
1448d9 |
+ XK_c, XK_C,
|
|
|
1448d9 |
+ XK_v, XK_V,
|
|
|
1448d9 |
+ XK_b, XK_B,
|
|
|
1448d9 |
+ XK_n, XK_N,
|
|
|
1448d9 |
+ XK_m, XK_M,
|
|
|
1448d9 |
+ XK_comma, XK_less,
|
|
|
1448d9 |
+ XK_period, XK_greater,
|
|
|
1448d9 |
+ XK_slash, XK_question,
|
|
|
1448d9 |
+ XK_Shift_R, NoSymbol,
|
|
|
1448d9 |
+ XK_KP_Multiply, NoSymbol,
|
|
|
1448d9 |
+ XK_Alt_L, XK_Meta_L,
|
|
|
1448d9 |
+ XK_space, NoSymbol,
|
|
|
1448d9 |
+ XK_Caps_Lock, NoSymbol,
|
|
|
1448d9 |
+ XK_F1, NoSymbol,
|
|
|
1448d9 |
+ XK_F2, NoSymbol,
|
|
|
1448d9 |
+ XK_F3, NoSymbol,
|
|
|
1448d9 |
+ XK_F4, NoSymbol,
|
|
|
1448d9 |
+ XK_F5, NoSymbol,
|
|
|
1448d9 |
+ XK_F6, NoSymbol,
|
|
|
1448d9 |
+ XK_F7, NoSymbol,
|
|
|
1448d9 |
+ XK_F8, NoSymbol,
|
|
|
1448d9 |
+ XK_F9, NoSymbol,
|
|
|
1448d9 |
+ XK_F10, NoSymbol,
|
|
|
1448d9 |
+ XK_Num_Lock, XK_Pointer_EnableKeys,
|
|
|
1448d9 |
+ XK_Scroll_Lock, NoSymbol,
|
|
|
1448d9 |
+ XK_KP_Home, XK_KP_7,
|
|
|
1448d9 |
+ XK_KP_Up, XK_KP_8,
|
|
|
1448d9 |
+ XK_KP_Prior, XK_KP_9,
|
|
|
1448d9 |
+ XK_KP_Subtract, NoSymbol,
|
|
|
1448d9 |
+ XK_KP_Left, XK_KP_4,
|
|
|
1448d9 |
+ XK_KP_Begin, XK_KP_5,
|
|
|
1448d9 |
+ XK_KP_Right, XK_KP_6,
|
|
|
1448d9 |
+ XK_KP_Add, NoSymbol,
|
|
|
1448d9 |
+ XK_KP_End, XK_KP_1,
|
|
|
1448d9 |
+ XK_KP_Down, XK_KP_2,
|
|
|
1448d9 |
+ XK_KP_Next, XK_KP_3,
|
|
|
1448d9 |
+ XK_KP_Insert, XK_KP_0,
|
|
|
1448d9 |
+ XK_KP_Delete, XK_KP_Decimal,
|
|
|
1448d9 |
+ NoSymbol, NoSymbol,
|
|
|
1448d9 |
+ NoSymbol, NoSymbol,
|
|
|
1448d9 |
+ NoSymbol, NoSymbol,
|
|
|
1448d9 |
+ XK_F11, NoSymbol,
|
|
|
1448d9 |
+ XK_F12, NoSymbol,
|
|
|
1448d9 |
+ XK_Home, NoSymbol,
|
|
|
1448d9 |
+ XK_Up, NoSymbol,
|
|
|
1448d9 |
+ XK_Prior, NoSymbol,
|
|
|
1448d9 |
+ XK_Left, NoSymbol,
|
|
|
1448d9 |
+ NoSymbol, NoSymbol,
|
|
|
1448d9 |
+ XK_Right, NoSymbol,
|
|
|
1448d9 |
+ XK_End, NoSymbol,
|
|
|
1448d9 |
+ XK_Down, NoSymbol,
|
|
|
1448d9 |
+ XK_Next, NoSymbol,
|
|
|
1448d9 |
+ XK_Insert, NoSymbol,
|
|
|
1448d9 |
+ XK_Delete, NoSymbol,
|
|
|
1448d9 |
+ XK_KP_Enter, NoSymbol,
|
|
|
1448d9 |
+ XK_Control_R, NoSymbol,
|
|
|
1448d9 |
+ XK_Pause, XK_Break,
|
|
|
1448d9 |
+ XK_Print, XK_Execute,
|
|
|
1448d9 |
+ XK_KP_Divide, NoSymbol,
|
|
|
1448d9 |
+ XK_Alt_R, XK_Meta_R,
|
|
|
1448d9 |
+ NoSymbol, NoSymbol,
|
|
|
1448d9 |
+ XK_Super_L, NoSymbol,
|
|
|
1448d9 |
+ XK_Super_R, NoSymbol,
|
|
|
1448d9 |
+ XK_Menu, NoSymbol,
|
|
|
1448d9 |
+};
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+void GetInitKeyboardMap(KeySymsPtr keysyms, CARD8 *modmap)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ int i;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (i = 0; i < MAP_LENGTH; i++)
|
|
|
1448d9 |
+ modmap[i] = NoSymbol;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (i = 0; i < MAP_LEN; i++) {
|
|
|
1448d9 |
+ switch (keyboardMap[i * KEYSYMS_PER_KEY]) {
|
|
|
1448d9 |
+ case XK_Shift_L:
|
|
|
1448d9 |
+ case XK_Shift_R:
|
|
|
1448d9 |
+ modmap[i + MIN_KEY] = ShiftMask;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XK_Caps_Lock:
|
|
|
1448d9 |
+ modmap[i + MIN_KEY] = LockMask;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XK_Control_L:
|
|
|
1448d9 |
+ case XK_Control_R:
|
|
|
1448d9 |
+ modmap[i + MIN_KEY] = ControlMask;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XK_Alt_L:
|
|
|
1448d9 |
+ case XK_Alt_R:
|
|
|
1448d9 |
+ modmap[i + MIN_KEY] = Mod1Mask;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XK_Num_Lock:
|
|
|
1448d9 |
+ modmap[i + MIN_KEY] = Mod2Mask;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ /* No defaults for Mod3Mask yet */
|
|
|
1448d9 |
+ case XK_Super_L:
|
|
|
1448d9 |
+ case XK_Super_R:
|
|
|
1448d9 |
+ case XK_Hyper_L:
|
|
|
1448d9 |
+ case XK_Hyper_R:
|
|
|
1448d9 |
+ modmap[i + MIN_KEY] = Mod4Mask;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XK_ISO_Level3_Shift:
|
|
|
1448d9 |
+ case XK_Mode_switch:
|
|
|
1448d9 |
+ modmap[i + MIN_KEY] = Mod5Mask;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keysyms->minKeyCode = MIN_KEY;
|
|
|
1448d9 |
+ keysyms->maxKeyCode = MAX_KEY;
|
|
|
1448d9 |
+ keysyms->mapWidth = KEYSYMS_PER_KEY;
|
|
|
1448d9 |
+ keysyms->map = keyboardMap;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+void InputDevice::PrepareInputDevices(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ /* Don't need to do anything here */
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+unsigned InputDevice::getKeyboardState(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ return keyboardDev->key->state;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+unsigned InputDevice::getLevelThreeMask(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ int i, j, k;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ int minKeyCode, mapWidth;
|
|
|
1448d9 |
+ KeySym *map;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ int maxKeysPerMod;
|
|
|
1448d9 |
+ CARD8 *modmap;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ minKeyCode = keyboardDev->key->curKeySyms.minKeyCode;
|
|
|
1448d9 |
+ mapWidth = keyboardDev->key->curKeySyms.mapWidth;
|
|
|
1448d9 |
+ map = keyboardDev->key->curKeySyms.map;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier;
|
|
|
1448d9 |
+ modmap = keyboardDev->key->modifierKeyMap;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (i = 3; i < 8; i++) {
|
|
|
1448d9 |
+ for (k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
+ int index = i * maxKeysPerMod + k;
|
|
|
1448d9 |
+ int keycode = modmap[index];
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (keycode == 0)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (j = 0; j < mapWidth; j++) {
|
|
|
1448d9 |
+ KeySym keysym;
|
|
|
1448d9 |
+ keysym = map[(keycode - minKeyCode) * mapWidth + j];
|
|
|
1448d9 |
+ if (keysym == XK_Mode_switch)
|
|
|
1448d9 |
+ return 1 << i;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+KeyCode InputDevice::pressShift(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ int maxKeysPerMod;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier;
|
|
|
1448d9 |
+ return keyboardDev->key->modifierKeyMap[ShiftMapIndex * maxKeysPerMod];
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+std::list<KeyCode> InputDevice::releaseShift(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ std::list<KeyCode> keys;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ int maxKeysPerMod;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier;
|
|
|
1448d9 |
+ for (int k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
+ int keycode;
|
|
|
1448d9 |
+ int index;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ index = ShiftMapIndex * maxKeysPerMod + k;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keycode = keyboardDev->key->modifierKeyMap[index];
|
|
|
1448d9 |
+ if (keycode == 0)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (!IS_PRESSED(keyboardDev, keycode))
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keys.push_back(keycode);
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return keys;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+KeyCode InputDevice::pressLevelThree(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ unsigned mask, index;
|
|
|
1448d9 |
+ int maxKeysPerMod;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ mask = getLevelThreeMask();
|
|
|
1448d9 |
+ if (mask == 0)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ index = ffs(mask) - 1;
|
|
|
1448d9 |
+ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier;
|
|
|
1448d9 |
+ return keyboardDev->key->modifierKeyMap[index * maxKeysPerMod];
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+std::list<KeyCode> InputDevice::releaseLevelThree(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ std::list<KeyCode> keys;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ unsigned mask, msindex;
|
|
|
1448d9 |
+ int maxKeysPerMod;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ mask = getLevelThreeMask();
|
|
|
1448d9 |
+ if (mask == 0)
|
|
|
1448d9 |
+ return keys;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ msindex = ffs(mask) - 1;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier;
|
|
|
1448d9 |
+ for (int k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
+ int keycode;
|
|
|
1448d9 |
+ int index;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ index = msindex * maxKeysPerMod + k;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keycode = keyboardDev->key->modifierKeyMap[index];
|
|
|
1448d9 |
+ if (keycode == 0)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (!IS_PRESSED(keyboardDev, keycode))
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keys.push_back(keycode);
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return keys;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ int per = keymap->mapWidth;
|
|
|
1448d9 |
+ KeySym *syms;
|
|
|
1448d9 |
+ KeySym lsym, usym;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if ((col < 0) || ((col >= per) && (col > 3)) ||
|
|
|
1448d9 |
+ (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode))
|
|
|
1448d9 |
+ return NoSymbol;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
|
|
|
1448d9 |
+ if (col >= 4)
|
|
|
1448d9 |
+ return syms[col];
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (col > 1) {
|
|
|
1448d9 |
+ while ((per > 2) && (syms[per - 1] == NoSymbol))
|
|
|
1448d9 |
+ per--;
|
|
|
1448d9 |
+ if (per < 3)
|
|
|
1448d9 |
+ col -= 2;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) {
|
|
|
1448d9 |
+ XkbConvertCase(syms[col&~1], &lsym, &usym);
|
|
|
1448d9 |
+ if (!(col & 1))
|
|
|
1448d9 |
+ return lsym;
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * I'm commenting out this logic because it's incorrect even
|
|
|
1448d9 |
+ * though it was copied from the Xlib sources. The X protocol
|
|
|
1448d9 |
+ * book quite clearly states that where a group consists of
|
|
|
1448d9 |
+ * element 1 being a non-alphabetic keysym and element 2 being
|
|
|
1448d9 |
+ * NoSymbol that you treat the second element as being the
|
|
|
1448d9 |
+ * same as the first. This also tallies with the behaviour
|
|
|
1448d9 |
+ * produced by the installed Xlib on my linux box (I believe
|
|
|
1448d9 |
+ * this is because it uses some XKB code rather than the
|
|
|
1448d9 |
+ * original Xlib code - compare XKBBind.c with KeyBind.c in
|
|
|
1448d9 |
+ * lib/X11).
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+#if 0
|
|
|
1448d9 |
+ else if (usym == lsym)
|
|
|
1448d9 |
+ return NoSymbol;
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
+ return usym;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return syms[col];
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+KeyCode InputDevice::keysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ int i, j;
|
|
|
1448d9 |
+ unsigned mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ KeySymsPtr keymap;
|
|
|
1448d9 |
+ int mapWidth;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ mask = getLevelThreeMask();
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keymap = &keyboardDev->key->curKeySyms;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * Column 0 means both shift and "mode_switch" (AltGr) must be released,
|
|
|
1448d9 |
+ * column 1 means shift must be pressed and mode_switch released,
|
|
|
1448d9 |
+ * column 2 means shift must be released and mode_switch pressed, and
|
|
|
1448d9 |
+ * column 3 means both shift and mode_switch must be pressed.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ j = 0;
|
|
|
1448d9 |
+ if (state & ShiftMask)
|
|
|
1448d9 |
+ j |= 0x1;
|
|
|
1448d9 |
+ if (state & mask)
|
|
|
1448d9 |
+ j |= 0x2;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ *new_state = state;
|
|
|
1448d9 |
+ for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
|
|
|
1448d9 |
+ if (KeyCodetoKeySym(keymap, i, j) == keysym)
|
|
|
1448d9 |
+ return i;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* Only the first four columns have well-defined meaning */
|
|
|
1448d9 |
+ mapWidth = keymap->mapWidth;
|
|
|
1448d9 |
+ if (mapWidth > 4)
|
|
|
1448d9 |
+ mapWidth = 4;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (j = 0; j < mapWidth; j++) {
|
|
|
1448d9 |
+ for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) {
|
|
|
1448d9 |
+ if (KeyCodetoKeySym(keymap, i, j) == keysym) {
|
|
|
1448d9 |
+ *new_state = state & ~(ShiftMask|mask);
|
|
|
1448d9 |
+ if (j & 0x1)
|
|
|
1448d9 |
+ *new_state |= ShiftMask;
|
|
|
1448d9 |
+ if (j & 0x2)
|
|
|
1448d9 |
+ *new_state |= mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return i;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+bool InputDevice::isLockModifier(KeyCode keycode, unsigned state)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ int i, j, k;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ int minKeyCode, mapWidth;
|
|
|
1448d9 |
+ KeySym *map;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ int maxKeysPerMod;
|
|
|
1448d9 |
+ CARD8 *modmap;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ int num_lock_index;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ minKeyCode = keyboardDev->key->curKeySyms.minKeyCode;
|
|
|
1448d9 |
+ mapWidth = keyboardDev->key->curKeySyms.mapWidth;
|
|
|
1448d9 |
+ map = keyboardDev->key->curKeySyms.map;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ maxKeysPerMod = keyboardDev->key->maxKeysPerModifier;
|
|
|
1448d9 |
+ modmap = keyboardDev->key->modifierKeyMap;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* Caps Lock is fairly easy as it has a dedicated modmap entry */
|
|
|
1448d9 |
+ for (k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
+ int index;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ index = LockMapIndex * maxKeysPerMod + k;
|
|
|
1448d9 |
+ if (keycode == modmap[index])
|
|
|
1448d9 |
+ return true;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* For Num Lock we need to find the correct modmap entry */
|
|
|
1448d9 |
+ num_lock_index = i;
|
|
|
1448d9 |
+ for (i = 3; i < 8; i++) {
|
|
|
1448d9 |
+ for (k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
+ int index = i * maxKeysPerMod + k;
|
|
|
1448d9 |
+ int keycode = modmap[index];
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (keycode == 0)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (j = 0; j < mapWidth; j++) {
|
|
|
1448d9 |
+ KeySym keysym;
|
|
|
1448d9 |
+ keysym = map[(keycode - minKeyCode) * mapWidth + j];
|
|
|
1448d9 |
+ if (keysym == XK_Num_Lock) {
|
|
|
1448d9 |
+ num_lock_index = i;
|
|
|
1448d9 |
+ goto done;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+done:
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (num_lock_index == 0)
|
|
|
1448d9 |
+ return false;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* Now we can look in the modmap */
|
|
|
1448d9 |
+ for (k = 0; k < maxKeysPerMod; k++) {
|
|
|
1448d9 |
+ int index;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ index = num_lock_index * maxKeysPerMod + k;
|
|
|
1448d9 |
+ if (keycode == modmap[index])
|
|
|
1448d9 |
+ return true;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return false;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+bool InputDevice::isAffectedByNumLock(KeyCode keycode)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ KeySymsPtr keymap;
|
|
|
1448d9 |
+ int i, per;
|
|
|
1448d9 |
+ KeySym *syms;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keymap = &keyboardDev->key->curKeySyms;
|
|
|
1448d9 |
+ per = keymap->mapWidth;
|
|
|
1448d9 |
+ syms = &keymap->map[(keycode - keymap->minKeyCode) * per];
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (i = 0;i < per;i++) {
|
|
|
1448d9 |
+ if (IsKeypadKey(syms[i]))
|
|
|
1448d9 |
+ return true;
|
|
|
1448d9 |
+ if (IsPrivateKeypadKey(syms[i]))
|
|
|
1448d9 |
+ return true;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return false;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+KeyCode InputDevice::addKeysym(KeySym keysym, unsigned state)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ KeyCode kc;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ int minKeyCode, maxKeyCode, mapWidth;
|
|
|
1448d9 |
+ KeySym *map;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ minKeyCode = keyboardDev->key->curKeySyms.minKeyCode;
|
|
|
1448d9 |
+ maxKeyCode = keyboardDev->key->curKeySyms.maxKeyCode;
|
|
|
1448d9 |
+ mapWidth = keyboardDev->key->curKeySyms.mapWidth;
|
|
|
1448d9 |
+ map = keyboardDev->key->curKeySyms.map;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * Magic, which dynamically adds keysym<->keycode mapping
|
|
|
1448d9 |
+ * depends on X.Org version. Quick explanation of that "magic":
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * 1.5
|
|
|
1448d9 |
+ * - has only one core keyboard so we have to keep core
|
|
|
1448d9 |
+ * keyboard mapping synchronized with vncKeyboardDevice. Do
|
|
|
1448d9 |
+ * it via SwitchCoreKeyboard()
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * 1.6 (aka MPX - Multi pointer X)
|
|
|
1448d9 |
+ * - multiple master devices (= core devices) exists, keep
|
|
|
1448d9 |
+ * vncKeyboardDevice synchronized with proper master device
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ for (kc = maxKeyCode; kc >= minKeyCode; kc--) {
|
|
|
1448d9 |
+ DeviceIntPtr master;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (map[(kc - minKeyCode) * mapWidth] != 0)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ map[(kc - minKeyCode) * mapWidth] = keysym;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#if XORG == 15
|
|
|
1448d9 |
+ master = inputInfo.keyboard;
|
|
|
1448d9 |
+#else
|
|
|
1448d9 |
+ master = keyboardDev->u.master;
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+ void *slave = dixLookupPrivate(&master->devPrivates,
|
|
|
1448d9 |
+ CoreDevicePrivateKey);
|
|
|
1448d9 |
+ if (keyboardDev == slave) {
|
|
|
1448d9 |
+ dixSetPrivate(&master->devPrivates,
|
|
|
1448d9 |
+ CoreDevicePrivateKey, NULL);
|
|
|
1448d9 |
+#if XORG == 15
|
|
|
1448d9 |
+ SwitchCoreKeyboard(keyboardDev);
|
|
|
1448d9 |
+#else
|
|
|
1448d9 |
+ CopyKeyClass(keyboardDev, master);
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return kc;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+
|
|
|
1448d9 |
diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.h.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.h
|
|
|
1448d9 |
--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.h.input 2010-04-14 10:24:06.000000000 +0100
|
|
|
1448d9 |
+++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Input.h 2014-01-17 16:01:13.141109454 +0000
|
|
|
1448d9 |
@@ -1,6 +1,7 @@
|
|
|
1448d9 |
/* Copyright (C) 2009 TightVNC Team
|
|
|
1448d9 |
* Copyright (C) 2009, 2010 Red Hat, Inc.
|
|
|
1448d9 |
* Copyright (C) 2009, 2010 TigerVNC Team
|
|
|
1448d9 |
+ * Copyright 2013 Pierre Ossman for Cendio AB
|
|
|
1448d9 |
*
|
|
|
1448d9 |
* This is free software; you can redistribute it and/or modify
|
|
|
1448d9 |
* it under the terms of the GNU General Public License as published by
|
|
|
1448d9 |
@@ -26,12 +27,16 @@
|
|
|
1448d9 |
#include <dix-config.h>
|
|
|
1448d9 |
#endif
|
|
|
1448d9 |
|
|
|
1448d9 |
+#include <list>
|
|
|
1448d9 |
+
|
|
|
1448d9 |
#include <rfb/VNCServerST.h>
|
|
|
1448d9 |
|
|
|
1448d9 |
extern "C" {
|
|
|
1448d9 |
#include "input.h"
|
|
|
1448d9 |
};
|
|
|
1448d9 |
|
|
|
1448d9 |
+#include "xorg-version.h"
|
|
|
1448d9 |
+
|
|
|
1448d9 |
/* Represents input device (keyboard + pointer) */
|
|
|
1448d9 |
class InputDevice {
|
|
|
1448d9 |
public:
|
|
|
1448d9 |
@@ -55,24 +60,58 @@ public:
|
|
|
1448d9 |
|
|
|
1448d9 |
void KeyboardPress(rdr::U32 keysym) { keyEvent(keysym, true); }
|
|
|
1448d9 |
void KeyboardRelease(rdr::U32 keysym) { keyEvent(keysym, false); }
|
|
|
1448d9 |
-private:
|
|
|
1448d9 |
+
|
|
|
1448d9 |
/*
|
|
|
1448d9 |
* Init input device. This cannot be done in the constructor
|
|
|
1448d9 |
* because constructor is called during X server extensions
|
|
|
1448d9 |
* initialization. Devices must be initialized after core
|
|
|
1448d9 |
* pointer/keyboard initialization which is actually after extesions
|
|
|
1448d9 |
* initialization. Check InitExtensions(), InitCoreDevices() and
|
|
|
1448d9 |
- * InitInput() calls in dix/main.c
|
|
|
1448d9 |
+ * InitInput() calls in dix/main.c. Instead it is called from
|
|
|
1448d9 |
+ * XserverDesktop at an appropriate time.
|
|
|
1448d9 |
*/
|
|
|
1448d9 |
- void initInputDevice(void);
|
|
|
1448d9 |
+ void InitInputDevice(void);
|
|
|
1448d9 |
|
|
|
1448d9 |
+private:
|
|
|
1448d9 |
void keyEvent(rdr::U32 keysym, bool down);
|
|
|
1448d9 |
|
|
|
1448d9 |
+ /* Backend dependent functions below here */
|
|
|
1448d9 |
+ void PrepareInputDevices(void);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ unsigned getKeyboardState(void);
|
|
|
1448d9 |
+ unsigned getLevelThreeMask(void);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ KeyCode pressShift(void);
|
|
|
1448d9 |
+ std::list<KeyCode> releaseShift(void);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ KeyCode pressLevelThree(void);
|
|
|
1448d9 |
+ std::list<KeyCode> releaseLevelThree(void);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ KeyCode keysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ bool isLockModifier(KeyCode keycode, unsigned state);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ bool isAffectedByNumLock(KeyCode keycode);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ KeyCode addKeysym(KeySym keysym, unsigned state);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+private:
|
|
|
1448d9 |
+#if XORG >= 17
|
|
|
1448d9 |
+ static void vncXkbProcessDeviceEvent(int screenNum,
|
|
|
1448d9 |
+ InternalEvent *event,
|
|
|
1448d9 |
+ DeviceIntPtr dev);
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+private:
|
|
|
1448d9 |
rfb::VNCServerST *server;
|
|
|
1448d9 |
+ bool initialized;
|
|
|
1448d9 |
DeviceIntPtr keyboardDev;
|
|
|
1448d9 |
DeviceIntPtr pointerDev;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
int oldButtonMask;
|
|
|
1448d9 |
rfb::Point cursorPos, oldCursorPos;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ KeySym pressedKeys[256];
|
|
|
1448d9 |
};
|
|
|
1448d9 |
|
|
|
1448d9 |
#endif
|
|
|
1448d9 |
diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputXKB.cc.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputXKB.cc
|
|
|
1448d9 |
--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputXKB.cc.input 2014-01-17 16:01:13.141109454 +0000
|
|
|
1448d9 |
+++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/InputXKB.cc 2014-01-17 16:01:13.141109454 +0000
|
|
|
1448d9 |
@@ -0,0 +1,669 @@
|
|
|
1448d9 |
+/* Copyright (C) 2009 TightVNC Team
|
|
|
1448d9 |
+ * Copyright (C) 2009 Red Hat, Inc.
|
|
|
1448d9 |
+ * Copyright 2013 Pierre Ossman for Cendio AB
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * This is free software; you can redistribute it and/or modify
|
|
|
1448d9 |
+ * it under the terms of the GNU General Public License as published by
|
|
|
1448d9 |
+ * the Free Software Foundation; either version 2 of the License, or
|
|
|
1448d9 |
+ * (at your option) any later version.
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * This software is distributed in the hope that it will be useful,
|
|
|
1448d9 |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
1448d9 |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
1448d9 |
+ * GNU General Public License for more details.
|
|
|
1448d9 |
+ *
|
|
|
1448d9 |
+ * You should have received a copy of the GNU General Public License
|
|
|
1448d9 |
+ * along with this software; if not, write to the Free Software
|
|
|
1448d9 |
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
|
|
1448d9 |
+ * USA.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#ifdef HAVE_DIX_CONFIG_H
|
|
|
1448d9 |
+#include <dix-config.h>
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#include "Input.h"
|
|
|
1448d9 |
+#include "xorg-version.h"
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#if XORG >= 17
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+extern "C" {
|
|
|
1448d9 |
+#define public c_public
|
|
|
1448d9 |
+#define class c_class
|
|
|
1448d9 |
+#include "xkbsrv.h"
|
|
|
1448d9 |
+#include "xkbstr.h"
|
|
|
1448d9 |
+#include "eventstr.h"
|
|
|
1448d9 |
+#include "scrnintstr.h"
|
|
|
1448d9 |
+#include "mi.h"
|
|
|
1448d9 |
+#include <X11/keysym.h>
|
|
|
1448d9 |
+#include <X11/Xlib.h>
|
|
|
1448d9 |
+#include <X11/Xutil.h>
|
|
|
1448d9 |
+#undef public
|
|
|
1448d9 |
+#undef class
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#if XORG < 19
|
|
|
1448d9 |
+static int vncXkbScreenPrivateKeyIndex;
|
|
|
1448d9 |
+static DevPrivateKey vncXkbScreenPrivateKey = &vncXkbScreenPrivateKeyIndex;
|
|
|
1448d9 |
+#else
|
|
|
1448d9 |
+static DevPrivateKeyRec vncXkbPrivateKeyRec;
|
|
|
1448d9 |
+#define vncXkbScreenPrivateKey (&vncXkbPrivateKeyRec)
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#define vncXkbScreenPrivate(pScreen) \
|
|
|
1448d9 |
+ (*(InputDevice**) dixLookupPrivate(&(pScreen)->devPrivates, \
|
|
|
1448d9 |
+ vncXkbScreenPrivateKey))
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#ifndef KEYBOARD_OR_FLOAT
|
|
|
1448d9 |
+#define KEYBOARD_OR_FLOAT MASTER_KEYBOARD
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+/* Stolen from libX11 */
|
|
|
1448d9 |
+static Bool
|
|
|
1448d9 |
+XkbTranslateKeyCode(register XkbDescPtr xkb, KeyCode key,
|
|
|
1448d9 |
+ register unsigned int mods, unsigned int *mods_rtrn,
|
|
|
1448d9 |
+ KeySym *keysym_rtrn)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ XkbKeyTypeRec *type;
|
|
|
1448d9 |
+ int col,nKeyGroups;
|
|
|
1448d9 |
+ unsigned preserve,effectiveGroup;
|
|
|
1448d9 |
+ KeySym *syms;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (mods_rtrn!=NULL)
|
|
|
1448d9 |
+ *mods_rtrn = 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ nKeyGroups= XkbKeyNumGroups(xkb,key);
|
|
|
1448d9 |
+ if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0)) {
|
|
|
1448d9 |
+ if (keysym_rtrn!=NULL)
|
|
|
1448d9 |
+ *keysym_rtrn = NoSymbol;
|
|
|
1448d9 |
+ return False;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ syms = XkbKeySymsPtr(xkb,key);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* find the offset of the effective group */
|
|
|
1448d9 |
+ col = 0;
|
|
|
1448d9 |
+ effectiveGroup= XkbGroupForCoreState(mods);
|
|
|
1448d9 |
+ if ( effectiveGroup>=nKeyGroups ) {
|
|
|
1448d9 |
+ unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
|
|
|
1448d9 |
+ switch (XkbOutOfRangeGroupAction(groupInfo)) {
|
|
|
1448d9 |
+ default:
|
|
|
1448d9 |
+ effectiveGroup %= nKeyGroups;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XkbClampIntoRange:
|
|
|
1448d9 |
+ effectiveGroup = nKeyGroups-1;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XkbRedirectIntoRange:
|
|
|
1448d9 |
+ effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
|
|
|
1448d9 |
+ if (effectiveGroup>=nKeyGroups)
|
|
|
1448d9 |
+ effectiveGroup= 0;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
|
|
|
1448d9 |
+ type = XkbKeyKeyType(xkb,key,effectiveGroup);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ preserve= 0;
|
|
|
1448d9 |
+ if (type->map) { /* find the column (shift level) within the group */
|
|
|
1448d9 |
+ register int i;
|
|
|
1448d9 |
+ register XkbKTMapEntryPtr entry;
|
|
|
1448d9 |
+ for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
|
|
|
1448d9 |
+ if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {
|
|
|
1448d9 |
+ col+= entry->level;
|
|
|
1448d9 |
+ if (type->preserve)
|
|
|
1448d9 |
+ preserve= type->preserve[i].mask;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (keysym_rtrn!=NULL)
|
|
|
1448d9 |
+ *keysym_rtrn= syms[col];
|
|
|
1448d9 |
+ if (mods_rtrn)
|
|
|
1448d9 |
+ *mods_rtrn= type->mods.mask&(~preserve);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return (syms[col]!=NoSymbol);
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+static XkbAction *XkbKeyActionPtr(XkbDescPtr xkb, KeyCode key, unsigned int mods)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ XkbKeyTypeRec *type;
|
|
|
1448d9 |
+ int col,nKeyGroups;
|
|
|
1448d9 |
+ unsigned effectiveGroup;
|
|
|
1448d9 |
+ XkbAction *acts;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (!XkbKeyHasActions(xkb, key))
|
|
|
1448d9 |
+ return NULL;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ nKeyGroups= XkbKeyNumGroups(xkb,key);
|
|
|
1448d9 |
+ if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0))
|
|
|
1448d9 |
+ return NULL;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ acts = XkbKeyActionsPtr(xkb,key);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* find the offset of the effective group */
|
|
|
1448d9 |
+ col = 0;
|
|
|
1448d9 |
+ effectiveGroup= XkbGroupForCoreState(mods);
|
|
|
1448d9 |
+ if ( effectiveGroup>=nKeyGroups ) {
|
|
|
1448d9 |
+ unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
|
|
|
1448d9 |
+ switch (XkbOutOfRangeGroupAction(groupInfo)) {
|
|
|
1448d9 |
+ default:
|
|
|
1448d9 |
+ effectiveGroup %= nKeyGroups;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XkbClampIntoRange:
|
|
|
1448d9 |
+ effectiveGroup = nKeyGroups-1;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XkbRedirectIntoRange:
|
|
|
1448d9 |
+ effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
|
|
|
1448d9 |
+ if (effectiveGroup>=nKeyGroups)
|
|
|
1448d9 |
+ effectiveGroup= 0;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ col= effectiveGroup*XkbKeyGroupsWidth(xkb,key);
|
|
|
1448d9 |
+ type = XkbKeyKeyType(xkb,key,effectiveGroup);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (type->map) { /* find the column (shift level) within the group */
|
|
|
1448d9 |
+ register int i;
|
|
|
1448d9 |
+ register XkbKTMapEntryPtr entry;
|
|
|
1448d9 |
+ for (i=0,entry=type->map;i<type->map_count;i++,entry++) {
|
|
|
1448d9 |
+ if ((entry->active)&&((mods&type->mods.mask)==entry->mods.mask)) {
|
|
|
1448d9 |
+ col+= entry->level;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return &acts[col];
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+static unsigned XkbKeyEffectiveGroup(XkbDescPtr xkb, KeyCode key, unsigned int mods)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ int nKeyGroups;
|
|
|
1448d9 |
+ unsigned effectiveGroup;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ nKeyGroups= XkbKeyNumGroups(xkb,key);
|
|
|
1448d9 |
+ if ((!XkbKeycodeInRange(xkb,key))||(nKeyGroups==0))
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ effectiveGroup= XkbGroupForCoreState(mods);
|
|
|
1448d9 |
+ if ( effectiveGroup>=nKeyGroups ) {
|
|
|
1448d9 |
+ unsigned groupInfo= XkbKeyGroupInfo(xkb,key);
|
|
|
1448d9 |
+ switch (XkbOutOfRangeGroupAction(groupInfo)) {
|
|
|
1448d9 |
+ default:
|
|
|
1448d9 |
+ effectiveGroup %= nKeyGroups;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XkbClampIntoRange:
|
|
|
1448d9 |
+ effectiveGroup = nKeyGroups-1;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ case XkbRedirectIntoRange:
|
|
|
1448d9 |
+ effectiveGroup = XkbOutOfRangeGroupNumber(groupInfo);
|
|
|
1448d9 |
+ if (effectiveGroup>=nKeyGroups)
|
|
|
1448d9 |
+ effectiveGroup= 0;
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return effectiveGroup;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+void InputDevice::PrepareInputDevices(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+#if XORG < 19
|
|
|
1448d9 |
+ if (!dixRequestPrivate(vncXkbScreenPrivateKey, sizeof(InputDevice*)))
|
|
|
1448d9 |
+ FatalError("Failed to register TigerVNC XKB screen key\n");
|
|
|
1448d9 |
+#else
|
|
|
1448d9 |
+ if (!dixRegisterPrivateKey(vncXkbScreenPrivateKey, PRIVATE_SCREEN,
|
|
|
1448d9 |
+ sizeof(InputDevice*)))
|
|
|
1448d9 |
+ FatalError("Failed to register TigerVNC XKB screen key\n");
|
|
|
1448d9 |
+#endif
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ for (int scr = 0; scr < screenInfo.numScreens; scr++)
|
|
|
1448d9 |
+ vncXkbScreenPrivate(screenInfo.screens[scr]) = this;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * Not ideal since these callbacks do not stack, but it's the only
|
|
|
1448d9 |
+ * decent way we can reliably catch events for both the slave and
|
|
|
1448d9 |
+ * master device.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ mieqSetHandler(ET_KeyPress, vncXkbProcessDeviceEvent);
|
|
|
1448d9 |
+ mieqSetHandler(ET_KeyRelease, vncXkbProcessDeviceEvent);
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+unsigned InputDevice::getKeyboardState(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ return XkbStateFieldFromRec(&keyboardDev->master->key->xkbInfo->state);
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+unsigned InputDevice::getLevelThreeMask(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ unsigned state;
|
|
|
1448d9 |
+ KeyCode keycode;
|
|
|
1448d9 |
+ XkbDescPtr xkb;
|
|
|
1448d9 |
+ XkbAction *act;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* Group state is still important */
|
|
|
1448d9 |
+ state = getKeyboardState();
|
|
|
1448d9 |
+ state &= ~0xff;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keycode = keysymToKeycode(XK_ISO_Level3_Shift, state, NULL);
|
|
|
1448d9 |
+ if (keycode == 0) {
|
|
|
1448d9 |
+ keycode = keysymToKeycode(XK_Mode_switch, state, NULL);
|
|
|
1448d9 |
+ if (keycode == 0)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ xkb = keyboardDev->master->key->xkbInfo->desc;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ act = XkbKeyActionPtr(xkb, keycode, state);
|
|
|
1448d9 |
+ if (act == NULL)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+ if (act->type != XkbSA_SetMods)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (act->mods.flags & XkbSA_UseModMapMods)
|
|
|
1448d9 |
+ return xkb->map->modmap[keycode];
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
+ return act->mods.mask;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+KeyCode InputDevice::pressShift(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ unsigned state;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ XkbDescPtr xkb;
|
|
|
1448d9 |
+ unsigned int key;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ state = getKeyboardState();
|
|
|
1448d9 |
+ if (state & ShiftMask)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ xkb = keyboardDev->master->key->xkbInfo->desc;
|
|
|
1448d9 |
+ for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
|
|
|
1448d9 |
+ XkbAction *act;
|
|
|
1448d9 |
+ unsigned char mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ act = XkbKeyActionPtr(xkb, key, state);
|
|
|
1448d9 |
+ if (act == NULL)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (act->type != XkbSA_SetMods)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (act->mods.flags & XkbSA_UseModMapMods)
|
|
|
1448d9 |
+ mask = xkb->map->modmap[key];
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
+ mask = act->mods.mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if ((mask & ShiftMask) == ShiftMask)
|
|
|
1448d9 |
+ return key;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+std::list<KeyCode> InputDevice::releaseShift(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ unsigned state;
|
|
|
1448d9 |
+ std::list<KeyCode> keys;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ DeviceIntPtr master;
|
|
|
1448d9 |
+ XkbDescPtr xkb;
|
|
|
1448d9 |
+ unsigned int key;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ state = getKeyboardState();
|
|
|
1448d9 |
+ if (!(state & ShiftMask))
|
|
|
1448d9 |
+ return keys;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ master = keyboardDev->master;
|
|
|
1448d9 |
+ xkb = master->key->xkbInfo->desc;
|
|
|
1448d9 |
+ for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
|
|
|
1448d9 |
+ XkbAction *act;
|
|
|
1448d9 |
+ unsigned char mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (!key_is_down(master, key, KEY_PROCESSED))
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ act = XkbKeyActionPtr(xkb, key, state);
|
|
|
1448d9 |
+ if (act == NULL)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (act->type != XkbSA_SetMods)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (act->mods.flags & XkbSA_UseModMapMods)
|
|
|
1448d9 |
+ mask = xkb->map->modmap[key];
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
+ mask = act->mods.mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (!(mask & ShiftMask))
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keys.push_back(key);
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return keys;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+KeyCode InputDevice::pressLevelThree(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ unsigned state, mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ KeyCode keycode;
|
|
|
1448d9 |
+ XkbDescPtr xkb;
|
|
|
1448d9 |
+ XkbAction *act;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ mask = getLevelThreeMask();
|
|
|
1448d9 |
+ if (mask == 0)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ state = getKeyboardState();
|
|
|
1448d9 |
+ if (state & mask)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keycode = keysymToKeycode(XK_ISO_Level3_Shift, state, NULL);
|
|
|
1448d9 |
+ if (keycode == 0) {
|
|
|
1448d9 |
+ keycode = keysymToKeycode(XK_Mode_switch, state, NULL);
|
|
|
1448d9 |
+ if (keycode == 0)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ xkb = keyboardDev->master->key->xkbInfo->desc;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ act = XkbKeyActionPtr(xkb, keycode, state);
|
|
|
1448d9 |
+ if (act == NULL)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+ if (act->type != XkbSA_SetMods)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return keycode;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+std::list<KeyCode> InputDevice::releaseLevelThree(void)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ unsigned state, mask;
|
|
|
1448d9 |
+ std::list<KeyCode> keys;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ DeviceIntPtr master;
|
|
|
1448d9 |
+ XkbDescPtr xkb;
|
|
|
1448d9 |
+ unsigned int key;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ mask = getLevelThreeMask();
|
|
|
1448d9 |
+ if (mask == 0)
|
|
|
1448d9 |
+ return keys;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ state = getKeyboardState();
|
|
|
1448d9 |
+ if (!(state & mask))
|
|
|
1448d9 |
+ return keys;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ master = keyboardDev->master;
|
|
|
1448d9 |
+ xkb = master->key->xkbInfo->desc;
|
|
|
1448d9 |
+ for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
|
|
|
1448d9 |
+ XkbAction *act;
|
|
|
1448d9 |
+ unsigned char key_mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (!key_is_down(master, key, KEY_PROCESSED))
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ act = XkbKeyActionPtr(xkb, key, state);
|
|
|
1448d9 |
+ if (act == NULL)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (act->type != XkbSA_SetMods)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (act->mods.flags & XkbSA_UseModMapMods)
|
|
|
1448d9 |
+ key_mask = xkb->map->modmap[key];
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
+ key_mask = act->mods.mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (!(key_mask & mask))
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ keys.push_back(key);
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return keys;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+KeyCode InputDevice::keysymToKeycode(KeySym keysym, unsigned state,
|
|
|
1448d9 |
+ unsigned *new_state)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ XkbDescPtr xkb;
|
|
|
1448d9 |
+ unsigned int key;
|
|
|
1448d9 |
+ KeySym ks;
|
|
|
1448d9 |
+ unsigned level_three_mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (new_state != NULL)
|
|
|
1448d9 |
+ *new_state = state;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ xkb = keyboardDev->master->key->xkbInfo->desc;
|
|
|
1448d9 |
+ for (key = xkb->min_key_code; key <= xkb->max_key_code; key++) {
|
|
|
1448d9 |
+ unsigned int state_out;
|
|
|
1448d9 |
+ KeySym dummy;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ XkbTranslateKeyCode(xkb, key, state, &state_out, &ks);
|
|
|
1448d9 |
+ if (ks == NoSymbol)
|
|
|
1448d9 |
+ continue;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * Despite every known piece of documentation on
|
|
|
1448d9 |
+ * XkbTranslateKeyCode() stating that mods_rtrn returns
|
|
|
1448d9 |
+ * the unconsumed modifiers, in reality it always
|
|
|
1448d9 |
+ * returns the _potentially consumed_ modifiers.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ state_out = state & ~state_out;
|
|
|
1448d9 |
+ if (state_out & LockMask)
|
|
|
1448d9 |
+ XkbConvertCase(ks, &dummy, &ks);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (ks == keysym)
|
|
|
1448d9 |
+ return key;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (new_state == NULL)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ *new_state = (state & ~ShiftMask) |
|
|
|
1448d9 |
+ ((state & ShiftMask) ? 0 : ShiftMask);
|
|
|
1448d9 |
+ key = keysymToKeycode(keysym, *new_state, NULL);
|
|
|
1448d9 |
+ if (key != 0)
|
|
|
1448d9 |
+ return key;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ level_three_mask = getLevelThreeMask();
|
|
|
1448d9 |
+ if (level_three_mask == 0)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ *new_state = (state & ~level_three_mask) |
|
|
|
1448d9 |
+ ((state & level_three_mask) ? 0 : level_three_mask);
|
|
|
1448d9 |
+ key = keysymToKeycode(keysym, *new_state, NULL);
|
|
|
1448d9 |
+ if (key != 0)
|
|
|
1448d9 |
+ return key;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ *new_state = (state & ~(ShiftMask | level_three_mask)) |
|
|
|
1448d9 |
+ ((state & ShiftMask) ? 0 : ShiftMask) |
|
|
|
1448d9 |
+ ((state & level_three_mask) ? 0 : level_three_mask);
|
|
|
1448d9 |
+ key = keysymToKeycode(keysym, *new_state, NULL);
|
|
|
1448d9 |
+ if (key != 0)
|
|
|
1448d9 |
+ return key;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+bool InputDevice::isLockModifier(KeyCode keycode, unsigned state)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ XkbDescPtr xkb;
|
|
|
1448d9 |
+ XkbAction *act;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ xkb = keyboardDev->master->key->xkbInfo->desc;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ act = XkbKeyActionPtr(xkb, keycode, state);
|
|
|
1448d9 |
+ if (act == NULL)
|
|
|
1448d9 |
+ return false;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (act->type != XkbSA_LockMods)
|
|
|
1448d9 |
+ return false;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return true;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+bool InputDevice::isAffectedByNumLock(KeyCode keycode)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ unsigned state;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ KeyCode numlock_keycode;
|
|
|
1448d9 |
+ unsigned numlock_mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ XkbDescPtr xkb;
|
|
|
1448d9 |
+ XkbAction *act;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ unsigned group;
|
|
|
1448d9 |
+ XkbKeyTypeRec *type;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* Group state is still important */
|
|
|
1448d9 |
+ state = getKeyboardState();
|
|
|
1448d9 |
+ state &= ~0xff;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * Not sure if hunting for a virtual modifier called "NumLock",
|
|
|
1448d9 |
+ * or following the keysym Num_Lock is the best approach. We
|
|
|
1448d9 |
+ * try the latter.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ numlock_keycode = keysymToKeycode(XK_Num_Lock, state, NULL);
|
|
|
1448d9 |
+ if (numlock_keycode == 0)
|
|
|
1448d9 |
+ return false;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ xkb = keyboardDev->master->key->xkbInfo->desc;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ act = XkbKeyActionPtr(xkb, numlock_keycode, state);
|
|
|
1448d9 |
+ if (act == NULL)
|
|
|
1448d9 |
+ return false;
|
|
|
1448d9 |
+ if (act->type != XkbSA_LockMods)
|
|
|
1448d9 |
+ return false;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (act->mods.flags & XkbSA_UseModMapMods)
|
|
|
1448d9 |
+ numlock_mask = xkb->map->modmap[keycode];
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
+ numlock_mask = act->mods.mask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ group = XkbKeyEffectiveGroup(xkb, keycode, state);
|
|
|
1448d9 |
+ type = XkbKeyKeyType(xkb, keycode, group);
|
|
|
1448d9 |
+ if ((type->mods.mask & numlock_mask) == 0)
|
|
|
1448d9 |
+ return false;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return true;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+KeyCode InputDevice::addKeysym(KeySym keysym, unsigned state)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ DeviceIntPtr master;
|
|
|
1448d9 |
+ XkbDescPtr xkb;
|
|
|
1448d9 |
+ unsigned int key;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ XkbEventCauseRec cause;
|
|
|
1448d9 |
+ XkbChangesRec changes;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ int types[1];
|
|
|
1448d9 |
+ KeySym *syms;
|
|
|
1448d9 |
+ KeySym upper, lower;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ master = keyboardDev->master;
|
|
|
1448d9 |
+ xkb = master->key->xkbInfo->desc;
|
|
|
1448d9 |
+ for (key = xkb->max_key_code; key >= xkb->min_key_code; key--) {
|
|
|
1448d9 |
+ if (XkbKeyNumGroups(xkb, key) == 0)
|
|
|
1448d9 |
+ break;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (key < xkb->min_key_code)
|
|
|
1448d9 |
+ return 0;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ memset(&changes, 0, sizeof(changes));
|
|
|
1448d9 |
+ memset(&cause, 0, sizeof(cause));
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ XkbSetCauseUnknown(&cause);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * Tools like xkbcomp get confused if there isn't a name
|
|
|
1448d9 |
+ * assigned to the keycode we're trying to use.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ if (xkb->names && xkb->names->keys &&
|
|
|
1448d9 |
+ (xkb->names->keys[key].name[0] == '\0')) {
|
|
|
1448d9 |
+ xkb->names->keys[key].name[0] = 'I';
|
|
|
1448d9 |
+ xkb->names->keys[key].name[1] = '0' + (key / 100) % 10;
|
|
|
1448d9 |
+ xkb->names->keys[key].name[2] = '0' + (key / 10) % 10;
|
|
|
1448d9 |
+ xkb->names->keys[key].name[3] = '0' + (key / 1) % 10;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ changes.names.changed |= XkbKeyNamesMask;
|
|
|
1448d9 |
+ changes.names.first_key = key;
|
|
|
1448d9 |
+ changes.names.num_keys = 1;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /* FIXME: Verify that ONE_LEVEL/ALPHABETIC isn't screwed up */
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * For keysyms that are affected by Lock, we are better off
|
|
|
1448d9 |
+ * using ALPHABETIC rather than ONE_LEVEL as the latter
|
|
|
1448d9 |
+ * generally cannot produce lower case when Lock is active.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ XkbConvertCase(keysym, &lower, &upper);
|
|
|
1448d9 |
+ if (upper == lower)
|
|
|
1448d9 |
+ types[XkbGroup1Index] = XkbOneLevelIndex;
|
|
|
1448d9 |
+ else
|
|
|
1448d9 |
+ types[XkbGroup1Index] = XkbAlphabeticIndex;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ XkbChangeTypesOfKey(xkb, key, 1, XkbGroup1Mask, types, &changes.map);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ syms = XkbKeySymsPtr(xkb,key);
|
|
|
1448d9 |
+ if (upper == lower)
|
|
|
1448d9 |
+ syms[0] = keysym;
|
|
|
1448d9 |
+ else {
|
|
|
1448d9 |
+ syms[0] = lower;
|
|
|
1448d9 |
+ syms[1] = upper;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ changes.map.changed |= XkbKeySymsMask;
|
|
|
1448d9 |
+ changes.map.first_key_sym = key;
|
|
|
1448d9 |
+ changes.map.num_key_syms = 1;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ XkbSendNotification(master, &changes, &cause);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ return key;
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+void InputDevice::vncXkbProcessDeviceEvent(int screenNum,
|
|
|
1448d9 |
+ InternalEvent *event,
|
|
|
1448d9 |
+ DeviceIntPtr dev)
|
|
|
1448d9 |
+{
|
|
|
1448d9 |
+ InputDevice *self = vncXkbScreenPrivate(screenInfo.screens[screenNum]);
|
|
|
1448d9 |
+ unsigned int backupctrls;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (event->device_event.sourceid == self->keyboardDev->id) {
|
|
|
1448d9 |
+ XkbControlsPtr ctrls;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * We need to bypass AccessX since it is timing sensitive and
|
|
|
1448d9 |
+ * the network can cause fake event delays.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ ctrls = dev->key->xkbInfo->desc->ctrls;
|
|
|
1448d9 |
+ backupctrls = ctrls->enabled_ctrls;
|
|
|
1448d9 |
+ ctrls->enabled_ctrls &= ~XkbAllFilteredEventsMask;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ /*
|
|
|
1448d9 |
+ * This flag needs to be set for key repeats to be properly
|
|
|
1448d9 |
+ * respected.
|
|
|
1448d9 |
+ */
|
|
|
1448d9 |
+ if ((event->device_event.type == ET_KeyPress) &&
|
|
|
1448d9 |
+ key_is_down(dev, event->device_event.detail.key, KEY_PROCESSED))
|
|
|
1448d9 |
+ event->device_event.key_repeat = TRUE;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ dev->c_public.processInputProc(event, dev);
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ if (event->device_event.sourceid == self->keyboardDev->id) {
|
|
|
1448d9 |
+ XkbControlsPtr ctrls;
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+ ctrls = dev->key->xkbInfo->desc->ctrls;
|
|
|
1448d9 |
+ ctrls->enabled_ctrls = backupctrls;
|
|
|
1448d9 |
+ }
|
|
|
1448d9 |
+}
|
|
|
1448d9 |
+
|
|
|
1448d9 |
+#endif /* XORG >= 117 */
|
|
|
1448d9 |
diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Makefile.am.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Makefile.am
|
|
|
1448d9 |
--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Makefile.am.input 2014-01-17 16:01:04.154064515 +0000
|
|
|
1448d9 |
+++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/Makefile.am 2014-01-17 16:01:13.142109459 +0000
|
|
|
1448d9 |
@@ -14,7 +14,7 @@ HDRS = RegionHelper.h vncExtInit.h vncHo
|
|
|
1448d9 |
Input.h
|
|
|
1448d9 |
|
|
|
1448d9 |
libvnccommon_la_SOURCES = $(HDRS) vncExtInit.cc vncHooks.cc XserverDesktop.cc \
|
|
|
1448d9 |
- Input.cc
|
|
|
1448d9 |
+ Input.cc InputCore.cc InputXKB.cc
|
|
|
1448d9 |
|
|
|
1448d9 |
libvnccommon_la_CPPFLAGS = -DVENDOR_RELEASE="$(VENDOR_RELEASE)" \
|
|
|
1448d9 |
-DVENDOR_STRING="\"$(VENDOR_STRING)\"" -I$(TIGERVNC_SRCDIR)/common -UHAVE_CONFIG_H \
|
|
|
1448d9 |
diff -up tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc.input tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc
|
|
|
1448d9 |
--- tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc.input 2014-01-17 16:01:32.532206349 +0000
|
|
|
1448d9 |
+++ tigervnc-1.2.80-20130314svn5065/unix/xserver/hw/vnc/XserverDesktop.cc 2014-01-17 16:02:13.775412129 +0000
|
|
|
1448d9 |
@@ -579,6 +579,12 @@ static struct timeval XserverDesktopTime
|
|
|
1448d9 |
|
|
|
1448d9 |
void XserverDesktop::blockHandler(fd_set* fds, OSTimePtr timeout)
|
|
|
1448d9 |
{
|
|
|
1448d9 |
+ // We don't have a good callback for when we can init input devices[1],
|
|
|
1448d9 |
+ // so we abuse the fact that this routine will be called first thing
|
|
|
1448d9 |
+ // once the dix is done initialising.
|
|
|
1448d9 |
+ // [1] Technically Xvnc has InitInput(), but libvnc.so has nothing.
|
|
|
1448d9 |
+ inputDevice->InitInputDevice();
|
|
|
1448d9 |
+
|
|
|
1448d9 |
try {
|
|
|
1448d9 |
int nextTimeout;
|
|
|
1448d9 |
|