Merge branch 'feature/KASM-2335_IME_support' into 'master'

Resolve KASM-2335 "Feature/ ime support"

Closes KASM-2335

See merge request kasm-technologies/internal/KasmVNC!30
This commit is contained in:
Matthew McClaskey 2022-03-25 16:18:17 +00:00
commit 08f5000b9f
9 changed files with 107 additions and 15 deletions

1
.gitignore vendored
View File

@ -21,3 +21,4 @@ debian/files
debian/kasmvncserver.substvars
debian/kasmvncserver/
.pc
.vscode/

2
.gitmodules vendored
View File

@ -1,4 +1,4 @@
[submodule "kasmweb"]
path = kasmweb
url = https://github.com/kasmtech/noVNC.git
branch = master
branch = feature/KASM-2335_IME_support_2

View File

@ -77,7 +77,6 @@ namespace rfb {
static BoolParameter ignoreClientSettingsKasm;
static BoolParameter selfBench;
static PresetParameter preferBandwidth;
};
};

@ -1 +1 @@
Subproject commit df9c9d0d96acef17423c237fea9497850a6c1c17
Subproject commit e2cc682243c55786e719436f214da0f0948f605a

View File

@ -39,6 +39,7 @@
#include "xkbsrv.h"
#include "xkbstr.h"
#include "xserver-properties.h"
#include "stdbool.h"
extern _X_EXPORT DevPrivateKey CoreDevicePrivateKey;
#include <X11/keysym.h>
#include <X11/Xlib.h>
@ -66,6 +67,8 @@ static const unsigned short *codeMap;
static unsigned int codeMapLen;
static KeySym pressedKeys[256];
static unsigned int needFree[256];
static bool freeKeys;
static int vncPointerProc(DeviceIntPtr pDevice, int onoff);
static void vncKeyboardBell(int percent, DeviceIntPtr device,
@ -91,7 +94,7 @@ static void vncKeysymKeyboardEvent(KeySym keysym, int down);
* Instead we call it from XserverDesktop at an appropriate
* time.
*/
void vncInitInputDevice(void)
void vncInitInputDevice(bool freeKeyMappings)
{
int i, ret;
@ -110,6 +113,8 @@ void vncInitInputDevice(void)
codeMap = code_map_qnum_to_xorgkbd;
codeMapLen = code_map_qnum_to_xorgkbd_len;
#endif
freeKeys = freeKeyMappings;
memset(needFree, 0, sizeof(needFree));
for (i = 0;i < 256;i++)
pressedKeys[i] = NoSymbol;
@ -500,6 +505,7 @@ static void vncKeysymKeyboardEvent(KeySym keysym, int down)
pressedKeys[i] = NoSymbol;
pressKey(vncKeyboardDev, i, FALSE, "keycode");
mieqProcessInputEvents();
return;
}
}
@ -544,7 +550,7 @@ static void vncKeysymKeyboardEvent(KeySym keysym, int down)
/* No matches. Will have to add a new entry... */
if (keycode == 0) {
keycode = vncAddKeysym(keysym, state);
keycode = vncAddKeysym(keysym, state, needFree, freeKeys);
if (keycode == 0) {
LOG_ERROR("Failure adding new keysym 0x%x", keysym);
return;

View File

@ -25,12 +25,13 @@
#include <stdlib.h>
#include <X11/X.h>
#include "stdbool.h"
#ifdef __cplusplus
extern "C" {
#endif
void vncInitInputDevice(void);
void vncInitInputDevice(bool freeKeyMappings);
void vncPointerButtonAction(int buttonMask, const unsigned char skipclick,
const unsigned char skiprelease);
@ -57,7 +58,8 @@ KeyCode vncKeysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state);
int vncIsAffectedByNumLock(KeyCode keycode);
KeyCode vncAddKeysym(KeySym keysym, unsigned state);
KeyCode vncAddKeysym(KeySym keysym, unsigned state, unsigned int *needfree, bool freeKeys);
void vncRemoveKeycode(unsigned keycode);
#ifdef __cplusplus
}

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,11 +547,15 @@ 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)

View File

@ -60,6 +60,10 @@ BoolParameter rawKeyboard("RawKeyboard",
"Send keyboard events straight through and "
"avoid mapping them to the current keyboard "
"layout", false);
BoolParameter freeKeyMappings("FreeKeyMappings",
"Automatically free added keyboard mappings "
"when there are not enough unused keys to "
"map symbols to.", false);
IntParameter queryConnectTimeout("QueryConnectTimeout",
"Number of seconds to show the "
"Accept Connection dialog before "
@ -370,7 +374,7 @@ void XserverDesktop::blockHandler(int* timeout)
// so we abuse the fact that this routine will be called first thing
// once the dix is done initialising.
// [1] Technically Xvnc has InitInput(), but libvnc.so has nothing.
vncInitInputDevice();
vncInitInputDevice(freeKeyMappings);
try {
std::list<Socket*> sockets;