[Spice-devel] [patch 6/6] spice-vdagent: directly inject keysyms to X11, using libXtst
Marc-André Lureau
mlureau at redhat.com
Wed Oct 16 12:48:01 CEST 2013
----- Original Message -----
> Note: This is an ugly hack because there is currently no clean way to do it.
>
> But experiments showed that the X11 agent is the wrong place to do such
> things, because it is started to late (after login).
That should not be a big problem, the greeter should run an agent too.
I don't think XTest is the best way to inject keysyms. Afaik, it's also quite insecure. I would rather rely on im/at framework, such as ibus or at-spi, but I haven't done enough research.
> Future: Maybe it is possible to extent the linux uinput framework for that
> purpose?
I wouldn't count on that possibility.
>
> Index: new/src/vdagent.c
> ===================================================================
> --- new.orig/src/vdagent.c 2013-10-14 14:52:01.000000000 +0200
> +++ new/src/vdagent.c 2013-10-15 12:32:42.000000000 +0200
> @@ -57,6 +57,12 @@
> struct udscs_message_header *header, uint8_t *data)
> {
> switch (header->type) {
> + case VDAGENTD_KEYSYM_MESSAGE: {
> + VDAgentKeySym *info = (VDAgentKeySym *)data;
> + vdagent_x11_send_keysym(x11, info->keysym, info->flags);
> + free(data);
> + break;
> + }
> case VDAGENTD_MONITORS_CONFIG:
> vdagent_x11_set_monitor_config(x11, (VDAgentMonitorsConfig *)data,
> 0);
> free(data);
> Index: new/src/vdagentd.c
> ===================================================================
> --- new.orig/src/vdagentd.c 2013-10-14 14:52:01.000000000 +0200
> +++ new/src/vdagentd.c 2013-10-15 12:34:34.000000000 +0200
> @@ -98,6 +98,7 @@
> VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_CLIPBOARD_SELECTION);
> VD_AGENT_SET_CAPABILITY(caps->caps,
> VD_AGENT_CAP_SPARSE_MONITORS_CONFIG);
> VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF);
> + VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_KEYSYM);
>
> vdagent_virtio_port_write(vport, VDP_CLIENT_PORT,
> VD_AGENT_ANNOUNCE_CAPABILITIES, 0,
> @@ -232,6 +233,20 @@
> data, size);
> }
>
> +static void do_client_keysym(struct vdagent_virtio_port *vport,
> + VDAgentMessage *message_header, uint8_t *data)
> +{
> + if (!active_session_conn) {
> + syslog(LOG_WARNING,
> + "Could not find an agent connection belonging to the "
> + "active session, ignoring client keysym request");
> + return;
> + }
> +
> + udscs_write(active_session_conn, VDAGENTD_KEYSYM_MESSAGE, 0, 0,
> + data, message_header->size);
> +}
> +
> static void cancel_file_xfer(struct vdagent_virtio_port *vport,
> const char *msg, uint32_t id)
> {
> @@ -304,6 +319,10 @@
> }
>
> switch (message_header->type) {
> + case VD_AGENT_KEYSYM_MESSAGE: {
> + do_client_keysym(vport, message_header, data);
> + break;
> + }
> case VD_AGENT_MOUSE_STATE:
> if (message_header->size != sizeof(VDAgentMouseState))
> goto size_error;
> Index: new/src/vdagentd-proto.h
> ===================================================================
> --- new.orig/src/vdagentd-proto.h 2013-10-15 07:49:58.000000000 +0200
> +++ new/src/vdagentd-proto.h 2013-10-15 07:50:34.000000000 +0200
> @@ -40,6 +40,7 @@
> VDAGENTD_FILE_XFER_STATUS,
> VDAGENTD_FILE_XFER_DATA,
> VDAGENTD_CLIENT_DISCONNECTED, /* daemon -> client */
> + VDAGENTD_KEYSYM_MESSAGE,
> VDAGENTD_NO_MESSAGES /* Must always be last */
> };
>
> Index: new/src/vdagent-x11.c
> ===================================================================
> --- new.orig/src/vdagent-x11.c 2013-10-14 14:52:01.000000000 +0200
> +++ new/src/vdagent-x11.c 2013-10-15 12:35:32.000000000 +0200
> @@ -111,6 +111,56 @@
> return error;
> }
>
> +void vdagent_x11_send_keysym(struct vdagent_x11 *x11, uint32_t keysym,
> uint32_t flags)
> +{
> + //syslog(LOG_INFO, "vdagent_x11_send_keysym %08x", keysym);
> +
> + /* Scratch space for temporary keycode bindings */
> + int scratch_keycode = 84; // use KEY_KPDOT
> + int keymap_changed = 0;
> +
> + static int orig_keysym = 0;
> +
> + if (orig_keysym == 0) {
> + int count = 0;
> + KeySym *res = XGetKeyboardMapping(x11->display, scratch_keycode, 1,
> &count);
> + if (count == 1) {
> + orig_keysym = res[0];
> + XFree(res);
> + } else {
> + orig_keysym = -1;
> + }
> + }
> +
> + int kc = XKeysymToKeycode(x11->display, keysym);
> + if (kc && ((keysym >= 0xffe1 && keysym <= 0xffee) ||
> + (keysym >= 0xfe01 && keysym <= 0xfe0f))) { // never remap
> Modifiers
> + //syslog(LOG_INFO, "use real keycode %d for modifier %08x", kc,
> keysym);
> + scratch_keycode = kc;
> + } else {
> + KeySym keysym_list[] = { keysym };
> + keymap_changed = 1;
> + XChangeKeyboardMapping(x11->display, scratch_keycode, 1,
> keysym_list, 1);
> + }
> +
> + if (flags & VD_AGENT_KEYSYM_FLAG_DOWN) {
> + //syslog(LOG_INFO, "vdagent_x11_send_keysym down %08x", keysym);
> + XTestFakeKeyEvent(x11->display, scratch_keycode, True, CurrentTime);
> + }
> +
> + if (flags & VD_AGENT_KEYSYM_FLAG_UP) {
> + //syslog(LOG_INFO, "vdagent_x11_send_keysym up %08x", keysym);
> + XTestFakeKeyEvent(x11->display, scratch_keycode, False,
> CurrentTime);
> + }
> +
> + if (keymap_changed && (orig_keysym > 0)) {
> + KeySym keysym_list[] = { orig_keysym };
> + XChangeKeyboardMapping(x11->display, scratch_keycode, 1,
> keysym_list, 1);
> + }
> +
> + XFlush(x11->display);
> +}
> +
> static void vdagent_x11_get_wm_name(struct vdagent_x11 *x11)
> {
> Atom type_ret;
> Index: new/src/vdagent-x11.h
> ===================================================================
> --- new.orig/src/vdagent-x11.h 2013-10-14 14:52:01.000000000 +0200
> +++ new/src/vdagent-x11.h 2013-10-15 09:06:44.000000000 +0200
> @@ -50,4 +50,6 @@
>
> int vdagent_x11_has_icons_on_desktop(struct vdagent_x11 *x11);
>
> +void vdagent_x11_send_keysym(struct vdagent_x11 *x11, uint32_t keysmy,
> uint32_t flags);
> +
> #endif
> Index: new/Makefile.am
> ===================================================================
> --- new.orig/Makefile.am 2013-10-14 14:52:01.000000000 +0200
> +++ new/Makefile.am 2013-10-15 09:12:45.000000000 +0200
> @@ -5,7 +5,7 @@
> sbin_PROGRAMS = src/spice-vdagentd
>
> src_spice_vdagent_CFLAGS = $(X_CFLAGS) $(SPICE_CFLAGS) $(GLIB2_CFLAGS)
> -src_spice_vdagent_LDADD = $(X_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS)
> +src_spice_vdagent_LDADD = -lXtst $(X_LIBS) $(SPICE_LIBS) $(GLIB2_LIBS)
> src_spice_vdagent_SOURCES = src/vdagent.c src/vdagent-x11.c
> src/vdagent-x11-randr.c src/vdagent-file-xfers.c src/udscs.c
>
> src_spice_vdagentd_CFLAGS = $(DBUS_CFLAGS) $(LIBSYSTEMD_LOGIN_CFLAGS) \
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
>
More information about the Spice-devel
mailing list