From 445e90fa82b1ccccde303754725b0248bb07b622 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Sat, 3 Mar 2001 21:34:19 +0000 Subject: [PATCH] Detectable auto-repeat - make a repeating key generate Sat Mar 3 16:26:33 2001 Owen Taylor * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c: Detectable auto-repeat - make a repeating key generate press/press/press/release instead of press/release pairs. If we have Xkb and XkbSetDectableAutoRepeat supports that, we do it that way. Otherwise, when we get a release event, we check ahead with XPending to see if the next key is a KeyPress with the same keycode and timestamp. (Not 100% reliable, but pretty close.) Tue Feb 27 02:16:14 2001 Owen Taylor * gtk/gtkmain.c (gtk_propagate_event): Only do special special key-press grab handling for widgets within GtkWindows. Otherwise, fall through to normal case. This prevents key events being sent twice to GtkInvisible widgets, which can cause all sorts of mischief. --- ChangeLog | 29 ++++++++++++++++++++++ ChangeLog.pre-2-0 | 29 ++++++++++++++++++++++ ChangeLog.pre-2-10 | 29 ++++++++++++++++++++++ ChangeLog.pre-2-2 | 29 ++++++++++++++++++++++ ChangeLog.pre-2-4 | 29 ++++++++++++++++++++++ ChangeLog.pre-2-6 | 29 ++++++++++++++++++++++ ChangeLog.pre-2-8 | 29 ++++++++++++++++++++++ gdk/x11/gdkevents-x11.c | 20 +++++++++++++++- gdk/x11/gdkkeys-x11.c | 6 +++++ gdk/x11/gdkmain-x11.c | 11 +++++++++ gdk/x11/gdkprivate-x11.h | 7 ++++++ gtk/gtkmain.c | 52 ++++++++++++++++++++++++++++++---------- 12 files changed, 285 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9c25cb1724..4274d77352 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +Sat Mar 3 16:26:33 2001 Owen Taylor + + * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c + gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c: + + Detectable auto-repeat - make a repeating key generate + press/press/press/release instead of press/release pairs. + + If we have Xkb and XkbSetDectableAutoRepeat supports + that, we do it that way. Otherwise, when we get + a release event, we check ahead with XPending to see + if the next key is a KeyPress with the same keycode + and timestamp. (Not 100% reliable, but pretty close.) + +Tue Feb 27 02:16:14 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): Only do special + special key-press grab handling for widgets within + GtkWindows. Otherwise, fall through to normal case. + + This prevents key events being sent twice to GtkInvisible + widgets, which can cause all sorts of mischief. + +Fri Feb 2 13:20:12 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): When a grab + widget is in effect, give the grab widget a first + crack at KEY_PRESS/RELEASE events. (#424) + Sat Mar 3 15:39:49 2001 Owen Taylor * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 9c25cb1724..4274d77352 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,32 @@ +Sat Mar 3 16:26:33 2001 Owen Taylor + + * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c + gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c: + + Detectable auto-repeat - make a repeating key generate + press/press/press/release instead of press/release pairs. + + If we have Xkb and XkbSetDectableAutoRepeat supports + that, we do it that way. Otherwise, when we get + a release event, we check ahead with XPending to see + if the next key is a KeyPress with the same keycode + and timestamp. (Not 100% reliable, but pretty close.) + +Tue Feb 27 02:16:14 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): Only do special + special key-press grab handling for widgets within + GtkWindows. Otherwise, fall through to normal case. + + This prevents key events being sent twice to GtkInvisible + widgets, which can cause all sorts of mischief. + +Fri Feb 2 13:20:12 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): When a grab + widget is in effect, give the grab widget a first + crack at KEY_PRESS/RELEASE events. (#424) + Sat Mar 3 15:39:49 2001 Owen Taylor * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 9c25cb1724..4274d77352 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,32 @@ +Sat Mar 3 16:26:33 2001 Owen Taylor + + * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c + gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c: + + Detectable auto-repeat - make a repeating key generate + press/press/press/release instead of press/release pairs. + + If we have Xkb and XkbSetDectableAutoRepeat supports + that, we do it that way. Otherwise, when we get + a release event, we check ahead with XPending to see + if the next key is a KeyPress with the same keycode + and timestamp. (Not 100% reliable, but pretty close.) + +Tue Feb 27 02:16:14 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): Only do special + special key-press grab handling for widgets within + GtkWindows. Otherwise, fall through to normal case. + + This prevents key events being sent twice to GtkInvisible + widgets, which can cause all sorts of mischief. + +Fri Feb 2 13:20:12 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): When a grab + widget is in effect, give the grab widget a first + crack at KEY_PRESS/RELEASE events. (#424) + Sat Mar 3 15:39:49 2001 Owen Taylor * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 9c25cb1724..4274d77352 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,32 @@ +Sat Mar 3 16:26:33 2001 Owen Taylor + + * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c + gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c: + + Detectable auto-repeat - make a repeating key generate + press/press/press/release instead of press/release pairs. + + If we have Xkb and XkbSetDectableAutoRepeat supports + that, we do it that way. Otherwise, when we get + a release event, we check ahead with XPending to see + if the next key is a KeyPress with the same keycode + and timestamp. (Not 100% reliable, but pretty close.) + +Tue Feb 27 02:16:14 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): Only do special + special key-press grab handling for widgets within + GtkWindows. Otherwise, fall through to normal case. + + This prevents key events being sent twice to GtkInvisible + widgets, which can cause all sorts of mischief. + +Fri Feb 2 13:20:12 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): When a grab + widget is in effect, give the grab widget a first + crack at KEY_PRESS/RELEASE events. (#424) + Sat Mar 3 15:39:49 2001 Owen Taylor * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 9c25cb1724..4274d77352 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,32 @@ +Sat Mar 3 16:26:33 2001 Owen Taylor + + * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c + gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c: + + Detectable auto-repeat - make a repeating key generate + press/press/press/release instead of press/release pairs. + + If we have Xkb and XkbSetDectableAutoRepeat supports + that, we do it that way. Otherwise, when we get + a release event, we check ahead with XPending to see + if the next key is a KeyPress with the same keycode + and timestamp. (Not 100% reliable, but pretty close.) + +Tue Feb 27 02:16:14 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): Only do special + special key-press grab handling for widgets within + GtkWindows. Otherwise, fall through to normal case. + + This prevents key events being sent twice to GtkInvisible + widgets, which can cause all sorts of mischief. + +Fri Feb 2 13:20:12 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): When a grab + widget is in effect, give the grab widget a first + crack at KEY_PRESS/RELEASE events. (#424) + Sat Mar 3 15:39:49 2001 Owen Taylor * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 9c25cb1724..4274d77352 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,32 @@ +Sat Mar 3 16:26:33 2001 Owen Taylor + + * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c + gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c: + + Detectable auto-repeat - make a repeating key generate + press/press/press/release instead of press/release pairs. + + If we have Xkb and XkbSetDectableAutoRepeat supports + that, we do it that way. Otherwise, when we get + a release event, we check ahead with XPending to see + if the next key is a KeyPress with the same keycode + and timestamp. (Not 100% reliable, but pretty close.) + +Tue Feb 27 02:16:14 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): Only do special + special key-press grab handling for widgets within + GtkWindows. Otherwise, fall through to normal case. + + This prevents key events being sent twice to GtkInvisible + widgets, which can cause all sorts of mischief. + +Fri Feb 2 13:20:12 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): When a grab + widget is in effect, give the grab widget a first + crack at KEY_PRESS/RELEASE events. (#424) + Sat Mar 3 15:39:49 2001 Owen Taylor * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 9c25cb1724..4274d77352 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,32 @@ +Sat Mar 3 16:26:33 2001 Owen Taylor + + * gdk/x11/gdkmain-x11.c gdk/x11/gdkkeys-x11.c + gdk/x11/gdkevents-x11.c gdk/x11/gdkprivate-x11.c: + + Detectable auto-repeat - make a repeating key generate + press/press/press/release instead of press/release pairs. + + If we have Xkb and XkbSetDectableAutoRepeat supports + that, we do it that way. Otherwise, when we get + a release event, we check ahead with XPending to see + if the next key is a KeyPress with the same keycode + and timestamp. (Not 100% reliable, but pretty close.) + +Tue Feb 27 02:16:14 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): Only do special + special key-press grab handling for widgets within + GtkWindows. Otherwise, fall through to normal case. + + This prevents key events being sent twice to GtkInvisible + widgets, which can cause all sorts of mischief. + +Fri Feb 2 13:20:12 2001 Owen Taylor + + * gtk/gtkmain.c (gtk_propagate_event): When a grab + widget is in effect, give the grab widget a first + crack at KEY_PRESS/RELEASE events. (#424) + Sat Mar 3 15:39:49 2001 Owen Taylor * gtk/gtkentry.c (gtk_entry_button_press): Add shift-clicking diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 0f590774c7..87ed392952 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -530,7 +530,7 @@ gdk_event_translate (GdkEvent *event, case KeyPress: /* Lookup the string corresponding to the given keysym. */ - + #ifdef USE_XIM if (buf_len == 0) { @@ -613,6 +613,24 @@ gdk_event_translate (GdkEvent *event, case KeyRelease: /* Lookup the string corresponding to the given keysym. */ + + /* Emulate detectable auto-repeat by checking to see + * if the next event is a key press with the same + * keycode and timestamp, and if so, ignoring the event. + */ + + if (!_gdk_have_xkb_autorepeat && XPending (gdk_display)) + { + XEvent next_event; + + XPeekEvent (gdk_display, &next_event); + + if (next_event.type == KeyPress && + next_event.xkey.keycode == xevent->xkey.keycode && + next_event.xkey.time == xevent->xkey.time) + break; + } + #ifdef USE_XIM if (buf_len == 0) { diff --git a/gdk/x11/gdkkeys-x11.c b/gdk/x11/gdkkeys-x11.c index dc807d8494..8d8876a1ad 100644 --- a/gdk/x11/gdkkeys-x11.c +++ b/gdk/x11/gdkkeys-x11.c @@ -82,6 +82,12 @@ get_xkb (void) } #endif /* HAVE_XKB */ +/* Whether we were able to turn on detectable-autorepeat using + * XkbSetDetectableAutorepeat. If FALSE, we'll fall back + * to checking the next event with XPending(). + */ +gboolean _gdk_have_xkb_autorepeat = FALSE; + static KeySym* keymap = NULL; static gint keysyms_per_keycode = 0; static XModifierKeymap* mod_keymap = NULL; diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c index ff6fa309cc..76a1ab1915 100644 --- a/gdk/x11/gdkmain-x11.c +++ b/gdk/x11/gdkmain-x11.c @@ -214,12 +214,23 @@ _gdk_windowing_init_check (int argc, char **argv) if (XkbQueryExtension (gdk_display, NULL, NULL, NULL, &xkb_major, &xkb_minor)) { + Bool detectable_autorepeat_supported; + _gdk_use_xkb = TRUE; XkbSelectEvents (gdk_display, XkbUseCoreKbd, XkbMapNotifyMask, XkbMapNotifyMask); + + XkbSetDetectableAutoRepeat (gdk_display, + True, + &detectable_autorepeat_supported); + + GDK_NOTE (MISC, g_message ("Detectable autorepeat %s.", + detectable_autorepeat_supported ? "supported" : "not supported")); + + _gdk_have_xkb_autorepeat = detectable_autorepeat_supported; } } } diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index 0d03177fd3..24f7075c40 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -113,8 +113,15 @@ extern GdkWindow *gdk_xim_window; /* currently using Window */ /* Used to detect not-up-to-date keymap */ extern guint _gdk_keymap_serial; + #ifdef HAVE_XKB extern gboolean _gdk_use_xkb; #endif +/* Whether we were able to turn on detectable-autorepeat using + * XkbSetDetectableAutorepeat. If FALSE, we'll fall back + * to checking the next event with XPending(). + */ +extern gboolean _gdk_have_xkb_autorepeat; + #endif /* __GDK_PRIVATE_X11_H__ */ diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 0689427e5a..f8801cc1b8 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -1509,6 +1509,8 @@ gtk_propagate_event (GtkWidget *widget, handled_event = FALSE; + gtk_widget_ref (widget); + if ((event->type == GDK_KEY_PRESS) || (event->type == GDK_KEY_RELEASE)) { @@ -1520,29 +1522,53 @@ gtk_propagate_event (GtkWidget *widget, GtkWidget *window; window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); - if (window) - { - if (GTK_WIDGET_IS_SENSITIVE (window)) - gtk_widget_event (window, event); - handled_event = TRUE; /* don't send to widget */ - } + if (window) + { + /* If there is a grab within the window, give the grab widget + * a first crack at the key event + */ + if (widget != window && GTK_WIDGET_HAS_GRAB (widget)) + handled_event = gtk_widget_event (widget, event); + + if (!handled_event) + { + window = gtk_widget_get_ancestor (widget, GTK_TYPE_WINDOW); + if (window) + { + if (GTK_WIDGET_IS_SENSITIVE (window)) + gtk_widget_event (window, event); + } + } + + handled_event = TRUE; /* don't send to widget */ + } } /* Other events get propagated up the widget tree * so that parents can see the button and motion * events of the children. */ - while (!handled_event && widget) + if (!handled_event) { - GtkWidget *tmp; + while (TRUE) + { + GtkWidget *tmp; + + handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event); + tmp = widget->parent; + gtk_widget_unref (widget); - gtk_widget_ref (widget); - handled_event = !GTK_WIDGET_IS_SENSITIVE (widget) || gtk_widget_event (widget, event); - tmp = widget->parent; - gtk_widget_unref (widget); - widget = tmp; + widget = tmp; + + if (!handled_event && widget) + gtk_widget_ref (widget); + else + break; + } } + else + gtk_widget_unref (widget); } #if 0