Imported Upstream version 1.15.1
[deb_xorg-server.git] / xkb / xkbEvents.c
CommitLineData
a09e091a
JB
1/************************************************************
2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
4Permission to use, copy, modify, and distribute this
5software and its documentation for any purpose and without
6fee is hereby granted, provided that the above copyright
7notice appear in all copies and that both that copyright
8notice and this permission notice appear in supporting
9documentation, and that the name of Silicon Graphics not be
10used in advertising or publicity pertaining to distribution
11of the software without specific prior written permission.
12Silicon Graphics makes no representation about the suitability
13of this software for any purpose. It is provided "as is"
14without any express or implied warranty.
15
16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
23THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25********************************************************/
26
27#ifdef HAVE_DIX_CONFIG_H
28#include <dix-config.h>
29#endif
30
31#include <stdio.h>
32#include <X11/X.h>
33#include <X11/Xproto.h>
34#include <X11/keysym.h>
35#include <X11/extensions/XI.h>
36#include <X11/extensions/XIproto.h>
37#include "inputstr.h"
38#include "exevents.h"
39#include "exglobals.h"
40#include "windowstr.h"
41#include <xkbsrv.h>
42#include "xkb.h"
43
44/***====================================================================***/
45
46/*
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!).
54 */
55static void
56XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed,
57 int first_key, int num_keys)
58{
59 int i;
60 int keymap_changed = 0;
61 int modmap_changed = 0;
62 CARD32 time = GetTimeInMillis();
63
64 if (xkb_event == XkbNewKeyboardNotify) {
65 if (changed & XkbNKN_KeycodesMask) {
66 keymap_changed = 1;
67 modmap_changed = 1;
68 }
69 }
70 else if (xkb_event == XkbMapNotify) {
71 if (changed & XkbKeySymsMask)
72 keymap_changed = 1;
73 if (changed & XkbModifierMapMask)
74 modmap_changed = 1;
75 }
76 if (!keymap_changed && !modmap_changed)
77 return;
78
79 /* 0 is serverClient. */
80 for (i = 1; i < currentMaxClients; i++) {
81 if (!clients[i] || clients[i]->clientState != ClientStateRunning)
82 continue;
83
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))
89 continue;
90 /* Emulate previous server behaviour: any client which has activated
91 * XKB will not receive core events emulated from a NewKeyboardNotify
92 * at all. */
93 if (xkb_event == XkbNewKeyboardNotify &&
94 (clients[i]->xkbClientFlags & _XkbClientInitialized))
95 continue;
96
97 /* Don't send core events to clients who don't know about us. */
98 if (!XIShouldNotify(clients[i], kbd))
99 continue;
100
101 if (keymap_changed) {
102 xEvent core_mn = { .u.u.type = MappingNotify };
103 core_mn.u.mappingNotify.request = MappingKeyboard;
104
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;
109 else
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;
113 else
114 core_mn.u.mappingNotify.count = clients[i]->maxKC -
115 clients[i]->minKC + 1;
116
117 WriteEventsToClient(clients[i], 1, &core_mn);
118 }
119 if (modmap_changed) {
120 xEvent core_mn = {
121 .u.mappingNotify.request = MappingModifier,
122 .u.mappingNotify.firstKeyCode = 0,
123 .u.mappingNotify.count = 0
124 };
125 core_mn.u.u.type = MappingNotify;
126 WriteEventsToClient(clients[i], 1, &core_mn);
127 }
128 }
129
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,
136 .deviceid = kbd->id,
137 .request = MappingKeyboard,
138 .firstKeyCode = first_key,
139 .count = num_keys,
140 .time = time
141 };
142 SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
143 1);
144 }
145 if (modmap_changed) {
146 deviceMappingNotify xi_mn = {
147 .type = DeviceMappingNotify,
148 .deviceid = kbd->id,
149 .request = MappingModifier,
150 .firstKeyCode = 0,
151 .count = 0,
152 .time = time
153 };
154 SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
155 1);
156 }
157}
158
159/***====================================================================***/
160
161void
162XkbSendNewKeyboardNotify(DeviceIntPtr kbd, xkbNewKeyboardNotify * pNKN)
163{
164 int i;
165 Time time = GetTimeInMillis();
166 CARD16 changed = pNKN->changed;
167
168 pNKN->type = XkbEventCode + XkbEventBase;
169 pNKN->xkbType = XkbNewKeyboardNotify;
170
171 for (i = 1; i < currentMaxClients; i++) {
172 if (!clients[i] || clients[i]->clientState != ClientStateRunning)
173 continue;
174
175 if (!(clients[i]->newKeyboardNotifyMask & changed))
176 continue;
177
178 pNKN->sequenceNumber = clients[i]->sequence;
179 pNKN->time = time;
180 pNKN->changed = changed;
181 if (clients[i]->swapped) {
182 swaps(&pNKN->sequenceNumber);
183 swapl(&pNKN->time);
184 swaps(&pNKN->changed);
185 }
186 WriteToClient(clients[i], sizeof(xEvent), pNKN);
187
188 if (changed & XkbNKN_KeycodesMask) {
189 clients[i]->minKC = pNKN->minKeyCode;
190 clients[i]->maxKC = pNKN->maxKeyCode;
191 }
192 }
193
194 XkbSendLegacyMapNotify(kbd, XkbNewKeyboardNotify, changed, pNKN->minKeyCode,
195 pNKN->maxKeyCode - pNKN->minKeyCode + 1);
196
197 return;
198}
199
200/***====================================================================***/
201
202void
203XkbSendStateNotify(DeviceIntPtr kbd, xkbStateNotify * pSN)
204{
205 XkbSrvInfoPtr xkbi;
206 XkbStatePtr state;
207 XkbInterestPtr interest;
208 Time time;
209 register CARD16 changed, bState;
210
211 interest = kbd->xkb_interest;
212 if (!interest || !kbd->key || !kbd->key->xkbInfo)
213 return;
214 xkbi = kbd->key->xkbInfo;
215 state = &xkbi->state;
216
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;
237
238 while (interest) {
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;
244 pSN->time = time;
245 pSN->changed = changed;
246 pSN->ptrBtnState = bState;
247 if (interest->client->swapped) {
248 swaps(&pSN->sequenceNumber);
249 swapl(&pSN->time);
250 swaps(&pSN->changed);
251 swaps(&pSN->ptrBtnState);
252 }
253 WriteToClient(interest->client, sizeof(xEvent), pSN);
254 }
255 interest = interest->next;
256 }
257 return;
258}
259
260/***====================================================================***/
261
262/*
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. */
266void
267XkbSendMapNotify(DeviceIntPtr kbd, xkbMapNotify * pMN)
268{
269 int i;
270 CARD32 time = GetTimeInMillis();
271 CARD16 changed = pMN->changed;
272 XkbSrvInfoPtr xkbi = kbd->key->xkbInfo;
273
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;
279
280 /* 0 is serverClient. */
281 for (i = 1; i < currentMaxClients; i++) {
282 if (!clients[i] || clients[i]->clientState != ClientStateRunning)
283 continue;
284
285 if (!(clients[i]->mapNotifyMask & changed))
286 continue;
287
288 pMN->time = time;
289 pMN->sequenceNumber = clients[i]->sequence;
290 pMN->changed = changed;
291
292 if (clients[i]->swapped) {
293 swaps(&pMN->sequenceNumber);
294 swapl(&pMN->time);
295 swaps(&pMN->changed);
296 }
297 WriteToClient(clients[i], sizeof(xEvent), pMN);
298 }
299
300 XkbSendLegacyMapNotify(kbd, XkbMapNotify, changed, pMN->firstKeySym,
301 pMN->nKeySyms);
302}
303
304int
305XkbComputeControlsNotify(DeviceIntPtr kbd,
306 XkbControlsPtr old,
307 XkbControlsPtr new,
308 xkbControlsNotify * pCN, Bool forceCtrlProc)
309{
310 int i;
311 CARD32 changedControls;
312
313 changedControls = 0;
314
315 if (!kbd || !kbd->kbdfeed)
316 return 0;
317
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;
350 }
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;
359
360 if (new->enabled_ctrls & XkbRepeatKeysMask)
361 kbd->kbdfeed->ctrl.autoRepeat = TRUE;
362 else
363 kbd->kbdfeed->ctrl.autoRepeat = FALSE;
364
365 if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc &&
366 (changedControls || forceCtrlProc))
367 (*kbd->kbdfeed->CtrlProc) (kbd, &kbd->kbdfeed->ctrl);
368
369 if ((!changedControls) && (old->num_groups == new->num_groups))
370 return 0;
371
372 if (!kbd->xkb_interest)
373 return 0;
374
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;
379
380 return 1;
381}
382
383void
384XkbSendControlsNotify(DeviceIntPtr kbd, xkbControlsNotify * pCN)
385{
386 int initialized;
387 CARD32 changedControls, enabledControls, enabledChanges = 0;
388 XkbSrvInfoPtr xkbi;
389 XkbInterestPtr interest;
390 Time time = 0;
391
392 interest = kbd->xkb_interest;
393 if (!interest || !kbd->key || !kbd->key->xkbInfo)
394 return;
395 xkbi = kbd->key->xkbInfo;
396
397 initialized = 0;
398 enabledControls = xkbi->desc->ctrls->enabled_ctrls;
399 changedControls = pCN->changedControls;
400 pCN->numGroups = xkbi->desc->ctrls->num_groups;
401 while (interest) {
402 if ((!interest->client->clientGone) &&
403 (interest->client->requestVector != InitialVector) &&
404 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
405 (interest->ctrlsNotifyMask & changedControls)) {
406 if (!initialized) {
407 pCN->type = XkbEventCode + XkbEventBase;
408 pCN->xkbType = XkbControlsNotify;
409 pCN->deviceID = kbd->id;
410 pCN->time = time = GetTimeInMillis();
411 enabledChanges = pCN->enabledControlChanges;
412 initialized = 1;
413 }
414 pCN->changedControls = changedControls;
415 pCN->enabledControls = enabledControls;
416 pCN->enabledControlChanges = enabledChanges;
417 pCN->sequenceNumber = interest->client->sequence;
418 pCN->time = time;
419 if (interest->client->swapped) {
420 swaps(&pCN->sequenceNumber);
421 swapl(&pCN->changedControls);
422 swapl(&pCN->enabledControls);
423 swapl(&pCN->enabledControlChanges);
424 swapl(&pCN->time);
425 }
426 WriteToClient(interest->client, sizeof(xEvent), pCN);
427 }
428 interest = interest->next;
429 }
430 return;
431}
432
433static void
434XkbSendIndicatorNotify(DeviceIntPtr kbd, int xkbType, xkbIndicatorNotify * pEv)
435{
436 int initialized;
437 XkbInterestPtr interest;
438 Time time = 0;
439 CARD32 state, changed;
440
441 interest = kbd->xkb_interest;
442 if (!interest)
443 return;
444
445 initialized = 0;
446 state = pEv->state;
447 changed = pEv->changed;
448 while (interest) {
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)))) {
456 if (!initialized) {
457 pEv->type = XkbEventCode + XkbEventBase;
458 pEv->xkbType = xkbType;
459 pEv->deviceID = kbd->id;
460 pEv->time = time = GetTimeInMillis();
461 initialized = 1;
462 }
463 pEv->sequenceNumber = interest->client->sequence;
464 pEv->time = time;
465 pEv->changed = changed;
466 pEv->state = state;
467 if (interest->client->swapped) {
468 swaps(&pEv->sequenceNumber);
469 swapl(&pEv->time);
470 swapl(&pEv->changed);
471 swapl(&pEv->state);
472 }
473 WriteToClient(interest->client, sizeof(xEvent), pEv);
474 }
475 interest = interest->next;
476 }
477 return;
478}
479
480void
481XkbHandleBell(BOOL force,
482 BOOL eventOnly,
483 DeviceIntPtr kbd,
484 CARD8 percent,
485 pointer pCtrl,
486 CARD8 class, Atom name, WindowPtr pWin, ClientPtr pClient)
487{
488 xkbBellNotify bn;
489 int initialized;
490 XkbSrvInfoPtr xkbi;
491 XkbInterestPtr interest;
492 CARD8 id;
493 CARD16 pitch, duration;
494 Time time = 0;
495 XID winID = 0;
496
497 if (!kbd->key || !kbd->key->xkbInfo)
498 return;
499
500 xkbi = kbd->key->xkbInfo;
501
502 if ((force || (xkbi->desc->ctrls->enabled_ctrls & XkbAudibleBellMask)) &&
503 (!eventOnly)) {
504 if (kbd->kbdfeed->BellProc)
505 (*kbd->kbdfeed->BellProc) (percent, kbd, (pointer) pCtrl, class);
506 }
507 interest = kbd->xkb_interest;
508 if ((!interest) || (force))
509 return;
510
511 if ((class == 0) || (class == KbdFeedbackClass)) {
512 KeybdCtrl *pKeyCtrl = (KeybdCtrl *) pCtrl;
513
514 id = pKeyCtrl->id;
515 pitch = pKeyCtrl->bell_pitch;
516 duration = pKeyCtrl->bell_duration;
517 }
518 else if (class == BellFeedbackClass) {
519 BellCtrl *pBellCtrl = (BellCtrl *) pCtrl;
520
521 id = pBellCtrl->id;
522 pitch = pBellCtrl->pitch;
523 duration = pBellCtrl->duration;
524 }
525 else
526 return;
527
528 initialized = 0;
529 while (interest) {
530 if ((!interest->client->clientGone) &&
531 (interest->client->requestVector != InitialVector) &&
532 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
533 (interest->bellNotifyMask)) {
534 if (!initialized) {
535 time = GetTimeInMillis();
536 bn.type = XkbEventCode + XkbEventBase;
537 bn.xkbType = XkbBellNotify;
538 bn.deviceID = kbd->id;
539 bn.bellClass = class;
540 bn.bellID = id;
541 bn.percent = percent;
542 bn.eventOnly = (eventOnly != 0);
543 winID = (pWin ? pWin->drawable.id : None);
544 initialized = 1;
545 }
546 bn.sequenceNumber = interest->client->sequence;
547 bn.time = time;
548 bn.pitch = pitch;
549 bn.duration = duration;
550 bn.name = name;
551 bn.window = winID;
552 if (interest->client->swapped) {
553 swaps(&bn.sequenceNumber);
554 swapl(&bn.time);
555 swaps(&bn.pitch);
556 swaps(&bn.duration);
557 swapl(&bn.name);
558 swapl(&bn.window);
559 }
560 WriteToClient(interest->client, sizeof(xEvent), &bn);
561 }
562 interest = interest->next;
563 }
564 return;
565}
566
567void
568XkbSendAccessXNotify(DeviceIntPtr kbd, xkbAccessXNotify * pEv)
569{
570 int initialized;
571 XkbInterestPtr interest;
572 Time time = 0;
573 CARD16 sk_delay, db_delay;
574
575 interest = kbd->xkb_interest;
576 if (!interest)
577 return;
578
579 initialized = 0;
580 sk_delay = pEv->slowKeysDelay;
581 db_delay = pEv->debounceDelay;
582 while (interest) {
583 if ((!interest->client->clientGone) &&
584 (interest->client->requestVector != InitialVector) &&
585 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
586 (interest->accessXNotifyMask & (1 << pEv->detail))) {
587 if (!initialized) {
588 pEv->type = XkbEventCode + XkbEventBase;
589 pEv->xkbType = XkbAccessXNotify;
590 pEv->deviceID = kbd->id;
591 pEv->time = time = GetTimeInMillis();
592 initialized = 1;
593 }
594 pEv->sequenceNumber = interest->client->sequence;
595 pEv->time = time;
596 pEv->slowKeysDelay = sk_delay;
597 pEv->debounceDelay = db_delay;
598 if (interest->client->swapped) {
599 swaps(&pEv->sequenceNumber);
600 swapl(&pEv->time);
601 swaps(&pEv->slowKeysDelay);
602 swaps(&pEv->debounceDelay);
603 }
604 WriteToClient(interest->client, sizeof(xEvent), pEv);
605 }
606 interest = interest->next;
607 }
608 return;
609}
610
611void
612XkbSendNamesNotify(DeviceIntPtr kbd, xkbNamesNotify * pEv)
613{
614 int initialized;
615 XkbInterestPtr interest;
616 Time time = 0;
617 CARD16 changed, changedVirtualMods;
618 CARD32 changedIndicators;
619
620 interest = kbd->xkb_interest;
621 if (!interest)
622 return;
623
624 initialized = 0;
625 changed = pEv->changed;
626 changedIndicators = pEv->changedIndicators;
627 changedVirtualMods = pEv->changedVirtualMods;
628 while (interest) {
629 if ((!interest->client->clientGone) &&
630 (interest->client->requestVector != InitialVector) &&
631 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
632 (interest->namesNotifyMask & pEv->changed)) {
633 if (!initialized) {
634 pEv->type = XkbEventCode + XkbEventBase;
635 pEv->xkbType = XkbNamesNotify;
636 pEv->deviceID = kbd->id;
637 pEv->time = time = GetTimeInMillis();
638 initialized = 1;
639 }
640 pEv->sequenceNumber = interest->client->sequence;
641 pEv->time = time;
642 pEv->changed = changed;
643 pEv->changedIndicators = changedIndicators;
644 pEv->changedVirtualMods = changedVirtualMods;
645 if (interest->client->swapped) {
646 swaps(&pEv->sequenceNumber);
647 swapl(&pEv->time);
648 swaps(&pEv->changed);
649 swapl(&pEv->changedIndicators);
650 swaps(&pEv->changedVirtualMods);
651 }
652 WriteToClient(interest->client, sizeof(xEvent), pEv);
653 }
654 interest = interest->next;
655 }
656 return;
657}
658
659void
660XkbSendCompatMapNotify(DeviceIntPtr kbd, xkbCompatMapNotify * pEv)
661{
662 int initialized;
663 XkbInterestPtr interest;
664 Time time = 0;
665 CARD16 firstSI = 0, nSI = 0, nTotalSI = 0;
666
667 interest = kbd->xkb_interest;
668 if (!interest)
669 return;
670
671 initialized = 0;
672 while (interest) {
673 if ((!interest->client->clientGone) &&
674 (interest->client->requestVector != InitialVector) &&
675 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
676 (interest->compatNotifyMask)) {
677 if (!initialized) {
678 pEv->type = XkbEventCode + XkbEventBase;
679 pEv->xkbType = XkbCompatMapNotify;
680 pEv->deviceID = kbd->id;
681 pEv->time = time = GetTimeInMillis();
682 firstSI = pEv->firstSI;
683 nSI = pEv->nSI;
684 nTotalSI = pEv->nTotalSI;
685 initialized = 1;
686 }
687 pEv->sequenceNumber = interest->client->sequence;
688 pEv->time = time;
689 pEv->firstSI = firstSI;
690 pEv->nSI = nSI;
691 pEv->nTotalSI = nTotalSI;
692 if (interest->client->swapped) {
693 swaps(&pEv->sequenceNumber);
694 swapl(&pEv->time);
695 swaps(&pEv->firstSI);
696 swaps(&pEv->nSI);
697 swaps(&pEv->nTotalSI);
698 }
699 WriteToClient(interest->client, sizeof(xEvent), pEv);
700 }
701 interest = interest->next;
702 }
703 return;
704}
705
706void
707XkbSendActionMessage(DeviceIntPtr kbd, xkbActionMessage * pEv)
708{
709 int initialized;
710 XkbSrvInfoPtr xkbi;
711 XkbInterestPtr interest;
712 Time time = 0;
713
714 interest = kbd->xkb_interest;
715 if (!interest || !kbd->key || !kbd->key->xkbInfo)
716 return;
717
718 xkbi = kbd->key->xkbInfo;
719
720 initialized = 0;
721 pEv->mods = xkbi->state.mods;
722 pEv->group = xkbi->state.group;
723 while (interest) {
724 if ((!interest->client->clientGone) &&
725 (interest->client->requestVector != InitialVector) &&
726 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
727 (interest->actionMessageMask)) {
728 if (!initialized) {
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();
734 initialized = 1;
735 }
736 pEv->sequenceNumber = interest->client->sequence;
737 pEv->time = time;
738 if (interest->client->swapped) {
739 swaps(&pEv->sequenceNumber);
740 swapl(&pEv->time);
741 }
742 WriteToClient(interest->client, sizeof(xEvent), pEv);
743 }
744 interest = interest->next;
745 }
746 return;
747}
748
749void
750XkbSendExtensionDeviceNotify(DeviceIntPtr dev,
751 ClientPtr client, xkbExtensionDeviceNotify * pEv)
752{
753 int initialized;
754 XkbInterestPtr interest;
755 Time time = 0;
756 CARD32 defined, state;
757 CARD16 reason;
758
759 interest = dev->xkb_interest;
760 if (!interest)
761 return;
762
763 initialized = 0;
764 reason = pEv->reason;
765 defined = pEv->ledsDefined;
766 state = pEv->ledState;
767 while (interest) {
768 if ((!interest->client->clientGone) &&
769 (interest->client->requestVector != InitialVector) &&
770 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
771 (interest->extDevNotifyMask & reason)) {
772 if (!initialized) {
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();
778 initialized = 1;
779 }
780 else {
781 pEv->sequenceNumber = interest->client->sequence;
782 pEv->time = time;
783 pEv->ledsDefined = defined;
784 pEv->ledState = state;
785 pEv->reason = reason;
786 pEv->supported = XkbXI_AllFeaturesMask;
787 }
788 if (interest->client->swapped) {
789 swaps(&pEv->sequenceNumber);
790 swapl(&pEv->time);
791 swapl(&pEv->ledsDefined);
792 swapl(&pEv->ledState);
793 swaps(&pEv->reason);
794 swaps(&pEv->supported);
795 }
796 WriteToClient(interest->client, sizeof(xEvent), pEv);
797 }
798 interest = interest->next;
799 }
800 return;
801}
802
803void
804XkbSendNotification(DeviceIntPtr kbd,
805 XkbChangesPtr pChanges, XkbEventCausePtr cause)
806{
807 XkbSrvLedInfoPtr sli;
808
809 sli = NULL;
810 if (pChanges->state_changes) {
811 xkbStateNotify sn;
812
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);
819 }
820 if (pChanges->map.changed) {
821 xkbMapNotify mn;
822
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);
841 }
842 if ((pChanges->ctrls.changed_ctrls) ||
843 (pChanges->ctrls.enabled_ctrls_changes)) {
844 xkbControlsNotify cn;
845
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);
854 }
855 if (pChanges->indicators.map_changes) {
856 xkbIndicatorNotify in;
857
858 if (sli == NULL)
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);
864 }
865 if (pChanges->indicators.state_changes) {
866 xkbIndicatorNotify in;
867
868 if (sli == NULL)
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);
874 }
875 if (pChanges->names.changed) {
876 xkbNamesNotify nn;
877
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);
888 }
889 if ((pChanges->compat.changed_groups) || (pChanges->compat.num_si > 0)) {
890 xkbCompatMapNotify cmn;
891
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);
898 }
899 return;
900}
901
902/***====================================================================***/
903
904void
905XkbFilterEvents(ClientPtr client, int nEvents, xEvent *xE)
906{
907 DeviceIntPtr dev = NULL;
908 XkbSrvInfoPtr xkbi;
909 CARD8 type = xE[0].u.u.type;
910
911 if (xE->u.u.type & EXTENSION_EVENT_BASE)
912 dev = XIGetDevice(xE);
913
914 if (!dev)
915 dev = PickKeyboard(client);
916
917 if (!dev->key)
918 return;
919
920 xkbi = dev->key->xkbInfo;
921
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);
928
929 if (dev->deviceGrab.grab != NullGrab && dev->deviceGrab.fromPassiveGrab
930 && (type == KeyPress || type == KeyRelease || type == DeviceKeyPress
931 || type == DeviceKeyRelease)) {
932 unsigned int state, flags;
933
934 flags = client->xkbClientFlags;
935 state = xkbi->state.compat_grab_mods;
936 if (flags & XkbPCF_GrabsUseXKBStateMask) {
937 int group;
938
939 if (flags & XkbPCF_LookupStateWhenGrabbed) {
940 group = xkbi->state.group;
941 state = xkbi->state.lookup_mods;
942 }
943 else {
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);
948 }
949 state = XkbBuildCoreState(state, group);
950 }
951 else if (flags & XkbPCF_LookupStateWhenGrabbed) {
952 state = xkbi->state.compat_lookup_mods;
953 }
954 xE[0].u.keyButtonPointer.state = state;
955 }
956 }
957 else {
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);
969 }
970 if (type >= KeyPress && type <= MotionNotify) {
971 CARD16 old, new;
972
973 old = xE[0].u.keyButtonPointer.state & ~0x1f00;
974 new = xE[0].u.keyButtonPointer.state & 0x1F00;
975
976 if (old == XkbStateFieldFromRec(&xkbi->state))
977 new |= xkbi->state.compat_lookup_mods;
978 else
979 new |= xkbi->state.compat_grab_mods;
980 xE[0].u.keyButtonPointer.state = new;
981 }
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;
985 }
986 else if (type >= DeviceKeyPress && type <= DeviceMotionNotify) {
987 CARD16 old, new;
988 deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) &xE[0];
989
990 old = kbp->state & ~0x1F00;
991 new = kbp->state & 0x1F00;
992 if (old == XkbStateFieldFromRec(&xkbi->state))
993 new |= xkbi->state.compat_lookup_mods;
994 else
995 new |= xkbi->state.compat_grab_mods;
996 kbp->state = new;
997 }
998 }
999}
1000
1001/***====================================================================***/
1002
1003XkbInterestPtr
1004XkbFindClientResource(DevicePtr inDev, ClientPtr client)
1005{
1006 DeviceIntPtr dev = (DeviceIntPtr) inDev;
1007 XkbInterestPtr interest;
1008
1009 if (dev->xkb_interest) {
1010 interest = dev->xkb_interest;
1011 while (interest) {
1012 if (interest->client == client) {
1013 return interest;
1014 }
1015 interest = interest->next;
1016 }
1017 }
1018 return NULL;
1019}
1020
1021XkbInterestPtr
1022XkbAddClientResource(DevicePtr inDev, ClientPtr client, XID id)
1023{
1024 DeviceIntPtr dev = (DeviceIntPtr) inDev;
1025 XkbInterestPtr interest;
1026
1027 interest = dev->xkb_interest;
1028 while (interest) {
1029 if (interest->client == client)
1030 return ((interest->resource == id) ? interest : NULL);
1031 interest = interest->next;
1032 }
1033 interest = calloc(1, sizeof(XkbInterestRec));
1034 if (interest) {
1035 interest->dev = dev;
1036 interest->client = client;
1037 interest->resource = id;
1038 interest->next = dev->xkb_interest;
1039 dev->xkb_interest = interest;
1040 return interest;
1041 }
1042 return NULL;
1043}
1044
1045int
1046XkbRemoveResourceClient(DevicePtr inDev, XID id)
1047{
1048 XkbSrvInfoPtr xkbi;
1049 DeviceIntPtr dev = (DeviceIntPtr) inDev;
1050 XkbInterestPtr interest;
1051 Bool found;
1052 unsigned long autoCtrls, autoValues;
1053 ClientPtr client = NULL;
1054
1055 found = FALSE;
1056
1057 if (!dev->key || !dev->key->xkbInfo)
1058 return found;
1059
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;
1068 free(interest);
1069 found = TRUE;
1070 }
1071 while ((!found) && (interest->next)) {
1072 if (interest->next->resource == id) {
1073 XkbInterestPtr victim = interest->next;
1074
1075 interest->next = victim->next;
1076 autoCtrls = victim->autoCtrls;
1077 autoValues = victim->autoCtrlValues;
1078 client = victim->client;
1079 free(victim);
1080 found = TRUE;
1081 }
1082 interest = interest->next;
1083 }
1084 }
1085 if (found && autoCtrls && dev->key && dev->key->xkbInfo) {
1086 XkbEventCauseRec cause;
1087
1088 xkbi = dev->key->xkbInfo;
1089 XkbSetCauseXkbReq(&cause, X_kbPerClientFlags, client);
1090 XkbEnableDisableControls(xkbi, autoCtrls, autoValues, NULL, &cause);
1091 }
1092 return found;
1093}