1 diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
2 index c473df1..0ac2c71 100644
5 @@ -341,22 +341,83 @@ _XkbFilterLatchState(XkbSrvInfoPtr xkbi,
9 -_XkbFilterLockState(XkbSrvInfoPtr xkbi,
10 +xkbSwitchGroupOnRelease(void)
12 + /* TODO: user configuring */
17 +xkbUpdateLockedGroup(XkbSrvInfoPtr xkbi, XkbAction *pAction)
19 + XkbGroupAction ga = pAction->group;
21 + if (ga.flags & XkbSA_GroupAbsolute)
22 + xkbi->state.locked_group = XkbSAGroup(&ga);
24 + xkbi->state.locked_group += XkbSAGroup(&ga);
27 +static XkbFilterPtr _XkbNextFreeFilter(XkbSrvInfoPtr xkbi);
30 +_XkbFilterLockGroup(XkbSrvInfoPtr xkbi,
31 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
33 - if (pAction && (pAction->type == XkbSA_LockGroup)) {
34 - if (pAction->group.flags & XkbSA_GroupAbsolute)
35 - xkbi->state.locked_group = XkbSAGroup(&pAction->group);
37 - xkbi->state.locked_group += XkbSAGroup(&pAction->group);
41 + if (!xkbSwitchGroupOnRelease()) {
42 + xkbUpdateLockedGroup(xkbi, pAction);
46 + /* Delay switch till button release */
47 + if (filter->keycode == 0) { /* initial press */
48 + filter->keycode = keycode;
50 + filter->filterOthers = 0; /* for what? */
51 + filter->filter = _XkbFilterLockGroup;
53 + /* filter->priv = 0; */
54 + filter->upAction = *pAction;
56 + /* Ok, now we need to simulate the action which would go if this action didn't block it.
57 + XkbSA_SetMods is the one: it is to set modifier' flag up. */
59 + XkbStateRec fake_state = xkbi->state;
62 + fake_state.mods = 0;
63 + act = XkbGetKeyAction(xkbi, &fake_state, keycode);
65 + /* KLUDGE: XkbSA_SetMods only? */
66 + if (act.type == XkbSA_SetMods) {
67 + XkbFilterPtr filter = _XkbNextFreeFilter(xkbi);
69 + sendEvent = _XkbFilterSetState(xkbi, filter, keycode, &act);
74 + /* do nothing if some button else is pressed */
76 + xkbUpdateLockedGroup(xkbi, &filter->upAction);
84 +_XkbFilterLockMods(XkbSrvInfoPtr xkbi,
85 + XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
87 if (filter->keycode == 0) { /* initial press */
88 filter->keycode = keycode;
90 filter->filterOthers = 0;
91 filter->priv = xkbi->state.locked_mods & pAction->mods.mask;
92 - filter->filter = _XkbFilterLockState;
93 + filter->filter = _XkbFilterLockMods;
94 filter->upAction = *pAction;
95 if (!(filter->upAction.mods.flags & XkbSA_LockNoLock))
96 xkbi->state.locked_mods |= pAction->mods.mask;
97 @@ -1129,9 +1190,12 @@ XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
98 sendEvent = _XkbFilterLatchState(xkbi, filter, key, &act);
101 + filter = _XkbNextFreeFilter(xkbi);
102 + sendEvent = _XkbFilterLockMods(xkbi, filter, key, &act);
104 case XkbSA_LockGroup:
105 filter = _XkbNextFreeFilter(xkbi);
106 - sendEvent = _XkbFilterLockState(xkbi, filter, key, &act);
107 + sendEvent = _XkbFilterLockGroup(xkbi, filter, key, &act);
110 filter = _XkbNextFreeFilter(xkbi);