1*4882a593Smuzhiyun /************************************************************
2*4882a593Smuzhiyun Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3*4882a593Smuzhiyun
4*4882a593Smuzhiyun Permission to use, copy, modify, and distribute this
5*4882a593Smuzhiyun software and its documentation for any purpose and without
6*4882a593Smuzhiyun fee is hereby granted, provided that the above copyright
7*4882a593Smuzhiyun notice appear in all copies and that both that copyright
8*4882a593Smuzhiyun notice and this permission notice appear in supporting
9*4882a593Smuzhiyun documentation, and that the name of Silicon Graphics not be
10*4882a593Smuzhiyun used in advertising or publicity pertaining to distribution
11*4882a593Smuzhiyun of the software without specific prior written permission.
12*4882a593Smuzhiyun Silicon Graphics makes no representation about the suitability
13*4882a593Smuzhiyun of this software for any purpose. It is provided "as is"
14*4882a593Smuzhiyun without any express or implied warranty.
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17*4882a593Smuzhiyun SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18*4882a593Smuzhiyun AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19*4882a593Smuzhiyun GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20*4882a593Smuzhiyun DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21*4882a593Smuzhiyun DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22*4882a593Smuzhiyun OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23*4882a593Smuzhiyun THE USE OR PERFORMANCE OF THIS SOFTWARE.
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun ********************************************************/
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
28*4882a593Smuzhiyun #include <dix-config.h>
29*4882a593Smuzhiyun #endif
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #include <stdio.h>
32*4882a593Smuzhiyun #include <math.h>
33*4882a593Smuzhiyun #include <X11/X.h>
34*4882a593Smuzhiyun #include <X11/Xproto.h>
35*4882a593Smuzhiyun #include <X11/keysym.h>
36*4882a593Smuzhiyun #include "exglobals.h"
37*4882a593Smuzhiyun #include <X11/extensions/XIproto.h>
38*4882a593Smuzhiyun #include "inputstr.h"
39*4882a593Smuzhiyun #include "eventstr.h"
40*4882a593Smuzhiyun #include "inpututils.h"
41*4882a593Smuzhiyun #include <xkbsrv.h>
42*4882a593Smuzhiyun #if !defined(WIN32)
43*4882a593Smuzhiyun #include <sys/time.h>
44*4882a593Smuzhiyun #endif
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun int XkbDfltRepeatDelay = 660;
47*4882a593Smuzhiyun int XkbDfltRepeatInterval = 40;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun #define DFLT_TIMEOUT_CTRLS (XkbAX_KRGMask|XkbStickyKeysMask|XkbMouseKeysMask)
50*4882a593Smuzhiyun #define DFLT_TIMEOUT_OPTS (XkbAX_IndicatorFBMask)
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun unsigned short XkbDfltAccessXTimeout = 120;
53*4882a593Smuzhiyun unsigned int XkbDfltAccessXTimeoutMask = DFLT_TIMEOUT_CTRLS;
54*4882a593Smuzhiyun static unsigned int XkbDfltAccessXTimeoutValues = 0;
55*4882a593Smuzhiyun static unsigned int XkbDfltAccessXTimeoutOptionsMask = DFLT_TIMEOUT_OPTS;
56*4882a593Smuzhiyun static unsigned int XkbDfltAccessXTimeoutOptionsValues = 0;
57*4882a593Smuzhiyun unsigned int XkbDfltAccessXFeedback = XkbAccessXFeedbackMask;
58*4882a593Smuzhiyun unsigned short XkbDfltAccessXOptions =
59*4882a593Smuzhiyun XkbAX_AllOptionsMask & ~(XkbAX_IndicatorFBMask | XkbAX_SKReleaseFBMask |
60*4882a593Smuzhiyun XkbAX_SKRejectFBMask);
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun void
AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi,XkbControlsPtr ctrls)63*4882a593Smuzhiyun AccessXComputeCurveFactor(XkbSrvInfoPtr xkbi, XkbControlsPtr ctrls)
64*4882a593Smuzhiyun {
65*4882a593Smuzhiyun xkbi->mouseKeysCurve = 1.0 + (((double) ctrls->mk_curve) * 0.001);
66*4882a593Smuzhiyun xkbi->mouseKeysCurveFactor = (((double) ctrls->mk_max_speed) /
67*4882a593Smuzhiyun pow((double) ctrls->mk_time_to_max,
68*4882a593Smuzhiyun xkbi->mouseKeysCurve));
69*4882a593Smuzhiyun return;
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun void
AccessXInit(DeviceIntPtr keybd)73*4882a593Smuzhiyun AccessXInit(DeviceIntPtr keybd)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
76*4882a593Smuzhiyun XkbControlsPtr ctrls = xkbi->desc->ctrls;
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun xkbi->shiftKeyCount = 0;
79*4882a593Smuzhiyun xkbi->mouseKeysCounter = 0;
80*4882a593Smuzhiyun xkbi->inactiveKey = 0;
81*4882a593Smuzhiyun xkbi->slowKey = 0;
82*4882a593Smuzhiyun xkbi->repeatKey = 0;
83*4882a593Smuzhiyun xkbi->krgTimerActive = _OFF_TIMER;
84*4882a593Smuzhiyun xkbi->beepType = _BEEP_NONE;
85*4882a593Smuzhiyun xkbi->beepCount = 0;
86*4882a593Smuzhiyun xkbi->mouseKeyTimer = NULL;
87*4882a593Smuzhiyun xkbi->slowKeysTimer = NULL;
88*4882a593Smuzhiyun xkbi->bounceKeysTimer = NULL;
89*4882a593Smuzhiyun xkbi->repeatKeyTimer = NULL;
90*4882a593Smuzhiyun xkbi->krgTimer = NULL;
91*4882a593Smuzhiyun xkbi->beepTimer = NULL;
92*4882a593Smuzhiyun xkbi->checkRepeat = NULL;
93*4882a593Smuzhiyun ctrls->repeat_delay = XkbDfltRepeatDelay;
94*4882a593Smuzhiyun ctrls->repeat_interval = XkbDfltRepeatInterval;
95*4882a593Smuzhiyun ctrls->debounce_delay = 300;
96*4882a593Smuzhiyun ctrls->slow_keys_delay = 300;
97*4882a593Smuzhiyun ctrls->mk_delay = 160;
98*4882a593Smuzhiyun ctrls->mk_interval = 40;
99*4882a593Smuzhiyun ctrls->mk_time_to_max = 30;
100*4882a593Smuzhiyun ctrls->mk_max_speed = 30;
101*4882a593Smuzhiyun ctrls->mk_curve = 500;
102*4882a593Smuzhiyun ctrls->mk_dflt_btn = 1;
103*4882a593Smuzhiyun ctrls->ax_timeout = XkbDfltAccessXTimeout;
104*4882a593Smuzhiyun ctrls->axt_ctrls_mask = XkbDfltAccessXTimeoutMask;
105*4882a593Smuzhiyun ctrls->axt_ctrls_values = XkbDfltAccessXTimeoutValues;
106*4882a593Smuzhiyun ctrls->axt_opts_mask = XkbDfltAccessXTimeoutOptionsMask;
107*4882a593Smuzhiyun ctrls->axt_opts_values = XkbDfltAccessXTimeoutOptionsValues;
108*4882a593Smuzhiyun if (XkbDfltAccessXTimeout)
109*4882a593Smuzhiyun ctrls->enabled_ctrls |= XkbAccessXTimeoutMask;
110*4882a593Smuzhiyun else
111*4882a593Smuzhiyun ctrls->enabled_ctrls &= ~XkbAccessXTimeoutMask;
112*4882a593Smuzhiyun ctrls->enabled_ctrls |= XkbDfltAccessXFeedback;
113*4882a593Smuzhiyun ctrls->ax_options = XkbDfltAccessXOptions;
114*4882a593Smuzhiyun AccessXComputeCurveFactor(xkbi, ctrls);
115*4882a593Smuzhiyun return;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /************************************************************************/
119*4882a593Smuzhiyun /* */
120*4882a593Smuzhiyun /* AccessXKeyboardEvent */
121*4882a593Smuzhiyun /* */
122*4882a593Smuzhiyun /* Generate a synthetic keyboard event. */
123*4882a593Smuzhiyun /* */
124*4882a593Smuzhiyun /************************************************************************/
125*4882a593Smuzhiyun static void
AccessXKeyboardEvent(DeviceIntPtr keybd,int type,BYTE keyCode,Bool isRepeat)126*4882a593Smuzhiyun AccessXKeyboardEvent(DeviceIntPtr keybd, int type, BYTE keyCode, Bool isRepeat)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun DeviceEvent event;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun init_device_event(&event, keybd, GetTimeInMillis(), EVENT_SOURCE_NORMAL);
131*4882a593Smuzhiyun event.type = type;
132*4882a593Smuzhiyun event.detail.key = keyCode;
133*4882a593Smuzhiyun event.key_repeat = isRepeat;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun if (xkbDebugFlags & 0x8) {
136*4882a593Smuzhiyun DebugF("[xkb] AXKE: Key %d %s\n", keyCode,
137*4882a593Smuzhiyun (event.type == ET_KeyPress ? "down" : "up"));
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun XkbProcessKeyboardEvent(&event, keybd);
141*4882a593Smuzhiyun return;
142*4882a593Smuzhiyun } /* AccessXKeyboardEvent */
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun /************************************************************************/
145*4882a593Smuzhiyun /* */
146*4882a593Smuzhiyun /* AccessXKRGTurnOn */
147*4882a593Smuzhiyun /* */
148*4882a593Smuzhiyun /* Turn the keyboard response group on. */
149*4882a593Smuzhiyun /* */
150*4882a593Smuzhiyun /************************************************************************/
151*4882a593Smuzhiyun static void
AccessXKRGTurnOn(DeviceIntPtr dev,CARD16 KRGControl,xkbControlsNotify * pCN)152*4882a593Smuzhiyun AccessXKRGTurnOn(DeviceIntPtr dev, CARD16 KRGControl, xkbControlsNotify * pCN)
153*4882a593Smuzhiyun {
154*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
155*4882a593Smuzhiyun XkbControlsPtr ctrls = xkbi->desc->ctrls;
156*4882a593Smuzhiyun XkbControlsRec old;
157*4882a593Smuzhiyun XkbEventCauseRec cause;
158*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun old = *ctrls;
161*4882a593Smuzhiyun ctrls->enabled_ctrls |= (KRGControl & XkbAX_KRGMask);
162*4882a593Smuzhiyun if (XkbComputeControlsNotify(dev, &old, ctrls, pCN, FALSE))
163*4882a593Smuzhiyun XkbSendControlsNotify(dev, pCN);
164*4882a593Smuzhiyun cause.kc = pCN->keycode;
165*4882a593Smuzhiyun cause.event = pCN->eventType;
166*4882a593Smuzhiyun cause.mjr = pCN->requestMajor;
167*4882a593Smuzhiyun cause.mnr = pCN->requestMinor;
168*4882a593Smuzhiyun sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
169*4882a593Smuzhiyun XkbUpdateIndicators(dev, sli->usesControls, TRUE, NULL, &cause);
170*4882a593Smuzhiyun if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask))
171*4882a593Smuzhiyun XkbDDXAccessXBeep(dev, _BEEP_FEATURE_ON, KRGControl);
172*4882a593Smuzhiyun return;
173*4882a593Smuzhiyun
174*4882a593Smuzhiyun } /* AccessXKRGTurnOn */
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun /************************************************************************/
177*4882a593Smuzhiyun /* */
178*4882a593Smuzhiyun /* AccessXKRGTurnOff */
179*4882a593Smuzhiyun /* */
180*4882a593Smuzhiyun /* Turn the keyboard response group off. */
181*4882a593Smuzhiyun /* */
182*4882a593Smuzhiyun /************************************************************************/
183*4882a593Smuzhiyun static void
AccessXKRGTurnOff(DeviceIntPtr dev,xkbControlsNotify * pCN)184*4882a593Smuzhiyun AccessXKRGTurnOff(DeviceIntPtr dev, xkbControlsNotify * pCN)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
187*4882a593Smuzhiyun XkbControlsPtr ctrls = xkbi->desc->ctrls;
188*4882a593Smuzhiyun XkbControlsRec old;
189*4882a593Smuzhiyun XkbEventCauseRec cause;
190*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun old = *ctrls;
193*4882a593Smuzhiyun ctrls->enabled_ctrls &= ~XkbAX_KRGMask;
194*4882a593Smuzhiyun if (XkbComputeControlsNotify(dev, &old, ctrls, pCN, FALSE))
195*4882a593Smuzhiyun XkbSendControlsNotify(dev, pCN);
196*4882a593Smuzhiyun cause.kc = pCN->keycode;
197*4882a593Smuzhiyun cause.event = pCN->eventType;
198*4882a593Smuzhiyun cause.mjr = pCN->requestMajor;
199*4882a593Smuzhiyun cause.mnr = pCN->requestMinor;
200*4882a593Smuzhiyun sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
201*4882a593Smuzhiyun XkbUpdateIndicators(dev, sli->usesControls, TRUE, NULL, &cause);
202*4882a593Smuzhiyun if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask)) {
203*4882a593Smuzhiyun unsigned changes = old.enabled_ctrls ^ ctrls->enabled_ctrls;
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun XkbDDXAccessXBeep(dev, _BEEP_FEATURE_OFF, changes);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun return;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun } /* AccessXKRGTurnOff */
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun /************************************************************************/
212*4882a593Smuzhiyun /* */
213*4882a593Smuzhiyun /* AccessXStickyKeysTurnOn */
214*4882a593Smuzhiyun /* */
215*4882a593Smuzhiyun /* Turn StickyKeys on. */
216*4882a593Smuzhiyun /* */
217*4882a593Smuzhiyun /************************************************************************/
218*4882a593Smuzhiyun static void
AccessXStickyKeysTurnOn(DeviceIntPtr dev,xkbControlsNotify * pCN)219*4882a593Smuzhiyun AccessXStickyKeysTurnOn(DeviceIntPtr dev, xkbControlsNotify * pCN)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
222*4882a593Smuzhiyun XkbControlsPtr ctrls = xkbi->desc->ctrls;
223*4882a593Smuzhiyun XkbControlsRec old;
224*4882a593Smuzhiyun XkbEventCauseRec cause;
225*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun old = *ctrls;
228*4882a593Smuzhiyun ctrls->enabled_ctrls |= XkbStickyKeysMask;
229*4882a593Smuzhiyun xkbi->shiftKeyCount = 0;
230*4882a593Smuzhiyun if (XkbComputeControlsNotify(dev, &old, ctrls, pCN, FALSE))
231*4882a593Smuzhiyun XkbSendControlsNotify(dev, pCN);
232*4882a593Smuzhiyun cause.kc = pCN->keycode;
233*4882a593Smuzhiyun cause.event = pCN->eventType;
234*4882a593Smuzhiyun cause.mjr = pCN->requestMajor;
235*4882a593Smuzhiyun cause.mnr = pCN->requestMinor;
236*4882a593Smuzhiyun sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
237*4882a593Smuzhiyun XkbUpdateIndicators(dev, sli->usesControls, TRUE, NULL, &cause);
238*4882a593Smuzhiyun if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask)) {
239*4882a593Smuzhiyun XkbDDXAccessXBeep(dev, _BEEP_FEATURE_ON, XkbStickyKeysMask);
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun return;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun } /* AccessXStickyKeysTurnOn */
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun /************************************************************************/
246*4882a593Smuzhiyun /* */
247*4882a593Smuzhiyun /* AccessXStickyKeysTurnOff */
248*4882a593Smuzhiyun /* */
249*4882a593Smuzhiyun /* Turn StickyKeys off. */
250*4882a593Smuzhiyun /* */
251*4882a593Smuzhiyun /************************************************************************/
252*4882a593Smuzhiyun static void
AccessXStickyKeysTurnOff(DeviceIntPtr dev,xkbControlsNotify * pCN)253*4882a593Smuzhiyun AccessXStickyKeysTurnOff(DeviceIntPtr dev, xkbControlsNotify * pCN)
254*4882a593Smuzhiyun {
255*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
256*4882a593Smuzhiyun XkbControlsPtr ctrls = xkbi->desc->ctrls;
257*4882a593Smuzhiyun XkbControlsRec old;
258*4882a593Smuzhiyun XkbEventCauseRec cause;
259*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun old = *ctrls;
262*4882a593Smuzhiyun ctrls->enabled_ctrls &= ~XkbStickyKeysMask;
263*4882a593Smuzhiyun xkbi->shiftKeyCount = 0;
264*4882a593Smuzhiyun if (XkbComputeControlsNotify(dev, &old, ctrls, pCN, FALSE))
265*4882a593Smuzhiyun XkbSendControlsNotify(dev, pCN);
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun cause.kc = pCN->keycode;
268*4882a593Smuzhiyun cause.event = pCN->eventType;
269*4882a593Smuzhiyun cause.mjr = pCN->requestMajor;
270*4882a593Smuzhiyun cause.mnr = pCN->requestMinor;
271*4882a593Smuzhiyun sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
272*4882a593Smuzhiyun XkbUpdateIndicators(dev, sli->usesControls, TRUE, NULL, &cause);
273*4882a593Smuzhiyun if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask)) {
274*4882a593Smuzhiyun XkbDDXAccessXBeep(dev, _BEEP_FEATURE_OFF, XkbStickyKeysMask);
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun #ifndef NO_CLEAR_LATCHES_FOR_STICKY_KEYS_OFF
277*4882a593Smuzhiyun XkbClearAllLatchesAndLocks(dev, xkbi, FALSE, &cause);
278*4882a593Smuzhiyun #endif
279*4882a593Smuzhiyun return;
280*4882a593Smuzhiyun } /* AccessXStickyKeysTurnOff */
281*4882a593Smuzhiyun
282*4882a593Smuzhiyun static CARD32
AccessXKRGExpire(OsTimerPtr timer,CARD32 now,void * arg)283*4882a593Smuzhiyun AccessXKRGExpire(OsTimerPtr timer, CARD32 now, void *arg)
284*4882a593Smuzhiyun {
285*4882a593Smuzhiyun xkbControlsNotify cn;
286*4882a593Smuzhiyun DeviceIntPtr dev = arg;
287*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
288*4882a593Smuzhiyun
289*4882a593Smuzhiyun if (xkbi->krgTimerActive == _KRG_WARN_TIMER) {
290*4882a593Smuzhiyun XkbDDXAccessXBeep(dev, _BEEP_SLOW_WARN, XkbStickyKeysMask);
291*4882a593Smuzhiyun xkbi->krgTimerActive = _KRG_TIMER;
292*4882a593Smuzhiyun return 4000;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun xkbi->krgTimerActive = _OFF_TIMER;
295*4882a593Smuzhiyun cn.keycode = xkbi->slowKeyEnableKey;
296*4882a593Smuzhiyun cn.eventType = KeyPress;
297*4882a593Smuzhiyun cn.requestMajor = 0;
298*4882a593Smuzhiyun cn.requestMinor = 0;
299*4882a593Smuzhiyun if (xkbi->desc->ctrls->enabled_ctrls & XkbSlowKeysMask) {
300*4882a593Smuzhiyun AccessXKRGTurnOff(dev, &cn);
301*4882a593Smuzhiyun LogMessage(X_INFO, "XKB SlowKeys are disabled.\n");
302*4882a593Smuzhiyun }
303*4882a593Smuzhiyun else {
304*4882a593Smuzhiyun AccessXKRGTurnOn(dev, XkbSlowKeysMask, &cn);
305*4882a593Smuzhiyun LogMessage(X_INFO, "XKB SlowKeys are now enabled. Hold shift to disable.\n");
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun xkbi->slowKeyEnableKey = 0;
309*4882a593Smuzhiyun return 0;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun static CARD32
AccessXRepeatKeyExpire(OsTimerPtr timer,CARD32 now,void * arg)313*4882a593Smuzhiyun AccessXRepeatKeyExpire(OsTimerPtr timer, CARD32 now, void *arg)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun DeviceIntPtr dev = (DeviceIntPtr) arg;
316*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun if (xkbi->repeatKey == 0)
319*4882a593Smuzhiyun return 0;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun if (xkbi->checkRepeat == NULL || xkbi->checkRepeat (dev, xkbi, xkbi->repeatKey))
322*4882a593Smuzhiyun AccessXKeyboardEvent(dev, ET_KeyPress, xkbi->repeatKey, TRUE);
323*4882a593Smuzhiyun
324*4882a593Smuzhiyun return xkbi->desc->ctrls->repeat_interval;
325*4882a593Smuzhiyun }
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun void
AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi,KeyCode key)328*4882a593Smuzhiyun AccessXCancelRepeatKey(XkbSrvInfoPtr xkbi, KeyCode key)
329*4882a593Smuzhiyun {
330*4882a593Smuzhiyun if (xkbi->repeatKey == key)
331*4882a593Smuzhiyun xkbi->repeatKey = 0;
332*4882a593Smuzhiyun return;
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun static CARD32
AccessXSlowKeyExpire(OsTimerPtr timer,CARD32 now,void * arg)336*4882a593Smuzhiyun AccessXSlowKeyExpire(OsTimerPtr timer, CARD32 now, void *arg)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun DeviceIntPtr keybd;
339*4882a593Smuzhiyun XkbSrvInfoPtr xkbi;
340*4882a593Smuzhiyun XkbDescPtr xkb;
341*4882a593Smuzhiyun XkbControlsPtr ctrls;
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun keybd = (DeviceIntPtr) arg;
344*4882a593Smuzhiyun xkbi = keybd->key->xkbInfo;
345*4882a593Smuzhiyun xkb = xkbi->desc;
346*4882a593Smuzhiyun ctrls = xkb->ctrls;
347*4882a593Smuzhiyun if (xkbi->slowKey != 0) {
348*4882a593Smuzhiyun xkbAccessXNotify ev;
349*4882a593Smuzhiyun KeySym *sym = XkbKeySymsPtr(xkb, xkbi->slowKey);
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun ev.detail = XkbAXN_SKAccept;
352*4882a593Smuzhiyun ev.keycode = xkbi->slowKey;
353*4882a593Smuzhiyun ev.slowKeysDelay = ctrls->slow_keys_delay;
354*4882a593Smuzhiyun ev.debounceDelay = ctrls->debounce_delay;
355*4882a593Smuzhiyun XkbSendAccessXNotify(keybd, &ev);
356*4882a593Smuzhiyun if (XkbAX_NeedFeedback(ctrls, XkbAX_SKAcceptFBMask))
357*4882a593Smuzhiyun XkbDDXAccessXBeep(keybd, _BEEP_SLOW_ACCEPT, XkbSlowKeysMask);
358*4882a593Smuzhiyun AccessXKeyboardEvent(keybd, ET_KeyPress, xkbi->slowKey, FALSE);
359*4882a593Smuzhiyun /* check for magic sequences */
360*4882a593Smuzhiyun if ((ctrls->enabled_ctrls & XkbAccessXKeysMask) &&
361*4882a593Smuzhiyun ((sym[0] == XK_Shift_R) || (sym[0] == XK_Shift_L)))
362*4882a593Smuzhiyun xkbi->shiftKeyCount++;
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* Start repeating if necessary. Stop autorepeating if the user
365*4882a593Smuzhiyun * presses a non-modifier key that doesn't autorepeat.
366*4882a593Smuzhiyun */
367*4882a593Smuzhiyun if (keybd->kbdfeed->ctrl.autoRepeat &&
368*4882a593Smuzhiyun ((xkbi->slowKey != xkbi->mouseKey) || (!xkbi->mouseKeysAccel)) &&
369*4882a593Smuzhiyun (ctrls->enabled_ctrls & XkbRepeatKeysMask)) {
370*4882a593Smuzhiyun if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats, xkbi->slowKey)) {
371*4882a593Smuzhiyun xkbi->repeatKey = xkbi->slowKey;
372*4882a593Smuzhiyun xkbi->repeatKeyTimer = TimerSet(xkbi->repeatKeyTimer,
373*4882a593Smuzhiyun 0, ctrls->repeat_delay,
374*4882a593Smuzhiyun AccessXRepeatKeyExpire,
375*4882a593Smuzhiyun (void *) keybd);
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun return 0;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun
382*4882a593Smuzhiyun static CARD32
AccessXBounceKeyExpire(OsTimerPtr timer,CARD32 now,void * arg)383*4882a593Smuzhiyun AccessXBounceKeyExpire(OsTimerPtr timer, CARD32 now, void *arg)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = ((DeviceIntPtr) arg)->key->xkbInfo;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun xkbi->inactiveKey = 0;
388*4882a593Smuzhiyun return 0;
389*4882a593Smuzhiyun }
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun static CARD32
AccessXTimeoutExpire(OsTimerPtr timer,CARD32 now,void * arg)392*4882a593Smuzhiyun AccessXTimeoutExpire(OsTimerPtr timer, CARD32 now, void *arg)
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun DeviceIntPtr dev = (DeviceIntPtr) arg;
395*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = dev->key->xkbInfo;
396*4882a593Smuzhiyun XkbControlsPtr ctrls = xkbi->desc->ctrls;
397*4882a593Smuzhiyun XkbControlsRec old;
398*4882a593Smuzhiyun xkbControlsNotify cn;
399*4882a593Smuzhiyun XkbEventCauseRec cause;
400*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun if (xkbi->lastPtrEventTime) {
403*4882a593Smuzhiyun unsigned timeToWait = (ctrls->ax_timeout * 1000);
404*4882a593Smuzhiyun unsigned timeElapsed = (now - xkbi->lastPtrEventTime);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun if (timeToWait > timeElapsed)
407*4882a593Smuzhiyun return timeToWait - timeElapsed;
408*4882a593Smuzhiyun }
409*4882a593Smuzhiyun old = *ctrls;
410*4882a593Smuzhiyun xkbi->shiftKeyCount = 0;
411*4882a593Smuzhiyun ctrls->enabled_ctrls &= ~ctrls->axt_ctrls_mask;
412*4882a593Smuzhiyun ctrls->enabled_ctrls |= (ctrls->axt_ctrls_values & ctrls->axt_ctrls_mask);
413*4882a593Smuzhiyun if (ctrls->axt_opts_mask) {
414*4882a593Smuzhiyun ctrls->ax_options &= ~ctrls->axt_opts_mask;
415*4882a593Smuzhiyun ctrls->ax_options |= (ctrls->axt_opts_values & ctrls->axt_opts_mask);
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun if (XkbComputeControlsNotify(dev, &old, ctrls, &cn, FALSE)) {
418*4882a593Smuzhiyun cn.keycode = 0;
419*4882a593Smuzhiyun cn.eventType = 0;
420*4882a593Smuzhiyun cn.requestMajor = 0;
421*4882a593Smuzhiyun cn.requestMinor = 0;
422*4882a593Smuzhiyun XkbSendControlsNotify(dev, &cn);
423*4882a593Smuzhiyun }
424*4882a593Smuzhiyun XkbSetCauseUnknown(&cause);
425*4882a593Smuzhiyun sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
426*4882a593Smuzhiyun XkbUpdateIndicators(dev, sli->usesControls, TRUE, NULL, &cause);
427*4882a593Smuzhiyun if (ctrls->ax_options != old.ax_options) {
428*4882a593Smuzhiyun unsigned set, cleared, bell;
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun set = ctrls->ax_options & (~old.ax_options);
431*4882a593Smuzhiyun cleared = (~ctrls->ax_options) & old.ax_options;
432*4882a593Smuzhiyun if (set && cleared)
433*4882a593Smuzhiyun bell = _BEEP_FEATURE_CHANGE;
434*4882a593Smuzhiyun else if (set)
435*4882a593Smuzhiyun bell = _BEEP_FEATURE_ON;
436*4882a593Smuzhiyun else
437*4882a593Smuzhiyun bell = _BEEP_FEATURE_OFF;
438*4882a593Smuzhiyun XkbDDXAccessXBeep(dev, bell, XkbAccessXTimeoutMask);
439*4882a593Smuzhiyun }
440*4882a593Smuzhiyun xkbi->krgTimerActive = _OFF_TIMER;
441*4882a593Smuzhiyun return 0;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun /************************************************************************/
445*4882a593Smuzhiyun /* */
446*4882a593Smuzhiyun /* AccessXFilterPressEvent */
447*4882a593Smuzhiyun /* */
448*4882a593Smuzhiyun /* Filter events before they get any further if SlowKeys is turned on. */
449*4882a593Smuzhiyun /* In addition, this routine handles the ever so popular magic key */
450*4882a593Smuzhiyun /* acts for turning various accessibility features on/off. */
451*4882a593Smuzhiyun /* */
452*4882a593Smuzhiyun /* Returns TRUE if this routine has discarded the event. */
453*4882a593Smuzhiyun /* Returns FALSE if the event needs further processing. */
454*4882a593Smuzhiyun /* */
455*4882a593Smuzhiyun /************************************************************************/
456*4882a593Smuzhiyun Bool
AccessXFilterPressEvent(DeviceEvent * event,DeviceIntPtr keybd)457*4882a593Smuzhiyun AccessXFilterPressEvent(DeviceEvent *event, DeviceIntPtr keybd)
458*4882a593Smuzhiyun {
459*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
460*4882a593Smuzhiyun XkbControlsPtr ctrls = xkbi->desc->ctrls;
461*4882a593Smuzhiyun Bool ignoreKeyEvent = FALSE;
462*4882a593Smuzhiyun KeyCode key = event->detail.key;
463*4882a593Smuzhiyun KeySym *sym = XkbKeySymsPtr(xkbi->desc, key);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun if (ctrls->enabled_ctrls & XkbAccessXKeysMask) {
466*4882a593Smuzhiyun /* check for magic sequences */
467*4882a593Smuzhiyun if ((sym[0] == XK_Shift_R) || (sym[0] == XK_Shift_L)) {
468*4882a593Smuzhiyun xkbi->slowKeyEnableKey = key;
469*4882a593Smuzhiyun if (XkbAX_NeedFeedback(ctrls, XkbAX_SlowWarnFBMask)) {
470*4882a593Smuzhiyun xkbi->krgTimerActive = _KRG_WARN_TIMER;
471*4882a593Smuzhiyun xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 4000,
472*4882a593Smuzhiyun AccessXKRGExpire, (void *) keybd);
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun else {
475*4882a593Smuzhiyun xkbi->krgTimerActive = _KRG_TIMER;
476*4882a593Smuzhiyun xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 8000,
477*4882a593Smuzhiyun AccessXKRGExpire, (void *) keybd);
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun if (!(ctrls->enabled_ctrls & XkbSlowKeysMask)) {
480*4882a593Smuzhiyun CARD32 now = GetTimeInMillis();
481*4882a593Smuzhiyun
482*4882a593Smuzhiyun if ((now - xkbi->lastShiftEventTime) > 15000)
483*4882a593Smuzhiyun xkbi->shiftKeyCount = 1;
484*4882a593Smuzhiyun else
485*4882a593Smuzhiyun xkbi->shiftKeyCount++;
486*4882a593Smuzhiyun xkbi->lastShiftEventTime = now;
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun else {
490*4882a593Smuzhiyun if (xkbi->krgTimerActive) {
491*4882a593Smuzhiyun xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL);
492*4882a593Smuzhiyun xkbi->krgTimerActive = _OFF_TIMER;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun }
495*4882a593Smuzhiyun }
496*4882a593Smuzhiyun
497*4882a593Smuzhiyun /* Don't transmit the KeyPress if SlowKeys is turned on;
498*4882a593Smuzhiyun * The wakeup handler will synthesize one for us if the user
499*4882a593Smuzhiyun * has held the key long enough.
500*4882a593Smuzhiyun */
501*4882a593Smuzhiyun if (ctrls->enabled_ctrls & XkbSlowKeysMask) {
502*4882a593Smuzhiyun xkbAccessXNotify ev;
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun /* If key was already pressed, ignore subsequent press events
505*4882a593Smuzhiyun * from the server's autorepeat
506*4882a593Smuzhiyun */
507*4882a593Smuzhiyun if (xkbi->slowKey == key)
508*4882a593Smuzhiyun return TRUE;
509*4882a593Smuzhiyun ev.detail = XkbAXN_SKPress;
510*4882a593Smuzhiyun ev.keycode = key;
511*4882a593Smuzhiyun ev.slowKeysDelay = ctrls->slow_keys_delay;
512*4882a593Smuzhiyun ev.debounceDelay = ctrls->debounce_delay;
513*4882a593Smuzhiyun XkbSendAccessXNotify(keybd, &ev);
514*4882a593Smuzhiyun if (XkbAX_NeedFeedback(ctrls, XkbAX_SKPressFBMask))
515*4882a593Smuzhiyun XkbDDXAccessXBeep(keybd, _BEEP_SLOW_PRESS, XkbSlowKeysMask);
516*4882a593Smuzhiyun xkbi->slowKey = key;
517*4882a593Smuzhiyun xkbi->slowKeysTimer = TimerSet(xkbi->slowKeysTimer,
518*4882a593Smuzhiyun 0, ctrls->slow_keys_delay,
519*4882a593Smuzhiyun AccessXSlowKeyExpire, (void *) keybd);
520*4882a593Smuzhiyun ignoreKeyEvent = TRUE;
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun /* Don't transmit the KeyPress if BounceKeys is turned on
524*4882a593Smuzhiyun * and the user pressed the same key within a given time period
525*4882a593Smuzhiyun * from the last release.
526*4882a593Smuzhiyun */
527*4882a593Smuzhiyun else if ((ctrls->enabled_ctrls & XkbBounceKeysMask) &&
528*4882a593Smuzhiyun (key == xkbi->inactiveKey)) {
529*4882a593Smuzhiyun if (XkbAX_NeedFeedback(ctrls, XkbAX_BKRejectFBMask))
530*4882a593Smuzhiyun XkbDDXAccessXBeep(keybd, _BEEP_BOUNCE_REJECT, XkbBounceKeysMask);
531*4882a593Smuzhiyun ignoreKeyEvent = TRUE;
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun
534*4882a593Smuzhiyun /* Start repeating if necessary. Stop autorepeating if the user
535*4882a593Smuzhiyun * presses a non-modifier key that doesn't autorepeat.
536*4882a593Smuzhiyun */
537*4882a593Smuzhiyun if (XkbDDXUsesSoftRepeat(keybd)) {
538*4882a593Smuzhiyun if ((keybd->kbdfeed->ctrl.autoRepeat) &&
539*4882a593Smuzhiyun ((ctrls->enabled_ctrls & (XkbSlowKeysMask | XkbRepeatKeysMask)) ==
540*4882a593Smuzhiyun XkbRepeatKeysMask)) {
541*4882a593Smuzhiyun if (BitIsOn(keybd->kbdfeed->ctrl.autoRepeats, key)) {
542*4882a593Smuzhiyun if (xkbDebugFlags & 0x10)
543*4882a593Smuzhiyun DebugF("Starting software autorepeat...\n");
544*4882a593Smuzhiyun if (xkbi->repeatKey == key)
545*4882a593Smuzhiyun ignoreKeyEvent = TRUE;
546*4882a593Smuzhiyun else {
547*4882a593Smuzhiyun xkbi->repeatKey = key;
548*4882a593Smuzhiyun xkbi->repeatKeyTimer = TimerSet(xkbi->repeatKeyTimer,
549*4882a593Smuzhiyun 0, ctrls->repeat_delay,
550*4882a593Smuzhiyun AccessXRepeatKeyExpire,
551*4882a593Smuzhiyun (void *) keybd);
552*4882a593Smuzhiyun }
553*4882a593Smuzhiyun }
554*4882a593Smuzhiyun }
555*4882a593Smuzhiyun }
556*4882a593Smuzhiyun
557*4882a593Smuzhiyun /* Check for two keys being pressed at the same time. This section
558*4882a593Smuzhiyun * essentially says the following:
559*4882a593Smuzhiyun *
560*4882a593Smuzhiyun * If StickyKeys is on, and a modifier is currently being held down,
561*4882a593Smuzhiyun * and one of the following is true: the current key is not a modifier
562*4882a593Smuzhiyun * or the currentKey is a modifier, but not the only modifier being
563*4882a593Smuzhiyun * held down, turn StickyKeys off if the TwoKeys off ctrl is set.
564*4882a593Smuzhiyun */
565*4882a593Smuzhiyun if ((ctrls->enabled_ctrls & XkbStickyKeysMask) &&
566*4882a593Smuzhiyun (xkbi->state.base_mods != 0) &&
567*4882a593Smuzhiyun (XkbAX_NeedOption(ctrls, XkbAX_TwoKeysMask))) {
568*4882a593Smuzhiyun xkbControlsNotify cn;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun cn.keycode = key;
571*4882a593Smuzhiyun cn.eventType = KeyPress;
572*4882a593Smuzhiyun cn.requestMajor = 0;
573*4882a593Smuzhiyun cn.requestMinor = 0;
574*4882a593Smuzhiyun AccessXStickyKeysTurnOff(keybd, &cn);
575*4882a593Smuzhiyun }
576*4882a593Smuzhiyun
577*4882a593Smuzhiyun if (!ignoreKeyEvent)
578*4882a593Smuzhiyun XkbProcessKeyboardEvent(event, keybd);
579*4882a593Smuzhiyun return ignoreKeyEvent;
580*4882a593Smuzhiyun } /* AccessXFilterPressEvent */
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun /************************************************************************/
583*4882a593Smuzhiyun /* */
584*4882a593Smuzhiyun /* AccessXFilterReleaseEvent */
585*4882a593Smuzhiyun /* */
586*4882a593Smuzhiyun /* Filter events before they get any further if SlowKeys is turned on. */
587*4882a593Smuzhiyun /* In addition, this routine handles the ever so popular magic key */
588*4882a593Smuzhiyun /* acts for turning various accessibility features on/off. */
589*4882a593Smuzhiyun /* */
590*4882a593Smuzhiyun /* Returns TRUE if this routine has discarded the event. */
591*4882a593Smuzhiyun /* Returns FALSE if the event needs further processing. */
592*4882a593Smuzhiyun /* */
593*4882a593Smuzhiyun /************************************************************************/
594*4882a593Smuzhiyun Bool
AccessXFilterReleaseEvent(DeviceEvent * event,DeviceIntPtr keybd)595*4882a593Smuzhiyun AccessXFilterReleaseEvent(DeviceEvent *event, DeviceIntPtr keybd)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = keybd->key->xkbInfo;
598*4882a593Smuzhiyun XkbControlsPtr ctrls = xkbi->desc->ctrls;
599*4882a593Smuzhiyun KeyCode key = event->detail.key;
600*4882a593Smuzhiyun Bool ignoreKeyEvent = FALSE;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun /* Don't transmit the KeyRelease if BounceKeys is on and
603*4882a593Smuzhiyun * this is the release of a key that was ignored due to
604*4882a593Smuzhiyun * BounceKeys.
605*4882a593Smuzhiyun */
606*4882a593Smuzhiyun if (ctrls->enabled_ctrls & XkbBounceKeysMask) {
607*4882a593Smuzhiyun if ((key != xkbi->mouseKey) && (!BitIsOn(keybd->key->down, key)))
608*4882a593Smuzhiyun ignoreKeyEvent = TRUE;
609*4882a593Smuzhiyun xkbi->inactiveKey = key;
610*4882a593Smuzhiyun xkbi->bounceKeysTimer = TimerSet(xkbi->bounceKeysTimer, 0,
611*4882a593Smuzhiyun ctrls->debounce_delay,
612*4882a593Smuzhiyun AccessXBounceKeyExpire,
613*4882a593Smuzhiyun (void *) keybd);
614*4882a593Smuzhiyun }
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun /* Don't transmit the KeyRelease if SlowKeys is turned on and
617*4882a593Smuzhiyun * the user didn't hold the key long enough. We know we passed
618*4882a593Smuzhiyun * the key if the down bit was set by CoreProcessKeyboadEvent.
619*4882a593Smuzhiyun */
620*4882a593Smuzhiyun if (ctrls->enabled_ctrls & XkbSlowKeysMask) {
621*4882a593Smuzhiyun xkbAccessXNotify ev;
622*4882a593Smuzhiyun unsigned beep_type;
623*4882a593Smuzhiyun unsigned mask;
624*4882a593Smuzhiyun
625*4882a593Smuzhiyun ev.keycode = key;
626*4882a593Smuzhiyun ev.slowKeysDelay = ctrls->slow_keys_delay;
627*4882a593Smuzhiyun ev.debounceDelay = ctrls->debounce_delay;
628*4882a593Smuzhiyun if (BitIsOn(keybd->key->down, key) || (xkbi->mouseKey == key)) {
629*4882a593Smuzhiyun ev.detail = XkbAXN_SKRelease;
630*4882a593Smuzhiyun beep_type = _BEEP_SLOW_RELEASE;
631*4882a593Smuzhiyun mask = XkbAX_SKReleaseFBMask;
632*4882a593Smuzhiyun }
633*4882a593Smuzhiyun else {
634*4882a593Smuzhiyun ev.detail = XkbAXN_SKReject;
635*4882a593Smuzhiyun beep_type = _BEEP_SLOW_REJECT;
636*4882a593Smuzhiyun mask = XkbAX_SKRejectFBMask;
637*4882a593Smuzhiyun ignoreKeyEvent = TRUE;
638*4882a593Smuzhiyun }
639*4882a593Smuzhiyun XkbSendAccessXNotify(keybd, &ev);
640*4882a593Smuzhiyun if (XkbAX_NeedFeedback(ctrls, mask)) {
641*4882a593Smuzhiyun XkbDDXAccessXBeep(keybd, beep_type, XkbSlowKeysMask);
642*4882a593Smuzhiyun }
643*4882a593Smuzhiyun if (xkbi->slowKey == key)
644*4882a593Smuzhiyun xkbi->slowKey = 0;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun /* Stop Repeating if the user releases the key that is currently
648*4882a593Smuzhiyun * repeating.
649*4882a593Smuzhiyun */
650*4882a593Smuzhiyun if (xkbi->repeatKey == key) {
651*4882a593Smuzhiyun xkbi->repeatKey = 0;
652*4882a593Smuzhiyun }
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun if ((ctrls->enabled_ctrls & XkbAccessXTimeoutMask) &&
655*4882a593Smuzhiyun (ctrls->ax_timeout > 0)) {
656*4882a593Smuzhiyun xkbi->lastPtrEventTime = 0;
657*4882a593Smuzhiyun xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0,
658*4882a593Smuzhiyun ctrls->ax_timeout * 1000,
659*4882a593Smuzhiyun AccessXTimeoutExpire, (void *) keybd);
660*4882a593Smuzhiyun xkbi->krgTimerActive = _ALL_TIMEOUT_TIMER;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun else if (xkbi->krgTimerActive != _OFF_TIMER) {
663*4882a593Smuzhiyun xkbi->krgTimer = TimerSet(xkbi->krgTimer, 0, 0, NULL, NULL);
664*4882a593Smuzhiyun xkbi->krgTimerActive = _OFF_TIMER;
665*4882a593Smuzhiyun }
666*4882a593Smuzhiyun
667*4882a593Smuzhiyun /* Keep track of how many times the Shift key has been pressed.
668*4882a593Smuzhiyun * If it has been pressed and released 5 times in a row, toggle
669*4882a593Smuzhiyun * the state of StickyKeys.
670*4882a593Smuzhiyun */
671*4882a593Smuzhiyun if ((!ignoreKeyEvent) && (xkbi->shiftKeyCount)) {
672*4882a593Smuzhiyun KeySym *pSym = XkbKeySymsPtr(xkbi->desc, key);
673*4882a593Smuzhiyun
674*4882a593Smuzhiyun if ((pSym[0] != XK_Shift_L) && (pSym[0] != XK_Shift_R)) {
675*4882a593Smuzhiyun xkbi->shiftKeyCount = 0;
676*4882a593Smuzhiyun }
677*4882a593Smuzhiyun else if (xkbi->shiftKeyCount >= 5) {
678*4882a593Smuzhiyun xkbControlsNotify cn;
679*4882a593Smuzhiyun
680*4882a593Smuzhiyun cn.keycode = key;
681*4882a593Smuzhiyun cn.eventType = KeyPress;
682*4882a593Smuzhiyun cn.requestMajor = 0;
683*4882a593Smuzhiyun cn.requestMinor = 0;
684*4882a593Smuzhiyun if (ctrls->enabled_ctrls & XkbStickyKeysMask)
685*4882a593Smuzhiyun AccessXStickyKeysTurnOff(keybd, &cn);
686*4882a593Smuzhiyun else
687*4882a593Smuzhiyun AccessXStickyKeysTurnOn(keybd, &cn);
688*4882a593Smuzhiyun xkbi->shiftKeyCount = 0;
689*4882a593Smuzhiyun }
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun if (!ignoreKeyEvent)
693*4882a593Smuzhiyun XkbProcessKeyboardEvent(event, keybd);
694*4882a593Smuzhiyun return ignoreKeyEvent;
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun } /* AccessXFilterReleaseEvent */
697*4882a593Smuzhiyun
698*4882a593Smuzhiyun /************************************************************************/
699*4882a593Smuzhiyun /* */
700*4882a593Smuzhiyun /* ProcessPointerEvent */
701*4882a593Smuzhiyun /* */
702*4882a593Smuzhiyun /* This routine merely sets the shiftKeyCount and clears the keyboard */
703*4882a593Smuzhiyun /* response group timer (if necessary) on a mouse event. This is so */
704*4882a593Smuzhiyun /* multiple shifts with just the mouse and shift-drags with the mouse */
705*4882a593Smuzhiyun /* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/
706*4882a593Smuzhiyun /* */
707*4882a593Smuzhiyun /************************************************************************/
708*4882a593Smuzhiyun extern int xkbDevicePrivateIndex;
709*4882a593Smuzhiyun void
ProcessPointerEvent(InternalEvent * ev,DeviceIntPtr mouse)710*4882a593Smuzhiyun ProcessPointerEvent(InternalEvent *ev, DeviceIntPtr mouse)
711*4882a593Smuzhiyun {
712*4882a593Smuzhiyun DeviceIntPtr dev;
713*4882a593Smuzhiyun XkbSrvInfoPtr xkbi = NULL;
714*4882a593Smuzhiyun unsigned changed = 0;
715*4882a593Smuzhiyun ProcessInputProc backupproc;
716*4882a593Smuzhiyun xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(mouse);
717*4882a593Smuzhiyun DeviceEvent *event = &ev->device_event;
718*4882a593Smuzhiyun
719*4882a593Smuzhiyun dev = IsFloating(mouse) ? mouse : GetMaster(mouse, MASTER_KEYBOARD);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun if (dev && dev->key) {
722*4882a593Smuzhiyun xkbi = dev->key->xkbInfo;
723*4882a593Smuzhiyun xkbi->shiftKeyCount = 0;
724*4882a593Smuzhiyun xkbi->lastPtrEventTime = event->time;
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun
727*4882a593Smuzhiyun if (event->type == ET_ButtonPress) {
728*4882a593Smuzhiyun changed |= XkbPointerButtonMask;
729*4882a593Smuzhiyun }
730*4882a593Smuzhiyun else if (event->type == ET_ButtonRelease) {
731*4882a593Smuzhiyun if (IsMaster(dev)) {
732*4882a593Smuzhiyun DeviceIntPtr source;
733*4882a593Smuzhiyun int rc;
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun rc = dixLookupDevice(&source, event->sourceid, serverClient,
736*4882a593Smuzhiyun DixWriteAccess);
737*4882a593Smuzhiyun if (rc != Success)
738*4882a593Smuzhiyun ErrorF("[xkb] bad sourceid '%d' on button release event.\n",
739*4882a593Smuzhiyun event->sourceid);
740*4882a593Smuzhiyun else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER))) {
741*4882a593Smuzhiyun DeviceIntPtr xtest_device;
742*4882a593Smuzhiyun
743*4882a593Smuzhiyun xtest_device = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
744*4882a593Smuzhiyun if (button_is_down(xtest_device, ev->device_event.detail.button, BUTTON_PROCESSED))
745*4882a593Smuzhiyun XkbFakeDeviceButton(dev, FALSE, event->detail.key);
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun }
748*4882a593Smuzhiyun
749*4882a593Smuzhiyun if (xkbi)
750*4882a593Smuzhiyun xkbi->lockedPtrButtons &= ~(1 << (event->detail.key & 0x7));
751*4882a593Smuzhiyun
752*4882a593Smuzhiyun changed |= XkbPointerButtonMask;
753*4882a593Smuzhiyun }
754*4882a593Smuzhiyun
755*4882a593Smuzhiyun UNWRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, backupproc);
756*4882a593Smuzhiyun mouse->public.processInputProc(ev, mouse);
757*4882a593Smuzhiyun COND_WRAP_PROCESS_INPUT_PROC(mouse, xkbPrivPtr, backupproc, xkbUnwrapProc);
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun if (!xkbi)
760*4882a593Smuzhiyun return;
761*4882a593Smuzhiyun
762*4882a593Smuzhiyun xkbi->state.ptr_buttons = (mouse->button) ? mouse->button->state : 0;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun /* clear any latched modifiers */
765*4882a593Smuzhiyun if (xkbi->state.latched_mods && (event->type == ET_ButtonRelease)) {
766*4882a593Smuzhiyun unsigned changed_leds;
767*4882a593Smuzhiyun XkbStateRec oldState;
768*4882a593Smuzhiyun XkbSrvLedInfoPtr sli;
769*4882a593Smuzhiyun
770*4882a593Smuzhiyun sli = XkbFindSrvLedInfo(dev, XkbDfltXIClass, XkbDfltXIId, 0);
771*4882a593Smuzhiyun oldState = xkbi->state;
772*4882a593Smuzhiyun XkbLatchModifiers(dev, 0xFF, 0x00);
773*4882a593Smuzhiyun
774*4882a593Smuzhiyun XkbComputeDerivedState(xkbi);
775*4882a593Smuzhiyun changed |= XkbStateChangedFlags(&oldState, &xkbi->state);
776*4882a593Smuzhiyun if (changed & sli->usedComponents) {
777*4882a593Smuzhiyun changed_leds = XkbIndicatorsToUpdate(dev, changed, FALSE);
778*4882a593Smuzhiyun if (changed_leds) {
779*4882a593Smuzhiyun XkbEventCauseRec cause;
780*4882a593Smuzhiyun
781*4882a593Smuzhiyun XkbSetCauseKey(&cause, (event->detail.key & 0x7), event->type);
782*4882a593Smuzhiyun XkbUpdateIndicators(dev, changed_leds, TRUE, NULL, &cause);
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun }
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun
787*4882a593Smuzhiyun if (((xkbi->flags & _XkbStateNotifyInProgress) == 0) && (changed != 0)) {
788*4882a593Smuzhiyun xkbStateNotify sn;
789*4882a593Smuzhiyun
790*4882a593Smuzhiyun sn.keycode = event->detail.key;
791*4882a593Smuzhiyun sn.eventType = event->type;
792*4882a593Smuzhiyun sn.requestMajor = sn.requestMinor = 0;
793*4882a593Smuzhiyun sn.changed = changed;
794*4882a593Smuzhiyun XkbSendStateNotify(dev, &sn);
795*4882a593Smuzhiyun }
796*4882a593Smuzhiyun
797*4882a593Smuzhiyun } /* ProcessPointerEvent */
798