Subject: Locking alternative layouts for wskbd [patch]
To: None <tech-kern@netbsd.org>
From: Mike M. Volokhov <mishka@netbsd.org>
List: tech-kern
Date: 03/29/2007 14:56:38
--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hello!

Many languages (for example, Greek and Cyrillic) 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.

The patch (against 3.1 sources) 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
from mode2 to mode1 as well. For example, you can use right Alt:

	keycode 184 = Mode_switch Multi_key

Among mentioned changes, the patch offers following small cleanups
(any of them may be dropped in case of any objections):

- KS_Cmd_Scroll* execution should be explicitly interrupted with 'break'.
- Some cleanups in ksym extraction algorithm.
- Note: implemented ksym translation isn't sufficient for l10n.

If noone objects I'll glad to see it commited (patch is against
3.1, but I'll adopt it for current).

--
Yours,
Mishka.


--GvXjxJ+pjyke8COw
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="wscons-modetoggle.patch"

diff -u wscons-3.1/wskbd.c wscons/wskbd.c
--- wscons-3.1/wskbd.c	2005-06-03 18:49:32.000000000 +0300
+++ wscons/wskbd.c	2007-03-26 13:55:43.000000000 +0300
@@ -1361,14 +1361,20 @@
 static inline void
 update_modifier(struct wskbd_internal *id, u_int type, int toggle, int mask)
 {
-	if (toggle) {
-		if (type == WSCONS_EVENT_KEY_DOWN)
-			id->t_modifiers ^= mask;
-	} else {
+	switch (toggle) {
+	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;
 	}
 }
 
@@ -1423,6 +1429,7 @@
 				return (0);
 			}
 		}
+		break;
 
 	case KS_Cmd_ScrollSlowUp:
 	case KS_Cmd_ScrollSlowDown:
@@ -1442,8 +1449,20 @@
 				return (0);
 			}
 		}
+		break;
 #endif
 
+	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;
+
 	case KS_Cmd:
 		update_modifier(sc->id, *type, 0, MOD_COMMAND);
 		ksym = ksym2;
@@ -1601,7 +1620,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:
@@ -1630,7 +1653,7 @@
 	else
 		group = & kp->group1[0];
 
-	if ((id->t_modifiers & MOD_NUMLOCK) != 0 &&
+	if (MOD_ONESET(id, MOD_NUMLOCK) &&
 	    KS_GROUP(group[1]) == KS_GROUP_Keypad) {
 		if (MOD_ONESET(id, MOD_ANYSHIFT))
 			ksym = group[0];
@@ -1639,10 +1662,16 @@
 	} else if (! MOD_ONESET(id, MOD_ANYSHIFT | MOD_CAPSLOCK)) {
 		ksym = group[0];
 	} else if (MOD_ONESET(id, MOD_CAPSLOCK)) {
-		if (! MOD_ONESET(id, MOD_SHIFT_L | MOD_SHIFT_R))
-			ksym = group[0];
-		else
+		if (MOD_ONESET(id, MOD_SHIFT_L | MOD_SHIFT_R))
 			ksym = group[1];
+		else
+			ksym = group[0];
+
+		/*
+		 * XXX: the following translation may (and in fact, is)
+		 * not work well for some localized layouts. IMHO the
+		 * convertion should be done on layout basis.  -- <mishka>
+		 */
 		if (ksym >= KS_a && ksym <= KS_z)
 			ksym += KS_A - KS_a;
 		else if (ksym >= KS_agrave && ksym <= KS_thorn &&
diff -u wscons-3.1/wsksymdef.h wscons/wsksymdef.h
--- wscons-3.1/wsksymdef.h	2005-04-04 21:21:06.000000000 +0300
+++ wscons/wsksymdef.h	2007-03-26 11:49:01.000000000 +0300
@@ -301,6 +301,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
@@ -446,6 +447,7 @@
 #define KS_Cmd_ScrollFastDown	0xf42d
 #define KS_Cmd_ScrollSlowUp	0xf42e
 #define KS_Cmd_ScrollSlowDown	0xf42f
+#define KS_Cmd_ModeToggle	0xf430
 
 /*
  * Group 5 (internal)

--GvXjxJ+pjyke8COw--