[Spice-devel] [spice-gtk [rfc] 2/2] gtk-session: add request targets delayed
Victor Toso
victortoso at redhat.com
Tue Jan 15 16:11:38 UTC 2019
From: Victor Toso <me at victortoso.com>
If SpiceGtkSession::allow-clipboard-managers is disabled, while the
spice client does not hold the keyboard-grab, every owner-change event
to clipboard change will be delayed and requested later when
keyboard-grab is received.
Signed-off-by: Victor Toso <victortoso at redhat.com>
---
src/spice-gtk-session.c | 77 ++++++++++++++++++++++++++++++++++++++---
1 file changed, 72 insertions(+), 5 deletions(-)
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;
}
--
2.20.1
More information about the Spice-devel
mailing list