[spice-gtk,[rfc] 2/2] gtk-session: add request targets delayed

Submitted by Victor Toso on Jan. 15, 2019, 4:11 p.m.

Details

Message ID 20190115161138.4538-3-victortoso@redhat.com
State New
Headers show

Not browsing as part of any series.

Patch hide | download patch | download mbox

diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c
index 7391e6a..384d090 100644
--- a/src/spice-gtk-session.c
+++ b/src/spice-gtk-session.c
@@ -56,6 +56,7 @@  struct _SpiceGtkSessionPrivate {
     GtkClipboard            *clipboard_primary;
     GtkTargetEntry          *clip_targets[CLIPBOARD_LAST];
     guint                   nclip_targets[CLIPBOARD_LAST];
+    gboolean                request_delayed_ptr[CLIPBOARD_LAST];
     gboolean                clip_hasdata[CLIPBOARD_LAST];
     gboolean                clip_grabbed[CLIPBOARD_LAST];
     gboolean                clipboard_by_guest[CLIPBOARD_LAST];
@@ -259,6 +260,7 @@  static void spice_gtk_session_finalize(GObject *gobject)
     /* release stuff */
     for (i = 0; i < CLIPBOARD_LAST; ++i) {
         g_clear_pointer(&s->clip_targets[i], g_free);
+        s->request_delayed_ptr[i] = FALSE;
     }
 
     /* Chain up to the parent class */
@@ -588,6 +590,9 @@  static void clipboard_get_targets(GtkClipboard *clipboard,
     int a;
     int selection;
 
+    /* Disable owner-event requests now if allow_clipboard_managers is disabled */
+    s->back_from_focus_out = FALSE;
+
     if (s->main == NULL)
         return;
 
@@ -644,6 +649,56 @@  static void clipboard_get_targets(GtkClipboard *clipboard,
     s->nclip_targets[selection] = 0;
 }
 
+static bool clipboard_client_request_targets(SpiceGtkSession *self,
+                                             GtkClipboard *clipboard)
+{
+    SpiceGtkSessionPrivate *s = self->priv;
+    gint selection = get_selection_from_clipboard(s, clipboard);
+
+    SPICE_DEBUG("clipboard request: %p %d", clipboard, selection);
+    s->clipboard_by_guest[selection] = FALSE;
+    s->clip_hasdata[selection] = TRUE;
+    if (s->auto_clipboard_enable && !read_only(self)) {
+        gtk_clipboard_request_targets(clipboard, clipboard_get_targets,
+                                      get_weak_ref(self));
+        return true;
+    }
+    return false;
+}
+
+static bool clipboard_owner_change_delayed(SpiceGtkSession *self, gint selection)
+{
+    SpiceGtkSessionPrivate *s = self->priv;
+    GtkClipboard *clipboard = get_clipboard_from_selection(s, selection);
+
+    g_return_val_if_fail(clipboard != NULL, false);
+
+    if (s->clip_grabbed[selection]) {
+        SPICE_DEBUG("clipboard delayed request: already made for %p %d",
+                    clipboard, selection);
+    }
+
+    s->request_delayed_ptr[selection] = FALSE;
+    return clipboard_client_request_targets(self, clipboard);
+}
+
+static bool request_delayed_run_all(SpiceGtkSession *self)
+{
+    gint i;
+    bool ret = false;
+    SpiceGtkSessionPrivate *s = self->priv;
+
+    for (i = 0; i < CLIPBOARD_LAST; ++i) {
+        if (s->request_delayed_ptr[i]) {
+            if (clipboard_owner_change_delayed(self, i)) {
+                ret = true;
+            }
+        }
+    }
+    return ret;
+}
+
+
 /* Callback for every owner-change event for given @clipboard.
  * This event is triggered in different ways depending on the environment of
  * the Client, some examples:
@@ -700,11 +755,17 @@  static void clipboard_owner_change(GtkClipboard        *clipboard,
         return;
     }
 
-    s->clipboard_by_guest[selection] = FALSE;
-    s->clip_hasdata[selection] = TRUE;
-    if (s->auto_clipboard_enable && !read_only(self))
-        gtk_clipboard_request_targets(clipboard, clipboard_get_targets,
-                                      get_weak_ref(self));
+    if (!s->allow_clipboard_managers && !s->back_from_focus_out) {
+        if (!s->request_delayed_ptr[selection]) {
+            SPICE_DEBUG("clipboard: owner-change: wait focus-in for clipboard-request %p %d",
+                        clipboard, selection);
+        }
+        s->request_delayed_ptr[selection] = TRUE;
+        return;
+    }
+
+    s->request_delayed_ptr[selection] = FALSE;
+    clipboard_client_request_targets(self, clipboard);
 }
 
 typedef struct
@@ -1324,6 +1385,12 @@  void spice_gtk_session_set_keyboard_has_focus(SpiceGtkSession *self,
         s->back_from_focus_out = FALSE;
     }
 
+    /* Clipboard requests made while on focus-out may be done now, if any is
+     * successfull, we can reset back_from_focus_out helper */
+    if (s->back_from_focus_out && request_delayed_run_all(self)) {
+        s->back_from_focus_out = FALSE;
+    }
+
     s->keyboard_has_focus = keyboard_has_focus;
 }