|
|
@ -25,16 +25,19 @@
|
|
|
|
#include "xorg-version.h"
|
|
|
|
#include "xorg-version.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "RFBGlue.h"
|
|
|
|
#include "xkbsrv.h"
|
|
|
|
#include "xkbsrv.h"
|
|
|
|
#include "xkbstr.h"
|
|
|
|
#include "xkbstr.h"
|
|
|
|
#include "eventstr.h"
|
|
|
|
#include "eventstr.h"
|
|
|
|
#include "scrnintstr.h"
|
|
|
|
#include "scrnintstr.h"
|
|
|
|
#include "mi.h"
|
|
|
|
#include "mi.h"
|
|
|
|
|
|
|
|
#include "stdbool.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "Input.h"
|
|
|
|
#include "Input.h"
|
|
|
|
|
|
|
|
|
|
|
@ -50,7 +53,15 @@
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define LOG_NAME "Input"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define LOG_ERROR(...) vncLogError(LOG_NAME, __VA_ARGS__)
|
|
|
|
|
|
|
|
#define LOG_STATUS(...) vncLogStatus(LOG_NAME, __VA_ARGS__)
|
|
|
|
|
|
|
|
#define LOG_INFO(...) vncLogInfo(LOG_NAME, __VA_ARGS__)
|
|
|
|
|
|
|
|
#define LOG_DEBUG(...) vncLogDebug(LOG_NAME, __VA_ARGS__)
|
|
|
|
|
|
|
|
|
|
|
|
extern DeviceIntPtr vncKeyboardDev;
|
|
|
|
extern DeviceIntPtr vncKeyboardDev;
|
|
|
|
|
|
|
|
static unsigned int MAX_MAPPINGS = UINT_MAX - 1;
|
|
|
|
|
|
|
|
|
|
|
|
static void vncXkbProcessDeviceEvent(int screenNum,
|
|
|
|
static void vncXkbProcessDeviceEvent(int screenNum,
|
|
|
|
InternalEvent *event,
|
|
|
|
InternalEvent *event,
|
|
|
@ -536,12 +547,16 @@ int vncIsAffectedByNumLock(KeyCode keycode)
|
|
|
|
return 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KeyCode vncAddKeysym(KeySym keysym, unsigned state)
|
|
|
|
KeyCode vncAddKeysym(KeySym keysym, unsigned state, unsigned int *needFree, bool freeKeys)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
DeviceIntPtr master;
|
|
|
|
DeviceIntPtr master;
|
|
|
|
XkbDescPtr xkb;
|
|
|
|
XkbDescPtr xkb;
|
|
|
|
unsigned int key;
|
|
|
|
unsigned int key = 0;
|
|
|
|
|
|
|
|
unsigned int i;
|
|
|
|
|
|
|
|
unsigned int newest_k = 0;
|
|
|
|
|
|
|
|
unsigned int oldest_k = 0;
|
|
|
|
|
|
|
|
unsigned int freeCnt = 0;
|
|
|
|
|
|
|
|
|
|
|
|
XkbEventCauseRec cause;
|
|
|
|
XkbEventCauseRec cause;
|
|
|
|
XkbChangesRec changes;
|
|
|
|
XkbChangesRec changes;
|
|
|
|
|
|
|
|
|
|
|
@ -551,14 +566,45 @@ KeyCode vncAddKeysym(KeySym keysym, unsigned state)
|
|
|
|
|
|
|
|
|
|
|
|
master = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);
|
|
|
|
master = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);
|
|
|
|
xkb = master->key->xkbInfo->desc;
|
|
|
|
xkb = master->key->xkbInfo->desc;
|
|
|
|
for (key = xkb->max_key_code; key >= xkb->min_key_code; key--) {
|
|
|
|
|
|
|
|
if (XkbKeyNumGroups(xkb, key) == 0)
|
|
|
|
//find the first free key to map
|
|
|
|
break;
|
|
|
|
for (i = xkb->max_key_code; i >= xkb->min_key_code; i--) {
|
|
|
|
|
|
|
|
if (XkbKeyNumGroups(xkb, i) == 0 && *(needFree + i) != UINT_MAX) {
|
|
|
|
|
|
|
|
if (++freeCnt == 1)
|
|
|
|
|
|
|
|
key = i;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (key < xkb->min_key_code)
|
|
|
|
if (key < xkb->min_key_code)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//find the oldest and newest keys that have been remapped
|
|
|
|
|
|
|
|
for (i = 1;i < 256;i++) {
|
|
|
|
|
|
|
|
//protect from uint rollover
|
|
|
|
|
|
|
|
if (*(needFree + i) == MAX_MAPPINGS)
|
|
|
|
|
|
|
|
*(needFree + i) = 1;
|
|
|
|
|
|
|
|
if (*(needFree + i) > *(needFree + newest_k) && *(needFree + i) != UINT_MAX)
|
|
|
|
|
|
|
|
newest_k = i;
|
|
|
|
|
|
|
|
if (*(needFree + i) < *(needFree + oldest_k) && *(needFree +i) > 0)
|
|
|
|
|
|
|
|
oldest_k = i;
|
|
|
|
|
|
|
|
//mark as free to use
|
|
|
|
|
|
|
|
if (*(needFree + i) == UINT_MAX)
|
|
|
|
|
|
|
|
*(needFree + i) = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
*(needFree + key) = ++(*(needFree + newest_k));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//if running low on free keys, free the oldest key that was used
|
|
|
|
|
|
|
|
if (freeCnt < 3 && *(needFree + oldest_k) > 0 && freeKeys) {
|
|
|
|
|
|
|
|
vncRemoveKeycode(oldest_k);
|
|
|
|
|
|
|
|
LOG_DEBUG("Removed mapping for keycode %d", oldest_k);
|
|
|
|
|
|
|
|
//mark as free to use after one more cycle
|
|
|
|
|
|
|
|
*(needFree + oldest_k) = UINT_MAX;
|
|
|
|
|
|
|
|
} else if (freeCnt < 3 && freeKeys) {
|
|
|
|
|
|
|
|
//this should only happen if the system had fewer than 3 free keys to begin with
|
|
|
|
|
|
|
|
LOG_INFO("The system has fewer than 3 unmapped keys with no available keys to free.");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
memset(&changes, 0, sizeof(changes));
|
|
|
|
memset(&changes, 0, sizeof(changes));
|
|
|
|
memset(&cause, 0, sizeof(cause));
|
|
|
|
memset(&cause, 0, sizeof(cause));
|
|
|
|
|
|
|
|
|
|
|
@ -612,6 +658,40 @@ KeyCode vncAddKeysym(KeySym keysym, unsigned state)
|
|
|
|
return key;
|
|
|
|
return key;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void vncRemoveKeycode(unsigned keycode)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
DeviceIntPtr master;
|
|
|
|
|
|
|
|
XkbDescPtr xkb;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XkbEventCauseRec cause;
|
|
|
|
|
|
|
|
XkbChangesRec changes;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
master = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);
|
|
|
|
|
|
|
|
xkb = master->key->xkbInfo->desc;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
memset(&changes, 0, sizeof(changes));
|
|
|
|
|
|
|
|
memset(&cause, 0, sizeof(cause));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XkbSetCauseUnknown(&cause);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KeySym ks = NoSymbol;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
KeySymsRec keysyms;
|
|
|
|
|
|
|
|
keysyms.minKeyCode = keycode;
|
|
|
|
|
|
|
|
keysyms.maxKeyCode = keycode;
|
|
|
|
|
|
|
|
keysyms.mapWidth = 1;
|
|
|
|
|
|
|
|
keysyms.map = &ks;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
unsigned check = 0;
|
|
|
|
|
|
|
|
XkbUpdateKeyTypesFromCore(master, &keysyms, keycode, 1, &changes);
|
|
|
|
|
|
|
|
XkbUpdateActions(master, keycode, 1, &changes, &check, &cause);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (check)
|
|
|
|
|
|
|
|
XkbCheckSecondaryEffects(master->key->xkbInfo, 1, &changes, &cause);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
XkbSendNotification(master, &changes, &cause);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void vncXkbProcessDeviceEvent(int screenNum,
|
|
|
|
static void vncXkbProcessDeviceEvent(int screenNum,
|
|
|
|
InternalEvent *event,
|
|
|
|
InternalEvent *event,
|
|
|
|
DeviceIntPtr dev)
|
|
|
|
DeviceIntPtr dev)
|
|
|
|