[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