initial commit
[profile/ivi/xorg-x11-server.git] / xkb / xkbEvents.c
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 "exevents.h"
42 #include <xkbsrv.h>
43 #include "xkb.h"
44
45 /***====================================================================***/
46
47 /*
48  * This function sends out two kinds of notification:
49  *   - Core mapping notify events sent to clients for whom kbd is the
50  *     current core ('picked') keyboard _and_ have not explicitly
51  *     selected for XKB mapping notify events;
52  *   - Xi mapping events, sent unconditionally to all clients who have
53  *     explicitly selected for them (including those who have explicitly
54  *     selected for XKB mapping notify events!).
55  */
56 static void
57 XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed,
58                        int first_key, int num_keys)
59 {
60     int i;
61     int keymap_changed = 0;
62     int modmap_changed = 0;
63     xEvent core_mn;
64     deviceMappingNotify xi_mn;
65     CARD32 time = GetTimeInMillis();
66
67     if (xkb_event == XkbNewKeyboardNotify) {
68         if (changed & XkbNKN_KeycodesMask) {
69             keymap_changed = 1;
70             modmap_changed = 1;
71         }
72     }
73     else if (xkb_event == XkbMapNotify) {
74         if (changed & XkbKeySymsMask)
75             keymap_changed = 1;
76         if (changed & XkbModifierMapMask)
77             modmap_changed = 1;
78     }
79     if (!keymap_changed && !modmap_changed)
80         return;
81
82     core_mn.u.u.type = MappingNotify;
83     xi_mn.type = DeviceMappingNotify;
84     xi_mn.deviceid = kbd->id;
85     xi_mn.time = time;
86
87     /* 0 is serverClient. */
88     for (i = 1; i < currentMaxClients; i++) {
89         if (!clients[i] || clients[i]->clientState != ClientStateRunning)
90             continue;
91
92         /* Ignore clients which will have already received this.
93          * Inconsistent with themselves, but consistent with previous
94          * behaviour.*/
95         if (xkb_event == XkbMapNotify && (clients[i]->mapNotifyMask & changed))
96             continue;
97         if (xkb_event == XkbNewKeyboardNotify &&
98             (clients[i]->xkbClientFlags & _XkbClientInitialized))
99             continue;
100
101         /* Don't send core events to clients who don't know about us. */
102         if (!XIShouldNotify(clients[i], kbd))
103             continue;
104
105         if (keymap_changed) {
106             core_mn.u.mappingNotify.request = MappingKeyboard;
107
108             /* Clip the keycode range to what the client knows about, so it
109              * doesn't freak out. */
110             if (first_key >= clients[i]->minKC)
111                 core_mn.u.mappingNotify.firstKeyCode = first_key;
112             else
113                 core_mn.u.mappingNotify.firstKeyCode = clients[i]->minKC;
114             if (first_key + num_keys - 1 <= clients[i]->maxKC)
115                 core_mn.u.mappingNotify.count = num_keys;
116             else
117                 core_mn.u.mappingNotify.count = clients[i]->maxKC -
118                                                  clients[i]->minKC + 1;
119
120             WriteEventsToClient(clients[i], 1, &core_mn);
121         }
122         if (modmap_changed) {
123             core_mn.u.mappingNotify.request = MappingModifier;
124             core_mn.u.mappingNotify.firstKeyCode = 0;
125             core_mn.u.mappingNotify.count = 0;
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         xi_mn.request = MappingKeyboard;
135         xi_mn.firstKeyCode = first_key;
136         xi_mn.count = num_keys;
137         SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
138                               1);
139     }
140     if (modmap_changed) {
141         xi_mn.request = MappingModifier;
142         xi_mn.firstKeyCode = 0;
143         xi_mn.count = 0;
144         SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
145                               1);
146     }
147 }
148
149 /***====================================================================***/
150
151 void
152 XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN)
153 {
154     int i;
155     Time time = GetTimeInMillis();
156     CARD16 changed = pNKN->changed;
157
158     pNKN->type = XkbEventCode + XkbEventBase;
159     pNKN->xkbType = XkbNewKeyboardNotify;
160
161     for (i=1; i<currentMaxClients; i++) {
162         if (!clients[i] || clients[i]->clientState != ClientStateRunning)
163             continue;
164
165         if (!(clients[i]->newKeyboardNotifyMask & changed))
166             continue;
167
168         if (!XIShouldNotify(clients[i], kbd))
169             continue;
170
171         pNKN->sequenceNumber = clients[i]->sequence;
172         pNKN->time = time;
173         pNKN->changed = changed;
174         if (clients[i]->swapped) {
175             int n;
176             swaps(&pNKN->sequenceNumber,n);
177             swapl(&pNKN->time,n);
178             swaps(&pNKN->changed,n);
179         }
180         WriteToClient(clients[i], sizeof(xEvent), pNKN);
181
182         if (changed & XkbNKN_KeycodesMask) {
183             clients[i]->minKC = pNKN->minKeyCode;
184             clients[i]->maxKC = pNKN->maxKeyCode;
185         }
186     }
187
188     XkbSendLegacyMapNotify(kbd, XkbNewKeyboardNotify, changed, pNKN->minKeyCode,
189                            pNKN->maxKeyCode - pNKN->minKeyCode + 1);
190
191     return;
192 }
193
194 /***====================================================================***/
195
196 void
197 XkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify *pSN)
198 {
199 XkbSrvInfoPtr   xkbi;
200 XkbStatePtr     state;
201 XkbInterestPtr  interest;
202 Time            time;
203 register CARD16 changed,bState;
204
205     interest = kbd->xkb_interest;
206     if (!interest || !kbd->key || !kbd->key->xkbInfo)
207         return;
208     xkbi = kbd->key->xkbInfo;
209     state= &xkbi->state;
210
211     pSN->type = XkbEventCode + XkbEventBase;
212     pSN->xkbType = XkbStateNotify;
213     pSN->deviceID = kbd->id;
214     pSN->time = time = GetTimeInMillis();
215     pSN->mods = state->mods;
216     pSN->baseMods = state->base_mods;
217     pSN->latchedMods = state->latched_mods;
218     pSN->lockedMods = state->locked_mods;
219     pSN->group = state->group;
220     pSN->baseGroup = state->base_group;
221     pSN->latchedGroup = state->latched_group;
222     pSN->lockedGroup = state->locked_group;
223     pSN->compatState = state->compat_state;
224     pSN->grabMods = state->grab_mods;
225     pSN->compatGrabMods = state->compat_grab_mods;
226     pSN->lookupMods = state->lookup_mods;
227     pSN->compatLookupMods = state->compat_lookup_mods;
228     pSN->ptrBtnState = state->ptr_buttons;
229     changed = pSN->changed;
230     bState= pSN->ptrBtnState;
231
232     while (interest) {
233         if ((!interest->client->clientGone) &&
234             (interest->client->requestVector != InitialVector) &&
235             (interest->client->xkbClientFlags&_XkbClientInitialized) &&
236             (interest->stateNotifyMask&changed) &&
237             XIShouldNotify(interest->client,kbd)) {
238             pSN->sequenceNumber = interest->client->sequence;
239             pSN->time = time;
240             pSN->changed = changed;
241             pSN->ptrBtnState = bState;
242             if ( interest->client->swapped ) {
243                 register int n;
244                 swaps(&pSN->sequenceNumber,n);
245                 swapl(&pSN->time,n);
246                 swaps(&pSN->changed,n);
247                 swaps(&pSN->ptrBtnState,n);
248             }
249             WriteToClient(interest->client, sizeof(xEvent), (char *)pSN);
250         }
251         interest= interest->next;
252     }
253     return;
254 }
255
256 /***====================================================================***/
257
258 /*
259  * This function sends out XKB mapping notify events to clients which
260  * have explicitly selected for them.  Core and Xi events are handled by
261  * XkbSendLegacyMapNotify. */
262 void
263 XkbSendMapNotify(DeviceIntPtr kbd, xkbMapNotify *pMN)
264 {
265     int i;
266     CARD32 time = GetTimeInMillis();
267     CARD16 changed = pMN->changed;
268     XkbSrvInfoPtr xkbi = kbd->key->xkbInfo;
269
270     pMN->minKeyCode = xkbi->desc->min_key_code;
271     pMN->maxKeyCode = xkbi->desc->max_key_code;
272     pMN->type = XkbEventCode + XkbEventBase;
273     pMN->xkbType = XkbMapNotify;
274     pMN->deviceID = kbd->id;
275
276     /* 0 is serverClient. */
277     for (i = 1; i < currentMaxClients; i++) {
278         if (!clients[i] || clients[i]->clientState != ClientStateRunning)
279             continue;
280
281         if (!(clients[i]->mapNotifyMask & changed))
282             continue;
283
284         if (!XIShouldNotify(clients[i], kbd))
285             continue;
286
287         pMN->time = time;
288         pMN->sequenceNumber = clients[i]->sequence;
289         pMN->changed = changed;
290
291         if (clients[i]->swapped) {
292             int n;
293             swaps(&pMN->sequenceNumber, n);
294             swapl(&pMN->time, n);
295             swaps(&pMN->changed, n);
296         }
297         WriteToClient(clients[i], sizeof(xEvent), pMN);
298     }
299
300     XkbSendLegacyMapNotify(kbd, XkbMapNotify, changed, pMN->firstKeySym,
301                            pMN->nKeySyms);
302 }
303
304 int
305 XkbComputeControlsNotify(       DeviceIntPtr            kbd,
306                                 XkbControlsPtr          old,
307                                 XkbControlsPtr          new,
308                                 xkbControlsNotify *     pCN,
309                                 Bool                    forceCtrlProc)
310 {
311 int             i;
312 CARD32          changedControls;
313
314     changedControls= 0;
315
316     if (!kbd || !kbd->kbdfeed)
317         return 0;
318     
319     if (old->enabled_ctrls!=new->enabled_ctrls)
320         changedControls|= XkbControlsEnabledMask;
321     if ((old->repeat_delay!=new->repeat_delay)||
322         (old->repeat_interval!=new->repeat_interval))
323         changedControls|= XkbRepeatKeysMask;
324     for (i = 0; i < XkbPerKeyBitArraySize; i++)
325         if (old->per_key_repeat[i] != new->per_key_repeat[i])
326             changedControls|= XkbPerKeyRepeatMask;
327     if (old->slow_keys_delay!=new->slow_keys_delay)
328         changedControls|= XkbSlowKeysMask;
329     if (old->debounce_delay!=new->debounce_delay)
330         changedControls|= XkbBounceKeysMask;
331     if ((old->mk_delay!=new->mk_delay)||
332         (old->mk_interval!=new->mk_interval)||
333         (old->mk_dflt_btn!=new->mk_dflt_btn))
334         changedControls|= XkbMouseKeysMask;
335     if ((old->mk_time_to_max!=new->mk_time_to_max)||
336         (old->mk_curve!=new->mk_curve)||
337         (old->mk_max_speed!=new->mk_max_speed))
338         changedControls|= XkbMouseKeysAccelMask;
339     if (old->ax_options!=new->ax_options)
340         changedControls|= XkbAccessXKeysMask;
341     if ((old->ax_options^new->ax_options) & XkbAX_SKOptionsMask)
342         changedControls|= XkbStickyKeysMask;
343     if ((old->ax_options^new->ax_options) & XkbAX_FBOptionsMask)
344         changedControls|= XkbAccessXFeedbackMask;
345     if ((old->ax_timeout!=new->ax_timeout)||
346         (old->axt_ctrls_mask!=new->axt_ctrls_mask)||
347         (old->axt_ctrls_values!=new->axt_ctrls_values)||
348         (old->axt_opts_mask!=new->axt_opts_mask)||
349         (old->axt_opts_values!= new->axt_opts_values)) {
350         changedControls|= XkbAccessXTimeoutMask;
351     }
352     if ((old->internal.mask!=new->internal.mask)||
353         (old->internal.real_mods!=new->internal.real_mods)||
354         (old->internal.vmods!=new->internal.vmods))
355         changedControls|= XkbInternalModsMask;
356     if ((old->ignore_lock.mask!=new->ignore_lock.mask)||
357         (old->ignore_lock.real_mods!=new->ignore_lock.real_mods)||
358         (old->ignore_lock.vmods!=new->ignore_lock.vmods))
359         changedControls|= XkbIgnoreLockModsMask;
360
361     if (new->enabled_ctrls&XkbRepeatKeysMask)
362          kbd->kbdfeed->ctrl.autoRepeat=TRUE;
363     else 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
383 void
384 XkbSendControlsNotify(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             XIShouldNotify(interest->client, kbd)) {
407             if (!initialized) {
408                 pCN->type = XkbEventCode + XkbEventBase;
409                 pCN->xkbType = XkbControlsNotify;
410                 pCN->deviceID = kbd->id;
411                 pCN->time = time = GetTimeInMillis();
412                 enabledChanges = pCN->enabledControlChanges;
413                 initialized= 1;
414             }
415             pCN->changedControls = changedControls;
416             pCN->enabledControls = enabledControls;
417             pCN->enabledControlChanges = enabledChanges;
418             pCN->sequenceNumber = interest->client->sequence;
419             pCN->time = time;
420             if ( interest->client->swapped ) {
421                 register int n;
422                 swaps(&pCN->sequenceNumber,n);
423                 swapl(&pCN->changedControls,n);
424                 swapl(&pCN->enabledControls,n);
425                 swapl(&pCN->enabledControlChanges,n);
426                 swapl(&pCN->time,n);
427             }
428             WriteToClient(interest->client, sizeof(xEvent), (char *)pCN);
429         }
430         interest= interest->next;
431     }
432     return;
433 }
434
435 static void
436 XkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify *pEv)
437 {
438 int             initialized;
439 XkbInterestPtr  interest;
440 Time            time = 0;
441 CARD32          state,changed;
442
443     interest = kbd->xkb_interest;
444     if (!interest)
445         return;
446  
447     initialized = 0;
448     state = pEv->state;
449     changed = pEv->changed;
450     while (interest) {
451         if ((!interest->client->clientGone) &&
452             (interest->client->requestVector != InitialVector) &&
453             (interest->client->xkbClientFlags&_XkbClientInitialized) &&
454             XIShouldNotify(interest->client, kbd) &&
455             (((xkbType==XkbIndicatorStateNotify)&&
456                                 (interest->iStateNotifyMask&changed))||
457              ((xkbType==XkbIndicatorMapNotify)&&
458                                 (interest->iMapNotifyMask&changed)))) {
459             if (!initialized) {
460                 pEv->type = XkbEventCode + XkbEventBase;
461                 pEv->xkbType = xkbType;
462                 pEv->deviceID = kbd->id;
463                 pEv->time = time = GetTimeInMillis();
464                 initialized= 1;
465             }
466             pEv->sequenceNumber = interest->client->sequence;
467             pEv->time = time;
468             pEv->changed = changed;
469             pEv->state = state;
470             if ( interest->client->swapped ) {
471                 register int n;
472                 swaps(&pEv->sequenceNumber,n);
473                 swapl(&pEv->time,n);
474                 swapl(&pEv->changed,n);
475                 swapl(&pEv->state,n);
476             }
477             WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
478         }
479         interest= interest->next;
480     }
481     return;
482 }
483
484
485 void
486 XkbHandleBell(  BOOL             force,
487                 BOOL             eventOnly,
488                 DeviceIntPtr     kbd,
489                 CARD8            percent,
490                 pointer          pCtrl,
491                 CARD8            class,
492                 Atom             name,
493                 WindowPtr        pWin,
494                 ClientPtr        pClient)
495 {
496 xkbBellNotify   bn;
497 int             initialized;
498 XkbSrvInfoPtr   xkbi;
499 XkbInterestPtr  interest;
500 CARD8           id;
501 CARD16          pitch,duration;
502 Time            time = 0;
503 XID             winID = 0;
504
505     if (!kbd->key || !kbd->key->xkbInfo)
506         return;
507
508     xkbi = kbd->key->xkbInfo;
509
510     if ((force||(xkbi->desc->ctrls->enabled_ctrls&XkbAudibleBellMask))&&
511                                                         (!eventOnly)) {
512         if (kbd->kbdfeed->BellProc)
513             (*kbd->kbdfeed->BellProc)(percent,kbd,(pointer)pCtrl,class);
514     }
515     interest = kbd->xkb_interest;
516     if ((!interest)||(force))
517         return;
518
519     if ((class==0)||(class==KbdFeedbackClass)) {
520         KeybdCtrl *pKeyCtrl= (KeybdCtrl *)pCtrl;
521         id= pKeyCtrl->id;
522         pitch= pKeyCtrl->bell_pitch;
523         duration= pKeyCtrl->bell_duration;
524     }
525     else if (class==BellFeedbackClass) {
526         BellCtrl *pBellCtrl= (BellCtrl *)pCtrl;
527         id= pBellCtrl->id;
528         pitch= pBellCtrl->pitch;
529         duration= pBellCtrl->duration;
530     }
531     else return;
532  
533     initialized = 0;
534     while (interest) {
535         if ((!interest->client->clientGone) &&
536             (interest->client->requestVector != InitialVector) &&
537             (interest->client->xkbClientFlags&_XkbClientInitialized) &&
538             (interest->bellNotifyMask) &&
539             XIShouldNotify(interest->client,kbd)) {
540             if (!initialized) {
541                 time = GetTimeInMillis();
542                 bn.type = XkbEventCode + XkbEventBase;
543                 bn.xkbType = XkbBellNotify;
544                 bn.deviceID = kbd->id;
545                 bn.bellClass = class;
546                 bn.bellID = id;
547                 bn.percent= percent;
548                 bn.eventOnly = (eventOnly!=0);
549                 winID= (pWin?pWin->drawable.id:None);
550                 initialized= 1;
551             }
552             bn.sequenceNumber = interest->client->sequence;
553             bn.time = time;
554             bn.pitch = pitch;
555             bn.duration = duration;
556             bn.name = name;
557             bn.window=  winID;
558             if ( interest->client->swapped ) {
559                 register int n;
560                 swaps(&bn.sequenceNumber,n);
561                 swapl(&bn.time,n);
562                 swaps(&bn.pitch,n);
563                 swaps(&bn.duration,n);
564                 swapl(&bn.name,n);
565                 swapl(&bn.window,n);
566             }
567             WriteToClient(interest->client, sizeof(xEvent), (char *)&bn);
568         }
569         interest= interest->next;
570     }
571     return;
572 }
573
574 void
575 XkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify *pEv)
576 {
577 int             initialized;
578 XkbInterestPtr  interest;
579 Time            time = 0;
580 CARD16          sk_delay,db_delay;
581
582     interest = kbd->xkb_interest;
583     if (!interest)
584         return;
585  
586     initialized = 0;
587     sk_delay= pEv->slowKeysDelay;
588     db_delay= pEv->debounceDelay;
589     while (interest) {
590         if ((!interest->client->clientGone) &&
591             (interest->client->requestVector != InitialVector) &&
592             (interest->client->xkbClientFlags&_XkbClientInitialized) &&
593             (interest->accessXNotifyMask&(1<<pEv->detail)) &&
594             XIShouldNotify(interest->client, kbd)) {
595             if (!initialized) {
596                 pEv->type = XkbEventCode + XkbEventBase;
597                 pEv->xkbType = XkbAccessXNotify;
598                 pEv->deviceID = kbd->id;
599                 pEv->time = time = GetTimeInMillis();
600                 initialized= 1;
601             }
602             pEv->sequenceNumber = interest->client->sequence;
603             pEv->time = time;
604             pEv->slowKeysDelay = sk_delay;
605             pEv->debounceDelay = db_delay;
606             if ( interest->client->swapped ) {
607                 register int n;
608                 swaps(&pEv->sequenceNumber,n);
609                 swapl(&pEv->time,n);
610                 swaps(&pEv->slowKeysDelay,n);
611                 swaps(&pEv->debounceDelay,n);
612             }
613             WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
614         }
615         interest= interest->next;
616     }
617     return;
618 }
619
620 void
621 XkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify *pEv)
622 {
623 int             initialized;
624 XkbInterestPtr  interest;
625 Time            time = 0;
626 CARD16          changed,changedVirtualMods;
627 CARD32          changedIndicators;
628
629     interest = kbd->xkb_interest;
630     if (!interest)
631         return;
632  
633     initialized = 0;
634     changed= pEv->changed;
635     changedIndicators= pEv->changedIndicators;
636     changedVirtualMods= pEv->changedVirtualMods;
637     while (interest) {
638         if ((!interest->client->clientGone) &&
639             (interest->client->requestVector != InitialVector) &&
640             (interest->client->xkbClientFlags&_XkbClientInitialized) &&
641             (interest->namesNotifyMask&pEv->changed) &&
642             XIShouldNotify(interest->client, kbd)) {
643             if (!initialized) {
644                 pEv->type = XkbEventCode + XkbEventBase;
645                 pEv->xkbType = XkbNamesNotify;
646                 pEv->deviceID = kbd->id;
647                 pEv->time = time = GetTimeInMillis();
648                 initialized= 1;
649             }
650             pEv->sequenceNumber = interest->client->sequence;
651             pEv->time = time;
652             pEv->changed = changed;
653             pEv->changedIndicators = changedIndicators;
654             pEv->changedVirtualMods= changedVirtualMods;
655             if ( interest->client->swapped ) {
656                 register int n;
657                 swaps(&pEv->sequenceNumber,n);
658                 swapl(&pEv->time,n);
659                 swaps(&pEv->changed,n);
660                 swapl(&pEv->changedIndicators,n);
661                 swaps(&pEv->changedVirtualMods,n);
662             }
663             WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
664         }
665         interest= interest->next;
666     }
667     return;
668 }
669
670 void
671 XkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify *pEv)
672 {
673 int             initialized;
674 XkbInterestPtr  interest;
675 Time            time = 0;
676 CARD16          firstSI = 0, nSI = 0, nTotalSI = 0;
677
678     interest = kbd->xkb_interest;
679     if (!interest)
680         return;
681  
682     initialized = 0;
683     while (interest) {
684         if ((!interest->client->clientGone) &&
685             (interest->client->requestVector != InitialVector) &&
686             (interest->client->xkbClientFlags&_XkbClientInitialized) &&
687             (interest->compatNotifyMask) &&
688             XIShouldNotify(interest->client, kbd)) {
689             if (!initialized) {
690                 pEv->type = XkbEventCode + XkbEventBase;
691                 pEv->xkbType = XkbCompatMapNotify;
692                 pEv->deviceID = kbd->id;
693                 pEv->time = time = GetTimeInMillis();
694                 firstSI= pEv->firstSI;
695                 nSI= pEv->nSI;
696                 nTotalSI= pEv->nTotalSI;
697                 initialized= 1;
698             }
699             pEv->sequenceNumber = interest->client->sequence;
700             pEv->time = time;
701             pEv->firstSI = firstSI;
702             pEv->nSI = nSI;
703             pEv->nTotalSI = nTotalSI;
704             if ( interest->client->swapped ) {
705                 register int n;
706                 swaps(&pEv->sequenceNumber,n);
707                 swapl(&pEv->time,n);
708                 swaps(&pEv->firstSI,n);
709                 swaps(&pEv->nSI,n);
710                 swaps(&pEv->nTotalSI,n);
711             }
712             WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
713         }
714         interest= interest->next;
715     }
716     return;
717 }
718
719 void
720 XkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage *pEv)
721 {
722 int              initialized;
723 XkbSrvInfoPtr    xkbi;
724 XkbInterestPtr   interest;
725 Time             time = 0;
726
727     interest = kbd->xkb_interest;
728     if (!interest || !kbd->key || !kbd->key->xkbInfo)
729         return;
730  
731     xkbi = kbd->key->xkbInfo;
732
733     initialized = 0;
734     pEv->mods= xkbi->state.mods;
735     pEv->group= xkbi->state.group;
736     while (interest) {
737         if ((!interest->client->clientGone) &&
738             (interest->client->requestVector != InitialVector) &&
739             (interest->client->xkbClientFlags&_XkbClientInitialized) &&
740             (interest->actionMessageMask) &&
741             XIShouldNotify(interest->client, kbd)) {
742             if (!initialized) {
743                 pEv->type = XkbEventCode + XkbEventBase;
744                 pEv->xkbType = XkbActionMessage;
745                 pEv->deviceID = kbd->id;
746                 pEv->sequenceNumber = interest->client->sequence;
747                 pEv->time = time = GetTimeInMillis();
748                 initialized= 1;
749             }
750             pEv->sequenceNumber = interest->client->sequence;
751             pEv->time = time;
752             if ( interest->client->swapped ) {
753                 register int n;
754                 swaps(&pEv->sequenceNumber,n);
755                 swapl(&pEv->time,n);
756             }
757             WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
758         }
759         interest= interest->next;
760     }
761     return;
762 }
763
764 void
765 XkbSendExtensionDeviceNotify(   DeviceIntPtr                    dev,
766                                 ClientPtr                       client,
767                                 xkbExtensionDeviceNotify *      pEv)
768 {
769 int              initialized;
770 XkbInterestPtr   interest;
771 Time             time = 0;
772 CARD32           defined, state;
773 CARD16           reason;
774
775     interest = dev->xkb_interest;
776     if (!interest)
777         return;
778  
779     initialized = 0;
780     reason= pEv->reason;
781     defined= pEv->ledsDefined;
782     state= pEv->ledState;
783     while (interest) {
784         if ((!interest->client->clientGone) &&
785             (interest->client->requestVector != InitialVector) &&
786             (interest->client->xkbClientFlags&_XkbClientInitialized) &&
787             (interest->extDevNotifyMask&reason) &&
788             XIShouldNotify(interest->client, dev)) {
789             if (!initialized) {
790                 pEv->type = XkbEventCode + XkbEventBase;
791                 pEv->xkbType = XkbExtensionDeviceNotify;
792                 pEv->deviceID = dev->id;
793                 pEv->sequenceNumber = interest->client->sequence;
794                 pEv->time = time = GetTimeInMillis();
795                 initialized= 1;
796             }
797             else {
798                 pEv->sequenceNumber = interest->client->sequence;
799                 pEv->time = time;
800                 pEv->ledsDefined= defined;
801                 pEv->ledState= state;
802                 pEv->reason= reason;
803                 pEv->supported= XkbXI_AllFeaturesMask;
804             }
805             if ( interest->client->swapped ) {
806                 register int n;
807                 swaps(&pEv->sequenceNumber,n);
808                 swapl(&pEv->time,n);
809                 swapl(&pEv->ledsDefined,n);
810                 swapl(&pEv->ledState,n);
811                 swaps(&pEv->reason,n);
812                 swaps(&pEv->supported,n);
813             }
814             WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
815         }
816         interest= interest->next;
817     }
818     return;
819 }
820
821 void
822 XkbSendNotification(    DeviceIntPtr            kbd,
823                         XkbChangesPtr           pChanges,
824                         XkbEventCausePtr        cause)
825 {
826 XkbSrvLedInfoPtr        sli;
827
828     sli= NULL;
829     if (pChanges->state_changes) {
830         xkbStateNotify sn;
831         sn.changed= pChanges->state_changes;
832         sn.keycode= cause->kc;
833         sn.eventType= cause->event;
834         sn.requestMajor= cause->mjr;
835         sn.requestMinor= cause->mnr;
836         XkbSendStateNotify(kbd,&sn);
837     }
838     if (pChanges->map.changed) {
839         xkbMapNotify mn;
840         memset(&mn, 0, sizeof(xkbMapNotify));
841         mn.changed= pChanges->map.changed;
842         mn.firstType= pChanges->map.first_type;
843         mn.nTypes= pChanges->map.num_types;
844         mn.firstKeySym= pChanges->map.first_key_sym;
845         mn.nKeySyms= pChanges->map.num_key_syms;
846         mn.firstKeyAct= pChanges->map.first_key_act;
847         mn.nKeyActs= pChanges->map.num_key_acts;
848         mn.firstKeyBehavior= pChanges->map.first_key_behavior;
849         mn.nKeyBehaviors= pChanges->map.num_key_behaviors;
850         mn.virtualMods= pChanges->map.vmods;
851         mn.firstKeyExplicit= pChanges->map.first_key_explicit;
852         mn.nKeyExplicit= pChanges->map.num_key_explicit;
853         mn.firstModMapKey= pChanges->map.first_modmap_key;
854         mn.nModMapKeys= pChanges->map.num_modmap_keys;
855         mn.firstVModMapKey= pChanges->map.first_vmodmap_key;
856         mn.nVModMapKeys= pChanges->map.num_vmodmap_keys;
857         XkbSendMapNotify(kbd,&mn);
858     }
859     if ((pChanges->ctrls.changed_ctrls)||
860         (pChanges->ctrls.enabled_ctrls_changes)) {
861         xkbControlsNotify cn;
862         memset(&cn, 0, sizeof(xkbControlsNotify));
863         cn.changedControls= pChanges->ctrls.changed_ctrls;
864         cn.enabledControlChanges= pChanges->ctrls.enabled_ctrls_changes;
865         cn.keycode= cause->kc;
866         cn.eventType= cause->event;
867         cn.requestMajor= cause->mjr;
868         cn.requestMinor= cause->mnr;
869         XkbSendControlsNotify(kbd,&cn);
870     }
871     if (pChanges->indicators.map_changes) {
872         xkbIndicatorNotify in;
873         if (sli==NULL)
874             sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
875         memset(&in, 0, sizeof(xkbIndicatorNotify));
876         in.state= sli->effectiveState;
877         in.changed= pChanges->indicators.map_changes;
878         XkbSendIndicatorNotify(kbd,XkbIndicatorMapNotify,&in);
879     }
880     if (pChanges->indicators.state_changes) {
881         xkbIndicatorNotify in;
882         if (sli==NULL)
883             sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
884         memset(&in, 0, sizeof(xkbIndicatorNotify));
885         in.state= sli->effectiveState;
886         in.changed= pChanges->indicators.state_changes;
887         XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in);
888     }
889     if (pChanges->names.changed) {
890         xkbNamesNotify nn;
891         memset(&nn, 0, sizeof(xkbNamesNotify));
892         nn.changed= pChanges->names.changed;
893         nn.firstType= pChanges->names.first_type;
894         nn.nTypes= pChanges->names.num_types;
895         nn.firstLevelName= pChanges->names.first_lvl;
896         nn.nLevelNames= pChanges->names.num_lvls;
897         nn.nRadioGroups= pChanges->names.num_rg;
898         nn.changedVirtualMods= pChanges->names.changed_vmods;
899         nn.changedIndicators= pChanges->names.changed_indicators;
900         XkbSendNamesNotify(kbd,&nn);
901     }
902     if ((pChanges->compat.changed_groups)||(pChanges->compat.num_si>0)) {
903         xkbCompatMapNotify cmn;
904         memset(&cmn, 0, sizeof(xkbCompatMapNotify));
905         cmn.changedGroups= pChanges->compat.changed_groups;
906         cmn.firstSI= pChanges->compat.first_si;
907         cmn.nSI= pChanges->compat.num_si;
908         cmn.nTotalSI= kbd->key->xkbInfo->desc->compat->num_si;
909         XkbSendCompatMapNotify(kbd,&cmn);
910     }
911     return;
912 }
913
914 /***====================================================================***/
915
916 void
917 XkbFilterEvents(ClientPtr client,int nEvents,xEvent *xE)
918 {
919     DeviceIntPtr dev = NULL;
920     XkbSrvInfoPtr xkbi;
921     CARD8 type = xE[0].u.u.type;
922
923     if (xE->u.u.type & EXTENSION_EVENT_BASE)
924         dev = XIGetDevice(xE);
925
926     if (!dev)
927         dev = PickKeyboard(client);
928
929     if (!dev->key)
930         return;
931
932     xkbi = dev->key->xkbInfo;
933
934     if (client->xkbClientFlags & _XkbClientInitialized) {
935         if ((xkbDebugFlags&0x10)&&
936             (type == KeyPress || type == KeyRelease ||
937              type == DeviceKeyPress || type == DeviceKeyRelease))
938             DebugF("[xkb] XkbFilterWriteEvents (XKB client): state 0x%04x\n",
939                    xE[0].u.keyButtonPointer.state);
940
941         if (dev->deviceGrab.grab != NullGrab && dev->deviceGrab.fromPassiveGrab &&
942             (type == KeyPress || type == KeyRelease ||
943              type == DeviceKeyPress || type == DeviceKeyRelease)) {
944             unsigned int state, flags;
945
946             flags = client->xkbClientFlags;
947             state = xkbi->state.compat_grab_mods;
948             if (flags & XkbPCF_GrabsUseXKBStateMask) {
949                 int group;
950                 if (flags & XkbPCF_LookupStateWhenGrabbed) {
951                      group = xkbi->state.group;
952                      state = xkbi->state.lookup_mods;
953                 }
954                 else {
955                     state = xkbi->state.grab_mods;
956                     group = xkbi->state.base_group + xkbi->state.latched_group;
957                     if (group < 0 || group >= xkbi->desc->ctrls->num_groups)
958                         group = XkbAdjustGroup(group, xkbi->desc->ctrls);
959                 }
960                 state = XkbBuildCoreState(state, group);
961             }
962             else if (flags & XkbPCF_LookupStateWhenGrabbed) {
963                 state = xkbi->state.compat_lookup_mods;
964             }
965             xE[0].u.keyButtonPointer.state = state;
966         }
967     }
968     else {
969         if ((xkbDebugFlags & 0x4) &&
970             (xE[0].u.u.type == KeyPress || xE[0].u.u.type==KeyRelease ||
971              xE[0].u.u.type == DeviceKeyPress ||
972              xE[0].u.u.type == DeviceKeyRelease)) {
973             DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
974             DebugF("[xkb] event= 0x%04x\n",xE[0].u.keyButtonPointer.state);
975             DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",
976                    xkbi->state.lookup_mods, xkbi->state.grab_mods);
977             DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
978                    xkbi->state.compat_lookup_mods, xkbi->state.compat_grab_mods);
979         }
980         if (type >= KeyPress && type <= MotionNotify) {
981             CARD16 old, new;
982
983             old = xE[0].u.keyButtonPointer.state & ~0x1f00;
984             new = xE[0].u.keyButtonPointer.state & 0x1F00;
985
986             if (old == XkbStateFieldFromRec(&xkbi->state))
987                 new |= xkbi->state.compat_lookup_mods;
988             else
989                 new |= xkbi->state.compat_grab_mods;
990             xE[0].u.keyButtonPointer.state = new;
991         }
992         else if (type == EnterNotify || type == LeaveNotify) {
993             xE[0].u.enterLeave.state &= 0x1F00;
994             xE[0].u.enterLeave.state |= xkbi->state.compat_grab_mods;
995         }
996         else if (type >= DeviceKeyPress && type <= DeviceMotionNotify) {
997             CARD16 old, new;
998             deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*) &xE[0];
999
1000             old = kbp->state & ~0x1F00;
1001             new = kbp->state & 0x1F00;
1002             if (old == XkbStateFieldFromRec(&xkbi->state))
1003                 new |= xkbi->state.compat_lookup_mods;
1004             else
1005                 new |= xkbi->state.compat_grab_mods;
1006             kbp->state = new;
1007         }
1008     }
1009 }
1010
1011 /***====================================================================***/
1012
1013 XkbInterestPtr
1014 XkbFindClientResource(DevicePtr inDev,ClientPtr client)
1015 {
1016 DeviceIntPtr    dev = (DeviceIntPtr)inDev;
1017 XkbInterestPtr  interest;
1018
1019     if ( dev->xkb_interest ) {
1020         interest = dev->xkb_interest;
1021         while (interest){
1022             if (interest->client==client) {
1023                 return interest;
1024             }
1025             interest = interest->next;
1026         }
1027     }
1028     return NULL;
1029 }
1030
1031 XkbInterestPtr
1032 XkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id)
1033 {
1034 DeviceIntPtr    dev = (DeviceIntPtr)inDev;
1035 XkbInterestPtr  interest;
1036
1037     interest = dev->xkb_interest;
1038     while (interest) {
1039         if (interest->client==client)
1040             return ((interest->resource==id)?interest:NULL);
1041         interest = interest->next;
1042     }
1043     interest = calloc(1, sizeof(XkbInterestRec));
1044     if (interest) {
1045         interest->dev = dev;
1046         interest->client = client;
1047         interest->resource = id;
1048         interest->stateNotifyMask= 0;
1049         interest->ctrlsNotifyMask= 0;
1050         interest->namesNotifyMask= 0;
1051         interest->compatNotifyMask= 0;
1052         interest->bellNotifyMask= FALSE;
1053         interest->accessXNotifyMask= 0;
1054         interest->iStateNotifyMask= 0;
1055         interest->iMapNotifyMask= 0;
1056         interest->altSymsNotifyMask= 0;
1057         interest->next = dev->xkb_interest;
1058         dev->xkb_interest= interest;
1059         return interest;
1060     }
1061     return NULL;
1062 }
1063
1064 int
1065 XkbRemoveResourceClient(DevicePtr inDev,XID id) 
1066 {
1067 XkbSrvInfoPtr   xkbi;
1068 DeviceIntPtr    dev = (DeviceIntPtr)inDev;
1069 XkbInterestPtr  interest;
1070 Bool            found;
1071 unsigned long   autoCtrls,autoValues;
1072 ClientPtr       client = NULL;
1073
1074     found= FALSE;
1075
1076     if (!dev->key || !dev->key->xkbInfo)
1077         return found;
1078
1079     autoCtrls= autoValues= 0;
1080     if ( dev->xkb_interest ) {
1081         interest = dev->xkb_interest;
1082         if (interest && (interest->resource==id)){
1083             dev->xkb_interest = interest->next;
1084             autoCtrls= interest->autoCtrls;
1085             autoValues= interest->autoCtrlValues;
1086             client= interest->client;
1087             free(interest);
1088             found= TRUE;
1089         }
1090         while ((!found)&&(interest->next)) {
1091             if (interest->next->resource==id) {
1092                 XkbInterestPtr  victim = interest->next;
1093                 interest->next = victim->next;
1094                 autoCtrls= victim->autoCtrls;
1095                 autoValues= victim->autoCtrlValues;
1096                 client= victim->client;
1097                 free(victim);
1098                 found= TRUE;
1099             }
1100             interest = interest->next;
1101         }
1102     }
1103     if (found && autoCtrls && dev->key && dev->key->xkbInfo ) {
1104         XkbEventCauseRec cause;
1105
1106         xkbi= dev->key->xkbInfo;
1107         XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client);
1108         XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause);
1109     }
1110     return found;
1111 }