[Spice-devel] [spice-gtk v3 7/7] Sync only on focus change
Marc-André Lureau
mlureau at redhat.com
Sat Sep 3 16:23:54 UTC 2016
Hi
----- Original Message -----
> Limit the virtual keystrokes sent to the remote machine.
> The modifiers are synced only when the application receive or lose
> the focus. This reduce a lot the possible virtual keystrokes sent
> to the guest to synchronize the modifiers.
> This affect the situations where modifiers are configured
> differently in client and guest.
> When the application receive the focus the synchronization is
> attempted from client to guest while when the application lose
> focus is attempted guest to client (basically is moved following
> user moving).
Does this mean that modifiers changes with the application in focus? That would be quite irritating imho, and I will likely want an option to disable that (actually the default).
What I don't understand is what you improving here, saving a few key events sent to the guest?
I don't understand the issue with the current behavior, and the change of behavior you propose here. Could you give an example?
>
> Only work on X11 and Windows, other platforms are unaffected.
>
> Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> ---
> src/spice-gtk-session-priv.h | 2 +-
> src/spice-gtk-session.c | 76
> ++++++++++++++++++++++++++++++++++++++++++--
> src/spice-widget.c | 5 ++-
> 3 files changed, 78 insertions(+), 5 deletions(-)
>
> diff --git a/src/spice-gtk-session-priv.h b/src/spice-gtk-session-priv.h
> index d7fe313..abf90d6 100644
> --- a/src/spice-gtk-session-priv.h
> +++ b/src/spice-gtk-session-priv.h
> @@ -38,13 +38,13 @@ struct _SpiceGtkSessionClass
> void spice_gtk_session_request_auto_usbredir(SpiceGtkSession *self,
> gboolean state);
> gboolean spice_gtk_session_get_read_only(SpiceGtkSession *self);
> -void spice_gtk_session_sync_keyboard_modifiers(SpiceGtkSession *self);
> void spice_gtk_session_set_pointer_grabbed(SpiceGtkSession *self, gboolean
> grabbed);
> gboolean spice_gtk_session_get_pointer_grabbed(SpiceGtkSession *self);
> void spice_gtk_session_set_keyboard_has_focus(SpiceGtkSession *self,
> gboolean keyboard_has_focus);
> void spice_gtk_session_set_mouse_has_pointer(SpiceGtkSession *self, gboolean
> mouse_has_pointer);
> gboolean spice_gtk_session_get_keyboard_has_focus(SpiceGtkSession *self);
> gboolean spice_gtk_session_get_mouse_has_pointer(SpiceGtkSession *self);
> +void spice_gtk_session_set_focus(SpiceGtkSession *self, gboolean focus);
>
> G_END_DECLS
>
> diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c
> index d88fed4..61a23fd 100644
> --- a/src/spice-gtk-session.c
> +++ b/src/spice-gtk-session.c
> @@ -67,6 +67,8 @@ struct _SpiceGtkSessionPrivate {
> gboolean keyboard_has_focus;
> gboolean mouse_has_pointer;
> gboolean sync_modifiers;
> + gboolean has_focus;
> + guint32 guest_modifiers;
> };
>
> /**
> @@ -104,6 +106,7 @@ static void channel_new(SpiceSession *session,
> SpiceChannel *channel,
> static void channel_destroy(SpiceSession *session, SpiceChannel *channel,
> gpointer user_data);
> static gboolean read_only(SpiceGtkSession *self);
> +static void spice_gtk_session_sync_keyboard_modifiers(SpiceGtkSession
> *self);
>
> /* ------------------------------------------------------------------ */
> /* gobject glue */
> @@ -127,7 +130,7 @@ static void
> spice_gtk_session_sync_keyboard_modifiers_for_channel(SpiceGtkSessio
> SpiceInputsChannel*
> inputs,
> gboolean
> force)
> {
> - guint32 guest_modifiers = 0, client_modifiers = 0;
> + guint32 guest_modifiers, client_modifiers;
>
> g_return_if_fail(SPICE_IS_INPUTS_CHANNEL(inputs));
>
> @@ -136,7 +139,20 @@ static void
> spice_gtk_session_sync_keyboard_modifiers_for_channel(SpiceGtkSessio
> return;
> }
>
> + // get and cache client modifiers
> + guest_modifiers = G_MAXUINT32;
> g_object_get(inputs, "key-modifiers", &guest_modifiers, NULL);
> + if (guest_modifiers == G_MAXUINT32) {
> + return;
> + }
> + self->priv->guest_modifiers = guest_modifiers;
> +
> + // if client synchronization is enabled the
> + // synchronization is done in spice_gtk_session_set_focus
> + if (!force && can_set_keyboard_lock_modifiers()) {
> + return;
> + }
> +
> client_modifiers = get_keyboard_lock_modifiers();
>
> if (force || client_modifiers != guest_modifiers) {
> @@ -146,10 +162,39 @@ static void
> spice_gtk_session_sync_keyboard_modifiers_for_channel(SpiceGtkSessio
> }
> }
>
> +static void spice_gtk_session_set_client_keyboard_modifiers(SpiceGtkSession
> *self)
> +{
> + guint32 guest_modifiers = 0, client_modifiers = 0;
> +
> + if (SPICE_IS_GTK_SESSION(self) && !self->priv->sync_modifiers) {
> + SPICE_DEBUG("Syncing modifiers is disabled");
> + return;
> + }
> +
> + if (!can_set_keyboard_lock_modifiers()) {
> + return;
> + }
> +
> + guest_modifiers = self->priv->guest_modifiers;
> + client_modifiers = get_keyboard_lock_modifiers();
> + if (client_modifiers == guest_modifiers) {
> + return;
> + }
> +
> + set_keyboard_lock_modifiers(guest_modifiers);
> +}
> +
> +/* Keyboard state changed in the client, try to sync
> + */
> static void keymap_modifiers_changed(GdkKeymap *keymap, gpointer data)
> {
> SpiceGtkSession *self = data;
>
> + /* client sync, sync done only when focus change */
> + if (can_set_keyboard_lock_modifiers()) {
> + return;
> + }
> +
> spice_gtk_session_sync_keyboard_modifiers(self);
> }
>
> @@ -1207,8 +1252,7 @@ void spice_gtk_session_paste_from_guest(SpiceGtkSession
> *self)
> s->clip_hasdata[selection] = FALSE;
> }
>
> -G_GNUC_INTERNAL
> -void spice_gtk_session_sync_keyboard_modifiers(SpiceGtkSession *self)
> +static void spice_gtk_session_sync_keyboard_modifiers(SpiceGtkSession *self)
> {
> GList *l = NULL, *channels =
> spice_session_get_channels(self->priv->session);
>
> @@ -1231,6 +1275,32 @@ void
> spice_gtk_session_set_pointer_grabbed(SpiceGtkSession *self, gboolean grabb
> }
>
> G_GNUC_INTERNAL
> +void spice_gtk_session_set_focus(SpiceGtkSession *self, gboolean focus)
> +{
> + g_return_if_fail(SPICE_IS_GTK_SESSION(self));
> +
> + /* TODO detect switch between monitors */
> +
> + /* not changed ? */
> + if (self->priv->has_focus == focus)
> + return;
> +
> + if (focus) {
> + /* User switched to the viewer, try to syncronize the keyboard
> + * modifiers.
> + * This should be called before setting has_focus
> + */
> + spice_gtk_session_sync_keyboard_modifiers(self);
> + } else {
> + /* User swicthed to another application, syncronize the client
> + * keyboard */
> + spice_gtk_session_set_client_keyboard_modifiers(self);
> + }
> +
> + self->priv->has_focus = focus;
> +}
> +
> +G_GNUC_INTERNAL
> gboolean spice_gtk_session_get_pointer_grabbed(SpiceGtkSession *self)
> {
> g_return_val_if_fail(SPICE_IS_GTK_SESSION(self), FALSE);
> diff --git a/src/spice-widget.c b/src/spice-widget.c
> index 9c8f7d1..8f601e7 100644
> --- a/src/spice-widget.c
> +++ b/src/spice-widget.c
> @@ -1745,7 +1745,7 @@ static gboolean focus_in_event(GtkWidget *widget,
> GdkEventFocus *focus G_GNUC_UN
> }
> #endif
> if (!d->disable_inputs)
> - spice_gtk_session_sync_keyboard_modifiers(d->gtk_session);
> + spice_gtk_session_set_focus(d->gtk_session, TRUE);
> if (d->keyboard_grab_released)
> memset(d->activeseq, 0, sizeof(gboolean) * d->grabseq->nkeysyms);
> update_keyboard_focus(display, true);
> @@ -1772,6 +1772,9 @@ static gboolean focus_out_event(GtkWidget *widget,
> GdkEventFocus *focus G_GNUC_U
> if (d->keyboard_grab_active)
> return true;
>
> + if (!d->disable_inputs)
> + spice_gtk_session_set_focus(d->gtk_session, FALSE);
> +
> release_keys(display);
> update_keyboard_focus(display, false);
>
> --
> 2.7.4
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
>
More information about the Spice-devel
mailing list