diff --git a/docs/changelog.md b/docs/changelog.md index e8a632d..b995b20 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -5,6 +5,7 @@ ### Bugs - Fixed TCP mux occasional freeze by adding write buffer to it. - Fixed stereo problem in chromium-based browsers, where it was only as mono by adding `stereo=1` to opus SDP to clients answer. +- Fixed keysym mapping for unknown keycodes, which was causing some key combinations to not work on some keyboards. ## [n.eko v2.7](https://github.com/m1k1o/neko/releases/tag/v2.7) diff --git a/server/internal/desktop/xorg/xorg.c b/server/internal/desktop/xorg/xorg.c index bc545c4..358d854 100644 --- a/server/internal/desktop/xorg/xorg.c +++ b/server/internal/desktop/xorg/xorg.c @@ -71,6 +71,7 @@ void XButton(unsigned int button, int down) { static xkeyentry_t *xKeysHead = NULL; +// add keycode->keysym mapping to list void XKeyEntryAdd(KeySym keysym, KeyCode keycode) { xkeyentry_t *entry = (xkeyentry_t *) malloc(sizeof(xkeyentry_t)); if (entry == NULL) @@ -82,6 +83,7 @@ void XKeyEntryAdd(KeySym keysym, KeyCode keycode) { xKeysHead = entry; } +// get keycode for keysym from list KeyCode XKeyEntryGet(KeySym keysym) { xkeyentry_t *prev = NULL; xkeyentry_t *curr = xKeysHead; @@ -147,6 +149,100 @@ 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; + } + + // 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; + + xkeycode_t *entry2 = (xkeycode_t *) malloc(sizeof(xkeycode_t)); + if (entry2 == NULL) return; + entry2->keycode = max-2; + + xFreeKeycodesHead = entry1; + entry1->next = entry2; + last = entry2; + } + + // make as circular list + last->next = xFreeKeycodesHead; + + XFree(keysyms); +} + +// get free keycode from list +KeyCode XFreeKeycodeGet() { + if (xFreeKeycodesHead == NULL) + return 0; + + // move head to next entry + xkeycode_t *entry = xFreeKeycodesHead; + xFreeKeycodesHead = entry->next; + + return entry->keycode; +} + +// map keysym to new keycode +KeyCode XKeysymMapNew(Display* dpy, KeySym keysym) { + // initialize free keycodes list + if (xFreeKeycodesHead == NULL) { + XFreeKeycodesInit(dpy); + } + + KeyCode keycode = XFreeKeycodeGet(); + + // no free keycodes, cannot map keysym + if (keycode != 0) { + KeySym keysym_list[xNumcodes]; + for(int i=0;ired_mask) >> 16; - pixels[pos+1] = (pixel & ximage->green_mask) >> 8; - pixels[pos+2] = pixel & ximage->blue_mask; + pixels[pos] = (pixel & ximage->red_mask) >> 16; + pixels[pos+1] = (pixel & ximage->green_mask) >> 8; + pixels[pos+2] = pixel & ximage->blue_mask; } } diff --git a/server/internal/desktop/xorg/xorg.h b/server/internal/desktop/xorg/xorg.h index f5ebd39..59a2b2c 100644 --- a/server/internal/desktop/xorg/xorg.h +++ b/server/internal/desktop/xorg/xorg.h @@ -26,6 +26,11 @@ typedef struct xkeyentry_t { struct xkeyentry_t *next; } xkeyentry_t; +typedef struct xkeycode_t { + KeyCode keycode; + struct xkeycode_t *next; +} xkeycode_t; + static void XKeyEntryAdd(KeySym keysym, KeyCode keycode); static KeyCode XKeyEntryGet(KeySym keysym); static KeyCode XkbKeysymToKeycode(Display *dpy, KeySym keysym);