[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