Resolve KASM-2335 "Feature/ ime support"

This commit is contained in:
Matthew McClaskey
2022-03-25 16:18:16 +00:00
parent 0c020f2e79
commit 3f89e5c117
9 changed files with 107 additions and 15 deletions

View File

@@ -25,16 +25,19 @@
#include "xorg-version.h"
#include <stdio.h>
#include <limits.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include "RFBGlue.h"
#include "xkbsrv.h"
#include "xkbstr.h"
#include "eventstr.h"
#include "scrnintstr.h"
#include "mi.h"
#include "stdbool.h"
#include "Input.h"
@@ -50,7 +53,15 @@
#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;
static unsigned int MAX_MAPPINGS = UINT_MAX - 1;
static void vncXkbProcessDeviceEvent(int screenNum,
InternalEvent *event,
@@ -536,12 +547,16 @@ int vncIsAffectedByNumLock(KeyCode keycode)
return 1;
}
KeyCode vncAddKeysym(KeySym keysym, unsigned state)
KeyCode vncAddKeysym(KeySym keysym, unsigned state, unsigned int *needFree, bool freeKeys)
{
DeviceIntPtr master;
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;
XkbChangesRec changes;
@@ -551,14 +566,45 @@ KeyCode vncAddKeysym(KeySym keysym, unsigned state)
master = GetMaster(vncKeyboardDev, KEYBOARD_OR_FLOAT);
xkb = master->key->xkbInfo->desc;
for (key = xkb->max_key_code; key >= xkb->min_key_code; key--) {
if (XkbKeyNumGroups(xkb, key) == 0)
break;
//find the first free key to map
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)
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(&cause, 0, sizeof(cause));
@@ -612,6 +658,40 @@ KeyCode vncAddKeysym(KeySym keysym, unsigned state)
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,
InternalEvent *event,
DeviceIntPtr dev)