xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

xkbEvents.c (36801B)


      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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 }