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 --- v4: - keyboard description for windows clients is based on GetLocaleInfo instead of parsing g_win32_getlocale v3: - wrong g_return_val_if_fail replaced by g_warn_if_fail v2: - reduced indentation level - removed checking all the channels --- gtk/spice-gtk-session-priv.h | 1 + gtk/spice-gtk-session.c | 71 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 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..60cf899 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 * @@ -993,6 +1002,7 @@ static void channel_new(SpiceSession *session, SpiceChannel *channel, SpiceGtkSessionPrivate *s = self->priv; if (SPICE_IS_MAIN_CHANNEL(channel)) { + gboolean agent_connected; SPICE_DEBUG("Changing main channel from %p to %p", s->main, channel); s->main = SPICE_MAIN_CHANNEL(channel); g_signal_connect(channel, "main-clipboard-selection-grab", @@ -1001,6 +1011,14 @@ 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); + 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,56 @@ 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); + g_return_val_if_fail(dpy != NULL, NULL); + + xkb = XkbGetKeyboard(dpy, XkbAllComponentsMask, XkbUseCoreKbd); + g_warn_if_fail(xkb != NULL); + if (xkb != NULL) { + char *xkb_symbols = XGetAtomName(dpy, xkb->names->symbols); + g_warn_if_fail(xkb_symbols != NULL); + if (xkb_symbols != NULL) + keyboard_description = g_strdelimit(g_strdup_printf("%s", xkb_symbols), "_",'+'); + XFree(xkb_symbols); + XkbFreeKeyboard(xkb, XkbAllComponentsMask, True); + } + XCloseDisplay(dpy); +#elif defined(G_OS_WIN32) + wchar_t region[KL_NAMELENGTH]; + int region_len = GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, region, KL_NAMELENGTH); + + g_return_val_if_fail(region_len > 0, NULL); + + CharLowerW(region); + keyboard_description = g_strdup_printf("pc+%ls", region); +#else + g_warning("%s unimplemented on this platform", __FUNCTION__); +#endif + return keyboard_description; +} + +G_GNUC_INTERNAL +void spice_gtk_session_sync_keyboard_layout(SpiceGtkSession *self) +{ + SpiceGtkSessionPrivate *s = self->priv; + gchar *keyboard_description; + gboolean agent_connected; + + keyboard_description = get_keyboard_description(); + if (keyboard_description == NULL) + return; + + g_object_get(s->main, "agent-connected", &agent_connected, NULL); + if (agent_connected) + spice_main_send_keyboard_description(s->main, keyboard_description); + g_free(keyboard_description); +} -- 1.9.3 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel