[gtk-vnc-devel] PATCH: sticky modifier keys
- From: "Daniel P. Berrange" <berrange redhat com>
- To: gtk-vnc-devel <gtk-vnc-devel lists sourceforge net>
- Subject: [gtk-vnc-devel] PATCH: sticky modifier keys
- Date: Fri, 6 Jul 2007 19:11:44 +0100
Even with the use of a keyboard grab, there are certain key combinations
that are completely ungrabbable using regular GTK / X libraries. The prime
examples are Ctrl-Alt-Backspace, and Ctrl+Alt+Fn. This isn't a problem
for traditional VNC servers, but when talking to a virtualed guest OS, then
you do need a way to send these combos to the guest OS.
This patch adds the 'sticky modifiers' concept currently used in virt-manager
Basically, if a Ctrl or Alt key is pressed 3 times in a row, then it is
treated as sticky until the next non-modifier key is released. This allows
you to type 'Ctrl Ctrl Ctrl Alt+F1' to send 'Ctrl+Alt+F1' to the guest.
This is off by default.
Dan.
--
|=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=|
|=- Perl modules: http://search.cpan.org/~danberr/ -=|
|=- Projects: http://freshmeat.net/~danielpb/ -=|
|=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
changeset: 27:3c2eb84af9ae
user: "Daniel P. Berrange <berrange redhat com>"
date: Fri Jul 06 13:39:41 2007 -0400
summary: Added support for 'sticky' modifier keys
diff -r 06fb3b1e2320 -r 3c2eb84af9ae examples/gvncviewer.c
--- a/examples/gvncviewer.c Fri Jul 06 11:40:33 2007 -0400
+++ b/examples/gvncviewer.c Fri Jul 06 13:39:41 2007 -0400
@@ -124,6 +124,7 @@ int main(int argc, char **argv)
vnc_display_set_keyboard_grab(VNC_DISPLAY(vnc), TRUE);
vnc_display_set_pointer_grab(VNC_DISPLAY(vnc), TRUE);
//vnc_display_set_pointer_local(VNC_DISPLAY(vnc), TRUE);
+ vnc_display_set_sticky_modifiers(VNC_DISPLAY(vnc), TRUE);
vnc_display_open_name(VNC_DISPLAY(vnc), argv[1], argv[2]);
gtk_signal_connect(GTK_OBJECT(window), "delete-event",
diff -r 06fb3b1e2320 -r 3c2eb84af9ae examples/gvncviewer.py
--- a/examples/gvncviewer.py Fri Jul 06 11:40:33 2007 -0400
+++ b/examples/gvncviewer.py Fri Jul 06 13:39:41 2007 -0400
@@ -70,6 +70,7 @@ v.set_pointer_grab(True)
v.set_pointer_grab(True)
v.set_keyboard_grab(True)
#v.set_pointer_local(True)
+v.set_sticky_modifiers(True)
if len(sys.argv) == 4:
v.set_credential(gtkvnc.CREDENTIAL_PASSWORD, sys.argv[3])
diff -r 06fb3b1e2320 -r 3c2eb84af9ae src/libgtk-vnc_sym.version
--- a/src/libgtk-vnc_sym.version Fri Jul 06 11:40:33 2007 -0400
+++ b/src/libgtk-vnc_sym.version Fri Jul 06 13:39:41 2007 -0400
@@ -18,6 +18,7 @@
vnc_display_set_pointer_local;
vnc_display_set_pointer_grab;
vnc_display_set_keyboard_grab;
+ vnc_display_set_sticky_modifiers;
vnc_display_get_width;
vnc_display_get_height;
diff -r 06fb3b1e2320 -r 3c2eb84af9ae src/vncdisplay.c
--- a/src/vncdisplay.c Fri Jul 06 11:40:33 2007 -0400
+++ b/src/vncdisplay.c Fri Jul 06 13:39:41 2007 -0400
@@ -36,6 +36,9 @@ struct _VncDisplayPrivate
struct coroutine coroutine;
struct gvnc *gvnc;
+ guint last_keyval;
+ guint last_repeat;
+
gboolean in_pointer_grab;
gboolean in_keyboard_grab;
@@ -49,6 +52,7 @@ struct _VncDisplayPrivate
gboolean grab_pointer;
gboolean grab_keyboard;
gboolean local_pointer;
+ gboolean sticky_modifiers;
};
/* Signals */
@@ -308,16 +312,56 @@ static gboolean key_event(GtkWidget *wid
VncDisplayPrivate *priv = VNC_DISPLAY(widget)->priv;
int down;
- if (priv->gvnc == NULL)
- return TRUE;
-
+ if (priv->gvnc == NULL || !gvnc_is_connected(priv->gvnc))
+ return TRUE;
+
+ /* Sticky key down processing */
+ if (key->type == GDK_KEY_PRESS && priv->sticky_modifiers) {
+ if (key->keyval == GDK_Control_L ||
+ key->keyval == GDK_Control_R ||
+ key->keyval == GDK_Alt_L ||
+ key->keyval == GDK_Alt_R) {
+ /* Got a modifier, start counting presses */
+ if (priv->last_keyval == key->keyval) {
+ priv->last_repeat++;
+ } else {
+ priv->last_keyval = key->keyval;
+ priv->last_repeat = 1;
+ }
+ } else if (priv->last_keyval != 0 && priv->last_repeat >= 3) {
+ /* Got a non-modifier & a sticky key was active, so
+ * send a fake key down event */
+ gvnc_key_event(priv->gvnc, 1, priv->last_keyval);
+ }
+ }
+
+
if (key->type == GDK_KEY_PRESS)
down = 1;
else
down = 0;
+ /* Send this real event */
gvnc_key_event(priv->gvnc, down, key->keyval);
+ /* Sticky key up processing */
+ if (key->type == GDK_KEY_RELEASE && priv->sticky_modifiers) {
+ /* If non-modifier need some sticky key processing */
+ if (key->keyval != GDK_Control_L &&
+ key->keyval != GDK_Control_R &&
+ key->keyval != GDK_Alt_L &&
+ key->keyval != GDK_Alt_R) {
+ /* Have a sticky key, might need a fake key up */
+ if (priv->last_keyval != 0 &&
+ priv->last_repeat >= 3)
+ gvnc_key_event(priv->gvnc, 0, priv->last_keyval);
+
+ /* Clear sticky key if any non-modifier was released */
+ priv->last_keyval = 0;
+ }
+ }
+
+ /* Release pointer grab with Ctrl+Alt */
if (key->type == GDK_KEY_PRESS &&
((key->keyval == GDK_Control_L && (key->state & GDK_MOD1_MASK)) ||
(key->keyval == GDK_Alt_L && (key->state & GDK_CONTROL_MASK)))) {
@@ -840,6 +884,11 @@ void vnc_display_set_keyboard_grab(VncDi
do_keyboard_ungrab(obj);
}
+void vnc_display_set_sticky_modifiers(VncDisplay *obj, gboolean enable)
+{
+ obj->priv->sticky_modifiers = enable;
+}
+
GType vnc_display_get_type(void)
{
diff -r 06fb3b1e2320 -r 3c2eb84af9ae src/vncdisplay.h
--- a/src/vncdisplay.h Fri Jul 06 11:40:33 2007 -0400
+++ b/src/vncdisplay.h Fri Jul 06 13:39:41 2007 -0400
@@ -78,6 +78,7 @@ void vnc_display_set_pointer_local(VncD
void vnc_display_set_pointer_local(VncDisplay *obj, gboolean enable);
void vnc_display_set_pointer_grab(VncDisplay *obj, gboolean enable);
void vnc_display_set_keyboard_grab(VncDisplay *obj, gboolean enable);
+void vnc_display_set_sticky_modifiers(VncDisplay *obj, gboolean enable);
GdkPixbuf * vnc_display_get_pixbuf(VncDisplay *obj);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]