Messages in this thread Patch in this message | | | From | Werner Almesberger <> | Subject | PATCH: sticky shift keys: bug fix and more intuitive behaviour | Date | Sat, 15 May 1999 06:38:49 +0200 (MET DST) |
| |
[ Copied to linux-kernel, in case there are objections. ]
Hi Linus,
I've just spotted the 2.3 release announcement. There doesn't seem to be a maintainer for keyboard.c, so I'm sending this directly to you. It's something from the Linux-7k project, which may also be useful for other Linux-on-PDA projects:
This patch adds a compile-time option CONFIG_SMART_SLOCK to improve the behaviour of "sticky" shift/ctrl/alt/etc. keys in virtual terminals. The current behaviour for the sticky keys is that they change the next key, and only that one. If CONFIG_SMART_SLOCK is enabled, they still change the next key, but they also continue changing while held down, i.e. like shift and friends do in normal (non-"sticky") operation.
Example: when pressing A, pressing (and releasing) Shift, pressing B, then holding down Shift, pressing C, pressing D, and then releasing Shift, we get:
Without sticky keys: a b C D With sticky keys, without CONFIG_SMART_SLOCK: a B C d With sticky keys, with CONFIG_SMART_SLOCK: a B C D
This is likely to be more intuitive than the current sticky behaviour on machines which are sometimes operated single-handedly, e.g. PDAs. I've introduced this extension at the beginning of March in the Linux-7k project and used it quite extensively on my Psion. I've tested the 2.3.2 version briefly on my PC without noticing any problems.
The patch also adds conflict resolution if a keypress doesn't yield a valid code. (The second change in do_slock.) This is a bug fix which you may want to add to 2.2 too. E.g. the keyboard currently locks up if you use the US layout, make Shift, Ctrl, and Alt "sticky", and then press each of them. Reason: there is no valid map for Shift+Ctrl+Alt, so all further keys are ignored.
Furthermore, the patch prevents sticky keys from being used to compose the boot sequence. (I've added this after noticing that I had a tendency of trying to "correct" typos in the Ctrl and Alt region by pressing Del ... ;-)
I've made this change a compile-time option because current users of sticky keys may need the traditional behaviour for some reason (e.g. special hardware). It would be good if current users of the sticky keys could comment on the change, so that it may perhaps become the standard behaviour in the future.
This extension was inspired by the way shift keys work on HP100/200LX palmtops.
Cheers, Werner
---------------------------------- cut here -----------------------------------
--- linux.orig/Documentation/Configure.help Fri May 14 17:59:54 1999 +++ linux/Documentation/Configure.help Sat May 15 06:05:20 1999 @@ -8111,6 +8111,11 @@ If unsure, say Y. +Smart "sticky" shifted keys +CONFIG_SMART_SLOCK + Make "sticky" shifted keys more similar to normal, non-sticky keys. + This is mainly useful for devices which are operated with one hand. + Software generated cursor CONFIG_SOFTCURSOR If you say Y here, you'll be able to do lots of nice things with the --- linux.orig/drivers/char/Config.in Fri May 7 20:05:30 1999 +++ linux/drivers/char/Config.in Sat May 15 05:51:37 1999 @@ -7,6 +7,7 @@ bool 'Virtual terminal' CONFIG_VT if [ "$CONFIG_VT" = "y" ]; then bool 'Support for console on virtual terminal' CONFIG_VT_CONSOLE + bool 'Smart "sticky" shifted keys' CONFIG_SMART_SLOCK fi tristate 'Standard/generic (dumb) serial support' CONFIG_SERIAL if [ "$CONFIG_SERIAL" = "y" ]; then --- linux.orig/drivers/char/keyboard.c Tue May 11 23:37:40 1999 +++ linux/drivers/char/keyboard.c Sat May 15 06:22:12 1999 @@ -278,8 +278,13 @@ u_short keysym; u_char type; +#ifndef CONFIG_SMART_SLOCK /* the XOR below used to be an OR */ int shift_final = shift_state ^ kbd->lockstate ^ kbd->slockstate; +#else + int shift_final = (shift_state | kbd->slockstate) ^ + kbd->lockstate; +#endif ushort *key_map = key_maps[shift_final]; if (key_map != NULL) { @@ -311,6 +316,7 @@ /* we have at least to update shift_state */ #if 1 /* how? two almost equivalent choices follow */ compute_shiftstate(); + kbd->slockstate = 0; /* play it safe */ #else keysym = U(plain_map[keycode]); type = KTYP(keysym); @@ -472,6 +478,7 @@ static void boot_it(void) { + if (kbd->slockstate & ~shift_state) return; ctrl_alt_del(); } @@ -741,7 +748,11 @@ for(j=0; j<BITS_PER_LONG; j++,k++) if(test_bit(k, key_down)) { sym = U(plain_map[k]); +#ifndef CONFIG_SMART_SLOCK if(KTYP(sym) == KT_SHIFT) { +#else + if(KTYP(sym) == KT_SHIFT || KTYP(sym) == KT_SLOCK) { +#endif val = KVAL(sym); if (val == KVAL(K_CAPSSHIFT)) val = KVAL(K_SHIFT); @@ -793,9 +804,17 @@ static void do_slock(unsigned char value, char up_flag) { +#ifdef CONFIG_SMART_SLOCK + do_shift(value,up_flag); +#endif if (up_flag || rep) return; chg_vc_kbd_slock(kbd, value); + /* try to make Alt, oops, AltGr and such work */ + if (!key_maps[kbd->lockstate ^ kbd->slockstate]) { + kbd->slockstate = 0; + chg_vc_kbd_slock(kbd, value); + } } /* -- _________________________________________________________________________ / Werner Almesberger, DI-ICA,EPFL,CH werner.almesberger@lrc.di.epfl.ch / /_IN_R_131__Tel_+41_21_693_6621__Fax_+41_21_693_6610_____________________/ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |