1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
4 Permission to use, copy, modify, and distribute this
5 software and its documentation for any purpose and without
6 fee is hereby granted, provided that the above copyright
7 notice appear in all copies and that both that copyright
8 notice and this permission notice appear in supporting
9 documentation, and that the name of Silicon Graphics not be
10 used in advertising or publicity pertaining to distribution
11 of the software without specific prior written permission.
12 Silicon Graphics makes no representation about the suitability
13 of this software for any purpose. It is provided "as is"
14 without any express or implied warranty.
16 SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17 SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18 AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19 GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22 OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23 THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 ********************************************************/
27 #ifdef HAVE_DIX_CONFIG_H
28 #include <dix-config.h>
34 #include <X11/Xproto.h>
35 #include <X11/keysym.h>
44 #include "mipointer.h"
45 #include "inpututils.h"
46 #define EXTENSION_EVENT_BASE 64
48 DevPrivateKeyRec xkbDevicePrivateKeyRec;
50 void XkbFakeDeviceButton(DeviceIntPtr dev, Bool press, int button);
51 static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags, int x,
55 xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, pointer data)
57 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
58 ProcessInputProc backupproc;
60 if (xkbPrivPtr->unwrapProc)
61 xkbPrivPtr->unwrapProc = NULL;
63 UNWRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, backupproc);
65 COND_WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, backupproc, xkbUnwrapProc);
71 return dixRegisterPrivateKey(&xkbDevicePrivateKeyRec, PRIVATE_DEVICE,
72 sizeof(xkbDeviceInfoRec));
76 XkbSetExtension(DeviceIntPtr device, ProcessInputProc proc)
78 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(device);
80 WRAP_PROCESS_INPUT_PROC(device, xkbPrivPtr, proc, xkbUnwrapProc);
83 /***====================================================================***/
86 _FixUpAction(XkbDescPtr xkb, XkbAction *act)
88 static XkbAction fake;
90 if (XkbIsPtrAction(act) &&
91 (!(xkb->ctrls->enabled_ctrls & XkbMouseKeysMask))) {
92 fake.type = XkbSA_NoAction;
95 if (xkb->ctrls->enabled_ctrls & XkbStickyKeysMask) {
96 if (act->any.type == XkbSA_SetMods) {
97 fake.mods.type = XkbSA_LatchMods;
98 fake.mods.mask = act->mods.mask;
99 if (XkbAX_NeedOption(xkb->ctrls, XkbAX_LatchToLockMask))
100 fake.mods.flags = XkbSA_ClearLocks | XkbSA_LatchToLock;
102 fake.mods.flags = XkbSA_ClearLocks;
105 if (act->any.type == XkbSA_SetGroup) {
106 fake.group.type = XkbSA_LatchGroup;
107 if (XkbAX_NeedOption(xkb->ctrls, XkbAX_LatchToLockMask))
108 fake.group.flags = XkbSA_ClearLocks | XkbSA_LatchToLock;
110 fake.group.flags = XkbSA_ClearLocks;
111 XkbSASetGroup(&fake.group, XkbSAGroup(&act->group));
119 XkbGetKeyAction(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 key)
126 static XkbAction fake;
129 if (!XkbKeyHasActions(xkb, key) || !XkbKeycodeInRange(xkb, key)) {
130 fake.type = XkbSA_NoAction;
133 pActs = XkbKeyActionsPtr(xkb, key);
136 effectiveGroup = XkbGetEffectiveGroup(xkbi, xkbState, key);
137 if (effectiveGroup != XkbGroup1Index)
138 col += (effectiveGroup * XkbKeyGroupsWidth(xkb, key));
140 type = XkbKeyKeyType(xkb, key, effectiveGroup);
141 if (type->map != NULL) {
142 register unsigned i, mods;
143 register XkbKTMapEntryPtr entry;
145 mods = xkbState->mods & type->mods.mask;
146 for (entry = type->map, i = 0; i < type->map_count; i++, entry++) {
147 if ((entry->active) && (entry->mods.mask == mods)) {
153 if (pActs[col].any.type == XkbSA_NoAction)
155 fake = _FixUpAction(xkb, &pActs[col]);
160 XkbGetButtonAction(DeviceIntPtr kbd, DeviceIntPtr dev, int button)
164 if ((dev->button) && (dev->button->xkb_acts)) {
165 if (dev->button->xkb_acts[button - 1].any.type != XkbSA_NoAction) {
166 fake = _FixUpAction(kbd->key->xkbInfo->desc,
167 &dev->button->xkb_acts[button - 1]);
171 fake.any.type = XkbSA_NoAction;
175 /***====================================================================***/
177 #define SYNTHETIC_KEYCODE 1
178 #define BTN_ACT_FLAG 0x100
181 _XkbFilterSetState(XkbSrvInfoPtr xkbi,
182 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
184 if (filter->keycode == 0) { /* initial press */
185 filter->keycode = keycode;
187 filter->filterOthers = ((pAction->mods.mask & XkbSA_ClearLocks) != 0);
189 filter->filter = _XkbFilterSetState;
190 if (pAction->type == XkbSA_SetMods) {
191 filter->upAction = *pAction;
192 xkbi->setMods = pAction->mods.mask;
195 xkbi->groupChange = XkbSAGroup(&pAction->group);
196 if (pAction->group.flags & XkbSA_GroupAbsolute)
197 xkbi->groupChange -= xkbi->state.base_group;
198 filter->upAction = *pAction;
199 XkbSASetGroup(&filter->upAction.group, xkbi->groupChange);
202 else if (filter->keycode == keycode) {
203 if (filter->upAction.type == XkbSA_SetMods) {
204 xkbi->clearMods = filter->upAction.mods.mask;
205 if (filter->upAction.mods.flags & XkbSA_ClearLocks) {
206 xkbi->state.locked_mods &= ~filter->upAction.mods.mask;
210 if (filter->upAction.group.flags & XkbSA_ClearLocks) {
211 xkbi->state.locked_group = 0;
213 xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
218 filter->upAction.mods.flags &= ~XkbSA_ClearLocks;
219 filter->filterOthers = 0;
224 #define LATCH_KEY_DOWN 1
225 #define LATCH_PENDING 2
229 _XkbFilterLatchState(XkbSrvInfoPtr xkbi,
230 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
233 if (filter->keycode == 0) { /* initial press */
234 filter->keycode = keycode;
236 filter->filterOthers = 1;
237 filter->priv = LATCH_KEY_DOWN;
238 filter->filter = _XkbFilterLatchState;
239 if (pAction->type == XkbSA_LatchMods) {
240 filter->upAction = *pAction;
241 xkbi->setMods = pAction->mods.mask;
244 xkbi->groupChange = XkbSAGroup(&pAction->group);
245 if (pAction->group.flags & XkbSA_GroupAbsolute)
246 xkbi->groupChange -= xkbi->state.base_group;
247 filter->upAction = *pAction;
248 XkbSASetGroup(&filter->upAction.group, xkbi->groupChange);
251 else if (pAction && (filter->priv == LATCH_PENDING)) {
252 if (((1 << pAction->type) & XkbSA_BreakLatch) != 0) {
254 if (filter->upAction.type == XkbSA_LatchMods)
255 xkbi->state.latched_mods &= ~filter->upAction.mods.mask;
257 xkbi->state.latched_group -=
258 XkbSAGroup(&filter->upAction.group);
260 else if ((pAction->type == filter->upAction.type) &&
261 (pAction->mods.flags == filter->upAction.mods.flags) &&
262 (pAction->mods.mask == filter->upAction.mods.mask)) {
263 if (filter->upAction.mods.flags & XkbSA_LatchToLock) {
264 XkbControlsPtr ctrls = xkbi->desc->ctrls;
266 if (filter->upAction.type == XkbSA_LatchMods)
267 pAction->mods.type = XkbSA_LockMods;
269 pAction->group.type = XkbSA_LockGroup;
270 if (XkbAX_NeedFeedback(ctrls, XkbAX_StickyKeysFBMask) &&
271 (ctrls->enabled_ctrls & XkbStickyKeysMask)) {
272 XkbDDXAccessXBeep(xkbi->device, _BEEP_STICKY_LOCK,
277 if (filter->upAction.type == XkbSA_LatchMods)
278 pAction->mods.type = XkbSA_SetMods;
280 pAction->group.type = XkbSA_SetGroup;
282 if (filter->upAction.type == XkbSA_LatchMods)
283 xkbi->state.latched_mods &= ~filter->upAction.mods.mask;
285 xkbi->state.latched_group -=
286 XkbSAGroup(&filter->upAction.group);
290 else if (filter->keycode == keycode) { /* release */
291 XkbControlsPtr ctrls = xkbi->desc->ctrls;
293 int beepType = _BEEP_NONE;
295 needBeep = ((ctrls->enabled_ctrls & XkbStickyKeysMask) &&
296 XkbAX_NeedFeedback(ctrls, XkbAX_StickyKeysFBMask));
297 if (filter->upAction.type == XkbSA_LatchMods) {
298 xkbi->clearMods = filter->upAction.mods.mask;
299 if ((filter->upAction.mods.flags & XkbSA_ClearLocks) &&
300 (xkbi->clearMods & xkbi->state.locked_mods) ==
302 xkbi->state.locked_mods &= ~xkbi->clearMods;
303 filter->priv = NO_LATCH;
304 beepType = _BEEP_STICKY_UNLOCK;
308 xkbi->groupChange = -XkbSAGroup(&filter->upAction.group);
309 if ((filter->upAction.group.flags & XkbSA_ClearLocks) &&
310 (xkbi->state.locked_group)) {
311 xkbi->state.locked_group = 0;
312 filter->priv = NO_LATCH;
313 beepType = _BEEP_STICKY_UNLOCK;
316 if (filter->priv == NO_LATCH) {
320 filter->priv = LATCH_PENDING;
321 if (filter->upAction.type == XkbSA_LatchMods) {
322 xkbi->state.latched_mods |= filter->upAction.mods.mask;
323 needBeep = xkbi->state.latched_mods ? needBeep : 0;
324 xkbi->state.latched_mods |= filter->upAction.mods.mask;
327 xkbi->state.latched_group +=
328 XkbSAGroup(&filter->upAction.group);
330 if (needBeep && (beepType == _BEEP_NONE))
331 beepType = _BEEP_STICKY_LATCH;
333 if (needBeep && (beepType != _BEEP_NONE))
334 XkbDDXAccessXBeep(xkbi->device, beepType, XkbStickyKeysMask);
336 else if (filter->priv == LATCH_KEY_DOWN) {
337 filter->priv = NO_LATCH;
338 filter->filterOthers = 0;
344 _XkbFilterLockState(XkbSrvInfoPtr xkbi,
345 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
347 if (pAction && (pAction->type == XkbSA_LockGroup)) {
348 if (pAction->group.flags & XkbSA_GroupAbsolute)
349 xkbi->state.locked_group = XkbSAGroup(&pAction->group);
351 xkbi->state.locked_group += XkbSAGroup(&pAction->group);
354 if (filter->keycode == 0) { /* initial press */
355 filter->keycode = keycode;
357 filter->filterOthers = 0;
358 filter->priv = xkbi->state.locked_mods & pAction->mods.mask;
359 filter->filter = _XkbFilterLockState;
360 filter->upAction = *pAction;
361 if (!(filter->upAction.mods.flags & XkbSA_LockNoLock))
362 xkbi->state.locked_mods |= pAction->mods.mask;
363 xkbi->setMods = pAction->mods.mask;
365 else if (filter->keycode == keycode) {
367 xkbi->clearMods = filter->upAction.mods.mask;
368 if (!(filter->upAction.mods.flags & XkbSA_LockNoUnlock))
369 xkbi->state.locked_mods &= ~filter->priv;
374 #define ISO_KEY_DOWN 0
375 #define NO_ISO_LOCK 1
378 _XkbFilterISOLock(XkbSrvInfoPtr xkbi,
379 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
382 if (filter->keycode == 0) { /* initial press */
383 CARD8 flags = pAction->iso.flags;
385 filter->keycode = keycode;
387 filter->filterOthers = 1;
388 filter->priv = ISO_KEY_DOWN;
389 filter->upAction = *pAction;
390 filter->filter = _XkbFilterISOLock;
391 if (flags & XkbSA_ISODfltIsGroup) {
392 xkbi->groupChange = XkbSAGroup(&pAction->iso);
396 xkbi->setMods = pAction->iso.mask;
397 xkbi->groupChange = 0;
399 if ((!(flags & XkbSA_ISONoAffectMods)) && (xkbi->state.base_mods)) {
400 filter->priv = NO_ISO_LOCK;
401 xkbi->state.locked_mods ^= xkbi->state.base_mods;
403 if ((!(flags & XkbSA_ISONoAffectGroup)) && (xkbi->state.base_group)) {
404 /* 6/22/93 (ef) -- lock groups if group key is down first */
406 if (!(flags & XkbSA_ISONoAffectPtr)) {
407 /* 6/22/93 (ef) -- lock mouse buttons if they're down */
410 else if (filter->keycode == keycode) {
411 CARD8 flags = filter->upAction.iso.flags;
413 if (flags & XkbSA_ISODfltIsGroup) {
414 xkbi->groupChange = -XkbSAGroup(&filter->upAction.iso);
416 if (filter->priv == ISO_KEY_DOWN)
417 xkbi->state.locked_group += XkbSAGroup(&filter->upAction.iso);
420 xkbi->clearMods = filter->upAction.iso.mask;
421 xkbi->groupChange = 0;
422 if (filter->priv == ISO_KEY_DOWN)
423 xkbi->state.locked_mods ^= filter->upAction.iso.mask;
428 CARD8 flags = filter->upAction.iso.flags;
430 switch (pAction->type) {
432 case XkbSA_LatchMods:
433 if (!(flags & XkbSA_ISONoAffectMods)) {
434 pAction->type = XkbSA_LockMods;
435 filter->priv = NO_ISO_LOCK;
439 case XkbSA_LatchGroup:
440 if (!(flags & XkbSA_ISONoAffectGroup)) {
441 pAction->type = XkbSA_LockGroup;
442 filter->priv = NO_ISO_LOCK;
446 if (!(flags & XkbSA_ISONoAffectPtr)) {
447 pAction->type = XkbSA_LockPtrBtn;
448 filter->priv = NO_ISO_LOCK;
451 case XkbSA_SetControls:
452 if (!(flags & XkbSA_ISONoAffectCtrls)) {
453 pAction->type = XkbSA_LockControls;
454 filter->priv = NO_ISO_LOCK;
463 _XkbPtrAccelExpire(OsTimerPtr timer, CARD32 now, pointer arg)
465 XkbSrvInfoPtr xkbi = (XkbSrvInfoPtr) arg;
466 XkbControlsPtr ctrls = xkbi->desc->ctrls;
469 if (xkbi->mouseKey == 0)
472 if (xkbi->mouseKeysAccel) {
473 if ((xkbi->mouseKeysCounter) < ctrls->mk_time_to_max) {
476 xkbi->mouseKeysCounter++;
477 step = xkbi->mouseKeysCurveFactor *
478 pow((double) xkbi->mouseKeysCounter, xkbi->mouseKeysCurve);
479 if (xkbi->mouseKeysDX < 0)
480 dx = floor(((double) xkbi->mouseKeysDX) * step);
482 dx = ceil(((double) xkbi->mouseKeysDX) * step);
483 if (xkbi->mouseKeysDY < 0)
484 dy = floor(((double) xkbi->mouseKeysDY) * step);
486 dy = ceil(((double) xkbi->mouseKeysDY) * step);
489 dx = xkbi->mouseKeysDX * ctrls->mk_max_speed;
490 dy = xkbi->mouseKeysDY * ctrls->mk_max_speed;
492 if (xkbi->mouseKeysFlags & XkbSA_MoveAbsoluteX)
493 dx = xkbi->mouseKeysDX;
494 if (xkbi->mouseKeysFlags & XkbSA_MoveAbsoluteY)
495 dy = xkbi->mouseKeysDY;
498 dx = xkbi->mouseKeysDX;
499 dy = xkbi->mouseKeysDY;
501 XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags, dx, dy);
502 return xkbi->desc->ctrls->mk_interval;
506 _XkbFilterPointerMove(XkbSrvInfoPtr xkbi,
507 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
512 if (filter->keycode == 0) { /* initial press */
513 filter->keycode = keycode;
515 filter->filterOthers = 0;
517 filter->filter = _XkbFilterPointerMove;
518 filter->upAction = *pAction;
519 xkbi->mouseKeysCounter = 0;
520 xkbi->mouseKey = keycode;
521 accel = ((pAction->ptr.flags & XkbSA_NoAcceleration) == 0);
522 x = XkbPtrActionX(&pAction->ptr);
523 y = XkbPtrActionY(&pAction->ptr);
524 XkbFakePointerMotion(xkbi->device, pAction->ptr.flags, x, y);
525 AccessXCancelRepeatKey(xkbi, keycode);
526 xkbi->mouseKeysAccel = accel &&
527 (xkbi->desc->ctrls->enabled_ctrls & XkbMouseKeysAccelMask);
528 xkbi->mouseKeysFlags = pAction->ptr.flags;
529 xkbi->mouseKeysDX = XkbPtrActionX(&pAction->ptr);
530 xkbi->mouseKeysDY = XkbPtrActionY(&pAction->ptr);
531 xkbi->mouseKeyTimer = TimerSet(xkbi->mouseKeyTimer, 0,
532 xkbi->desc->ctrls->mk_delay,
533 _XkbPtrAccelExpire, (pointer) xkbi);
535 else if (filter->keycode == keycode) {
537 if (xkbi->mouseKey == keycode) {
539 xkbi->mouseKeyTimer = TimerSet(xkbi->mouseKeyTimer, 0, 0,
547 _XkbFilterPointerBtn(XkbSrvInfoPtr xkbi,
548 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
550 if (filter->keycode == 0) { /* initial press */
551 int button = pAction->btn.button;
553 if (button == XkbSA_UseDfltButton)
554 button = xkbi->desc->ctrls->mk_dflt_btn;
556 filter->keycode = keycode;
558 filter->filterOthers = 0;
560 filter->filter = _XkbFilterPointerBtn;
561 filter->upAction = *pAction;
562 filter->upAction.btn.button = button;
563 switch (pAction->type) {
564 case XkbSA_LockPtrBtn:
565 if (((xkbi->lockedPtrButtons & (1 << button)) == 0) &&
566 ((pAction->btn.flags & XkbSA_LockNoLock) == 0)) {
567 xkbi->lockedPtrButtons |= (1 << button);
568 AccessXCancelRepeatKey(xkbi, keycode);
569 XkbFakeDeviceButton(xkbi->device, 1, button);
570 filter->upAction.type = XkbSA_NoAction;
575 register int i, nClicks;
577 AccessXCancelRepeatKey(xkbi, keycode);
578 if (pAction->btn.count > 0) {
579 nClicks = pAction->btn.count;
580 for (i = 0; i < nClicks; i++) {
581 XkbFakeDeviceButton(xkbi->device, 1, button);
582 XkbFakeDeviceButton(xkbi->device, 0, button);
584 filter->upAction.type = XkbSA_NoAction;
587 XkbFakeDeviceButton(xkbi->device, 1, button);
590 case XkbSA_SetPtrDflt:
592 XkbControlsPtr ctrls = xkbi->desc->ctrls;
594 xkbControlsNotify cn;
597 AccessXCancelRepeatKey(xkbi, keycode);
598 switch (pAction->dflt.affect) {
599 case XkbSA_AffectDfltBtn:
600 if (pAction->dflt.flags & XkbSA_DfltBtnAbsolute)
601 ctrls->mk_dflt_btn = XkbSAPtrDfltValue(&pAction->dflt);
603 ctrls->mk_dflt_btn += XkbSAPtrDfltValue(&pAction->dflt);
604 if (ctrls->mk_dflt_btn > 5)
605 ctrls->mk_dflt_btn = 5;
606 else if (ctrls->mk_dflt_btn < 1)
607 ctrls->mk_dflt_btn = 1;
612 ("Attempt to change unknown pointer default (%d) ignored\n",
613 pAction->dflt.affect);
616 if (XkbComputeControlsNotify(xkbi->device,
617 &old, xkbi->desc->ctrls, &cn, FALSE)) {
618 cn.keycode = keycode;
619 /* XXX: what about DeviceKeyPress? */
620 cn.eventType = KeyPress;
623 XkbSendControlsNotify(xkbi->device, &cn);
629 else if (filter->keycode == keycode) {
630 int button = filter->upAction.btn.button;
632 switch (filter->upAction.type) {
633 case XkbSA_LockPtrBtn:
634 if (((filter->upAction.btn.flags & XkbSA_LockNoUnlock) != 0) ||
635 ((xkbi->lockedPtrButtons & (1 << button)) == 0)) {
638 xkbi->lockedPtrButtons &= ~(1 << button);
640 if (IsMaster(xkbi->device)) {
641 XkbMergeLockedPtrBtns(xkbi->device);
642 /* One SD still has lock set, don't post event */
643 if ((xkbi->lockedPtrButtons & (1 << button)) != 0)
649 XkbFakeDeviceButton(xkbi->device, 0, button);
658 _XkbFilterControls(XkbSrvInfoPtr xkbi,
659 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
662 XkbControlsPtr ctrls;
665 XkbEventCauseRec cause;
668 ctrls = xkbi->desc->ctrls;
670 if (filter->keycode == 0) { /* initial press */
671 filter->keycode = keycode;
673 filter->filterOthers = 0;
674 change = XkbActionCtrls(&pAction->ctrls);
675 filter->priv = change;
676 filter->filter = _XkbFilterControls;
677 filter->upAction = *pAction;
679 if (pAction->type == XkbSA_LockControls) {
680 filter->priv = (ctrls->enabled_ctrls & change);
681 change &= ~ctrls->enabled_ctrls;
685 xkbControlsNotify cn;
686 XkbSrvLedInfoPtr sli;
688 ctrls->enabled_ctrls |= change;
689 if (XkbComputeControlsNotify(kbd, &old, ctrls, &cn, FALSE)) {
690 cn.keycode = keycode;
691 /* XXX: what about DeviceKeyPress? */
692 cn.eventType = KeyPress;
695 XkbSendControlsNotify(kbd, &cn);
698 XkbSetCauseKey(&cause, keycode, KeyPress);
700 /* If sticky keys were disabled, clear all locks and latches */
701 if ((old.enabled_ctrls & XkbStickyKeysMask) &&
702 (!(ctrls->enabled_ctrls & XkbStickyKeysMask))) {
703 XkbClearAllLatchesAndLocks(kbd, xkbi, FALSE, &cause);
705 sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
706 XkbUpdateIndicators(kbd, sli->usesControls, TRUE, NULL, &cause);
707 if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask))
708 XkbDDXAccessXBeep(kbd, _BEEP_FEATURE_ON, change);
711 else if (filter->keycode == keycode) {
712 change = filter->priv;
714 xkbControlsNotify cn;
715 XkbSrvLedInfoPtr sli;
717 ctrls->enabled_ctrls &= ~change;
718 if (XkbComputeControlsNotify(kbd, &old, ctrls, &cn, FALSE)) {
719 cn.keycode = keycode;
720 cn.eventType = KeyRelease;
723 XkbSendControlsNotify(kbd, &cn);
726 XkbSetCauseKey(&cause, keycode, KeyRelease);
727 /* If sticky keys were disabled, clear all locks and latches */
728 if ((old.enabled_ctrls & XkbStickyKeysMask) &&
729 (!(ctrls->enabled_ctrls & XkbStickyKeysMask))) {
730 XkbClearAllLatchesAndLocks(kbd, xkbi, FALSE, &cause);
732 sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
733 XkbUpdateIndicators(kbd, sli->usesControls, TRUE, NULL, &cause);
734 if (XkbAX_NeedFeedback(ctrls, XkbAX_FeatureFBMask))
735 XkbDDXAccessXBeep(kbd, _BEEP_FEATURE_OFF, change);
744 _XkbFilterActionMessage(XkbSrvInfoPtr xkbi,
746 unsigned keycode, XkbAction *pAction)
748 XkbMessageAction *pMsg;
752 if (filter->keycode == 0) { /* initial press */
753 pMsg = &pAction->msg;
754 if ((pMsg->flags & XkbSA_MessageOnRelease) ||
755 ((pMsg->flags & XkbSA_MessageGenKeyEvent) == 0)) {
756 filter->keycode = keycode;
758 filter->filterOthers = 0;
760 filter->filter = _XkbFilterActionMessage;
761 filter->upAction = *pAction;
763 if (pMsg->flags & XkbSA_MessageOnPress) {
764 xkbActionMessage msg;
766 msg.keycode = keycode;
768 msg.keyEventFollows =
769 ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
770 memcpy((char *) msg.message, (char *) pMsg->message,
771 XkbActionMessageLength);
772 XkbSendActionMessage(kbd, &msg);
774 return ((pAction->msg.flags & XkbSA_MessageGenKeyEvent) != 0);
776 else if (filter->keycode == keycode) {
777 pMsg = &filter->upAction.msg;
778 if (pMsg->flags & XkbSA_MessageOnRelease) {
779 xkbActionMessage msg;
781 msg.keycode = keycode;
783 msg.keyEventFollows =
784 ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
785 memcpy((char *) msg.message, (char *) pMsg->message,
786 XkbActionMessageLength);
787 XkbSendActionMessage(kbd, &msg);
791 return ((pMsg->flags & XkbSA_MessageGenKeyEvent) != 0);
797 _XkbFilterRedirectKey(XkbSrvInfoPtr xkbi,
798 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
802 XkbStateRec old, old_prev;
804 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(xkbi->device);
805 ProcessInputProc backupproc;
807 /* never actually used uninitialised, but gcc isn't smart enough
808 * to work that out. */
809 memset(&old, 0, sizeof(old));
810 memset(&old_prev, 0, sizeof(old_prev));
811 memset(&ev, 0, sizeof(ev));
813 if ((filter->keycode != 0) && (filter->keycode != keycode))
816 GetSpritePosition(xkbi->device, &x, &y);
817 ev.header = ET_Internal;
818 ev.length = sizeof(DeviceEvent);
819 ev.time = GetTimeInMillis();
822 /* redirect actions do not work across devices, therefore the following is
824 ev.deviceid = xkbi->device->id;
825 /* filter->priv must be set up by the caller for the initial press. */
826 ev.sourceid = filter->priv;
828 if (filter->keycode == 0) { /* initial press */
829 if ((pAction->redirect.new_key < xkbi->desc->min_key_code) ||
830 (pAction->redirect.new_key > xkbi->desc->max_key_code)) {
833 filter->keycode = keycode;
835 filter->filterOthers = 0;
836 filter->filter = _XkbFilterRedirectKey;
837 filter->upAction = *pAction;
839 ev.type = ET_KeyPress;
840 ev.detail.key = pAction->redirect.new_key;
842 mask = XkbSARedirectVModsMask(&pAction->redirect);
843 mods = XkbSARedirectVMods(&pAction->redirect);
845 XkbVirtualModsToReal(xkbi->desc, mask, &mask);
847 XkbVirtualModsToReal(xkbi->desc, mods, &mods);
848 mask |= pAction->redirect.mods_mask;
849 mods |= pAction->redirect.mods;
853 old_prev = xkbi->prev_state;
854 xkbi->state.base_mods &= ~mask;
855 xkbi->state.base_mods |= (mods & mask);
856 xkbi->state.latched_mods &= ~mask;
857 xkbi->state.latched_mods |= (mods & mask);
858 xkbi->state.locked_mods &= ~mask;
859 xkbi->state.locked_mods |= (mods & mask);
860 XkbComputeDerivedState(xkbi);
861 xkbi->prev_state = xkbi->state;
864 UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
865 xkbi->device->public.processInputProc((InternalEvent *) &ev,
867 COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
872 xkbi->prev_state = old_prev;
875 else if (filter->keycode == keycode) {
877 ev.type = ET_KeyRelease;
878 ev.detail.key = filter->upAction.redirect.new_key;
880 mask = XkbSARedirectVModsMask(&filter->upAction.redirect);
881 mods = XkbSARedirectVMods(&filter->upAction.redirect);
883 XkbVirtualModsToReal(xkbi->desc, mask, &mask);
885 XkbVirtualModsToReal(xkbi->desc, mods, &mods);
886 mask |= filter->upAction.redirect.mods_mask;
887 mods |= filter->upAction.redirect.mods;
891 old_prev = xkbi->prev_state;
892 xkbi->state.base_mods &= ~mask;
893 xkbi->state.base_mods |= (mods & mask);
894 xkbi->state.latched_mods &= ~mask;
895 xkbi->state.latched_mods |= (mods & mask);
896 xkbi->state.locked_mods &= ~mask;
897 xkbi->state.locked_mods |= (mods & mask);
898 XkbComputeDerivedState(xkbi);
899 xkbi->prev_state = xkbi->state;
902 UNWRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc);
903 xkbi->device->public.processInputProc((InternalEvent *) &ev,
905 COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, backupproc,
910 xkbi->prev_state = old_prev;
920 _XkbFilterSwitchScreen(XkbSrvInfoPtr xkbi,
922 unsigned keycode, XkbAction *pAction)
924 DeviceIntPtr dev = xkbi->device;
926 if (dev == inputInfo.keyboard)
929 if (filter->keycode == 0) { /* initial press */
930 filter->keycode = keycode;
932 filter->filterOthers = 0;
933 filter->filter = _XkbFilterSwitchScreen;
934 AccessXCancelRepeatKey(xkbi, keycode);
935 XkbDDXSwitchScreen(dev, keycode, pAction);
938 else if (filter->keycode == keycode) {
946 _XkbFilterXF86Private(XkbSrvInfoPtr xkbi,
947 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
949 DeviceIntPtr dev = xkbi->device;
951 if (dev == inputInfo.keyboard)
954 if (filter->keycode == 0) { /* initial press */
955 filter->keycode = keycode;
957 filter->filterOthers = 0;
958 filter->filter = _XkbFilterXF86Private;
959 XkbDDXPrivate(dev, keycode, pAction);
962 else if (filter->keycode == keycode) {
970 _XkbFilterDeviceBtn(XkbSrvInfoPtr xkbi,
971 XkbFilterPtr filter, unsigned keycode, XkbAction *pAction)
973 if (xkbi->device == inputInfo.keyboard)
976 if (filter->keycode == 0) { /* initial press */
980 _XkbLookupButtonDevice(&dev, pAction->devbtn.device, serverClient,
981 DixUnknownAccess, &button);
982 if (!dev || !dev->public.on)
985 button = pAction->devbtn.button;
986 if ((button < 1) || (button > dev->button->numButtons))
989 filter->keycode = keycode;
991 filter->filterOthers = 0;
993 filter->filter = _XkbFilterDeviceBtn;
994 filter->upAction = *pAction;
995 switch (pAction->type) {
996 case XkbSA_LockDeviceBtn:
997 if ((pAction->devbtn.flags & XkbSA_LockNoLock) ||
998 BitIsOn(dev->button->down, button))
1000 XkbFakeDeviceButton(dev, TRUE, button);
1001 filter->upAction.type = XkbSA_NoAction;
1003 case XkbSA_DeviceBtn:
1004 if (pAction->devbtn.count > 0) {
1007 nClicks = pAction->btn.count;
1008 for (i = 0; i < nClicks; i++) {
1009 XkbFakeDeviceButton(dev, TRUE, button);
1010 XkbFakeDeviceButton(dev, FALSE, button);
1012 filter->upAction.type = XkbSA_NoAction;
1015 XkbFakeDeviceButton(dev, TRUE, button);
1019 else if (filter->keycode == keycode) {
1024 _XkbLookupButtonDevice(&dev, filter->upAction.devbtn.device,
1025 serverClient, DixUnknownAccess, &button);
1026 if (!dev || !dev->public.on)
1029 button = filter->upAction.btn.button;
1030 switch (filter->upAction.type) {
1031 case XkbSA_LockDeviceBtn:
1032 if ((filter->upAction.devbtn.flags & XkbSA_LockNoUnlock) ||
1033 !BitIsOn(dev->button->down, button))
1035 XkbFakeDeviceButton(dev, FALSE, button);
1037 case XkbSA_DeviceBtn:
1038 XkbFakeDeviceButton(dev, FALSE, button);
1047 _XkbNextFreeFilter(XkbSrvInfoPtr xkbi)
1051 if (xkbi->szFilters == 0) {
1052 xkbi->szFilters = 4;
1053 xkbi->filters = calloc(xkbi->szFilters, sizeof(XkbFilterRec));
1054 /* 6/21/93 (ef) -- XXX! deal with allocation failure */
1056 for (i = 0; i < xkbi->szFilters; i++) {
1057 if (!xkbi->filters[i].active) {
1058 xkbi->filters[i].keycode = 0;
1059 return &xkbi->filters[i];
1062 xkbi->szFilters *= 2;
1063 xkbi->filters = realloc(xkbi->filters,
1064 xkbi->szFilters * sizeof(XkbFilterRec));
1065 /* 6/21/93 (ef) -- XXX! deal with allocation failure */
1066 memset(&xkbi->filters[xkbi->szFilters / 2], 0,
1067 (xkbi->szFilters / 2) * sizeof(XkbFilterRec));
1068 return &xkbi->filters[xkbi->szFilters / 2];
1072 _XkbApplyFilters(XkbSrvInfoPtr xkbi, unsigned kc, XkbAction *pAction)
1074 register int i, send;
1077 for (i = 0; i < xkbi->szFilters; i++) {
1078 if ((xkbi->filters[i].active) && (xkbi->filters[i].filter))
1080 ((*xkbi->filters[i].filter) (xkbi, &xkbi->filters[i], kc,
1088 XkbHandleActions(DeviceIntPtr dev, DeviceIntPtr kbd, DeviceEvent *event)
1093 int changed, sendEvent;
1094 Bool genStateNotify;
1096 XkbFilterPtr filter;
1099 ProcessInputProc backupproc;
1101 xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev);
1104 xkbi = keyc->xkbInfo;
1105 key = event->detail.key;
1106 /* The state may change, so if we're not in the middle of sending a state
1107 * notify, prepare for it */
1108 if ((xkbi->flags & _XkbStateNotifyInProgress) == 0) {
1109 xkbi->prev_state = xkbi->state;
1110 xkbi->flags |= _XkbStateNotifyInProgress;
1111 genStateNotify = TRUE;
1114 genStateNotify = FALSE;
1116 xkbi->clearMods = xkbi->setMods = 0;
1117 xkbi->groupChange = 0;
1120 keyEvent = ((event->type == ET_KeyPress) || (event->type == ET_KeyRelease));
1121 pressEvent = ((event->type == ET_KeyPress) ||
1122 (event->type == ET_ButtonPress));
1126 act = XkbGetKeyAction(xkbi, &xkbi->state, key);
1128 act = XkbGetButtonAction(kbd, dev, key);
1129 key |= BTN_ACT_FLAG;
1131 sendEvent = _XkbApplyFilters(xkbi, key, &act);
1135 case XkbSA_SetGroup:
1136 filter = _XkbNextFreeFilter(xkbi);
1137 sendEvent = _XkbFilterSetState(xkbi, filter, key, &act);
1139 case XkbSA_LatchMods:
1140 case XkbSA_LatchGroup:
1141 filter = _XkbNextFreeFilter(xkbi);
1142 sendEvent = _XkbFilterLatchState(xkbi, filter, key, &act);
1144 case XkbSA_LockMods:
1145 case XkbSA_LockGroup:
1146 filter = _XkbNextFreeFilter(xkbi);
1147 sendEvent = _XkbFilterLockState(xkbi, filter, key, &act);
1150 filter = _XkbNextFreeFilter(xkbi);
1151 sendEvent = _XkbFilterISOLock(xkbi, filter, key, &act);
1154 filter = _XkbNextFreeFilter(xkbi);
1155 sendEvent = _XkbFilterPointerMove(xkbi, filter, key, &act);
1158 case XkbSA_LockPtrBtn:
1159 case XkbSA_SetPtrDflt:
1160 filter = _XkbNextFreeFilter(xkbi);
1161 sendEvent = _XkbFilterPointerBtn(xkbi, filter, key, &act);
1163 case XkbSA_Terminate:
1164 sendEvent = XkbDDXTerminateServer(dev, key, &act);
1166 case XkbSA_SwitchScreen:
1167 filter = _XkbNextFreeFilter(xkbi);
1168 sendEvent = _XkbFilterSwitchScreen(xkbi, filter, key, &act);
1170 case XkbSA_SetControls:
1171 case XkbSA_LockControls:
1172 filter = _XkbNextFreeFilter(xkbi);
1173 sendEvent = _XkbFilterControls(xkbi, filter, key, &act);
1175 case XkbSA_ActionMessage:
1176 filter = _XkbNextFreeFilter(xkbi);
1177 sendEvent = _XkbFilterActionMessage(xkbi, filter, key, &act);
1179 case XkbSA_RedirectKey:
1180 filter = _XkbNextFreeFilter(xkbi);
1181 /* redirect actions must create a new DeviceEvent. The
1182 * source device id for this event cannot be obtained from
1183 * xkbi, so we pass it here explicitly. The field deviceid
1184 * equals to xkbi->device->id. */
1185 filter->priv = event->sourceid;
1186 sendEvent = _XkbFilterRedirectKey(xkbi, filter, key, &act);
1188 case XkbSA_DeviceBtn:
1189 case XkbSA_LockDeviceBtn:
1190 filter = _XkbNextFreeFilter(xkbi);
1191 sendEvent = _XkbFilterDeviceBtn(xkbi, filter, key, &act);
1193 case XkbSA_XFree86Private:
1194 filter = _XkbNextFreeFilter(xkbi);
1195 sendEvent = _XkbFilterXF86Private(xkbi, filter, key, &act);
1202 key |= BTN_ACT_FLAG;
1203 sendEvent = _XkbApplyFilters(xkbi, key, NULL);
1206 if (xkbi->groupChange != 0)
1207 xkbi->state.base_group += xkbi->groupChange;
1208 if (xkbi->setMods) {
1209 for (i = 0, bit = 1; xkbi->setMods; i++, bit <<= 1) {
1210 if (xkbi->setMods & bit) {
1211 keyc->modifierKeyCount[i]++;
1212 xkbi->state.base_mods |= bit;
1213 xkbi->setMods &= ~bit;
1217 if (xkbi->clearMods) {
1218 for (i = 0, bit = 1; xkbi->clearMods; i++, bit <<= 1) {
1219 if (xkbi->clearMods & bit) {
1220 keyc->modifierKeyCount[i]--;
1221 if (keyc->modifierKeyCount[i] <= 0) {
1222 xkbi->state.base_mods &= ~bit;
1223 keyc->modifierKeyCount[i] = 0;
1225 xkbi->clearMods &= ~bit;
1231 DeviceIntPtr tmpdev;
1236 tmpdev = GetMaster(dev, POINTER_OR_FLOAT);
1238 UNWRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr, backupproc);
1239 dev->public.processInputProc((InternalEvent *) event, tmpdev);
1240 COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr,
1241 backupproc, xkbUnwrapProc);
1243 else if (keyEvent) {
1244 FixKeyState(event, dev);
1247 XkbComputeDerivedState(xkbi);
1248 changed = XkbStateChangedFlags(&xkbi->prev_state, &xkbi->state);
1249 if (genStateNotify) {
1254 sn.eventType = event->type;
1255 sn.requestMajor = sn.requestMinor = 0;
1256 sn.changed = changed;
1257 XkbSendStateNotify(dev, &sn);
1259 xkbi->flags &= ~_XkbStateNotifyInProgress;
1261 changed = XkbIndicatorsToUpdate(dev, changed, FALSE);
1263 XkbEventCauseRec cause;
1265 XkbSetCauseKey(&cause, key, event->type);
1266 XkbUpdateIndicators(dev, changed, FALSE, NULL, &cause);
1272 XkbLatchModifiers(DeviceIntPtr pXDev, CARD8 mask, CARD8 latches)
1275 XkbFilterPtr filter;
1279 if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
1280 xkbi = pXDev->key->xkbInfo;
1281 clear = (mask & (~latches));
1282 xkbi->state.latched_mods &= ~clear;
1283 /* Clear any pending latch to locks.
1285 act.type = XkbSA_NoAction;
1286 _XkbApplyFilters(xkbi, SYNTHETIC_KEYCODE, &act);
1287 act.type = XkbSA_LatchMods;
1289 act.mods.mask = mask & latches;
1290 filter = _XkbNextFreeFilter(xkbi);
1291 _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
1292 _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
1293 (XkbAction *) NULL);
1300 XkbLatchGroup(DeviceIntPtr pXDev, int group)
1303 XkbFilterPtr filter;
1306 if (pXDev && pXDev->key && pXDev->key->xkbInfo) {
1307 xkbi = pXDev->key->xkbInfo;
1308 act.type = XkbSA_LatchGroup;
1309 act.group.flags = 0;
1310 XkbSASetGroup(&act.group, group);
1311 filter = _XkbNextFreeFilter(xkbi);
1312 _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE, &act);
1313 _XkbFilterLatchState(xkbi, filter, SYNTHETIC_KEYCODE,
1314 (XkbAction *) NULL);
1320 /***====================================================================***/
1323 XkbClearAllLatchesAndLocks(DeviceIntPtr dev,
1325 Bool genEv, XkbEventCausePtr cause)
1332 if (os.latched_mods) { /* clear all latches */
1333 XkbLatchModifiers(dev, ~0, 0);
1334 sn.changed |= XkbModifierLatchMask;
1336 if (os.latched_group) {
1337 XkbLatchGroup(dev, 0);
1338 sn.changed |= XkbGroupLatchMask;
1340 if (os.locked_mods) {
1341 xkbi->state.locked_mods = 0;
1342 sn.changed |= XkbModifierLockMask;
1344 if (os.locked_group) {
1345 xkbi->state.locked_group = 0;
1346 sn.changed |= XkbGroupLockMask;
1348 if (genEv && sn.changed) {
1351 XkbComputeDerivedState(xkbi);
1352 sn.keycode = cause->kc;
1353 sn.eventType = cause->event;
1354 sn.requestMajor = cause->mjr;
1355 sn.requestMinor = cause->mnr;
1356 sn.changed = XkbStateChangedFlags(&os, &xkbi->state);
1357 XkbSendStateNotify(dev, &sn);
1358 changed = XkbIndicatorsToUpdate(dev, sn.changed, FALSE);
1360 XkbUpdateIndicators(dev, changed, TRUE, NULL, cause);
1367 * The event is injected into the event processing, not the EQ. Thus,
1368 * ensure that we restore the master after the event sequence to the
1369 * original set of classes. Otherwise, the master remains on the XTEST
1370 * classes and drops events that don't fit into the XTEST layout (e.g.
1371 * events with more than 2 valuators).
1373 * FIXME: EQ injection in the processing stage is not designed for, so this
1374 * is a rather awkward hack. The event list returned by GetPointerEvents()
1375 * and friends is always prefixed with a DCE if the last _posted_ device was
1376 * different. For normal events, this sequence then resets the master during
1377 * the processing stage. Since we inject the PointerKey events in the
1378 * processing stage though, we need to manually reset to restore the
1379 * previous order, because the events already in the EQ must be sent for the
1381 * So we post-fix the event list we get from GPE with a DCE back to the
1382 * previous slave device.
1384 * First one on drinking island wins!
1387 InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags,
1391 InternalEvent *events;
1393 DeviceIntPtr ptr, mpointer, lastSlave = NULL;
1396 if (IsMaster(dev)) {
1397 mpointer = GetMaster(dev, MASTER_POINTER);
1398 lastSlave = mpointer->lastSlave;
1399 ptr = GetXTestDevice(mpointer);
1401 else if (IsFloating(dev))
1406 events = InitEventList(GetMaximumEventsNum() + 1);
1408 pScreen = miPointerGetScreen(ptr);
1409 saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
1410 nevents = GetPointerEvents(events, ptr, type, button, flags, mask);
1411 if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
1412 UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT,
1414 miPointerSetWaitForUpdate(pScreen, saveWait);
1417 for (i = 0; i < nevents; i++)
1418 mieqProcessDeviceEvent(ptr, &events[i], NULL);
1420 FreeEventList(events, GetMaximumEventsNum());
1425 XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags, int x, int y)
1430 /* ignore attached SDs */
1431 if (!IsMaster(dev) && !IsFloating(dev))
1434 if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
1435 gpe_flags = POINTER_ABSOLUTE;
1437 gpe_flags = POINTER_RELATIVE;
1439 valuator_mask_set_range(&mask, 0, 2, (int[]) {
1442 InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask);
1446 XkbFakeDeviceButton(DeviceIntPtr dev, Bool press, int button)
1451 /* If dev is a slave device, and the SD is attached, do nothing. If we'd
1452 * post through the attached master pointer we'd get duplicate events.
1454 * if dev is a master keyboard, post through the XTEST device
1456 * if dev is a floating slave, post through the device itself.
1459 if (IsMaster(dev)) {
1460 DeviceIntPtr mpointer = GetMaster(dev, MASTER_POINTER);
1462 ptr = GetXTestDevice(mpointer);
1464 else if (IsFloating(dev))
1469 down = button_is_down(ptr, button, BUTTON_PROCESSED);
1473 InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,