Subject: kern/36762: Locking alternative layouts for wskbd
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: None <mishka@netbsd.org>
List: netbsd-bugs
Date: 08/10/2007 08:45:00
>Number:         36762
>Category:       kern
>Synopsis:       Locking alternative layouts for wskbd
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Fri Aug 10 08:45:00 +0000 2007
>Originator:     Mike M. Volokhov
>Release:        NetBSD-current, 4.x, 3.x
>Organization:
>Environment:
>Description:
Many languages (for example, Greek and Russian) are based on 
completely different alphabet. Such, typesetting with one of
modifiers pressed all the time is just a PITA. It would be good to
have a toogle behaviour of Mode Switch. Also, it's often convenient
to have an ability switch the mode temporarily.

>How-To-Repeat:
Try to use wsconsole with one of the mentioned alphabets. Feel the PITA.
>Fix:
The patch below implements this idea using two different methods
(names somewhat inconsistent in order to be consistent with names
used before):

1) KS_Mode_toggle (modifier, group 1). You can assign it on any
   key and mode will be fixed until you press the key next time.
   This looks exactly like Caps Lock behaviour. For example, F12
   may be used for this purpose:

        keycode 88 = Mode_toggle

2) KS_Cmd_ModeToggle (command, group 4). With this new command you
   can switch the mode by pressing a combination of two keys - any
   Command key (usually Alt or Ctrl) and assigned button. In my own
   setup I usually use the left Shift:

        keycode 42 = Cmd_ModeToggle Shift_L

Old mode switch is also available, but was improved to allow 
switching back from mode2 to mode1, and modes still switched until
the key released. For example, you can use right Alt for temporarily 
switch to the second layout:

        keycode 184 = Mode_switch Multi_key


-------- 8< -------- 8< -------- 8< -------- 8< --------

Index: wskbd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wskbd.c,v
retrieving revision 1.105
diff -u -r1.105 wskbd.c
--- wskbd.c     6 Aug 2007 03:07:52 -0000       1.105
+++ wskbd.c     10 Aug 2007 07:41:17 -0000
@@ -1406,16 +1406,22 @@
 }
 
 static inline void
-update_modifier(struct wskbd_internal *id, u_int type, int toggle, int mask)
+update_modifier(struct wskbd_internal *id, u_int type, int togglemode, int mask
)
 {
-       if (toggle) {
-               if (type == WSCONS_EVENT_KEY_DOWN)
-                       id->t_modifiers ^= mask;
-       } else {
+       switch (togglemode) {
+       case 0: /* down - on, up - off */
                if (type == WSCONS_EVENT_KEY_DOWN)
                        id->t_modifiers |= mask;
                else
                        id->t_modifiers &= ~mask;
+               break;
+       case 1: /* down - invert */
+               if (type == WSCONS_EVENT_KEY_DOWN)
+                       id->t_modifiers ^= mask;
+               break;
+       case 2: /* either down or up - invert */
+               id->t_modifiers ^= mask;
+               break;
        }
 }
 
@@ -1503,6 +1509,17 @@
        case KS_Cmd2:
                update_modifier(sc->id, *type, 0, MOD_COMMAND2);
                break;
+
+       case KS_Cmd_ModeToggle:
+               if (*type == WSCONS_EVENT_KEY_DOWN) {
+                   if (MOD_ONESET(sc->id, MOD_COMMAND1 | MOD_COMMAND2)) {
+                       update_modifier(sc->id, *type, 1, MOD_MODESHIFT);
+                       return (1);
+                   } else {
+                       return (0);
+                   }
+               }
+               break;
        }
 
        if (*type != WSCONS_EVENT_KEY_DOWN ||
@@ -1648,7 +1665,11 @@
                break;
 
        case KS_Mode_switch:
-               update_modifier(id, type, 0, MOD_MODESHIFT);
+               update_modifier(id, type, 2, MOD_MODESHIFT);
+               break;
+
+       case KS_Mode_toggle:
+               update_modifier(id, type, 1, MOD_MODESHIFT);
                break;
 
        case KS_Num_Lock:
Index: wsksymdef.h
===================================================================
RCS file: /cvsroot/src/sys/dev/wscons/wsksymdef.h,v
retrieving revision 1.58
diff -u -r1.58 wsksymdef.h
--- wsksymdef.h 4 Apr 2007 14:50:21 -0000       1.58
+++ wsksymdef.h 10 Aug 2007 07:41:17 -0000
@@ -377,6 +377,7 @@
 #define KS_Henkan_Mode         0xf114  /* Start/Stop Conversion */
 #define KS_Henkan              0xf115  /* Alias for Henkan_Mode */
 #define KS_Muhenkan            0xf116  /* Cancel Conversion */
+#define KS_Mode_toggle         0xf117
 
 /*
  * Group 2 (keypad) character in low byte
@@ -524,6 +525,7 @@
 #define KS_Cmd_ScrollFastDown  0xf42d
 #define KS_Cmd_ScrollSlowUp    0xf42e
 #define KS_Cmd_ScrollSlowDown  0xf42f
+#define KS_Cmd_ModeToggle      0xf430
 
 /*
  * Group 5 (internal)
-------- 8< -------- 8< -------- 8< -------- 8< --------

P.S. I've committed extended version of patch some time ago, but it
was known to cause some problems (unwanted entering into ddb, etc).
In this version any unrelated code was removed and functionality was
extensively tested on DEBUG / DIAGNOSTIC kernels; testing for X11 vs
wscons layout switchers correlation was done on Xorg 6.9.