summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAaron Campbell <aaron@cvs.openbsd.org>2000-11-24 14:05:26 +0000
committerAaron Campbell <aaron@cvs.openbsd.org>2000-11-24 14:05:26 +0000
commit037e831b215b1948c5b99e6d813f47fb6ca0deeb (patch)
tree796a760dd05785dcde4917eed0e15d369e12b2e8 /sys
parent6f74be63e7fc1ba42fc035e3602765a8e0fbfe1f (diff)
Better key repeat logic. When we're in repeat mode, with the exception of
modifier keys (SHIFT, CTRL, ALT, etc.), and a key "up" event is received, only delete the key repeat timeout if the key that generated the "up" event is the key currently being repeated. When a key "down" event is received, the opposite -- only delete the key repeat if the key that generated the "down" event is _not_ the key currently being repeated. Playing here is a bit dangerous since we are constraining the conditions in which a timeout(9) is deleted (we don't want to mistakenly get stuck in a non-legitamite key repeat). Using timeout(9) for this is kind of gross. I guess it is done here to avoid key repeat code in all of the actual hardware keyboard drivers. There is still a bug here. If you have a key held down and detach your keyboard (by either unplugging it or doing a KVM switch), the timeout is not deleted and the key continues to repeat until it gets the keyboard back and receives an interrupt. Perhaps we should not be ignoring typematic keys after all?
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/wscons/wskbd.c48
1 files changed, 31 insertions, 17 deletions
diff --git a/sys/dev/wscons/wskbd.c b/sys/dev/wscons/wskbd.c
index 16be7a19ebe..c9e11f700a3 100644
--- a/sys/dev/wscons/wskbd.c
+++ b/sys/dev/wscons/wskbd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wskbd.c,v 1.3 2000/11/15 20:00:40 aaron Exp $ */
+/* $OpenBSD: wskbd.c,v 1.4 2000/11/24 14:05:25 aaron Exp $ */
/* $NetBSD: wskbd.c,v 1.38 2000/03/23 07:01:47 thorpej Exp $ */
/*
@@ -164,6 +164,7 @@ struct wskbd_softc {
struct wskbd_keyrepeat_data sc_keyrepeat_data;
int sc_repeating; /* we've called timeout() */
+ int sc_repkey;
struct timeout sc_repeat_ch;
int sc_translating; /* xlate to chars for emulation */
@@ -521,6 +522,11 @@ wskbd_detach(self, flags)
#if NWSMUX > 0
int mux;
+ if (sc->sc_repeating) {
+ sc->sc_repeating = 0;
+ timeout_del(&sc->sc_repeat_ch);
+ }
+
mux = sc->sc_dv.dv_cfdata->wskbddevcf_mux;
if (mux != WSMOUSEDEVCF_MUX_DEFAULT)
wsmux_detach(mux, &sc->sc_dv);
@@ -570,11 +576,6 @@ wskbd_input(dev, type, value)
int put;
#if NWSDISPLAY > 0
- if (sc->sc_repeating) {
- sc->sc_repeating = 0;
- timeout_del(&sc->sc_repeat_ch);
- }
-
/*
* If /dev/wskbd is not connected in event mode translate and
* send upstream.
@@ -1397,43 +1398,43 @@ wskbd_translate(id, type, value)
switch (kp->group1[0]) {
case KS_Shift_L:
update_modifier(id, type, 0, MOD_SHIFT_L);
- break;
+ goto kbrep;
case KS_Shift_R:
update_modifier(id, type, 0, MOD_SHIFT_R);
- break;
+ goto kbrep;
case KS_Shift_Lock:
update_modifier(id, type, 1, MOD_SHIFTLOCK);
- break;
+ goto kbrep;
case KS_Caps_Lock:
update_modifier(id, type, 1, MOD_CAPSLOCK);
- break;
+ goto kbrep;
case KS_Control_L:
update_modifier(id, type, 0, MOD_CONTROL_L);
- break;
+ goto kbrep;
case KS_Control_R:
update_modifier(id, type, 0, MOD_CONTROL_R);
- break;
+ goto kbrep;
case KS_Alt_L:
update_modifier(id, type, 0, MOD_META_L);
- break;
+ goto kbrep;
case KS_Alt_R:
update_modifier(id, type, 0, MOD_META_R);
- break;
+ goto kbrep;
case KS_Mode_switch:
update_modifier(id, type, 0, MOD_MODESHIFT);
- break;
+ goto kbrep;
case KS_Num_Lock:
update_modifier(id, type, 1, MOD_NUMLOCK);
- break;
+ goto kbrep;
#if NWSDISPLAY > 0
case KS_Hold_Screen:
@@ -1441,10 +1442,23 @@ wskbd_translate(id, type, value)
update_modifier(id, type, 1, MOD_HOLDSCREEN);
wskbd_holdscreen(sc, id->t_modifiers & MOD_HOLDSCREEN);
}
- break;
+ goto kbrep;
#endif
}
+ if (sc->sc_repeating) {
+ if ((type == WSCONS_EVENT_KEY_UP && value != sc->sc_repkey) ||
+ (type == WSCONS_EVENT_KEY_DOWN && value == sc->sc_repkey))
+ return (0);
+ }
+
+kbrep:
+ if (sc->sc_repeating) {
+ sc->sc_repeating = 0;
+ timeout_del(&sc->sc_repeat_ch);
+ }
+ sc->sc_repkey = value;
+
/* If this is a key release or we are in command mode, we are done */
if (type != WSCONS_EVENT_KEY_DOWN || iscommand) {
update_leds(id);