commit 5ded4dac370ce5d8d727c5d3891448f942edbfdf Author: tv Date: Sat Feb 27 22:54:55 2021 +0100 x11: add input forwarding support diff --git a/video/out/x11_common.c b/video/out/x11_common.c index ac551fae8e..2e95451d7f 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -25,6 +25,10 @@ #include #include +#include +#include +#include + #include #include #include @@ -1097,6 +1101,73 @@ static void release_all_keys(struct vo *vo) x11->win_drag_button1_down = false; } + +#define FORWARD_START 1 +#define FORWARD_READY 2 +#define FORWARD_ERROR 3 +static int forward_state = FORWARD_START; +static int forward_fd, forward_len; +static struct sockaddr_un forward_un; +static char forward_buf[BUFSIZ]; + +static void forward_start(void) { + const char *socket_path = getenv("FORWARD_SOCKET"); + if (socket_path == NULL) { + fprintf(stderr, "forward_start: environment variable FORWARD_SOCKET not set\n"); + forward_state = FORWARD_ERROR; + return; + } + + if ((forward_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { + perror("socket"); + } else { + memset(&forward_un, 0, sizeof(forward_un)); + forward_un.sun_family = AF_UNIX; + strcpy(forward_un.sun_path, socket_path); + forward_len = offsetof(struct sockaddr_un, sun_path) + strlen(socket_path); + forward_state = FORWARD_READY; + } +} +static void forward_send(const char *fmt, ...) { + if (forward_state != FORWARD_READY) return; + + va_list argp; + va_start(argp, fmt); + int n1 = vsnprintf(forward_buf, BUFSIZ, fmt, argp); + if (n1 < BUFSIZ + 1) { + forward_buf[n1++] = '\n'; + forward_buf[n1] = '\0'; + int n2 = sendto(forward_fd, forward_buf, n1, 0, (struct sockaddr *)&forward_un, forward_len); + if (n2 < 0) { + perror("sendto"); + } + } +} +static const char *forward_keyname(KeySym keySym) { + const char *name; + if (keySym == NoSymbol) { + name = "NoSymbol"; + } else if (!(name = XKeysymToString(keySym))) { + name = "NoName"; + } + return name; +} +static void forward_keydown(KeySym keySym) { + forward_send("xdotool keydown %s", forward_keyname(keySym)); +} +static void forward_keyup(KeySym keySym) { + forward_send("xdotool keyup %s", forward_keyname(keySym)); +} +static void forward_mousedown(int button) { + forward_send("xdotool mousedown %d", button); +} +static void forward_mouseup(int button) { + forward_send("xdotool mouseup %d", button); +} +static void forward_mousemove(int x, int y) { + forward_send("xdotool mousemove %d %d", x, y); +} + void vo_x11_check_events(struct vo *vo) { struct vo_x11_state *x11 = vo->x11; @@ -1105,6 +1176,10 @@ void vo_x11_check_events(struct vo *vo) xscreensaver_heartbeat(vo->x11); + if (forward_state == FORWARD_START) { + forward_start(); + } + while (XPending(display)) { XNextEvent(display, &Event); MP_TRACE(x11, "XEvent: %d\n", Event.type); @@ -1146,6 +1221,7 @@ void vo_x11_check_events(struct vo *vo) if (mpkey) mp_input_put_key(x11->input_ctx, mpkey | modifiers); } + forward_keydown(XLookupKeysym(&Event.xkey, 0)); break; } case FocusIn: @@ -1161,6 +1237,7 @@ void vo_x11_check_events(struct vo *vo) break; case KeyRelease: release_all_keys(vo); + forward_keyup(XLookupKeysym(&Event.xkey, 0)); break; case MotionNotify: if (x11->win_drag_button1_down && !x11->fs && @@ -1182,6 +1259,7 @@ void vo_x11_check_events(struct vo *vo) Event.xmotion.y); } x11->win_drag_button1_down = false; + forward_mousemove(Event.xmotion.x, Event.xmotion.y); break; case LeaveNotify: if (Event.xcrossing.mode != NotifyNormal) @@ -1204,6 +1282,7 @@ void vo_x11_check_events(struct vo *vo) get_mods(Event.xbutton.state) | MP_KEY_STATE_DOWN); long msg[4] = {XEMBED_REQUEST_FOCUS}; vo_x11_xembed_send_message(x11, msg); + forward_mousedown(Event.xbutton.button); break; case ButtonRelease: if (Event.xbutton.button - 1 >= MP_KEY_MOUSE_BTN_COUNT) @@ -1213,6 +1292,7 @@ void vo_x11_check_events(struct vo *vo) mp_input_put_key(x11->input_ctx, (MP_MBTN_BASE + Event.xbutton.button - 1) | get_mods(Event.xbutton.state) | MP_KEY_STATE_UP); + forward_mouseup(Event.xbutton.button); break; case MapNotify: x11->window_hidden = false;