[Spice-devel] [Spice-commits] 2 commits - gtk/spice-gtk-session.c gtk/spice-gtk-session.h gtk/spice-widget.c

longguang.yue bigclouds at 163.com
Thu Apr 3 20:40:33 PDT 2014


have you decided ?  i do not get your code from git.
where is the code   you judge  whether  need to sync or not?
according to your code, i think  there are at least two times to sync lock status, first , your code of state-changed,
the another is  key_press_and_release. 
i think  we just ensure that at the beginning of  connection we can make the lock status  identical , and just only once.
 
 
thanks


 

At 2014-04-04 05:09:08,"Jonathon Jongsma" <jjongsma at kemper.freedesktop.org> wrote:
> gtk/spice-gtk-session.c |  106 ++++++++++++++++++++++++++++++++++++++++++++++++
> gtk/spice-gtk-session.h |    1 
> gtk/spice-widget.c      |   91 -----------------------------------------
> 3 files changed, 109 insertions(+), 89 deletions(-)
>
>New commits:
>commit d06b256710cf91aec1275785d8cd65283581f544
>Author: Jonathon Jongsma <jjongsma at redhat.com>
>Date:   Mon Mar 31 11:07:53 2014 -0500
>
>    Use GdkKeymap to listen for keyboard modifier changes
>    
>    Connect to the GdkKeymap::state-changed signal to detect when the client
>    keyboard modifiers have changed. This keeps the client and the guest in sync
>    even when the SpiceDisplay widget isn't focused. New values are only sent down
>    to the guest if the new value is different than the current value.
>
>diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
>index f0f7edf..fe77f47 100644
>--- a/gtk/spice-gtk-session.c
>+++ b/gtk/spice-gtk-session.c
>@@ -171,6 +171,12 @@ static void spice_gtk_session_sync_keyboard_modifiers_for_channel(SpiceGtkSessio

>         spice_inputs_set_key_locks(inputs, client_modifiers);
> }
> 
>+static void keymap_modifiers_changed(GdkKeymap *keymap, gpointer data)
>+{
>+    SpiceGtkSession *self = data;
>+    spice_gtk_session_sync_keyboard_modifiers(self);
>+}
>+
> static void guest_modifiers_changed(SpiceInputsChannel *inputs, gpointer data)
> {
>     SpiceGtkSession *self = data;
>@@ -180,6 +186,7 @@ static void guest_modifiers_changed(SpiceInputsChannel *inputs, gpointer data)
> static void spice_gtk_session_init(SpiceGtkSession *self)
> {
>     SpiceGtkSessionPrivate *s;
>+    GdkKeymap *keymap = gdk_keymap_get_default();
> 
>     s = self->priv = SPICE_GTK_SESSION_GET_PRIVATE(self);
> 
>@@ -189,6 +196,8 @@ static void spice_gtk_session_init(SpiceGtkSession *self)
>     s->clipboard_primary = gtk_clipboard_get(GDK_SELECTION_PRIMARY);
>     g_signal_connect(G_OBJECT(s->clipboard_primary), "owner-change",
>                      G_CALLBACK(clipboard_owner_change), self);
>+    spice_g_signal_connect_object(keymap, "state-changed",
>+                                  G_CALLBACK(keymap_modifiers_changed), self, 0);
> }
> 
> static GObject *
>commit 9c75c7ee33d8567fef88594ae7844b9121c6291f
>Author: Jonathon Jongsma <jjongsma at redhat.com>
>Date:   Mon Mar 31 10:52:49 2014 -0500
>
>    Ensure keyboard modifiers are synchronized properly
>    
>    In certain circumstances, the keyboard modifiers get out-of-sync between the
>    guest and the client. This is easy to reproduce with the following steps:
>     - launch virt-viewer with a guest that is not running
>     - start the guest
>     - while guest is booting, enable CAPS LOCK on the client
>     - after guest finishes booting, it will set its modifiers to a default value
>       (e.g. numlock on, capslock off)
>     - now capslock is OFF in the guest, but ON in the client
>     - toggle caps lock
>     - now capslock is ON in the guest, but OFF in the client
>    
>    This moves the responsibility for synchronizing client and guest modifiers into
>    SpiceGtkSession. It can't be handled easily within the SpiceDisplay widget since
>    there can be multiple display widgets for each inputs channel.
>    
>    A new function (spice_gtk_session_sync_keyboard_modifiers()) was added so that
>    synchronization can be triggered manually if desired. But it also registers a
>    signal handler for the InputsChannel::inputs-modifiers signal to detect when the
>    guest has changed its modifiers. The signal handler simply overrides the guests
>    modifiers and sets them back to the value from the client.
>
>diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
>index a9ce025..f0f7edf 100644
>--- a/gtk/spice-gtk-session.c
>+++ b/gtk/spice-gtk-session.c
>@@ -17,6 +17,22 @@
> */
> #include "config.h"
> 
>+#if HAVE_X11_XKBLIB_H
>+#include <X11/XKBlib.h>
>+#include <gdk/gdkx.h>
>+#endif
>+#ifdef GDK_WINDOWING_X11
>+#include <X11/Xlib.h>
>+#include <gdk/gdkx.h>
>+#endif
>+#ifdef WIN32
>+#include <windows.h>
>+#include <gdk/gdkwin32.h>
>+#ifndef MAPVK_VK_TO_VSC /* may be undefined in older mingw-headers */
>+#define MAPVK_VK_TO_VSC 0
>+#endif
>+#endif
>+
> #include <gtk/gtk.h>
> #include <spice/vd_agent.h>
> #include "desktop-integration.h"
>@@ -97,6 +113,70 @@ enum {
>     PROP_AUTO_USBREDIR,
> };
> 
>+static guint32 get_keyboard_lock_modifiers(void)
>+{
>+    guint32 modifiers = 0;
>+#if HAVE_X11_XKBLIB_H
>+    Display *x_display = NULL;
>+    XKeyboardState keyboard_state;
>+
>+    GdkScreen *screen = gdk_screen_get_default();
>+    if (!GDK_IS_X11_DISPLAY(gdk_screen_get_display(screen))) {
>+        SPICE_DEBUG("FIXME: gtk backend is not X11");
>+        return 0;
>+    }
>+
>+    x_display = GDK_SCREEN_XDISPLAY(screen);
>+    XGetKeyboardControl(x_display, &keyboard_state);
>+
>+    if (keyboard_state.led_mask & 0x01) {
>+        modifiers |= SPICE_INPUTS_CAPS_LOCK;
>+    }
>+    if (keyboard_state.led_mask & 0x02) {
>+        modifiers |= SPICE_INPUTS_NUM_LOCK;
>+    }
>+    if (keyboard_state.led_mask & 0x04) {
>+        modifiers |= SPICE_INPUTS_SCROLL_LOCK;
>+    }
>+#elif defined(win32)
>+    if (GetKeyState(VK_CAPITAL) & 1) {
>+        modifiers |= SPICE_INPUTS_CAPS_LOCK;
>+    }
>+    if (GetKeyState(VK_NUMLOCK) & 1) {
>+        modifiers |= SPICE_INPUTS_NUM_LOCK;
>+    }
>+    if (GetKeyState(VK_SCROLL) & 1) {
>+        modifiers |= SPICE_INPUTS_SCROLL_LOCK;
>+    }
>+#else
>+    g_warning("get_keyboard_lock_modifiers not implemented");
>+#endif // HAVE_X11_XKBLIB_H
>+    return modifiers;
>+}
>+
>+static void spice_gtk_session_sync_keyboard_modifiers_for_channel(SpiceGtkSession *self,
>+                                                                  SpiceInputsChannel* inputs)
>+{
>+    gint guest_modifiers = 0, client_modifiers = 0;
>+
>+    g_return_if_fail(SPICE_IS_INPUTS_CHANNEL(inputs));
>+
>+    g_object_get(inputs, "key-modifiers", &guest_modifiers, NULL);
>+
>+    client_modifiers = get_keyboard_lock_modifiers();
>+    g_debug("%s: input:%p client_modifiers:0x%x, guest_modifiers:0x%x",
>+            G_STRFUNC, inputs, client_modifiers, guest_modifiers);
>+
>+    if (client_modifiers != guest_modifiers)
>+        spice_inputs_set_key_locks(inputs, client_modifiers);
>+}

>+
>+static void guest_modifiers_changed(SpiceInputsChannel *inputs, gpointer data)
>+{
>+    SpiceGtkSession *self = data;
>+    spice_gtk_session_sync_keyboard_modifiers_for_channel(self, inputs);
>+}
>+
> static void spice_gtk_session_init(SpiceGtkSession *self)
> {
>     SpiceGtkSessionPrivate *s;
>@@ -872,6 +952,11 @@ static void channel_new(SpiceSession *session, SpiceChannel *channel,
>         g_signal_connect(channel, "main-clipboard-selection-release",
>                          G_CALLBACK(clipboard_release), self);
>     }
>+    if (SPICE_IS_INPUTS_CHANNEL(channel)) {
>+        spice_g_signal_connect_object(channel, "inputs-modifiers",
>+                                      G_CALLBACK(guest_modifiers_changed), self, 0);
>+        spice_gtk_session_sync_keyboard_modifiers_for_channel(self, SPICE_INPUTS_CHANNEL(channel));
>+    }
> }
> 
> static void channel_destroy(SpiceSession *session, SpiceChannel *channel,
>@@ -1029,3 +1114,15 @@ void spice_gtk_session_paste_from_guest(SpiceGtkSession *self)
>     s->clipboard_by_guest[selection] = TRUE;
>     s->clip_hasdata[selection] = FALSE;
> }
>+
>+void spice_gtk_session_sync_keyboard_modifiers(SpiceGtkSession *self)
>+{
>+    GList *l = NULL, *channels = spice_session_get_channels(self->priv->session);
>+
>+    for (l = channels; l != NULL; l = l->next) {
>+        if (SPICE_IS_INPUTS_CHANNEL(l->data)) {
>+            SpiceInputsChannel *inputs = SPICE_INPUTS_CHANNEL(l->data);
>+            spice_gtk_session_sync_keyboard_modifiers_for_channel(self, inputs);
>+        }
>+    }
>+}
>diff --git a/gtk/spice-gtk-session.h b/gtk/spice-gtk-session.h
>index 3b4eac6..fbcc353 100644
>--- a/gtk/spice-gtk-session.h
>+++ b/gtk/spice-gtk-session.h
>@@ -59,6 +59,7 @@ GType spice_gtk_session_get_type(void);
> SpiceGtkSession *spice_gtk_session_get(SpiceSession *session);
> void spice_gtk_session_copy_to_guest(SpiceGtkSession *self);
> void spice_gtk_session_paste_from_guest(SpiceGtkSession *self);
>+void spice_gtk_session_sync_keyboard_modifiers(SpiceGtkSession *self);
> 
> G_END_DECLS
> 
>diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
>index 0e4a0de..2044513 100644
>--- a/gtk/spice-widget.c
>+++ b/gtk/spice-widget.c
>@@ -131,7 +131,6 @@ static void try_mouse_ungrab(SpiceDisplay *display);
> static void recalc_geometry(GtkWidget *widget);
> static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data);
> static void channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer data);
>-static void sync_keyboard_lock_modifiers(SpiceDisplay *display);
> static void cursor_invalidate(SpiceDisplay *display);
> static void update_area(SpiceDisplay *display, gint x, gint y, gint width, gint height);
> static void release_keys(SpiceDisplay *display);
>@@ -1457,7 +1456,8 @@ static gboolean focus_in_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UN
>         return true;
> 
>     release_keys(display);
>-    sync_keyboard_lock_modifiers(display);
>+    if (!d->disable_inputs)
>+        spice_gtk_session_sync_keyboard_modifiers(d->gtk_session);
>     update_keyboard_focus(display, true);
>     try_keyboard_grab(display);
>     update_display(display);
>@@ -2411,7 +2411,6 @@ static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data)
>     if (SPICE_IS_INPUTS_CHANNEL(channel)) {
>         d->inputs = SPICE_INPUTS_CHANNEL(channel);
>         spice_channel_connect(channel);
>-        sync_keyboard_lock_modifiers(display);
>         return;
>     }
> 
>@@ -2600,89 +2599,3 @@ GdkPixbuf *spice_display_get_pixbuf(SpiceDisplay *display)
>     return pixbuf;
> }
> 
>-#if HAVE_X11_XKBLIB_H
>-static guint32 get_keyboard_lock_modifiers(Display *x_display)
>-{
>-    XKeyboardState keyboard_state;
>-    guint32 modifiers = 0;
>-
>-    XGetKeyboardControl(x_display, &keyboard_state);
>-
>-    if (keyboard_state.led_mask & 0x01) {
>-        modifiers |= SPICE_INPUTS_CAPS_LOCK;
>-    }
>-    if (keyboard_state.led_mask & 0x02) {
>-        modifiers |= SPICE_INPUTS_NUM_LOCK;
>-    }
>-    if (keyboard_state.led_mask & 0x04) {
>-        modifiers |= SPICE_INPUTS_SCROLL_LOCK;
>-    }
>-    return modifiers;
>-}
>-
>-static void sync_keyboard_lock_modifiers(SpiceDisplay *display)
>-{
>-    Display *x_display;
>-    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
>-    guint32 modifiers;
>-    GdkWindow *w;
>-
>-    if (d->disable_inputs)
>-        return;
>-
>-    w = gtk_widget_get_parent_window(GTK_WIDGET(display));
>-    if (w == NULL) /* it can happen if the display is not yet shown */
>-        return;
>-
>-    if (!GDK_IS_X11_DISPLAY(gdk_window_get_display(w))) {
>-        SPICE_DEBUG("FIXME: gtk backend is not X11");
>-        return;
>-    }
>-
>-    x_display = GDK_WINDOW_XDISPLAY(w);
>-    modifiers = get_keyboard_lock_modifiers(x_display);
>-    if (d->inputs)
>-        spice_inputs_set_key_locks(d->inputs, modifiers);
>-}
>-
>-#elif defined (WIN32)
>-static guint32 get_keyboard_lock_modifiers(void)
>-{
>-    guint32 modifiers = 0;
>-
>-    if (GetKeyState(VK_CAPITAL) & 1) {
>-        modifiers |= SPICE_INPUTS_CAPS_LOCK;
>-    }
>-    if (GetKeyState(VK_NUMLOCK) & 1) {
>-        modifiers |= SPICE_INPUTS_NUM_LOCK;
>-    }
>-    if (GetKeyState(VK_SCROLL) & 1) {
>-        modifiers |= SPICE_INPUTS_SCROLL_LOCK;
>-    }
>-
>-    return modifiers;
>-}
>-
>-static void sync_keyboard_lock_modifiers(SpiceDisplay *display)
>-{
>-    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
>-    guint32 modifiers;
>-    GdkWindow *w;
>-
>-    if (d->disable_inputs)
>-        return;
>-
>-    w = gtk_widget_get_parent_window(GTK_WIDGET(display));
>-    if (w == NULL) /* it can happen if the display is not yet shown */
>-        return;
>-
>-    modifiers = get_keyboard_lock_modifiers();
>-    if (d->inputs)
>-        spice_inputs_set_key_locks(d->inputs, modifiers);
>-}
>-#else
>-static void sync_keyboard_lock_modifiers(SpiceDisplay *display)
>-{
>-    g_warning("sync_keyboard_lock_modifiers not implemented");
>-}
>-#endif // HAVE_X11_XKBLIB_H
>_______________________________________________
>Spice-commits mailing list
>Spice-commits at lists.freedesktop.org
>http://lists.freedesktop.org/mailman/listinfo/spice-commits
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/spice-devel/attachments/20140404/280e6a70/attachment-0001.html>


More information about the Spice-devel mailing list