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