Skip to content

Commit

Permalink
update XkbAddKeyKeysym.
Browse files Browse the repository at this point in the history
  • Loading branch information
m1k1o committed Jan 15, 2023
1 parent a02f47f commit cd9ac70
Showing 1 changed file with 39 additions and 78 deletions.
117 changes: 39 additions & 78 deletions server/internal/desktop/xorg/xorg.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,98 +149,59 @@ KeyCode XkbKeysymToKeycode(Display* dpy, KeySym keysym) {
return keycode;
}

static xkeycode_t *xFreeKeycodesHead = NULL;
int xNumcodes = 0;

void XFreeKeycodesInit(Display* dpy) {
if (xFreeKeycodesHead != NULL)
return;

KeyCode keycode;
KeySym *keysyms;
int min, max, numcodes;

// get full keyboard mapping
XDisplayKeycodes(dpy, &min, &max);
keysyms = XGetKeyboardMapping(dpy, min, max-min, &numcodes);
xNumcodes = numcodes;

// loop through all keycodes
xkeycode_t *last = NULL;
for (int i = min; i <= max; ++i) {
// check if keycode is empty
int isEmpty = 1;
for (int j = 0; j < numcodes; ++j) {
int symindex = ((i - min) * numcodes) + j;
if (keysyms[symindex] != 0) {
isEmpty = 0;
break;
}
}
if (!isEmpty) continue;

xkeycode_t *entry = (xkeycode_t *) malloc(sizeof(xkeycode_t));
if (entry == NULL) return;

entry->keycode = i;
if (last == NULL) {
xFreeKeycodesHead = entry;
} else {
last->next = entry;
}
last = entry;
}
// From https://github.com/TigerVNC/tigervnc/blob/a434ef3377943e89165ac13c537cd0f28be97f84/unix/x0vncserver/XDesktop.cxx#L401-L453
KeyCode XkbAddKeyKeysym(Display* dpy, KeySym keysym) {
int types[1];
unsigned int key;
XkbDescPtr xkb;
XkbMapChangesRec changes;
KeySym *syms;
KeySym upper, lower;

// no free keycodes, pick last two keycodes anyway
if (last == NULL) {
xkeycode_t *entry1 = (xkeycode_t *) malloc(sizeof(xkeycode_t));
if (entry1 == NULL) return;
entry1->keycode = max-1;
xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);

xkeycode_t *entry2 = (xkeycode_t *) malloc(sizeof(xkeycode_t));
if (entry2 == NULL) return;
entry2->keycode = max-2;
if (!xkb)
return 0;

xFreeKeycodesHead = entry1;
entry1->next = entry2;
last = entry2;
for (key = xkb->max_key_code; key >= xkb->min_key_code; key--) {
if (XkbKeyNumGroups(xkb, key) == 0)
break;
}

// make as circular list
last->next = xFreeKeycodesHead;
// no free keycodes
if (key < xkb->min_key_code)
return 0;

XFree(keysyms);
}
// assign empty structure
changes = *(XkbMapChangesRec *) malloc(sizeof(XkbMapChangesRec));
for (int i = 0; i < sizeof(changes); i++) ((char *) &changes)[i] = 0;

// get free keycode from list
KeyCode XFreeKeycodeGet() {
if (xFreeKeycodesHead == NULL)
return 0;
XConvertCase(keysym, &lower, &upper);

// move head to next entry
xkeycode_t *entry = xFreeKeycodesHead;
xFreeKeycodesHead = entry->next;
if (upper == lower)
types[XkbGroup1Index] = XkbOneLevelIndex;
else
types[XkbGroup1Index] = XkbAlphabeticIndex;

return entry->keycode;
}
XkbChangeTypesOfKey(xkb, key, 1, XkbGroup1Mask, types, &changes);

// map keysym to new keycode
KeyCode XKeysymMapNew(Display* dpy, KeySym keysym) {
// initialize free keycodes list
if (xFreeKeycodesHead == NULL) {
XFreeKeycodesInit(dpy);
syms = XkbKeySymsPtr(xkb,key);
if (upper == lower)
syms[0] = keysym;
else {
syms[0] = lower;
syms[1] = upper;
}

KeyCode keycode = XFreeKeycodeGet();
changes.changed |= XkbKeySymsMask;
changes.first_key_sym = key;
changes.num_key_syms = 1;

// no free keycodes, cannot map keysym
if (keycode != 0) {
KeySym keysym_list[xNumcodes];
for(int i=0;i<xNumcodes;i++) keysym_list[i] = keysym;
XChangeKeyboardMapping(dpy, keycode, xNumcodes, keysym_list, 1);
if (XkbChangeMap(dpy, xkb, &changes)) {
return key;
}

return keycode;
return 0;
}

void XKey(KeySym keysym, int down) {
Expand All @@ -259,7 +220,7 @@ void XKey(KeySym keysym, int down) {

// Map non-existing keysyms to new keycodes
if (keycode == 0)
keycode = XKeysymMapNew(display, keysym);
keycode = XkbAddKeyKeysym(display, keysym);

if (down)
XKeyEntryAdd(keysym, keycode);
Expand Down

0 comments on commit cd9ac70

Please sign in to comment.