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>
33 #include <X11/Xproto.h>
34 #include <X11/keysym.h>
35 #include <X11/extensions/XI.h>
36 #include <X11/extensions/XIproto.h>
39 #include "exglobals.h"
40 #include "windowstr.h"
44 /***====================================================================***/
47 * This function sends out two kinds of notification:
48 * - Core mapping notify events sent to clients for whom kbd is the
49 * current core ('picked') keyboard _and_ have not explicitly
50 * selected for XKB mapping notify events;
51 * - Xi mapping events, sent unconditionally to all clients who have
52 * explicitly selected for them (including those who have explicitly
53 * selected for XKB mapping notify events!).
56 XkbSendLegacyMapNotify(DeviceIntPtr kbd
, CARD16 xkb_event
, CARD16 changed
,
57 int first_key
, int num_keys
)
60 int keymap_changed
= 0;
61 int modmap_changed
= 0;
62 CARD32 time
= GetTimeInMillis();
64 if (xkb_event
== XkbNewKeyboardNotify
) {
65 if (changed
& XkbNKN_KeycodesMask
) {
70 else if (xkb_event
== XkbMapNotify
) {
71 if (changed
& XkbKeySymsMask
)
73 if (changed
& XkbModifierMapMask
)
76 if (!keymap_changed
&& !modmap_changed
)
79 /* 0 is serverClient. */
80 for (i
= 1; i
< currentMaxClients
; i
++) {
81 if (!clients
[i
] || clients
[i
]->clientState
!= ClientStateRunning
)
84 /* XKB allows clients to restrict the MappingNotify events sent to
85 * them. This was broken for three years. Sorry. */
86 if (xkb_event
== XkbMapNotify
&&
87 (clients
[i
]->xkbClientFlags
& _XkbClientInitialized
) &&
88 !(clients
[i
]->mapNotifyMask
& changed
))
90 /* Emulate previous server behaviour: any client which has activated
91 * XKB will not receive core events emulated from a NewKeyboardNotify
93 if (xkb_event
== XkbNewKeyboardNotify
&&
94 (clients
[i
]->xkbClientFlags
& _XkbClientInitialized
))
97 /* Don't send core events to clients who don't know about us. */
98 if (!XIShouldNotify(clients
[i
], kbd
))
101 if (keymap_changed
) {
102 xEvent core_mn
= { .u
.u
.type
= MappingNotify
};
103 core_mn
.u
.mappingNotify
.request
= MappingKeyboard
;
105 /* Clip the keycode range to what the client knows about, so it
106 * doesn't freak out. */
107 if (first_key
>= clients
[i
]->minKC
)
108 core_mn
.u
.mappingNotify
.firstKeyCode
= first_key
;
110 core_mn
.u
.mappingNotify
.firstKeyCode
= clients
[i
]->minKC
;
111 if (first_key
+ num_keys
- 1 <= clients
[i
]->maxKC
)
112 core_mn
.u
.mappingNotify
.count
= num_keys
;
114 core_mn
.u
.mappingNotify
.count
= clients
[i
]->maxKC
-
115 clients
[i
]->minKC
+ 1;
117 WriteEventsToClient(clients
[i
], 1, &core_mn
);
119 if (modmap_changed
) {
121 .u
.mappingNotify
.request
= MappingModifier
,
122 .u
.mappingNotify
.firstKeyCode
= 0,
123 .u
.mappingNotify
.count
= 0
125 core_mn
.u
.u
.type
= MappingNotify
;
126 WriteEventsToClient(clients
[i
], 1, &core_mn
);
130 /* Hmm, maybe we can accidentally generate Xi events for core devices
131 * here? Clients might be upset, but that seems better than the
132 * alternative of stale keymaps. -ds */
133 if (keymap_changed
) {
134 deviceMappingNotify xi_mn
= {
135 .type
= DeviceMappingNotify
,
137 .request
= MappingKeyboard
,
138 .firstKeyCode
= first_key
,
142 SendEventToAllWindows(kbd
, DeviceMappingNotifyMask
, (xEvent
*) &xi_mn
,
145 if (modmap_changed
) {
146 deviceMappingNotify xi_mn
= {
147 .type
= DeviceMappingNotify
,
149 .request
= MappingModifier
,
154 SendEventToAllWindows(kbd
, DeviceMappingNotifyMask
, (xEvent
*) &xi_mn
,
159 /***====================================================================***/
162 XkbSendNewKeyboardNotify(DeviceIntPtr kbd
, xkbNewKeyboardNotify
* pNKN
)
165 Time time
= GetTimeInMillis();
166 CARD16 changed
= pNKN
->changed
;
168 pNKN
->type
= XkbEventCode
+ XkbEventBase
;
169 pNKN
->xkbType
= XkbNewKeyboardNotify
;
171 for (i
= 1; i
< currentMaxClients
; i
++) {
172 if (!clients
[i
] || clients
[i
]->clientState
!= ClientStateRunning
)
175 if (!(clients
[i
]->newKeyboardNotifyMask
& changed
))
178 pNKN
->sequenceNumber
= clients
[i
]->sequence
;
180 pNKN
->changed
= changed
;
181 if (clients
[i
]->swapped
) {
182 swaps(&pNKN
->sequenceNumber
);
184 swaps(&pNKN
->changed
);
186 WriteToClient(clients
[i
], sizeof(xEvent
), pNKN
);
188 if (changed
& XkbNKN_KeycodesMask
) {
189 clients
[i
]->minKC
= pNKN
->minKeyCode
;
190 clients
[i
]->maxKC
= pNKN
->maxKeyCode
;
194 XkbSendLegacyMapNotify(kbd
, XkbNewKeyboardNotify
, changed
, pNKN
->minKeyCode
,
195 pNKN
->maxKeyCode
- pNKN
->minKeyCode
+ 1);
200 /***====================================================================***/
203 XkbSendStateNotify(DeviceIntPtr kbd
, xkbStateNotify
* pSN
)
207 XkbInterestPtr interest
;
209 register CARD16 changed
, bState
;
211 interest
= kbd
->xkb_interest
;
212 if (!interest
|| !kbd
->key
|| !kbd
->key
->xkbInfo
)
214 xkbi
= kbd
->key
->xkbInfo
;
215 state
= &xkbi
->state
;
217 pSN
->type
= XkbEventCode
+ XkbEventBase
;
218 pSN
->xkbType
= XkbStateNotify
;
219 pSN
->deviceID
= kbd
->id
;
220 pSN
->time
= time
= GetTimeInMillis();
221 pSN
->mods
= state
->mods
;
222 pSN
->baseMods
= state
->base_mods
;
223 pSN
->latchedMods
= state
->latched_mods
;
224 pSN
->lockedMods
= state
->locked_mods
;
225 pSN
->group
= state
->group
;
226 pSN
->baseGroup
= state
->base_group
;
227 pSN
->latchedGroup
= state
->latched_group
;
228 pSN
->lockedGroup
= state
->locked_group
;
229 pSN
->compatState
= state
->compat_state
;
230 pSN
->grabMods
= state
->grab_mods
;
231 pSN
->compatGrabMods
= state
->compat_grab_mods
;
232 pSN
->lookupMods
= state
->lookup_mods
;
233 pSN
->compatLookupMods
= state
->compat_lookup_mods
;
234 pSN
->ptrBtnState
= state
->ptr_buttons
;
235 changed
= pSN
->changed
;
236 bState
= pSN
->ptrBtnState
;
239 if ((!interest
->client
->clientGone
) &&
240 (interest
->client
->requestVector
!= InitialVector
) &&
241 (interest
->client
->xkbClientFlags
& _XkbClientInitialized
) &&
242 (interest
->stateNotifyMask
& changed
)) {
243 pSN
->sequenceNumber
= interest
->client
->sequence
;
245 pSN
->changed
= changed
;
246 pSN
->ptrBtnState
= bState
;
247 if (interest
->client
->swapped
) {
248 swaps(&pSN
->sequenceNumber
);
250 swaps(&pSN
->changed
);
251 swaps(&pSN
->ptrBtnState
);
253 WriteToClient(interest
->client
, sizeof(xEvent
), pSN
);
255 interest
= interest
->next
;
260 /***====================================================================***/
263 * This function sends out XKB mapping notify events to clients which
264 * have explicitly selected for them. Core and Xi events are handled by
265 * XkbSendLegacyMapNotify. */
267 XkbSendMapNotify(DeviceIntPtr kbd
, xkbMapNotify
* pMN
)
270 CARD32 time
= GetTimeInMillis();
271 CARD16 changed
= pMN
->changed
;
272 XkbSrvInfoPtr xkbi
= kbd
->key
->xkbInfo
;
274 pMN
->minKeyCode
= xkbi
->desc
->min_key_code
;
275 pMN
->maxKeyCode
= xkbi
->desc
->max_key_code
;
276 pMN
->type
= XkbEventCode
+ XkbEventBase
;
277 pMN
->xkbType
= XkbMapNotify
;
278 pMN
->deviceID
= kbd
->id
;
280 /* 0 is serverClient. */
281 for (i
= 1; i
< currentMaxClients
; i
++) {
282 if (!clients
[i
] || clients
[i
]->clientState
!= ClientStateRunning
)
285 if (!(clients
[i
]->mapNotifyMask
& changed
))
289 pMN
->sequenceNumber
= clients
[i
]->sequence
;
290 pMN
->changed
= changed
;
292 if (clients
[i
]->swapped
) {
293 swaps(&pMN
->sequenceNumber
);
295 swaps(&pMN
->changed
);
297 WriteToClient(clients
[i
], sizeof(xEvent
), pMN
);
300 XkbSendLegacyMapNotify(kbd
, XkbMapNotify
, changed
, pMN
->firstKeySym
,
305 XkbComputeControlsNotify(DeviceIntPtr kbd
,
308 xkbControlsNotify
* pCN
, Bool forceCtrlProc
)
311 CARD32 changedControls
;
315 if (!kbd
|| !kbd
->kbdfeed
)
318 if (old
->enabled_ctrls
!= new->enabled_ctrls
)
319 changedControls
|= XkbControlsEnabledMask
;
320 if ((old
->repeat_delay
!= new->repeat_delay
) ||
321 (old
->repeat_interval
!= new->repeat_interval
))
322 changedControls
|= XkbRepeatKeysMask
;
323 for (i
= 0; i
< XkbPerKeyBitArraySize
; i
++)
324 if (old
->per_key_repeat
[i
] != new->per_key_repeat
[i
])
325 changedControls
|= XkbPerKeyRepeatMask
;
326 if (old
->slow_keys_delay
!= new->slow_keys_delay
)
327 changedControls
|= XkbSlowKeysMask
;
328 if (old
->debounce_delay
!= new->debounce_delay
)
329 changedControls
|= XkbBounceKeysMask
;
330 if ((old
->mk_delay
!= new->mk_delay
) ||
331 (old
->mk_interval
!= new->mk_interval
) ||
332 (old
->mk_dflt_btn
!= new->mk_dflt_btn
))
333 changedControls
|= XkbMouseKeysMask
;
334 if ((old
->mk_time_to_max
!= new->mk_time_to_max
) ||
335 (old
->mk_curve
!= new->mk_curve
) ||
336 (old
->mk_max_speed
!= new->mk_max_speed
))
337 changedControls
|= XkbMouseKeysAccelMask
;
338 if (old
->ax_options
!= new->ax_options
)
339 changedControls
|= XkbAccessXKeysMask
;
340 if ((old
->ax_options
^ new->ax_options
) & XkbAX_SKOptionsMask
)
341 changedControls
|= XkbStickyKeysMask
;
342 if ((old
->ax_options
^ new->ax_options
) & XkbAX_FBOptionsMask
)
343 changedControls
|= XkbAccessXFeedbackMask
;
344 if ((old
->ax_timeout
!= new->ax_timeout
) ||
345 (old
->axt_ctrls_mask
!= new->axt_ctrls_mask
) ||
346 (old
->axt_ctrls_values
!= new->axt_ctrls_values
) ||
347 (old
->axt_opts_mask
!= new->axt_opts_mask
) ||
348 (old
->axt_opts_values
!= new->axt_opts_values
)) {
349 changedControls
|= XkbAccessXTimeoutMask
;
351 if ((old
->internal
.mask
!= new->internal
.mask
) ||
352 (old
->internal
.real_mods
!= new->internal
.real_mods
) ||
353 (old
->internal
.vmods
!= new->internal
.vmods
))
354 changedControls
|= XkbInternalModsMask
;
355 if ((old
->ignore_lock
.mask
!= new->ignore_lock
.mask
) ||
356 (old
->ignore_lock
.real_mods
!= new->ignore_lock
.real_mods
) ||
357 (old
->ignore_lock
.vmods
!= new->ignore_lock
.vmods
))
358 changedControls
|= XkbIgnoreLockModsMask
;
360 if (new->enabled_ctrls
& XkbRepeatKeysMask
)
361 kbd
->kbdfeed
->ctrl
.autoRepeat
= TRUE
;
363 kbd
->kbdfeed
->ctrl
.autoRepeat
= FALSE
;
365 if (kbd
->kbdfeed
&& kbd
->kbdfeed
->CtrlProc
&&
366 (changedControls
|| forceCtrlProc
))
367 (*kbd
->kbdfeed
->CtrlProc
) (kbd
, &kbd
->kbdfeed
->ctrl
);
369 if ((!changedControls
) && (old
->num_groups
== new->num_groups
))
372 if (!kbd
->xkb_interest
)
375 pCN
->changedControls
= changedControls
;
376 pCN
->enabledControls
= new->enabled_ctrls
;
377 pCN
->enabledControlChanges
= (new->enabled_ctrls
^ old
->enabled_ctrls
);
378 pCN
->numGroups
= new->num_groups
;
384 XkbSendControlsNotify(DeviceIntPtr kbd
, xkbControlsNotify
* pCN
)
387 CARD32 changedControls
, enabledControls
, enabledChanges
= 0;
389 XkbInterestPtr interest
;
392 interest
= kbd
->xkb_interest
;
393 if (!interest
|| !kbd
->key
|| !kbd
->key
->xkbInfo
)
395 xkbi
= kbd
->key
->xkbInfo
;
398 enabledControls
= xkbi
->desc
->ctrls
->enabled_ctrls
;
399 changedControls
= pCN
->changedControls
;
400 pCN
->numGroups
= xkbi
->desc
->ctrls
->num_groups
;
402 if ((!interest
->client
->clientGone
) &&
403 (interest
->client
->requestVector
!= InitialVector
) &&
404 (interest
->client
->xkbClientFlags
& _XkbClientInitialized
) &&
405 (interest
->ctrlsNotifyMask
& changedControls
)) {
407 pCN
->type
= XkbEventCode
+ XkbEventBase
;
408 pCN
->xkbType
= XkbControlsNotify
;
409 pCN
->deviceID
= kbd
->id
;
410 pCN
->time
= time
= GetTimeInMillis();
411 enabledChanges
= pCN
->enabledControlChanges
;
414 pCN
->changedControls
= changedControls
;
415 pCN
->enabledControls
= enabledControls
;
416 pCN
->enabledControlChanges
= enabledChanges
;
417 pCN
->sequenceNumber
= interest
->client
->sequence
;
419 if (interest
->client
->swapped
) {
420 swaps(&pCN
->sequenceNumber
);
421 swapl(&pCN
->changedControls
);
422 swapl(&pCN
->enabledControls
);
423 swapl(&pCN
->enabledControlChanges
);
426 WriteToClient(interest
->client
, sizeof(xEvent
), pCN
);
428 interest
= interest
->next
;
434 XkbSendIndicatorNotify(DeviceIntPtr kbd
, int xkbType
, xkbIndicatorNotify
* pEv
)
437 XkbInterestPtr interest
;
439 CARD32 state
, changed
;
441 interest
= kbd
->xkb_interest
;
447 changed
= pEv
->changed
;
449 if ((!interest
->client
->clientGone
) &&
450 (interest
->client
->requestVector
!= InitialVector
) &&
451 (interest
->client
->xkbClientFlags
& _XkbClientInitialized
) &&
452 (((xkbType
== XkbIndicatorStateNotify
) &&
453 (interest
->iStateNotifyMask
& changed
)) ||
454 ((xkbType
== XkbIndicatorMapNotify
) &&
455 (interest
->iMapNotifyMask
& changed
)))) {
457 pEv
->type
= XkbEventCode
+ XkbEventBase
;
458 pEv
->xkbType
= xkbType
;
459 pEv
->deviceID
= kbd
->id
;
460 pEv
->time
= time
= GetTimeInMillis();
463 pEv
->sequenceNumber
= interest
->client
->sequence
;
465 pEv
->changed
= changed
;
467 if (interest
->client
->swapped
) {
468 swaps(&pEv
->sequenceNumber
);
470 swapl(&pEv
->changed
);
473 WriteToClient(interest
->client
, sizeof(xEvent
), pEv
);
475 interest
= interest
->next
;
481 XkbHandleBell(BOOL force
,
486 CARD8
class, Atom name
, WindowPtr pWin
, ClientPtr pClient
)
491 XkbInterestPtr interest
;
493 CARD16 pitch
, duration
;
497 if (!kbd
->key
|| !kbd
->key
->xkbInfo
)
500 xkbi
= kbd
->key
->xkbInfo
;
502 if ((force
|| (xkbi
->desc
->ctrls
->enabled_ctrls
& XkbAudibleBellMask
)) &&
504 if (kbd
->kbdfeed
->BellProc
)
505 (*kbd
->kbdfeed
->BellProc
) (percent
, kbd
, (pointer
) pCtrl
, class);
507 interest
= kbd
->xkb_interest
;
508 if ((!interest
) || (force
))
511 if ((class == 0) || (class == KbdFeedbackClass
)) {
512 KeybdCtrl
*pKeyCtrl
= (KeybdCtrl
*) pCtrl
;
515 pitch
= pKeyCtrl
->bell_pitch
;
516 duration
= pKeyCtrl
->bell_duration
;
518 else if (class == BellFeedbackClass
) {
519 BellCtrl
*pBellCtrl
= (BellCtrl
*) pCtrl
;
522 pitch
= pBellCtrl
->pitch
;
523 duration
= pBellCtrl
->duration
;
530 if ((!interest
->client
->clientGone
) &&
531 (interest
->client
->requestVector
!= InitialVector
) &&
532 (interest
->client
->xkbClientFlags
& _XkbClientInitialized
) &&
533 (interest
->bellNotifyMask
)) {
535 time
= GetTimeInMillis();
536 bn
.type
= XkbEventCode
+ XkbEventBase
;
537 bn
.xkbType
= XkbBellNotify
;
538 bn
.deviceID
= kbd
->id
;
539 bn
.bellClass
= class;
541 bn
.percent
= percent
;
542 bn
.eventOnly
= (eventOnly
!= 0);
543 winID
= (pWin
? pWin
->drawable
.id
: None
);
546 bn
.sequenceNumber
= interest
->client
->sequence
;
549 bn
.duration
= duration
;
552 if (interest
->client
->swapped
) {
553 swaps(&bn
.sequenceNumber
);
560 WriteToClient(interest
->client
, sizeof(xEvent
), &bn
);
562 interest
= interest
->next
;
568 XkbSendAccessXNotify(DeviceIntPtr kbd
, xkbAccessXNotify
* pEv
)
571 XkbInterestPtr interest
;
573 CARD16 sk_delay
, db_delay
;
575 interest
= kbd
->xkb_interest
;
580 sk_delay
= pEv
->slowKeysDelay
;
581 db_delay
= pEv
->debounceDelay
;
583 if ((!interest
->client
->clientGone
) &&
584 (interest
->client
->requestVector
!= InitialVector
) &&
585 (interest
->client
->xkbClientFlags
& _XkbClientInitialized
) &&
586 (interest
->accessXNotifyMask
& (1 << pEv
->detail
))) {
588 pEv
->type
= XkbEventCode
+ XkbEventBase
;
589 pEv
->xkbType
= XkbAccessXNotify
;
590 pEv
->deviceID
= kbd
->id
;
591 pEv
->time
= time
= GetTimeInMillis();
594 pEv
->sequenceNumber
= interest
->client
->sequence
;
596 pEv
->slowKeysDelay
= sk_delay
;
597 pEv
->debounceDelay
= db_delay
;
598 if (interest
->client
->swapped
) {
599 swaps(&pEv
->sequenceNumber
);
601 swaps(&pEv
->slowKeysDelay
);
602 swaps(&pEv
->debounceDelay
);
604 WriteToClient(interest
->client
, sizeof(xEvent
), pEv
);
606 interest
= interest
->next
;
612 XkbSendNamesNotify(DeviceIntPtr kbd
, xkbNamesNotify
* pEv
)
615 XkbInterestPtr interest
;
617 CARD16 changed
, changedVirtualMods
;
618 CARD32 changedIndicators
;
620 interest
= kbd
->xkb_interest
;
625 changed
= pEv
->changed
;
626 changedIndicators
= pEv
->changedIndicators
;
627 changedVirtualMods
= pEv
->changedVirtualMods
;
629 if ((!interest
->client
->clientGone
) &&
630 (interest
->client
->requestVector
!= InitialVector
) &&
631 (interest
->client
->xkbClientFlags
& _XkbClientInitialized
) &&
632 (interest
->namesNotifyMask
& pEv
->changed
)) {
634 pEv
->type
= XkbEventCode
+ XkbEventBase
;
635 pEv
->xkbType
= XkbNamesNotify
;
636 pEv
->deviceID
= kbd
->id
;
637 pEv
->time
= time
= GetTimeInMillis();
640 pEv
->sequenceNumber
= interest
->client
->sequence
;
642 pEv
->changed
= changed
;
643 pEv
->changedIndicators
= changedIndicators
;
644 pEv
->changedVirtualMods
= changedVirtualMods
;
645 if (interest
->client
->swapped
) {
646 swaps(&pEv
->sequenceNumber
);
648 swaps(&pEv
->changed
);
649 swapl(&pEv
->changedIndicators
);
650 swaps(&pEv
->changedVirtualMods
);
652 WriteToClient(interest
->client
, sizeof(xEvent
), pEv
);
654 interest
= interest
->next
;
660 XkbSendCompatMapNotify(DeviceIntPtr kbd
, xkbCompatMapNotify
* pEv
)
663 XkbInterestPtr interest
;
665 CARD16 firstSI
= 0, nSI
= 0, nTotalSI
= 0;
667 interest
= kbd
->xkb_interest
;
673 if ((!interest
->client
->clientGone
) &&
674 (interest
->client
->requestVector
!= InitialVector
) &&
675 (interest
->client
->xkbClientFlags
& _XkbClientInitialized
) &&
676 (interest
->compatNotifyMask
)) {
678 pEv
->type
= XkbEventCode
+ XkbEventBase
;
679 pEv
->xkbType
= XkbCompatMapNotify
;
680 pEv
->deviceID
= kbd
->id
;
681 pEv
->time
= time
= GetTimeInMillis();
682 firstSI
= pEv
->firstSI
;
684 nTotalSI
= pEv
->nTotalSI
;
687 pEv
->sequenceNumber
= interest
->client
->sequence
;
689 pEv
->firstSI
= firstSI
;
691 pEv
->nTotalSI
= nTotalSI
;
692 if (interest
->client
->swapped
) {
693 swaps(&pEv
->sequenceNumber
);
695 swaps(&pEv
->firstSI
);
697 swaps(&pEv
->nTotalSI
);
699 WriteToClient(interest
->client
, sizeof(xEvent
), pEv
);
701 interest
= interest
->next
;
707 XkbSendActionMessage(DeviceIntPtr kbd
, xkbActionMessage
* pEv
)
711 XkbInterestPtr interest
;
714 interest
= kbd
->xkb_interest
;
715 if (!interest
|| !kbd
->key
|| !kbd
->key
->xkbInfo
)
718 xkbi
= kbd
->key
->xkbInfo
;
721 pEv
->mods
= xkbi
->state
.mods
;
722 pEv
->group
= xkbi
->state
.group
;
724 if ((!interest
->client
->clientGone
) &&
725 (interest
->client
->requestVector
!= InitialVector
) &&
726 (interest
->client
->xkbClientFlags
& _XkbClientInitialized
) &&
727 (interest
->actionMessageMask
)) {
729 pEv
->type
= XkbEventCode
+ XkbEventBase
;
730 pEv
->xkbType
= XkbActionMessage
;
731 pEv
->deviceID
= kbd
->id
;
732 pEv
->sequenceNumber
= interest
->client
->sequence
;
733 pEv
->time
= time
= GetTimeInMillis();
736 pEv
->sequenceNumber
= interest
->client
->sequence
;
738 if (interest
->client
->swapped
) {
739 swaps(&pEv
->sequenceNumber
);
742 WriteToClient(interest
->client
, sizeof(xEvent
), pEv
);
744 interest
= interest
->next
;
750 XkbSendExtensionDeviceNotify(DeviceIntPtr dev
,
751 ClientPtr client
, xkbExtensionDeviceNotify
* pEv
)
754 XkbInterestPtr interest
;
756 CARD32 defined
, state
;
759 interest
= dev
->xkb_interest
;
764 reason
= pEv
->reason
;
765 defined
= pEv
->ledsDefined
;
766 state
= pEv
->ledState
;
768 if ((!interest
->client
->clientGone
) &&
769 (interest
->client
->requestVector
!= InitialVector
) &&
770 (interest
->client
->xkbClientFlags
& _XkbClientInitialized
) &&
771 (interest
->extDevNotifyMask
& reason
)) {
773 pEv
->type
= XkbEventCode
+ XkbEventBase
;
774 pEv
->xkbType
= XkbExtensionDeviceNotify
;
775 pEv
->deviceID
= dev
->id
;
776 pEv
->sequenceNumber
= interest
->client
->sequence
;
777 pEv
->time
= time
= GetTimeInMillis();
781 pEv
->sequenceNumber
= interest
->client
->sequence
;
783 pEv
->ledsDefined
= defined
;
784 pEv
->ledState
= state
;
785 pEv
->reason
= reason
;
786 pEv
->supported
= XkbXI_AllFeaturesMask
;
788 if (interest
->client
->swapped
) {
789 swaps(&pEv
->sequenceNumber
);
791 swapl(&pEv
->ledsDefined
);
792 swapl(&pEv
->ledState
);
794 swaps(&pEv
->supported
);
796 WriteToClient(interest
->client
, sizeof(xEvent
), pEv
);
798 interest
= interest
->next
;
804 XkbSendNotification(DeviceIntPtr kbd
,
805 XkbChangesPtr pChanges
, XkbEventCausePtr cause
)
807 XkbSrvLedInfoPtr sli
;
810 if (pChanges
->state_changes
) {
813 sn
.changed
= pChanges
->state_changes
;
814 sn
.keycode
= cause
->kc
;
815 sn
.eventType
= cause
->event
;
816 sn
.requestMajor
= cause
->mjr
;
817 sn
.requestMinor
= cause
->mnr
;
818 XkbSendStateNotify(kbd
, &sn
);
820 if (pChanges
->map
.changed
) {
823 memset(&mn
, 0, sizeof(xkbMapNotify
));
824 mn
.changed
= pChanges
->map
.changed
;
825 mn
.firstType
= pChanges
->map
.first_type
;
826 mn
.nTypes
= pChanges
->map
.num_types
;
827 mn
.firstKeySym
= pChanges
->map
.first_key_sym
;
828 mn
.nKeySyms
= pChanges
->map
.num_key_syms
;
829 mn
.firstKeyAct
= pChanges
->map
.first_key_act
;
830 mn
.nKeyActs
= pChanges
->map
.num_key_acts
;
831 mn
.firstKeyBehavior
= pChanges
->map
.first_key_behavior
;
832 mn
.nKeyBehaviors
= pChanges
->map
.num_key_behaviors
;
833 mn
.virtualMods
= pChanges
->map
.vmods
;
834 mn
.firstKeyExplicit
= pChanges
->map
.first_key_explicit
;
835 mn
.nKeyExplicit
= pChanges
->map
.num_key_explicit
;
836 mn
.firstModMapKey
= pChanges
->map
.first_modmap_key
;
837 mn
.nModMapKeys
= pChanges
->map
.num_modmap_keys
;
838 mn
.firstVModMapKey
= pChanges
->map
.first_vmodmap_key
;
839 mn
.nVModMapKeys
= pChanges
->map
.num_vmodmap_keys
;
840 XkbSendMapNotify(kbd
, &mn
);
842 if ((pChanges
->ctrls
.changed_ctrls
) ||
843 (pChanges
->ctrls
.enabled_ctrls_changes
)) {
844 xkbControlsNotify cn
;
846 memset(&cn
, 0, sizeof(xkbControlsNotify
));
847 cn
.changedControls
= pChanges
->ctrls
.changed_ctrls
;
848 cn
.enabledControlChanges
= pChanges
->ctrls
.enabled_ctrls_changes
;
849 cn
.keycode
= cause
->kc
;
850 cn
.eventType
= cause
->event
;
851 cn
.requestMajor
= cause
->mjr
;
852 cn
.requestMinor
= cause
->mnr
;
853 XkbSendControlsNotify(kbd
, &cn
);
855 if (pChanges
->indicators
.map_changes
) {
856 xkbIndicatorNotify in
;
859 sli
= XkbFindSrvLedInfo(kbd
, XkbDfltXIClass
, XkbDfltXIId
, 0);
860 memset(&in
, 0, sizeof(xkbIndicatorNotify
));
861 in
.state
= sli
->effectiveState
;
862 in
.changed
= pChanges
->indicators
.map_changes
;
863 XkbSendIndicatorNotify(kbd
, XkbIndicatorMapNotify
, &in
);
865 if (pChanges
->indicators
.state_changes
) {
866 xkbIndicatorNotify in
;
869 sli
= XkbFindSrvLedInfo(kbd
, XkbDfltXIClass
, XkbDfltXIId
, 0);
870 memset(&in
, 0, sizeof(xkbIndicatorNotify
));
871 in
.state
= sli
->effectiveState
;
872 in
.changed
= pChanges
->indicators
.state_changes
;
873 XkbSendIndicatorNotify(kbd
, XkbIndicatorStateNotify
, &in
);
875 if (pChanges
->names
.changed
) {
878 memset(&nn
, 0, sizeof(xkbNamesNotify
));
879 nn
.changed
= pChanges
->names
.changed
;
880 nn
.firstType
= pChanges
->names
.first_type
;
881 nn
.nTypes
= pChanges
->names
.num_types
;
882 nn
.firstLevelName
= pChanges
->names
.first_lvl
;
883 nn
.nLevelNames
= pChanges
->names
.num_lvls
;
884 nn
.nRadioGroups
= pChanges
->names
.num_rg
;
885 nn
.changedVirtualMods
= pChanges
->names
.changed_vmods
;
886 nn
.changedIndicators
= pChanges
->names
.changed_indicators
;
887 XkbSendNamesNotify(kbd
, &nn
);
889 if ((pChanges
->compat
.changed_groups
) || (pChanges
->compat
.num_si
> 0)) {
890 xkbCompatMapNotify cmn
;
892 memset(&cmn
, 0, sizeof(xkbCompatMapNotify
));
893 cmn
.changedGroups
= pChanges
->compat
.changed_groups
;
894 cmn
.firstSI
= pChanges
->compat
.first_si
;
895 cmn
.nSI
= pChanges
->compat
.num_si
;
896 cmn
.nTotalSI
= kbd
->key
->xkbInfo
->desc
->compat
->num_si
;
897 XkbSendCompatMapNotify(kbd
, &cmn
);
902 /***====================================================================***/
905 XkbFilterEvents(ClientPtr client
, int nEvents
, xEvent
*xE
)
907 DeviceIntPtr dev
= NULL
;
909 CARD8 type
= xE
[0].u
.u
.type
;
911 if (xE
->u
.u
.type
& EXTENSION_EVENT_BASE
)
912 dev
= XIGetDevice(xE
);
915 dev
= PickKeyboard(client
);
920 xkbi
= dev
->key
->xkbInfo
;
922 if (client
->xkbClientFlags
& _XkbClientInitialized
) {
923 if ((xkbDebugFlags
& 0x10) &&
924 (type
== KeyPress
|| type
== KeyRelease
||
925 type
== DeviceKeyPress
|| type
== DeviceKeyRelease
))
926 DebugF("[xkb] XkbFilterWriteEvents (XKB client): state 0x%04x\n",
927 xE
[0].u
.keyButtonPointer
.state
);
929 if (dev
->deviceGrab
.grab
!= NullGrab
&& dev
->deviceGrab
.fromPassiveGrab
930 && (type
== KeyPress
|| type
== KeyRelease
|| type
== DeviceKeyPress
931 || type
== DeviceKeyRelease
)) {
932 unsigned int state
, flags
;
934 flags
= client
->xkbClientFlags
;
935 state
= xkbi
->state
.compat_grab_mods
;
936 if (flags
& XkbPCF_GrabsUseXKBStateMask
) {
939 if (flags
& XkbPCF_LookupStateWhenGrabbed
) {
940 group
= xkbi
->state
.group
;
941 state
= xkbi
->state
.lookup_mods
;
944 state
= xkbi
->state
.grab_mods
;
945 group
= xkbi
->state
.base_group
+ xkbi
->state
.latched_group
;
946 if (group
< 0 || group
>= xkbi
->desc
->ctrls
->num_groups
)
947 group
= XkbAdjustGroup(group
, xkbi
->desc
->ctrls
);
949 state
= XkbBuildCoreState(state
, group
);
951 else if (flags
& XkbPCF_LookupStateWhenGrabbed
) {
952 state
= xkbi
->state
.compat_lookup_mods
;
954 xE
[0].u
.keyButtonPointer
.state
= state
;
958 if ((xkbDebugFlags
& 0x4) &&
959 (xE
[0].u
.u
.type
== KeyPress
|| xE
[0].u
.u
.type
== KeyRelease
||
960 xE
[0].u
.u
.type
== DeviceKeyPress
||
961 xE
[0].u
.u
.type
== DeviceKeyRelease
)) {
962 DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
963 DebugF("[xkb] event= 0x%04x\n", xE
[0].u
.keyButtonPointer
.state
);
964 DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",
965 xkbi
->state
.lookup_mods
, xkbi
->state
.grab_mods
);
966 DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
967 xkbi
->state
.compat_lookup_mods
,
968 xkbi
->state
.compat_grab_mods
);
970 if (type
>= KeyPress
&& type
<= MotionNotify
) {
973 old
= xE
[0].u
.keyButtonPointer
.state
& ~0x1f00;
974 new = xE
[0].u
.keyButtonPointer
.state
& 0x1F00;
976 if (old
== XkbStateFieldFromRec(&xkbi
->state
))
977 new |= xkbi
->state
.compat_lookup_mods
;
979 new |= xkbi
->state
.compat_grab_mods
;
980 xE
[0].u
.keyButtonPointer
.state
= new;
982 else if (type
== EnterNotify
|| type
== LeaveNotify
) {
983 xE
[0].u
.enterLeave
.state
&= 0x1F00;
984 xE
[0].u
.enterLeave
.state
|= xkbi
->state
.compat_grab_mods
;
986 else if (type
>= DeviceKeyPress
&& type
<= DeviceMotionNotify
) {
988 deviceKeyButtonPointer
*kbp
= (deviceKeyButtonPointer
*) &xE
[0];
990 old
= kbp
->state
& ~0x1F00;
991 new = kbp
->state
& 0x1F00;
992 if (old
== XkbStateFieldFromRec(&xkbi
->state
))
993 new |= xkbi
->state
.compat_lookup_mods
;
995 new |= xkbi
->state
.compat_grab_mods
;
1001 /***====================================================================***/
1004 XkbFindClientResource(DevicePtr inDev
, ClientPtr client
)
1006 DeviceIntPtr dev
= (DeviceIntPtr
) inDev
;
1007 XkbInterestPtr interest
;
1009 if (dev
->xkb_interest
) {
1010 interest
= dev
->xkb_interest
;
1012 if (interest
->client
== client
) {
1015 interest
= interest
->next
;
1022 XkbAddClientResource(DevicePtr inDev
, ClientPtr client
, XID id
)
1024 DeviceIntPtr dev
= (DeviceIntPtr
) inDev
;
1025 XkbInterestPtr interest
;
1027 interest
= dev
->xkb_interest
;
1029 if (interest
->client
== client
)
1030 return ((interest
->resource
== id
) ? interest
: NULL
);
1031 interest
= interest
->next
;
1033 interest
= calloc(1, sizeof(XkbInterestRec
));
1035 interest
->dev
= dev
;
1036 interest
->client
= client
;
1037 interest
->resource
= id
;
1038 interest
->next
= dev
->xkb_interest
;
1039 dev
->xkb_interest
= interest
;
1046 XkbRemoveResourceClient(DevicePtr inDev
, XID id
)
1049 DeviceIntPtr dev
= (DeviceIntPtr
) inDev
;
1050 XkbInterestPtr interest
;
1052 unsigned long autoCtrls
, autoValues
;
1053 ClientPtr client
= NULL
;
1057 if (!dev
->key
|| !dev
->key
->xkbInfo
)
1060 autoCtrls
= autoValues
= 0;
1061 if (dev
->xkb_interest
) {
1062 interest
= dev
->xkb_interest
;
1063 if (interest
&& (interest
->resource
== id
)) {
1064 dev
->xkb_interest
= interest
->next
;
1065 autoCtrls
= interest
->autoCtrls
;
1066 autoValues
= interest
->autoCtrlValues
;
1067 client
= interest
->client
;
1071 while ((!found
) && (interest
->next
)) {
1072 if (interest
->next
->resource
== id
) {
1073 XkbInterestPtr victim
= interest
->next
;
1075 interest
->next
= victim
->next
;
1076 autoCtrls
= victim
->autoCtrls
;
1077 autoValues
= victim
->autoCtrlValues
;
1078 client
= victim
->client
;
1082 interest
= interest
->next
;
1085 if (found
&& autoCtrls
&& dev
->key
&& dev
->key
->xkbInfo
) {
1086 XkbEventCauseRec cause
;
1088 xkbi
= dev
->key
->xkbInfo
;
1089 XkbSetCauseXkbReq(&cause
, X_kbPerClientFlags
, client
);
1090 XkbEnableDisableControls(xkbi
, autoCtrls
, autoValues
, NULL
, &cause
);