Commit | Line | Data |
---|---|---|
7217e0ca ML |
1 | --- a/xkb/xkbActions.c |
2 | +++ b/xkb/xkbActions.c | |
4db25562 | 3 | @@ -351,22 +351,83 @@ _XkbFilterLatchState(XkbSrvInfoPtr xkbi, |
7217e0ca ML |
4 | } |
5 | ||
6 | static int | |
7 | -_XkbFilterLockState(XkbSrvInfoPtr xkbi, | |
8 | +xkbSwitchGroupOnRelease(void) | |
9 | +{ | |
10 | + /* TODO: user configuring */ | |
11 | + return TRUE; | |
12 | +} | |
13 | + | |
14 | +static void | |
15 | +xkbUpdateLockedGroup(XkbSrvInfoPtr xkbi, XkbAction *pAction) | |
16 | +{ | |
17 | + XkbGroupAction ga = pAction->group; | |
18 | + | |
19 | + if (ga.flags & XkbSA_GroupAbsolute) | |
20 | + xkbi->state.locked_group = XkbSAGroup(&ga); | |
21 | + else | |
22 | + xkbi->state.locked_group += XkbSAGroup(&ga); | |
23 | +} | |
24 | + | |
25 | +static XkbFilterPtr _XkbNextFreeFilter(XkbSrvInfoPtr xkbi); | |
26 | + | |
27 | +static int | |
28 | +_XkbFilterLockGroup(XkbSrvInfoPtr xkbi, | |
29 | XkbFilterPtr filter, unsigned keycode, XkbAction *pAction) | |
30 | { | |
31 | - if (pAction && (pAction->type == XkbSA_LockGroup)) { | |
32 | - if (pAction->group.flags & XkbSA_GroupAbsolute) | |
33 | - xkbi->state.locked_group = XkbSAGroup(&pAction->group); | |
34 | - else | |
35 | - 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 | + | |
67 | + sendEvent = _XkbFilterSetState(xkbi, filter, keycode, &act); | |
68 | + } | |
69 | + } | |
70 | + } | |
71 | + else { | |
72 | + /* do nothing if some button else is pressed */ | |
73 | + if (!pAction) | |
74 | + xkbUpdateLockedGroup(xkbi, &filter->upAction); | |
75 | + filter->active = 0; | |
76 | + } | |
77 | + | |
78 | + return sendEvent; | |
79 | +} | |
80 | + | |
81 | +static int | |
82 | +_XkbFilterLockMods(XkbSrvInfoPtr xkbi, | |
83 | + XkbFilterPtr filter, unsigned keycode, XkbAction *pAction) | |
84 | +{ | |
85 | if (filter->keycode == 0) { /* initial press */ | |
86 | filter->keycode = keycode; | |
87 | filter->active = 1; | |
88 | filter->filterOthers = 0; | |
89 | filter->priv = xkbi->state.locked_mods & pAction->mods.mask; | |
90 | - filter->filter = _XkbFilterLockState; | |
91 | + filter->filter = _XkbFilterLockMods; | |
92 | filter->upAction = *pAction; | |
93 | if (!(filter->upAction.mods.flags & XkbSA_LockNoLock)) | |
94 | xkbi->state.locked_mods |= pAction->mods.mask; | |
4db25562 | 95 | @@ -1185,9 +1246,12 @@ XkbHandleActions(DeviceIntPtr dev, Devic |
7217e0ca ML |
96 | sendEvent = _XkbFilterLatchState(xkbi, filter, key, &act); |
97 | break; | |
98 | case XkbSA_LockMods: | |
99 | + filter = _XkbNextFreeFilter(xkbi); | |
100 | + sendEvent = _XkbFilterLockMods(xkbi, filter, key, &act); | |
101 | + break; | |
102 | case XkbSA_LockGroup: | |
103 | filter = _XkbNextFreeFilter(xkbi); | |
104 | - sendEvent = _XkbFilterLockState(xkbi, filter, key, &act); | |
105 | + sendEvent = _XkbFilterLockGroup(xkbi, filter, key, &act); | |
106 | break; | |
107 | case XkbSA_ISOLock: | |
108 | filter = _XkbNextFreeFilter(xkbi); |