1 /************************************************************
2 Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
3
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.
15
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.
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 */
55 static void
XkbSendLegacyMapNotify(DeviceIntPtr kbd,CARD16 xkb_event,CARD16 changed,int first_key,int num_keys)56 XkbSendLegacyMapNotify(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
161 void
XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify * pNKN)162 XkbSendNewKeyboardNotify(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
202 void
XkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify * pSN)203 XkbSendStateNotify(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->xkbClientFlags & _XkbClientInitialized) &&
241 (interest->stateNotifyMask & changed)) {
242 pSN->sequenceNumber = interest->client->sequence;
243 pSN->time = time;
244 pSN->changed = changed;
245 pSN->ptrBtnState = bState;
246 if (interest->client->swapped) {
247 swaps(&pSN->sequenceNumber);
248 swapl(&pSN->time);
249 swaps(&pSN->changed);
250 swaps(&pSN->ptrBtnState);
251 }
252 WriteToClient(interest->client, sizeof(xEvent), pSN);
253 }
254 interest = interest->next;
255 }
256 return;
257 }
258
259 /***====================================================================***/
260
261 /*
262 * This function sends out XKB mapping notify events to clients which
263 * have explicitly selected for them. Core and Xi events are handled by
264 * XkbSendLegacyMapNotify. */
265 void
XkbSendMapNotify(DeviceIntPtr kbd,xkbMapNotify * pMN)266 XkbSendMapNotify(DeviceIntPtr kbd, xkbMapNotify * pMN)
267 {
268 int i;
269 CARD32 time = GetTimeInMillis();
270 CARD16 changed = pMN->changed;
271 XkbSrvInfoPtr xkbi = kbd->key->xkbInfo;
272
273 pMN->minKeyCode = xkbi->desc->min_key_code;
274 pMN->maxKeyCode = xkbi->desc->max_key_code;
275 pMN->type = XkbEventCode + XkbEventBase;
276 pMN->xkbType = XkbMapNotify;
277 pMN->deviceID = kbd->id;
278
279 /* 0 is serverClient. */
280 for (i = 1; i < currentMaxClients; i++) {
281 if (!clients[i] || clients[i]->clientState != ClientStateRunning)
282 continue;
283
284 if (!(clients[i]->mapNotifyMask & changed))
285 continue;
286
287 pMN->time = time;
288 pMN->sequenceNumber = clients[i]->sequence;
289 pMN->changed = changed;
290
291 if (clients[i]->swapped) {
292 swaps(&pMN->sequenceNumber);
293 swapl(&pMN->time);
294 swaps(&pMN->changed);
295 }
296 WriteToClient(clients[i], sizeof(xEvent), pMN);
297 }
298
299 XkbSendLegacyMapNotify(kbd, XkbMapNotify, changed, pMN->firstKeySym,
300 pMN->nKeySyms);
301 }
302
303 int
XkbComputeControlsNotify(DeviceIntPtr kbd,XkbControlsPtr old,XkbControlsPtr new,xkbControlsNotify * pCN,Bool forceCtrlProc)304 XkbComputeControlsNotify(DeviceIntPtr kbd,
305 XkbControlsPtr old,
306 XkbControlsPtr new,
307 xkbControlsNotify * pCN, Bool forceCtrlProc)
308 {
309 int i;
310 CARD32 changedControls;
311
312 changedControls = 0;
313
314 if (!kbd || !kbd->kbdfeed)
315 return 0;
316
317 if (old->enabled_ctrls != new->enabled_ctrls)
318 changedControls |= XkbControlsEnabledMask;
319 if ((old->repeat_delay != new->repeat_delay) ||
320 (old->repeat_interval != new->repeat_interval))
321 changedControls |= XkbRepeatKeysMask;
322 for (i = 0; i < XkbPerKeyBitArraySize; i++)
323 if (old->per_key_repeat[i] != new->per_key_repeat[i])
324 changedControls |= XkbPerKeyRepeatMask;
325 if (old->slow_keys_delay != new->slow_keys_delay)
326 changedControls |= XkbSlowKeysMask;
327 if (old->debounce_delay != new->debounce_delay)
328 changedControls |= XkbBounceKeysMask;
329 if ((old->mk_delay != new->mk_delay) ||
330 (old->mk_interval != new->mk_interval) ||
331 (old->mk_dflt_btn != new->mk_dflt_btn))
332 changedControls |= XkbMouseKeysMask;
333 if ((old->mk_time_to_max != new->mk_time_to_max) ||
334 (old->mk_curve != new->mk_curve) ||
335 (old->mk_max_speed != new->mk_max_speed))
336 changedControls |= XkbMouseKeysAccelMask;
337 if (old->ax_options != new->ax_options)
338 changedControls |= XkbAccessXKeysMask;
339 if ((old->ax_options ^ new->ax_options) & XkbAX_SKOptionsMask)
340 changedControls |= XkbStickyKeysMask;
341 if ((old->ax_options ^ new->ax_options) & XkbAX_FBOptionsMask)
342 changedControls |= XkbAccessXFeedbackMask;
343 if ((old->ax_timeout != new->ax_timeout) ||
344 (old->axt_ctrls_mask != new->axt_ctrls_mask) ||
345 (old->axt_ctrls_values != new->axt_ctrls_values) ||
346 (old->axt_opts_mask != new->axt_opts_mask) ||
347 (old->axt_opts_values != new->axt_opts_values)) {
348 changedControls |= XkbAccessXTimeoutMask;
349 }
350 if ((old->internal.mask != new->internal.mask) ||
351 (old->internal.real_mods != new->internal.real_mods) ||
352 (old->internal.vmods != new->internal.vmods))
353 changedControls |= XkbInternalModsMask;
354 if ((old->ignore_lock.mask != new->ignore_lock.mask) ||
355 (old->ignore_lock.real_mods != new->ignore_lock.real_mods) ||
356 (old->ignore_lock.vmods != new->ignore_lock.vmods))
357 changedControls |= XkbIgnoreLockModsMask;
358
359 if (new->enabled_ctrls & XkbRepeatKeysMask)
360 kbd->kbdfeed->ctrl.autoRepeat = TRUE;
361 else
362 kbd->kbdfeed->ctrl.autoRepeat = FALSE;
363
364 if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc &&
365 (changedControls || forceCtrlProc))
366 (*kbd->kbdfeed->CtrlProc) (kbd, &kbd->kbdfeed->ctrl);
367
368 if ((!changedControls) && (old->num_groups == new->num_groups))
369 return 0;
370
371 if (!kbd->xkb_interest)
372 return 0;
373
374 pCN->changedControls = changedControls;
375 pCN->enabledControls = new->enabled_ctrls;
376 pCN->enabledControlChanges = (new->enabled_ctrls ^ old->enabled_ctrls);
377 pCN->numGroups = new->num_groups;
378
379 return 1;
380 }
381
382 void
XkbSendControlsNotify(DeviceIntPtr kbd,xkbControlsNotify * pCN)383 XkbSendControlsNotify(DeviceIntPtr kbd, xkbControlsNotify * pCN)
384 {
385 int initialized;
386 CARD32 changedControls, enabledControls, enabledChanges = 0;
387 XkbSrvInfoPtr xkbi;
388 XkbInterestPtr interest;
389 Time time = 0;
390
391 interest = kbd->xkb_interest;
392 if (!interest || !kbd->key || !kbd->key->xkbInfo)
393 return;
394 xkbi = kbd->key->xkbInfo;
395
396 initialized = 0;
397 enabledControls = xkbi->desc->ctrls->enabled_ctrls;
398 changedControls = pCN->changedControls;
399 pCN->numGroups = xkbi->desc->ctrls->num_groups;
400 while (interest) {
401 if ((!interest->client->clientGone) &&
402 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
403 (interest->ctrlsNotifyMask & changedControls)) {
404 if (!initialized) {
405 pCN->type = XkbEventCode + XkbEventBase;
406 pCN->xkbType = XkbControlsNotify;
407 pCN->deviceID = kbd->id;
408 pCN->time = time = GetTimeInMillis();
409 enabledChanges = pCN->enabledControlChanges;
410 initialized = 1;
411 }
412 pCN->changedControls = changedControls;
413 pCN->enabledControls = enabledControls;
414 pCN->enabledControlChanges = enabledChanges;
415 pCN->sequenceNumber = interest->client->sequence;
416 pCN->time = time;
417 if (interest->client->swapped) {
418 swaps(&pCN->sequenceNumber);
419 swapl(&pCN->changedControls);
420 swapl(&pCN->enabledControls);
421 swapl(&pCN->enabledControlChanges);
422 swapl(&pCN->time);
423 }
424 WriteToClient(interest->client, sizeof(xEvent), pCN);
425 }
426 interest = interest->next;
427 }
428 return;
429 }
430
431 static void
XkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify * pEv)432 XkbSendIndicatorNotify(DeviceIntPtr kbd, int xkbType, xkbIndicatorNotify * pEv)
433 {
434 int initialized;
435 XkbInterestPtr interest;
436 Time time = 0;
437 CARD32 state, changed;
438
439 interest = kbd->xkb_interest;
440 if (!interest)
441 return;
442
443 initialized = 0;
444 state = pEv->state;
445 changed = pEv->changed;
446 while (interest) {
447 if ((!interest->client->clientGone) &&
448 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
449 (((xkbType == XkbIndicatorStateNotify) &&
450 (interest->iStateNotifyMask & changed)) ||
451 ((xkbType == XkbIndicatorMapNotify) &&
452 (interest->iMapNotifyMask & changed)))) {
453 if (!initialized) {
454 pEv->type = XkbEventCode + XkbEventBase;
455 pEv->xkbType = xkbType;
456 pEv->deviceID = kbd->id;
457 pEv->time = time = GetTimeInMillis();
458 initialized = 1;
459 }
460 pEv->sequenceNumber = interest->client->sequence;
461 pEv->time = time;
462 pEv->changed = changed;
463 pEv->state = state;
464 if (interest->client->swapped) {
465 swaps(&pEv->sequenceNumber);
466 swapl(&pEv->time);
467 swapl(&pEv->changed);
468 swapl(&pEv->state);
469 }
470 WriteToClient(interest->client, sizeof(xEvent), pEv);
471 }
472 interest = interest->next;
473 }
474 return;
475 }
476
477 void
XkbHandleBell(BOOL force,BOOL eventOnly,DeviceIntPtr kbd,CARD8 percent,void * pCtrl,CARD8 class,Atom name,WindowPtr pWin,ClientPtr pClient)478 XkbHandleBell(BOOL force,
479 BOOL eventOnly,
480 DeviceIntPtr kbd,
481 CARD8 percent,
482 void *pCtrl,
483 CARD8 class, Atom name, WindowPtr pWin, ClientPtr pClient)
484 {
485 xkbBellNotify bn;
486 int initialized;
487 XkbSrvInfoPtr xkbi;
488 XkbInterestPtr interest;
489 CARD8 id;
490 CARD16 pitch, duration;
491 Time time = 0;
492 XID winID = 0;
493
494 if (!kbd->key || !kbd->key->xkbInfo)
495 return;
496
497 xkbi = kbd->key->xkbInfo;
498
499 if ((force || (xkbi->desc->ctrls->enabled_ctrls & XkbAudibleBellMask)) &&
500 (!eventOnly)) {
501 if (kbd->kbdfeed->BellProc)
502 (*kbd->kbdfeed->BellProc) (percent, kbd, (void *) pCtrl, class);
503 }
504 interest = kbd->xkb_interest;
505 if ((!interest) || (force))
506 return;
507
508 if (class == KbdFeedbackClass) {
509 KeybdCtrl *pKeyCtrl = (KeybdCtrl *) pCtrl;
510
511 id = pKeyCtrl->id;
512 pitch = pKeyCtrl->bell_pitch;
513 duration = pKeyCtrl->bell_duration;
514 }
515 else if (class == BellFeedbackClass) {
516 BellCtrl *pBellCtrl = (BellCtrl *) pCtrl;
517
518 id = pBellCtrl->id;
519 pitch = pBellCtrl->pitch;
520 duration = pBellCtrl->duration;
521 }
522 else
523 return;
524
525 initialized = 0;
526 while (interest) {
527 if ((!interest->client->clientGone) &&
528 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
529 (interest->bellNotifyMask)) {
530 if (!initialized) {
531 time = GetTimeInMillis();
532 bn.type = XkbEventCode + XkbEventBase;
533 bn.xkbType = XkbBellNotify;
534 bn.deviceID = kbd->id;
535 bn.bellClass = class;
536 bn.bellID = id;
537 bn.percent = percent;
538 bn.eventOnly = (eventOnly != 0);
539 winID = (pWin ? pWin->drawable.id : None);
540 initialized = 1;
541 }
542 bn.sequenceNumber = interest->client->sequence;
543 bn.time = time;
544 bn.pitch = pitch;
545 bn.duration = duration;
546 bn.name = name;
547 bn.window = winID;
548 if (interest->client->swapped) {
549 swaps(&bn.sequenceNumber);
550 swapl(&bn.time);
551 swaps(&bn.pitch);
552 swaps(&bn.duration);
553 swapl(&bn.name);
554 swapl(&bn.window);
555 }
556 WriteToClient(interest->client, sizeof(xEvent), &bn);
557 }
558 interest = interest->next;
559 }
560 return;
561 }
562
563 void
XkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify * pEv)564 XkbSendAccessXNotify(DeviceIntPtr kbd, xkbAccessXNotify * pEv)
565 {
566 int initialized;
567 XkbInterestPtr interest;
568 Time time = 0;
569 CARD16 sk_delay, db_delay;
570
571 interest = kbd->xkb_interest;
572 if (!interest)
573 return;
574
575 initialized = 0;
576 sk_delay = pEv->slowKeysDelay;
577 db_delay = pEv->debounceDelay;
578 while (interest) {
579 if ((!interest->client->clientGone) &&
580 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
581 (interest->accessXNotifyMask & (1 << pEv->detail))) {
582 if (!initialized) {
583 pEv->type = XkbEventCode + XkbEventBase;
584 pEv->xkbType = XkbAccessXNotify;
585 pEv->deviceID = kbd->id;
586 pEv->time = time = GetTimeInMillis();
587 initialized = 1;
588 }
589 pEv->sequenceNumber = interest->client->sequence;
590 pEv->time = time;
591 pEv->slowKeysDelay = sk_delay;
592 pEv->debounceDelay = db_delay;
593 if (interest->client->swapped) {
594 swaps(&pEv->sequenceNumber);
595 swapl(&pEv->time);
596 swaps(&pEv->slowKeysDelay);
597 swaps(&pEv->debounceDelay);
598 }
599 WriteToClient(interest->client, sizeof(xEvent), pEv);
600 }
601 interest = interest->next;
602 }
603 return;
604 }
605
606 void
XkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify * pEv)607 XkbSendNamesNotify(DeviceIntPtr kbd, xkbNamesNotify * pEv)
608 {
609 int initialized;
610 XkbInterestPtr interest;
611 Time time = 0;
612 CARD16 changed, changedVirtualMods;
613 CARD32 changedIndicators;
614
615 interest = kbd->xkb_interest;
616 if (!interest)
617 return;
618
619 initialized = 0;
620 changed = pEv->changed;
621 changedIndicators = pEv->changedIndicators;
622 changedVirtualMods = pEv->changedVirtualMods;
623 while (interest) {
624 if ((!interest->client->clientGone) &&
625 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
626 (interest->namesNotifyMask & pEv->changed)) {
627 if (!initialized) {
628 pEv->type = XkbEventCode + XkbEventBase;
629 pEv->xkbType = XkbNamesNotify;
630 pEv->deviceID = kbd->id;
631 pEv->time = time = GetTimeInMillis();
632 initialized = 1;
633 }
634 pEv->sequenceNumber = interest->client->sequence;
635 pEv->time = time;
636 pEv->changed = changed;
637 pEv->changedIndicators = changedIndicators;
638 pEv->changedVirtualMods = changedVirtualMods;
639 if (interest->client->swapped) {
640 swaps(&pEv->sequenceNumber);
641 swapl(&pEv->time);
642 swaps(&pEv->changed);
643 swapl(&pEv->changedIndicators);
644 swaps(&pEv->changedVirtualMods);
645 }
646 WriteToClient(interest->client, sizeof(xEvent), pEv);
647 }
648 interest = interest->next;
649 }
650 return;
651 }
652
653 void
XkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify * pEv)654 XkbSendCompatMapNotify(DeviceIntPtr kbd, xkbCompatMapNotify * pEv)
655 {
656 int initialized;
657 XkbInterestPtr interest;
658 Time time = 0;
659 CARD16 firstSI = 0, nSI = 0, nTotalSI = 0;
660
661 interest = kbd->xkb_interest;
662 if (!interest)
663 return;
664
665 initialized = 0;
666 while (interest) {
667 if ((!interest->client->clientGone) &&
668 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
669 (interest->compatNotifyMask)) {
670 if (!initialized) {
671 pEv->type = XkbEventCode + XkbEventBase;
672 pEv->xkbType = XkbCompatMapNotify;
673 pEv->deviceID = kbd->id;
674 pEv->time = time = GetTimeInMillis();
675 firstSI = pEv->firstSI;
676 nSI = pEv->nSI;
677 nTotalSI = pEv->nTotalSI;
678 initialized = 1;
679 }
680 pEv->sequenceNumber = interest->client->sequence;
681 pEv->time = time;
682 pEv->firstSI = firstSI;
683 pEv->nSI = nSI;
684 pEv->nTotalSI = nTotalSI;
685 if (interest->client->swapped) {
686 swaps(&pEv->sequenceNumber);
687 swapl(&pEv->time);
688 swaps(&pEv->firstSI);
689 swaps(&pEv->nSI);
690 swaps(&pEv->nTotalSI);
691 }
692 WriteToClient(interest->client, sizeof(xEvent), pEv);
693 }
694 interest = interest->next;
695 }
696 return;
697 }
698
699 void
XkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage * pEv)700 XkbSendActionMessage(DeviceIntPtr kbd, xkbActionMessage * pEv)
701 {
702 int initialized;
703 XkbSrvInfoPtr xkbi;
704 XkbInterestPtr interest;
705 Time time = 0;
706
707 interest = kbd->xkb_interest;
708 if (!interest || !kbd->key || !kbd->key->xkbInfo)
709 return;
710
711 xkbi = kbd->key->xkbInfo;
712
713 initialized = 0;
714 pEv->mods = xkbi->state.mods;
715 pEv->group = xkbi->state.group;
716 while (interest) {
717 if ((!interest->client->clientGone) &&
718 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
719 (interest->actionMessageMask)) {
720 if (!initialized) {
721 pEv->type = XkbEventCode + XkbEventBase;
722 pEv->xkbType = XkbActionMessage;
723 pEv->deviceID = kbd->id;
724 pEv->sequenceNumber = interest->client->sequence;
725 pEv->time = time = GetTimeInMillis();
726 initialized = 1;
727 }
728 pEv->sequenceNumber = interest->client->sequence;
729 pEv->time = time;
730 if (interest->client->swapped) {
731 swaps(&pEv->sequenceNumber);
732 swapl(&pEv->time);
733 }
734 WriteToClient(interest->client, sizeof(xEvent), pEv);
735 }
736 interest = interest->next;
737 }
738 return;
739 }
740
741 void
XkbSendExtensionDeviceNotify(DeviceIntPtr dev,ClientPtr client,xkbExtensionDeviceNotify * pEv)742 XkbSendExtensionDeviceNotify(DeviceIntPtr dev,
743 ClientPtr client, xkbExtensionDeviceNotify * pEv)
744 {
745 int initialized;
746 XkbInterestPtr interest;
747 Time time = 0;
748 CARD32 defined, state;
749 CARD16 reason;
750
751 interest = dev->xkb_interest;
752 if (!interest)
753 return;
754
755 initialized = 0;
756 reason = pEv->reason;
757 defined = pEv->ledsDefined;
758 state = pEv->ledState;
759 while (interest) {
760 if ((!interest->client->clientGone) &&
761 (interest->client->xkbClientFlags & _XkbClientInitialized) &&
762 (interest->extDevNotifyMask & reason)) {
763 if (!initialized) {
764 pEv->type = XkbEventCode + XkbEventBase;
765 pEv->xkbType = XkbExtensionDeviceNotify;
766 pEv->deviceID = dev->id;
767 pEv->sequenceNumber = interest->client->sequence;
768 pEv->time = time = GetTimeInMillis();
769 initialized = 1;
770 }
771 else {
772 pEv->sequenceNumber = interest->client->sequence;
773 pEv->time = time;
774 pEv->ledsDefined = defined;
775 pEv->ledState = state;
776 pEv->reason = reason;
777 pEv->supported = XkbXI_AllFeaturesMask;
778 }
779 if (interest->client->swapped) {
780 swaps(&pEv->sequenceNumber);
781 swapl(&pEv->time);
782 swapl(&pEv->ledsDefined);
783 swapl(&pEv->ledState);
784 swaps(&pEv->reason);
785 swaps(&pEv->supported);
786 }
787 WriteToClient(interest->client, sizeof(xEvent), pEv);
788 }
789 interest = interest->next;
790 }
791 return;
792 }
793
794 void
XkbSendNotification(DeviceIntPtr kbd,XkbChangesPtr pChanges,XkbEventCausePtr cause)795 XkbSendNotification(DeviceIntPtr kbd,
796 XkbChangesPtr pChanges, XkbEventCausePtr cause)
797 {
798 XkbSrvLedInfoPtr sli;
799
800 sli = NULL;
801 if (pChanges->state_changes) {
802 xkbStateNotify sn;
803
804 sn.changed = pChanges->state_changes;
805 sn.keycode = cause->kc;
806 sn.eventType = cause->event;
807 sn.requestMajor = cause->mjr;
808 sn.requestMinor = cause->mnr;
809 XkbSendStateNotify(kbd, &sn);
810 }
811 if (pChanges->map.changed) {
812 xkbMapNotify mn;
813
814 memset(&mn, 0, sizeof(xkbMapNotify));
815 mn.changed = pChanges->map.changed;
816 mn.firstType = pChanges->map.first_type;
817 mn.nTypes = pChanges->map.num_types;
818 mn.firstKeySym = pChanges->map.first_key_sym;
819 mn.nKeySyms = pChanges->map.num_key_syms;
820 mn.firstKeyAct = pChanges->map.first_key_act;
821 mn.nKeyActs = pChanges->map.num_key_acts;
822 mn.firstKeyBehavior = pChanges->map.first_key_behavior;
823 mn.nKeyBehaviors = pChanges->map.num_key_behaviors;
824 mn.virtualMods = pChanges->map.vmods;
825 mn.firstKeyExplicit = pChanges->map.first_key_explicit;
826 mn.nKeyExplicit = pChanges->map.num_key_explicit;
827 mn.firstModMapKey = pChanges->map.first_modmap_key;
828 mn.nModMapKeys = pChanges->map.num_modmap_keys;
829 mn.firstVModMapKey = pChanges->map.first_vmodmap_key;
830 mn.nVModMapKeys = pChanges->map.num_vmodmap_keys;
831 XkbSendMapNotify(kbd, &mn);
832 }
833 if ((pChanges->ctrls.changed_ctrls) ||
834 (pChanges->ctrls.enabled_ctrls_changes)) {
835 xkbControlsNotify cn;
836
837 memset(&cn, 0, sizeof(xkbControlsNotify));
838 cn.changedControls = pChanges->ctrls.changed_ctrls;
839 cn.enabledControlChanges = pChanges->ctrls.enabled_ctrls_changes;
840 cn.keycode = cause->kc;
841 cn.eventType = cause->event;
842 cn.requestMajor = cause->mjr;
843 cn.requestMinor = cause->mnr;
844 XkbSendControlsNotify(kbd, &cn);
845 }
846 if (pChanges->indicators.map_changes) {
847 xkbIndicatorNotify in;
848
849 if (sli == NULL)
850 sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
851 memset(&in, 0, sizeof(xkbIndicatorNotify));
852 in.state = sli->effectiveState;
853 in.changed = pChanges->indicators.map_changes;
854 XkbSendIndicatorNotify(kbd, XkbIndicatorMapNotify, &in);
855 }
856 if (pChanges->indicators.state_changes) {
857 xkbIndicatorNotify in;
858
859 if (sli == NULL)
860 sli = XkbFindSrvLedInfo(kbd, XkbDfltXIClass, XkbDfltXIId, 0);
861 memset(&in, 0, sizeof(xkbIndicatorNotify));
862 in.state = sli->effectiveState;
863 in.changed = pChanges->indicators.state_changes;
864 XkbSendIndicatorNotify(kbd, XkbIndicatorStateNotify, &in);
865 }
866 if (pChanges->names.changed) {
867 xkbNamesNotify nn;
868
869 memset(&nn, 0, sizeof(xkbNamesNotify));
870 nn.changed = pChanges->names.changed;
871 nn.firstType = pChanges->names.first_type;
872 nn.nTypes = pChanges->names.num_types;
873 nn.firstLevelName = pChanges->names.first_lvl;
874 nn.nLevelNames = pChanges->names.num_lvls;
875 nn.nRadioGroups = pChanges->names.num_rg;
876 nn.changedVirtualMods = pChanges->names.changed_vmods;
877 nn.changedIndicators = pChanges->names.changed_indicators;
878 XkbSendNamesNotify(kbd, &nn);
879 }
880 if ((pChanges->compat.changed_groups) || (pChanges->compat.num_si > 0)) {
881 xkbCompatMapNotify cmn;
882
883 memset(&cmn, 0, sizeof(xkbCompatMapNotify));
884 cmn.changedGroups = pChanges->compat.changed_groups;
885 cmn.firstSI = pChanges->compat.first_si;
886 cmn.nSI = pChanges->compat.num_si;
887 cmn.nTotalSI = kbd->key->xkbInfo->desc->compat->num_si;
888 XkbSendCompatMapNotify(kbd, &cmn);
889 }
890 return;
891 }
892
893 /***====================================================================***/
894
895 void
XkbFilterEvents(ClientPtr client,int nEvents,xEvent * xE)896 XkbFilterEvents(ClientPtr client, int nEvents, xEvent *xE)
897 {
898 DeviceIntPtr dev = NULL;
899 XkbSrvInfoPtr xkbi;
900 CARD8 type = xE[0].u.u.type;
901
902 if (xE->u.u.type & EXTENSION_EVENT_BASE)
903 dev = XIGetDevice(xE);
904
905 if (!dev)
906 dev = PickKeyboard(client);
907
908 if (!dev->key)
909 return;
910
911 xkbi = dev->key->xkbInfo;
912
913 if (client->xkbClientFlags & _XkbClientInitialized) {
914 if ((xkbDebugFlags & 0x10) &&
915 (type == KeyPress || type == KeyRelease ||
916 type == DeviceKeyPress || type == DeviceKeyRelease))
917 DebugF("[xkb] XkbFilterWriteEvents (XKB client): state 0x%04x\n",
918 xE[0].u.keyButtonPointer.state);
919
920 if (dev->deviceGrab.grab != NullGrab && dev->deviceGrab.fromPassiveGrab
921 && (type == KeyPress || type == KeyRelease || type == DeviceKeyPress
922 || type == DeviceKeyRelease)) {
923 unsigned int state, flags;
924
925 flags = client->xkbClientFlags;
926 state = xkbi->state.compat_grab_mods;
927 if (flags & XkbPCF_GrabsUseXKBStateMask) {
928 int group;
929
930 if (flags & XkbPCF_LookupStateWhenGrabbed) {
931 group = xkbi->state.group;
932 state = xkbi->state.lookup_mods;
933 }
934 else {
935 state = xkbi->state.grab_mods;
936 group = xkbi->state.base_group + xkbi->state.latched_group;
937 if (group < 0 || group >= xkbi->desc->ctrls->num_groups)
938 group = XkbAdjustGroup(group, xkbi->desc->ctrls);
939 }
940 state = XkbBuildCoreState(state, group);
941 }
942 else if (flags & XkbPCF_LookupStateWhenGrabbed) {
943 state = xkbi->state.compat_lookup_mods;
944 }
945 xE[0].u.keyButtonPointer.state = state;
946 }
947 }
948 else {
949 if ((xkbDebugFlags & 0x4) &&
950 (xE[0].u.u.type == KeyPress || xE[0].u.u.type == KeyRelease ||
951 xE[0].u.u.type == DeviceKeyPress ||
952 xE[0].u.u.type == DeviceKeyRelease)) {
953 DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
954 DebugF("[xkb] event= 0x%04x\n", xE[0].u.keyButtonPointer.state);
955 DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",
956 xkbi->state.lookup_mods, xkbi->state.grab_mods);
957 DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
958 xkbi->state.compat_lookup_mods,
959 xkbi->state.compat_grab_mods);
960 }
961 if (type >= KeyPress && type <= MotionNotify) {
962 CARD16 old, new;
963
964 old = xE[0].u.keyButtonPointer.state & ~0x1f00;
965 new = xE[0].u.keyButtonPointer.state & 0x1F00;
966
967 if (old == XkbStateFieldFromRec(&xkbi->state))
968 new |= xkbi->state.compat_lookup_mods;
969 else
970 new |= xkbi->state.compat_grab_mods;
971 xE[0].u.keyButtonPointer.state = new;
972 }
973 else if (type == EnterNotify || type == LeaveNotify) {
974 xE[0].u.enterLeave.state &= 0x1F00;
975 xE[0].u.enterLeave.state |= xkbi->state.compat_grab_mods;
976 }
977 else if (type >= DeviceKeyPress && type <= DeviceMotionNotify) {
978 CARD16 old, new;
979 deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) &xE[0];
980
981 old = kbp->state & ~0x1F00;
982 new = kbp->state & 0x1F00;
983 if (old == XkbStateFieldFromRec(&xkbi->state))
984 new |= xkbi->state.compat_lookup_mods;
985 else
986 new |= xkbi->state.compat_grab_mods;
987 kbp->state = new;
988 }
989 }
990 }
991
992 /***====================================================================***/
993
994 XkbInterestPtr
XkbFindClientResource(DevicePtr inDev,ClientPtr client)995 XkbFindClientResource(DevicePtr inDev, ClientPtr client)
996 {
997 DeviceIntPtr dev = (DeviceIntPtr) inDev;
998 XkbInterestPtr interest;
999
1000 if (dev->xkb_interest) {
1001 interest = dev->xkb_interest;
1002 while (interest) {
1003 if (interest->client == client) {
1004 return interest;
1005 }
1006 interest = interest->next;
1007 }
1008 }
1009 return NULL;
1010 }
1011
1012 XkbInterestPtr
XkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id)1013 XkbAddClientResource(DevicePtr inDev, ClientPtr client, XID id)
1014 {
1015 DeviceIntPtr dev = (DeviceIntPtr) inDev;
1016 XkbInterestPtr interest;
1017
1018 interest = dev->xkb_interest;
1019 while (interest) {
1020 if (interest->client == client)
1021 return ((interest->resource == id) ? interest : NULL);
1022 interest = interest->next;
1023 }
1024 interest = calloc(1, sizeof(XkbInterestRec));
1025 if (interest) {
1026 interest->dev = dev;
1027 interest->client = client;
1028 interest->resource = id;
1029 interest->next = dev->xkb_interest;
1030 dev->xkb_interest = interest;
1031 return interest;
1032 }
1033 return NULL;
1034 }
1035
1036 int
XkbRemoveResourceClient(DevicePtr inDev,XID id)1037 XkbRemoveResourceClient(DevicePtr inDev, XID id)
1038 {
1039 XkbSrvInfoPtr xkbi;
1040 DeviceIntPtr dev = (DeviceIntPtr) inDev;
1041 XkbInterestPtr interest;
1042 Bool found;
1043 unsigned long autoCtrls, autoValues;
1044 ClientPtr client = NULL;
1045
1046 found = FALSE;
1047
1048 if (!dev->key || !dev->key->xkbInfo)
1049 return found;
1050
1051 autoCtrls = autoValues = 0;
1052 if (dev->xkb_interest) {
1053 interest = dev->xkb_interest;
1054 if (interest && (interest->resource == id)) {
1055 dev->xkb_interest = interest->next;
1056 autoCtrls = interest->autoCtrls;
1057 autoValues = interest->autoCtrlValues;
1058 client = interest->client;
1059 free(interest);
1060 found = TRUE;
1061 }
1062 while ((!found) && (interest->next)) {
1063 if (interest->next->resource == id) {
1064 XkbInterestPtr victim = interest->next;
1065
1066 interest->next = victim->next;
1067 autoCtrls = victim->autoCtrls;
1068 autoValues = victim->autoCtrlValues;
1069 client = victim->client;
1070 free(victim);
1071 found = TRUE;
1072 }
1073 interest = interest->next;
1074 }
1075 }
1076 if (found && autoCtrls && dev->key && dev->key->xkbInfo) {
1077 XkbEventCauseRec cause;
1078
1079 xkbi = dev->key->xkbInfo;
1080 XkbSetCauseXkbReq(&cause, X_kbPerClientFlags, client);
1081 XkbEnableDisableControls(xkbi, autoCtrls, autoValues, NULL, &cause);
1082 }
1083 return found;
1084 }
1085