1 Index: xorg-server/xkb/xkbActions.c
2 ===================================================================
3 --- xorg-server.orig/xkb/xkbActions.c 2011-12-14 15:15:20.000000000 -0800
4 +++ xorg-server/xkb/xkbActions.c 2011-12-14 15:26:43.372680253 -0800
5 @@ -328,24 +328,83 @@ _XkbFilterLatchState( XkbSrvInfoPtr xkbi
6 return 1;
7 }
9 +static int xkbSwitchGroupOnRelease(void)
10 +{
11 + /* TODO: user configuring */
12 + return TRUE;
13 +}
14 +
15 +static void xkbUpdateLockedGroup(XkbSrvInfoPtr xkbi, XkbAction* pAction)
16 +{
17 + XkbGroupAction ga = pAction->group;
18 + if (ga.flags&XkbSA_GroupAbsolute)
19 + xkbi->state.locked_group= XkbSAGroup(&ga);
20 + else xkbi->state.locked_group+= XkbSAGroup(&ga);
21 +}
22 +
23 +static XkbFilterPtr _XkbNextFreeFilter(XkbSrvInfoPtr xkbi);
24 +
25 static int
26 -_XkbFilterLockState( XkbSrvInfoPtr xkbi,
27 +_XkbFilterLockGroup( XkbSrvInfoPtr xkbi,
28 XkbFilterPtr filter,
29 unsigned keycode,
30 XkbAction * pAction)
31 {
32 - if (pAction&&(pAction->type==XkbSA_LockGroup)) {
33 - if (pAction->group.flags&XkbSA_GroupAbsolute)
34 - xkbi->state.locked_group= XkbSAGroup(&pAction->group);
35 - else xkbi->state.locked_group+= XkbSAGroup(&pAction->group);
36 - return 1;
37 + int sendEvent = 1;
38 +
39 + if (!xkbSwitchGroupOnRelease()) {
40 + xkbUpdateLockedGroup(xkbi, pAction);
41 + return sendEvent;
42 + }
43 +
44 + /* Delay switch till button release */
45 + if (filter->keycode==0) { /* initial press */
46 + filter->keycode = keycode;
47 + filter->active = 1;
48 + filter->filterOthers = 0; /* for what? */
49 + filter->filter = _XkbFilterLockGroup;
50 +
51 + /* filter->priv = 0; */
52 + filter->upAction = *pAction;
53 +
54 + /* Ok, now we need to simulate the action which would go if this action didn't block it.
55 + XkbSA_SetMods is the one: it is to set modifier' flag up. */
56 + {
57 + XkbStateRec fake_state = xkbi->state;
58 + XkbAction act;
59 +
60 + fake_state.mods = 0;
61 + act = XkbGetKeyAction(xkbi, &fake_state, keycode);
62 +
63 + /* KLUDGE: XkbSA_SetMods only? */
64 + if (act.type == XkbSA_SetMods) {
65 + XkbFilterPtr filter = _XkbNextFreeFilter(xkbi);
66 + sendEvent = _XkbFilterSetState(xkbi,filter,keycode,&act);
67 + }
68 + }
69 + }
70 + else {
71 + /* do nothing if some button else is pressed */
72 + if (!pAction)
73 + xkbUpdateLockedGroup(xkbi, &filter->upAction);
74 + filter->active = 0;
75 }
76 +
77 + return sendEvent;
78 +}
79 +
80 +static int
81 +_XkbFilterLockMods( XkbSrvInfoPtr xkbi,
82 + XkbFilterPtr filter,
83 + unsigned keycode,
84 + XkbAction * pAction)
85 +{
86 if (filter->keycode==0) { /* initial press */
87 filter->keycode = keycode;
88 filter->active = 1;
89 filter->filterOthers = 0;
90 filter->priv = xkbi->state.locked_mods&pAction->mods.mask;
91 - filter->filter = _XkbFilterLockState;
92 + filter->filter = _XkbFilterLockMods;
93 filter->upAction = *pAction;
94 if (!(filter->upAction.mods.flags&XkbSA_LockNoLock))
95 xkbi->state.locked_mods|= pAction->mods.mask;
96 @@ -1118,9 +1177,12 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEI
97 sendEvent=_XkbFilterLatchState(xkbi,filter,key,&act);
98 break;
99 case XkbSA_LockMods:
100 + filter = _XkbNextFreeFilter(xkbi);
101 + sendEvent=_XkbFilterLockMods(xkbi,filter,key,&act);
102 + break;
103 case XkbSA_LockGroup:
104 filter = _XkbNextFreeFilter(xkbi);
105 - sendEvent=_XkbFilterLockState(xkbi,filter,key,&act);
106 + sendEvent=_XkbFilterLockGroup(xkbi,filter,key,&act);
107 break;
108 case XkbSA_ISOLock:
109 filter = _XkbNextFreeFilter(xkbi);