[Spice-commits] 5 commits - gtk/spice-channel.c gtk/spice-widget-priv.h gtk/spice-widget.c

Hans de Goede jwrdegoede at kemper.freedesktop.org
Wed Aug 17 11:08:41 PDT 2011


 gtk/spice-channel.c     |   30 ++++++++++++++++++++++++++++--
 gtk/spice-widget-priv.h |    2 --
 gtk/spice-widget.c      |   34 +++++++++++++++++-----------------
 3 files changed, 45 insertions(+), 21 deletions(-)

New commits:
commit bfe2d402b2722c01d33d341a28a46c016f9d4bac
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Aug 17 10:32:00 2011 -0700

    spice-channel: fix writing a byte twice when a write blocks
    
    When a write blocks, and thus ret == -1 (and the gerror matches EAGAIN) we
    still do offset += ret, causing the last written byte to be send twice.
    Lets not do that :)
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 3017180..f8c79eb 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -603,6 +603,7 @@ static void spice_channel_flush_wire(SpiceChannel *channel,
         if (ret == -1) {
             if (cond != 0) {
                 g_io_wait(c->sock, cond);
+                continue;
             } else {
                 SPICE_DEBUG("Closing the channel: spice_channel_flush %d", errno);
                 c->has_error = TRUE;
commit bf319a38de95006ddf3f63187e69f5166de53771
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Aug 12 16:37:42 2011 +0200

    spice-widget: release_keys on focus out
    
    This fixes alt getting stuck in the guest when the user alt-tabs away from the
    spice-widget (thus making it see the alt press but not the release) and then
    closing it without giving it the focus back (by using the windows close button
    for example).
    
    Note that doing this on focus out (when we know we may be missing key releases
    afterwards) makes a lot more sense then doing this on focus in, and with
    the release_keys on focus out I don't really see a reason any more to do it
    on focus in. But I'm leaving it in on focus in just in case, it certainly
    cannot hurt there.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index 61b4d02..c4f7226 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -878,6 +878,7 @@ static gboolean focus_out_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_U
     if (d->keyboard_grab_active)
         return true;
 
+    release_keys(display);
     d->keyboard_have_focus = false;
     return true;
 }
commit 4f013a181a3f7298598e4833ee4a891001d3843d
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Aug 12 16:33:43 2011 +0200

    spice-widget: remove keyboard_grab_count / keyboard_grab_time hack
    
    With the filtering of focus in / out events caused by grabs we should no
    longer need this.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/spice-widget-priv.h b/gtk/spice-widget-priv.h
index 3711aaa..a567f1b 100644
--- a/gtk/spice-widget-priv.h
+++ b/gtk/spice-widget-priv.h
@@ -104,8 +104,6 @@ struct _SpiceDisplayPrivate {
 
     bool                    keyboard_grab_active;
     bool                    keyboard_have_focus;
-    int                     keyboard_grab_count;
-    time_t                  keyboard_grab_time;
 
     const guint16 const     *keycode_map;
     size_t                  keycode_maplen;
diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index d9dc960..61b4d02 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -368,7 +368,6 @@ static void try_keyboard_grab(SpiceDisplay *display)
 {
     GtkWidget *widget = GTK_WIDGET(display);
     SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
-    time_t now;
     GdkGrabStatus status;
 
     if (d->keyboard_grab_active)
@@ -384,22 +383,6 @@ static void try_keyboard_grab(SpiceDisplay *display)
     g_return_if_fail(gtk_widget_is_focus(widget));
     g_return_if_fail(gtk_widget_has_focus(widget));
 
-    /*
-     * focus / keyboard grab behavior is funky sometime
-     * when going fullscreen (with KDE and GNOME-shell):
-     * focus-in-event -> grab -> focus-out-event -> ungrab -> repeat
-     * I have no idea why the grab triggers focus-out :-(
-     */
-    now = time(NULL);
-    if (d->keyboard_grab_time != now) {
-        d->keyboard_grab_time = now;
-        d->keyboard_grab_count = 0;
-    }
-    if (d->keyboard_grab_count++ > 32) {
-        g_critical("32 grabs last second -> emergency exit");
-        return;
-    }
-
     SPICE_DEBUG("grab keyboard");
 
 #ifdef WIN32
commit e09aed63db13567822d0bbf8b393086565e1bd4c
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Fri Aug 12 16:20:59 2011 +0200

    spice-widget: ignore focus in / out events caused by keyb ungrab/grab
    
    As documented in XGrabKeyboard(3): "The XGrabKeyboard function actively grabs
    control of the keyboard and generates FocusIn and FocusOut events."
    
    Note that for some reason this only happens when we call XGrabKeyboard
    from our enter_event / leave_event callbacks and not from our focus_in /
    focus_out callbacks? Either way we still need to filter these out.
    
    Filtering these out fixes 4 issues:
    1) keyboard_have_focus now no longer gets unset when the keyboard is grabbed,
       making USB auto redirection when focussed actually work
    2) Before this patch, if you pressed alt and then (accidentally) moved the
       cursor out of the spice-widget window before pressing a second key,
       the focus in event would clear the keyboard status causing the guest to no
       longer see alt as pressed and register the second key press as a regular
       keypress rather then as alt-foo.
    3) It allows us to remove the keyboard_grab_count / keyboard_grab_time hack
       from try_keyboard_grab, although since we are no longer doing an
       ungrab on focus out, this likely could have been removed before.
       I will do this in a separate patch for easier reverting if necessary.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index 208762e..d9dc960 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -862,6 +862,14 @@ static gboolean focus_in_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UN
     SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
 
     SPICE_DEBUG("%s", __FUNCTION__);
+
+    /*
+     * Ignore focus in when we already have the focus
+     * (this happens when doing an ungrab from the leave_event callback).
+     */
+    if (d->keyboard_have_focus)
+        return true;
+
     release_keys(display);
     sync_keyboard_lock_modifiers(display);
     d->keyboard_have_focus = true;
@@ -879,6 +887,14 @@ static gboolean focus_out_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_U
     SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
 
     SPICE_DEBUG("%s", __FUNCTION__);
+
+    /*
+     * Ignore focus out after a keyboard grab
+     * (this happens when doing the grab from the enter_event callback).
+     */
+    if (d->keyboard_grab_active)
+        return true;
+
     d->keyboard_have_focus = false;
     return true;
 }
commit 7ad43d9d7f6f06cf4e1bbf5c0b3f5eac1541a66a
Author: Hans de Goede <hdegoede at redhat.com>
Date:   Wed Jul 27 16:42:32 2011 +0200

    spice-channel: Fix a possible race triggered by spice_channel_iterate_write
    
    Fix a race between spice_channel_buffered_write and
    spice_channel_iterate_write.
    
    Signed-off-by: Hans de Goede <hdegoede at redhat.com>

diff --git a/gtk/spice-channel.c b/gtk/spice-channel.c
index 8834143..3017180 100644
--- a/gtk/spice-channel.c
+++ b/gtk/spice-channel.c
@@ -1750,9 +1750,34 @@ static void spice_channel_iterate_write(SpiceChannel *channel)
 {
     SpiceChannelPrivate *c = channel->priv;
 
-    if (c->xmit_buffer_size) {
-        spice_channel_write(channel, c->xmit_buffer, c->xmit_buffer_size);
+    if (c->xmit_buffer) {
+        /*
+         * Take ownership of the buffer, so that if spice_channel_write calls
+         * g_io_wait and thus yields to the main context, and that then calls
+         * spice_channel_buffered_write it does not mess with the buffer
+         * being written out.
+         */
+        guint8 *buffer = c->xmit_buffer;
+        int size = c->xmit_buffer_size;
+        int capacity = c->xmit_buffer_capacity;
+
+        c->xmit_buffer = NULL;
         c->xmit_buffer_size = 0;
+        c->xmit_buffer_capacity = 0;
+
+        spice_channel_write(channel, buffer, size);
+
+        /*
+         * If no write has been done in the mean time, we can return the buffer
+         * so that it can be re-used.
+         */
+        if (c->xmit_buffer == NULL) {
+            c->xmit_buffer = buffer;
+            c->xmit_buffer_capacity = capacity;
+            c->xmit_buffer_size = 0;
+        } else {
+            g_free(buffer);
+        }
     }
 }
 


More information about the Spice-commits mailing list