Skip to content

Commit

Permalink
update xorg bindings.
Browse files Browse the repository at this point in the history
  • Loading branch information
m1k1o committed Jan 14, 2023
1 parent ccc1df9 commit a02f47f
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 16 deletions.
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
121 changes: 105 additions & 16 deletions server/internal/desktop/xorg/xorg.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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;i<xNumcodes;i++) keysym_list[i] = keysym;
XChangeKeyboardMapping(dpy, keycode, xNumcodes, keysym_list, 1);
}

return keycode;
}

void XKey(KeySym keysym, int down) {
if (keysym == 0)
return;
Expand All @@ -157,20 +253,13 @@ void XKey(KeySym keysym, int down) {
if (!down)
keycode = XKeyEntryGet(keysym);

// Try to get keysyms from existing keycodes
if (keycode == 0)
keycode = XkbKeysymToKeycode(display, keysym);

// Map non-existing keysyms to new keycodes
if (keycode == 0) {
int min, max, numcodes;
XDisplayKeycodes(display, &min, &max);
XGetKeyboardMapping(display, min, max-min, &numcodes);

keycode = (max-min+1)*numcodes;
KeySym keysym_list[numcodes];
for(int i=0;i<numcodes;i++) keysym_list[i] = keysym;
XChangeKeyboardMapping(display, keycode, numcodes, keysym_list, 1);
}
if (keycode == 0)
keycode = XKeysymMapNew(display, keysym);

if (down)
XKeyEntryAdd(keysym, keycode);
Expand Down Expand Up @@ -250,14 +339,14 @@ char *XGetScreenshot(int *w, int *h) {
*h = height;
char *pixels = (char *)malloc(width * height * 3);

for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
int pos = ((row * width) + col) * 3;
for (int row = 0; row < height; row++) {
for (int col = 0; col < width; col++) {
int pos = ((row * width) + col) * 3;
unsigned long pixel = XGetPixel(ximage, col, row);

pixels[pos] = (pixel & ximage->red_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;
}
}

Expand Down
5 changes: 5 additions & 0 deletions server/internal/desktop/xorg/xorg.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit a02f47f

Please sign in to comment.