mirror of
https://github.com/kasmtech/KasmVNC.git
synced 2025-02-18 03:10:47 +01:00
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:
commit
08f5000b9f
1
.gitignore
vendored
1
.gitignore
vendored
@ -21,3 +21,4 @@ debian/files
|
|||||||
debian/kasmvncserver.substvars
|
debian/kasmvncserver.substvars
|
||||||
debian/kasmvncserver/
|
debian/kasmvncserver/
|
||||||
.pc
|
.pc
|
||||||
|
.vscode/
|
||||||
|
2
.gitmodules
vendored
2
.gitmodules
vendored
@ -1,4 +1,4 @@
|
|||||||
[submodule "kasmweb"]
|
[submodule "kasmweb"]
|
||||||
path = kasmweb
|
path = kasmweb
|
||||||
url = https://github.com/kasmtech/noVNC.git
|
url = https://github.com/kasmtech/noVNC.git
|
||||||
branch = master
|
branch = feature/KASM-2335_IME_support_2
|
||||||
|
@ -226,4 +226,4 @@ static void bandwidthPreset() {
|
|||||||
rfb::PresetParameter rfb::Server::preferBandwidth
|
rfb::PresetParameter rfb::Server::preferBandwidth
|
||||||
("PreferBandwidth",
|
("PreferBandwidth",
|
||||||
"Set various options for lower bandwidth use. The default is off, aka to prefer quality.",
|
"Set various options for lower bandwidth use. The default is off, aka to prefer quality.",
|
||||||
false, bandwidthPreset);
|
false, bandwidthPreset);
|
@ -77,7 +77,6 @@ namespace rfb {
|
|||||||
static BoolParameter ignoreClientSettingsKasm;
|
static BoolParameter ignoreClientSettingsKasm;
|
||||||
static BoolParameter selfBench;
|
static BoolParameter selfBench;
|
||||||
static PresetParameter preferBandwidth;
|
static PresetParameter preferBandwidth;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
2
kasmweb
2
kasmweb
@ -1 +1 @@
|
|||||||
Subproject commit df9c9d0d96acef17423c237fea9497850a6c1c17
|
Subproject commit e2cc682243c55786e719436f214da0f0948f605a
|
@ -39,6 +39,7 @@
|
|||||||
#include "xkbsrv.h"
|
#include "xkbsrv.h"
|
||||||
#include "xkbstr.h"
|
#include "xkbstr.h"
|
||||||
#include "xserver-properties.h"
|
#include "xserver-properties.h"
|
||||||
|
#include "stdbool.h"
|
||||||
extern _X_EXPORT DevPrivateKey CoreDevicePrivateKey;
|
extern _X_EXPORT DevPrivateKey CoreDevicePrivateKey;
|
||||||
#include <X11/keysym.h>
|
#include <X11/keysym.h>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
@ -66,6 +67,8 @@ static const unsigned short *codeMap;
|
|||||||
static unsigned int codeMapLen;
|
static unsigned int codeMapLen;
|
||||||
|
|
||||||
static KeySym pressedKeys[256];
|
static KeySym pressedKeys[256];
|
||||||
|
static unsigned int needFree[256];
|
||||||
|
static bool freeKeys;
|
||||||
|
|
||||||
static int vncPointerProc(DeviceIntPtr pDevice, int onoff);
|
static int vncPointerProc(DeviceIntPtr pDevice, int onoff);
|
||||||
static void vncKeyboardBell(int percent, DeviceIntPtr device,
|
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
|
* Instead we call it from XserverDesktop at an appropriate
|
||||||
* time.
|
* time.
|
||||||
*/
|
*/
|
||||||
void vncInitInputDevice(void)
|
void vncInitInputDevice(bool freeKeyMappings)
|
||||||
{
|
{
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
@ -110,6 +113,8 @@ void vncInitInputDevice(void)
|
|||||||
codeMap = code_map_qnum_to_xorgkbd;
|
codeMap = code_map_qnum_to_xorgkbd;
|
||||||
codeMapLen = code_map_qnum_to_xorgkbd_len;
|
codeMapLen = code_map_qnum_to_xorgkbd_len;
|
||||||
#endif
|
#endif
|
||||||
|
freeKeys = freeKeyMappings;
|
||||||
|
memset(needFree, 0, sizeof(needFree));
|
||||||
|
|
||||||
for (i = 0;i < 256;i++)
|
for (i = 0;i < 256;i++)
|
||||||
pressedKeys[i] = NoSymbol;
|
pressedKeys[i] = NoSymbol;
|
||||||
@ -500,6 +505,7 @@ static void vncKeysymKeyboardEvent(KeySym keysym, int down)
|
|||||||
pressedKeys[i] = NoSymbol;
|
pressedKeys[i] = NoSymbol;
|
||||||
pressKey(vncKeyboardDev, i, FALSE, "keycode");
|
pressKey(vncKeyboardDev, i, FALSE, "keycode");
|
||||||
mieqProcessInputEvents();
|
mieqProcessInputEvents();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -544,7 +550,7 @@ static void vncKeysymKeyboardEvent(KeySym keysym, int down)
|
|||||||
|
|
||||||
/* No matches. Will have to add a new entry... */
|
/* No matches. Will have to add a new entry... */
|
||||||
if (keycode == 0) {
|
if (keycode == 0) {
|
||||||
keycode = vncAddKeysym(keysym, state);
|
keycode = vncAddKeysym(keysym, state, needFree, freeKeys);
|
||||||
if (keycode == 0) {
|
if (keycode == 0) {
|
||||||
LOG_ERROR("Failure adding new keysym 0x%x", keysym);
|
LOG_ERROR("Failure adding new keysym 0x%x", keysym);
|
||||||
return;
|
return;
|
||||||
|
@ -25,12 +25,13 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <X11/X.h>
|
#include <X11/X.h>
|
||||||
|
#include "stdbool.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void vncInitInputDevice(void);
|
void vncInitInputDevice(bool freeKeyMappings);
|
||||||
|
|
||||||
void vncPointerButtonAction(int buttonMask, const unsigned char skipclick,
|
void vncPointerButtonAction(int buttonMask, const unsigned char skipclick,
|
||||||
const unsigned char skiprelease);
|
const unsigned char skiprelease);
|
||||||
@ -57,7 +58,8 @@ KeyCode vncKeysymToKeycode(KeySym keysym, unsigned state, unsigned *new_state);
|
|||||||
|
|
||||||
int vncIsAffectedByNumLock(KeyCode keycode);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -60,6 +60,10 @@ BoolParameter rawKeyboard("RawKeyboard",
|
|||||||
"Send keyboard events straight through and "
|
"Send keyboard events straight through and "
|
||||||
"avoid mapping them to the current keyboard "
|
"avoid mapping them to the current keyboard "
|
||||||
"layout", false);
|
"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",
|
IntParameter queryConnectTimeout("QueryConnectTimeout",
|
||||||
"Number of seconds to show the "
|
"Number of seconds to show the "
|
||||||
"Accept Connection dialog before "
|
"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
|
// so we abuse the fact that this routine will be called first thing
|
||||||
// once the dix is done initialising.
|
// once the dix is done initialising.
|
||||||
// [1] Technically Xvnc has InitInput(), but libvnc.so has nothing.
|
// [1] Technically Xvnc has InitInput(), but libvnc.so has nothing.
|
||||||
vncInitInputDevice();
|
vncInitInputDevice(freeKeyMappings);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
std::list<Socket*> sockets;
|
std::list<Socket*> sockets;
|
||||||
|
Loading…
Reference in New Issue
Block a user