[Spice-devel] [PATCH spice-gtk 2/2] Send keyboard description

Marc-André Lureau mlureau at redhat.com
Wed Nov 5 03:04:09 PST 2014



----- Original Message -----
> The keyboard description of the client will be sent to the guest
> when the connection is established.
> 
> RFE: https://bugs.freedesktop.org/show_bug.cgi?id=85332
> ---
>  gtk/spice-gtk-session-priv.h |  1 +
>  gtk/spice-gtk-session.c      | 72
>  ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 73 insertions(+)
> 
> diff --git a/gtk/spice-gtk-session-priv.h b/gtk/spice-gtk-session-priv.h
> index 91304b2..571f91f 100644
> --- a/gtk/spice-gtk-session-priv.h
> +++ b/gtk/spice-gtk-session-priv.h
> @@ -28,6 +28,7 @@ gboolean spice_gtk_session_get_read_only(SpiceGtkSession
> *self);
>  void spice_gtk_session_sync_keyboard_modifiers(SpiceGtkSession *self);
>  void spice_gtk_session_set_pointer_grabbed(SpiceGtkSession *self, gboolean
>  grabbed);
>  gboolean spice_gtk_session_get_pointer_grabbed(SpiceGtkSession *self);
> +void spice_gtk_session_sync_keyboard_layout(SpiceGtkSession *self);
>  
>  G_END_DECLS
>  
> diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
> index 52ad597..180f2ed 100644
> --- a/gtk/spice-gtk-session.c
> +++ b/gtk/spice-gtk-session.c
> @@ -178,6 +178,13 @@ static void
> spice_gtk_session_sync_keyboard_modifiers_for_channel(SpiceGtkSessio
>      }
>  }
>  
> +static void keymap_layout_changed(GdkKeymap *keymap, gpointer data)
> +{
> +    SpiceGtkSession *self = data;
> +
> +    spice_gtk_session_sync_keyboard_layout(self);
> +}
> +
>  static void keymap_modifiers_changed(GdkKeymap *keymap, gpointer data)
>  {
>      SpiceGtkSession *self = data;
> @@ -207,6 +214,8 @@ static void spice_gtk_session_init(SpiceGtkSession *self)
>                       G_CALLBACK(clipboard_owner_change), self);
>      spice_g_signal_connect_object(keymap, "state-changed",
>                                    G_CALLBACK(keymap_modifiers_changed),
>                                    self, 0);
> +    spice_g_signal_connect_object(keymap, "keys-changed",
> +                                  G_CALLBACK(keymap_layout_changed), self,
> 0);
>  }
>  
>  static GObject *
> @@ -1001,6 +1010,15 @@ static void channel_new(SpiceSession *session,
> SpiceChannel *channel,
>                           G_CALLBACK(clipboard_request), self);
>          g_signal_connect(channel, "main-clipboard-selection-release",
>                           G_CALLBACK(clipboard_release), self);
> +        gboolean agent_connected;
> +        g_object_get(channel, "agent-connected", &agent_connected, NULL);
> +        if (agent_connected) {
> +            spice_gtk_session_sync_keyboard_layout(self);
> +        } else {
> +            g_signal_connect_swapped(channel, "notify::agent-connected",
> +
> G_CALLBACK(spice_gtk_session_sync_keyboard_layout),
> +                                     self);
> +        }
>      }
>      if (SPICE_IS_INPUTS_CHANNEL(channel)) {
>          spice_g_signal_connect_object(channel, "inputs-modifiers",
> @@ -1195,3 +1213,57 @@ gboolean
> spice_gtk_session_get_pointer_grabbed(SpiceGtkSession *self)
>  
>      return self->priv->pointer_grabbed;
>  }
> +
> +static gchar *get_keyboard_description(void)
> +{
> +    gchar *keyboard_description = NULL;
> +#ifdef HAVE_X11_XKBLIB_H
> +    Display *dpy;
> +    XkbDescPtr xkb;
> +    int major = XkbMajorVersion, minor = XkbMinorVersion;
> +
> +    dpy = XkbOpenDisplay(NULL, NULL, NULL, &major, &minor, NULL);
> +    if (dpy != NULL) {

Please use g_return_val_if_fail() here, as this should not happen.

> +        xkb = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
> +        if (xkb != NULL) {

Same here

> +            keyboard_description = g_strdelimit(
> +                g_strdup_printf("%s", XGetAtomName(dpy,
> xkb->names->symbols)), "_",'+');
> +            XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
> +        }
> +        XCloseDisplay(dpy);
> +    }
> +#elif defined(G_OS_WIN32)
> +    gchar  *locale, *region;
> +    locale = g_win32_getlocale();
> +    region = g_ascii_strdown(g_strrstr(locale, "_")+1, -1);
> +    g_free(locale);
> +    keyboard_description = g_strdup_printf("pc+%s", region);
> +    g_free(region);
> +#endif
> +    return keyboard_description;
> +}
> +
> +G_GNUC_INTERNAL
> +void spice_gtk_session_sync_keyboard_layout(SpiceGtkSession *self)
> +{
> +    GList *l, *channels;
> +    gchar *keyboard_description = get_keyboard_description();
> +
> +    if (keyboard_description != NULL) {

To avoid deep blocks, it's easy to return early, this time with simple return (NULL is ok)

> +        channels = spice_session_get_channels(self->priv->session);
> +        for (l = channels; l != NULL; l = l->next) {

No need to look up all channels, there is a single main channel, and you can take it from priv->main

> +            if (SPICE_IS_MAIN_CHANNEL(l->data)) {
> +                SpiceMainChannel *main_channel =
> SPICE_MAIN_CHANNEL(l->data);
> +                gboolean agent_connected;
> +                g_object_get(main_channel, "agent-connected",
> &agent_connected, NULL);
> +                if (!agent_connected)
> +                    continue;
> +                spice_main_keyboard_description(main_channel,
> +                                                keyboard_description,
> +
> strlen(keyboard_description)+1);
> +            }
> +        }
> +        g_list_free(channels);
> +        g_free(keyboard_description);
> +    }
> +}
> --
> 1.9.3
> 
> _______________________________________________
> 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