summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/spice-gtk-session-priv.h2
-rw-r--r--src/spice-gtk-session.c76
-rw-r--r--src/spice-widget.c5
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 ad93bd1..3c662ab 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);
}
@@ -1216,8 +1261,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);
@@ -1240,6 +1284,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 72fbbc8..187b144 100644
--- a/src/spice-widget.c
+++ b/src/spice-widget.c
@@ -1783,7 +1783,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);
@@ -1810,6 +1810,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);