diff --git a/gtk-vnc-0.3.2-keystate-tracking.patch b/gtk-vnc-0.3.2-keystate-tracking.patch new file mode 100644 index 0000000..8fd1bad --- /dev/null +++ b/gtk-vnc-0.3.2-keystate-tracking.patch @@ -0,0 +1,119 @@ +changeset: 111:95f570fc49e1 +user: "Daniel P. Berrange " +date: Wed Jan 09 23:54:24 2008 -0500 +files: src/vncdisplay.c +description: +Track keystate & send fake events for GTK key-repeat flaw & to reset state on focus out + + +diff -r 73b4f4043cb5 -r 95f570fc49e1 src/vncdisplay.c +--- a/src/vncdisplay.c Tue Jan 01 14:57:39 2008 -0600 ++++ b/src/vncdisplay.c Wed Jan 09 23:54:24 2008 -0500 +@@ -43,6 +43,8 @@ struct _VncDisplayPrivate + + gboolean in_pointer_grab; + gboolean in_keyboard_grab; ++ ++ guint down_keyval[16]; + + int button_mask; + int last_x; +@@ -392,7 +394,58 @@ static gboolean key_event(GtkWidget *wid + &level, + &consumed); + +- gvnc_key_event(priv->gvnc, key->type == GDK_KEY_PRESS ? 1 : 0, keyval); ++ /* ++ * More VNC suckiness with key state & modifiers in particular ++ * ++ * Because VNC has no concept of modifiers, we have to track what keys are ++ * pressed and when the widget looses focus send fake key up events for all ++ * keys current held down. This is because upon gaining focus any keys held ++ * down are no longer likely to be down. This would thus result in keys ++ * being 'stuck on' in the remote server. eg upon Alt-Tab to switch window ++ * focus you'd never see key up for the Alt or Tab keys without this :-( ++ * ++ * This is mostly a problem with modifier keys, but its best to just track ++ * all key presses regardless. There's a limit to how many keys a user can ++ * press at once due to a max of 10 fingers (normally :-), so down_key_vals ++ * is only storing upto 16 for now. Should be plenty... ++ * ++ * Arggggh. ++ */ ++ if (key->type == GDK_KEY_PRESS) { ++ int i; ++ for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) { ++ if (priv->down_keyval[i] == 0) { ++ priv->down_keyval[i] = keyval; ++ /* Send the actual key event we're dealing with */ ++ gvnc_key_event(priv->gvnc, 1, keyval); ++ break; ++ } else if (priv->down_keyval[i] == keyval) { ++ /* Got an press when we're already pressed ! Why ... ? ++ * ++ * Well, GTK merges sequential press+release pairs of the same ++ * key so instead of press+release,press+release,press+release ++ * we only get press+press+press+press+press+release. This ++ * really annoys some VNC servers, so we have to un-merge ++ * them into a sensible stream of press+release pairs ++ */ ++ /* Fake an up event for the previous down event */ ++ gvnc_key_event(priv->gvnc, 0, keyval); ++ /* Now send our actual ldown event */ ++ gvnc_key_event(priv->gvnc, 1, keyval); ++ } ++ } ++ } else { ++ int i; ++ for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) { ++ /* We were pressed, and now we're released, so... */ ++ if (priv->down_keyval[i] == keyval) { ++ priv->down_keyval[i] = 0; ++ /* ..send the key releae event we're dealing with */ ++ gvnc_key_event(priv->gvnc, 0, keyval); ++ break; ++ } ++ } ++ } + + if (key->type == GDK_KEY_PRESS && + ((keyval == GDK_Control_L && (key->state & GDK_MOD1_MASK)) || +@@ -436,6 +489,28 @@ static gboolean leave_event(GtkWidget *w + + if (priv->grab_keyboard) + do_keyboard_ungrab(VNC_DISPLAY(widget), FALSE); ++ ++ return TRUE; ++} ++ ++ ++static gboolean focus_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UNUSED, ++ gpointer data G_GNUC_UNUSED) ++{ ++ VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv; ++ int i; ++ ++ if (priv->gvnc == NULL || !gvnc_is_initialized(priv->gvnc)) ++ return TRUE; ++ ++ for (i = 0 ; i < (int)(sizeof(priv->down_keyval)/sizeof(priv->down_keyval[0])) ; i++) { ++ /* We are currently pressed so... */ ++ if (priv->down_keyval[i] != 0) { ++ /* ..send the fake key releae event to match */ ++ gvnc_key_event(priv->gvnc, 0, priv->down_keyval[i]); ++ priv->down_keyval[i] = 0; ++ } ++ } + + return TRUE; + } +@@ -1128,6 +1203,8 @@ static void vnc_display_init(VncDisplay + G_CALLBACK(enter_event), NULL); + g_signal_connect(obj, "leave-notify-event", + G_CALLBACK(leave_event), NULL); ++ g_signal_connect(obj, "focus-out-event", ++ G_CALLBACK(focus_event), NULL); + + GTK_WIDGET_SET_FLAGS(obj, GTK_CAN_FOCUS); + + diff --git a/gtk-vnc.spec b/gtk-vnc.spec index 089edc3..102e69b 100644 --- a/gtk-vnc.spec +++ b/gtk-vnc.spec @@ -3,10 +3,11 @@ Summary: A GTK widget for VNC clients Name: gtk-vnc Version: 0.3.2 -Release: 1%{?dist} +Release: 2%{?dist} License: LGPLv2+ Group: Development/Libraries Source: http://downloads.sourceforge.net/%{name}/%{name}-%{version}.tar.gz +Patch1: %{name}-%{version}-keystate-tracking.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) URL: http://gtk-vnc.sf.net/ BuildRequires: gtk2-devel pygtk2-devel python-devel gnutls-devel zlib-devel @@ -41,6 +42,7 @@ A module allowing use of the GTK-VNC widget from python %prep %setup -q +%patch1 -p1 %build %configure @@ -80,6 +82,9 @@ rm -fr %{buildroot} %{_libdir}/python*/site-packages/gtkvnc.so %changelog +* Mon Jan 14 2008 Daniel P. Berrange - 0.3.2-2.fc9 +- Track keystate to avoid stuck modifier keys + * Mon Dec 31 2007 Daniel P. Berrange - 0.3.2-1.fc9 - Update to 0.3.2 release - Added dep on zlib-devel