Home | History | Annotate | Line # | Download | only in xkb
      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_CONFIG_H
     28 #include <config.h>
     29 #endif
     30 #include <stdio.h>
     31 #include "Xlibint.h"
     32 #include <X11/extensions/XKBproto.h>
     33 #include "XKBlibint.h"
     34 
     35 XkbInternAtomFunc       _XkbInternAtomFunc  = XInternAtom;
     36 XkbGetAtomNameFunc      _XkbGetAtomNameFunc = XGetAtomName;
     37 
     38 Bool
     39 XkbQueryExtension(Display *dpy,
     40                   int *opcodeReturn,
     41                   int *eventBaseReturn,
     42                   int *errorBaseReturn,
     43                   int *majorReturn,
     44                   int *minorReturn)
     45 {
     46     if (!XkbUseExtension(dpy, majorReturn, minorReturn))
     47         return False;
     48     if (opcodeReturn)
     49         *opcodeReturn = dpy->xkb_info->codes->major_opcode;
     50     if (eventBaseReturn)
     51         *eventBaseReturn = dpy->xkb_info->codes->first_event;
     52     if (errorBaseReturn)
     53         *errorBaseReturn = dpy->xkb_info->codes->first_error;
     54     if (majorReturn)
     55         *majorReturn = dpy->xkb_info->srv_major;
     56     if (minorReturn)
     57         *minorReturn = dpy->xkb_info->srv_minor;
     58     return True;
     59 }
     60 
     61 Bool
     62 XkbLibraryVersion(int *libMajorRtrn, int *libMinorRtrn)
     63 {
     64     int supported;
     65 
     66     if (*libMajorRtrn != XkbMajorVersion) {
     67         /* version 0.65 is (almost) compatible with 1.00 */
     68         if ((XkbMajorVersion == 1) &&
     69             (((*libMajorRtrn) == 0) && ((*libMinorRtrn) == 65)))
     70             supported = True;
     71         else
     72             supported = False;
     73     }
     74     else {
     75         supported = True;
     76     }
     77 
     78     *libMajorRtrn = XkbMajorVersion;
     79     *libMinorRtrn = XkbMinorVersion;
     80     return supported;
     81 }
     82 
     83 Bool
     84 XkbSelectEvents(Display *dpy,
     85                 unsigned int deviceSpec,
     86                 unsigned int affect,
     87                 unsigned int selectAll)
     88 {
     89     register xkbSelectEventsReq *req;
     90     XkbInfoPtr xkbi;
     91 
     92     if ((dpy->flags & XlibDisplayNoXkb) ||
     93         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
     94         return False;
     95     LockDisplay(dpy);
     96     xkbi = dpy->xkb_info;
     97     xkbi->selected_events &= ~affect;
     98     xkbi->selected_events |= (affect & selectAll);
     99     GetReq(kbSelectEvents, req);
    100     req->reqType = xkbi->codes->major_opcode;
    101     req->xkbReqType = X_kbSelectEvents;
    102     req->deviceSpec = deviceSpec;
    103     req->affectWhich = (CARD16) affect;
    104     req->clear = affect & (~selectAll);
    105     req->selectAll = affect & selectAll;
    106     if (affect & XkbMapNotifyMask) {
    107         req->affectMap = XkbAllMapComponentsMask;
    108         /* the implicit support needs the client info */
    109         /* even if the client itself doesn't want it */
    110         if (selectAll & XkbMapNotifyMask)
    111             req->map = XkbAllMapEventsMask;
    112         else
    113             req->map = XkbAllClientInfoMask;
    114         if (selectAll & XkbMapNotifyMask)
    115             xkbi->selected_map_details = XkbAllMapEventsMask;
    116         else
    117             xkbi->selected_map_details = 0;
    118     }
    119     if (affect & XkbNewKeyboardNotifyMask) {
    120         if (selectAll & XkbNewKeyboardNotifyMask)
    121             xkbi->selected_nkn_details = XkbAllNewKeyboardEventsMask;
    122         else
    123             xkbi->selected_nkn_details = 0;
    124         if (!(xkbi->xlib_ctrls & XkbLC_IgnoreNewKeyboards)) {
    125             /* we want it, even if the client doesn't.  Don't mess */
    126             /* around with details -- ask for all of them and throw */
    127             /* away the ones we don't need */
    128             req->selectAll |= XkbNewKeyboardNotifyMask;
    129         }
    130     }
    131     UnlockDisplay(dpy);
    132     SyncHandle();
    133     return True;
    134 }
    135 
    136 Bool
    137 XkbSelectEventDetails(Display *dpy,
    138                       unsigned deviceSpec,
    139                       unsigned eventType,
    140                       unsigned long int affect,
    141                       unsigned long int details)
    142 {
    143     register xkbSelectEventsReq *req;
    144     XkbInfoPtr  xkbi;
    145     int         size = 0;
    146     char        *out;
    147     union {
    148         CARD8   *c8;
    149         CARD16  *c16;
    150         CARD32  *c32;
    151     } u;
    152 
    153     if ((dpy->flags & XlibDisplayNoXkb) ||
    154         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    155         return False;
    156     LockDisplay(dpy);
    157     xkbi = dpy->xkb_info;
    158     if (affect & details)
    159         xkbi->selected_events |= (1 << eventType);
    160     else
    161         xkbi->selected_events &= ~(1 << eventType);
    162     GetReq(kbSelectEvents, req);
    163     req->reqType = xkbi->codes->major_opcode;
    164     req->xkbReqType = X_kbSelectEvents;
    165     req->deviceSpec = deviceSpec;
    166     req->clear = req->selectAll = 0;
    167     if (eventType == XkbMapNotify) {
    168         /* we need all of the client info, even if the application */
    169         /* doesn't.   Make sure that we always request the stuff */
    170         /* that the implicit support needs, and just filter out anything */
    171         /* the client doesn't want later */
    172         req->affectMap = (CARD16) affect;
    173         req->map = (CARD16) details | (XkbAllClientInfoMask & affect);
    174         req->affectWhich = XkbMapNotifyMask;
    175         xkbi->selected_map_details &= ~affect;
    176         xkbi->selected_map_details |= (details & affect);
    177     }
    178     else {
    179         req->affectMap = req->map = 0;
    180         req->affectWhich = (1 << eventType);
    181         switch (eventType) {
    182         case XkbNewKeyboardNotify:
    183             xkbi->selected_nkn_details &= ~affect;
    184             xkbi->selected_nkn_details |= (details & affect);
    185             if (!(xkbi->xlib_ctrls & XkbLC_IgnoreNewKeyboards))
    186                 details = (affect & XkbAllNewKeyboardEventsMask);
    187         case XkbStateNotify:
    188         case XkbNamesNotify:
    189         case XkbAccessXNotify:
    190         case XkbExtensionDeviceNotify:
    191             size = 2;
    192             req->length += 1;
    193             break;
    194         case XkbControlsNotify:
    195         case XkbIndicatorStateNotify:
    196         case XkbIndicatorMapNotify:
    197             size = 4;
    198             req->length += 2;
    199             break;
    200         case XkbBellNotify:
    201         case XkbActionMessage:
    202         case XkbCompatMapNotify:
    203             size = 1;
    204             req->length += 1;
    205             break;
    206         }
    207         BufAlloc(char *, out, (((size * 2) + (unsigned) 3) / 4) * 4);
    208 
    209         u.c8 = (CARD8 *) out;
    210         if (size == 2) {
    211             u.c16[0] = (CARD16) affect;
    212             u.c16[1] = (CARD16) details;
    213         }
    214         else if (size == 4) {
    215             u.c32[0] = (CARD32) affect;
    216             u.c32[1] = (CARD32) details;
    217         }
    218         else {
    219             u.c8[0] = (CARD8) affect;
    220             u.c8[1] = (CARD8) details;
    221         }
    222     }
    223     UnlockDisplay(dpy);
    224     SyncHandle();
    225     return True;
    226 }
    227 
    228 Bool
    229 XkbLockModifiers(Display *dpy,
    230                  unsigned int deviceSpec,
    231                  unsigned int affect,
    232                  unsigned int values)
    233 {
    234     register xkbLatchLockStateReq *req;
    235     XkbInfoPtr xkbi;
    236 
    237     if ((dpy->flags & XlibDisplayNoXkb) ||
    238         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    239         return False;
    240     LockDisplay(dpy);
    241     xkbi = dpy->xkb_info;
    242     GetReq(kbLatchLockState, req);
    243     req->reqType = xkbi->codes->major_opcode;
    244     req->xkbReqType = X_kbLatchLockState;
    245     req->deviceSpec = deviceSpec;
    246     req->affectModLocks = affect;
    247     req->modLocks = values;
    248     req->lockGroup = False;
    249     req->groupLock = 0;
    250 
    251     req->affectModLatches = req->modLatches = 0;
    252     req->latchGroup = False;
    253     req->groupLatch = 0;
    254     UnlockDisplay(dpy);
    255     SyncHandle();
    256     return True;
    257 }
    258 
    259 Bool
    260 XkbLatchModifiers(Display *dpy,
    261                   unsigned int deviceSpec,
    262                   unsigned int affect,
    263                   unsigned int values)
    264 {
    265     register xkbLatchLockStateReq *req;
    266     XkbInfoPtr xkbi;
    267 
    268     if ((dpy->flags & XlibDisplayNoXkb) ||
    269         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    270         return False;
    271     LockDisplay(dpy);
    272     xkbi = dpy->xkb_info;
    273     GetReq(kbLatchLockState, req);
    274     req->reqType = xkbi->codes->major_opcode;
    275     req->xkbReqType = X_kbLatchLockState;
    276     req->deviceSpec = deviceSpec;
    277 
    278     req->affectModLatches = affect;
    279     req->modLatches = values;
    280     req->latchGroup = False;
    281     req->groupLatch = 0;
    282 
    283     req->affectModLocks = req->modLocks = 0;
    284     req->lockGroup = False;
    285     req->groupLock = 0;
    286 
    287     UnlockDisplay(dpy);
    288     SyncHandle();
    289     return True;
    290 }
    291 
    292 Bool
    293 XkbLockGroup(Display *dpy, unsigned int deviceSpec, unsigned int group)
    294 {
    295     register xkbLatchLockStateReq *req;
    296     XkbInfoPtr xkbi;
    297 
    298     if ((dpy->flags & XlibDisplayNoXkb) ||
    299         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    300         return False;
    301     LockDisplay(dpy);
    302     xkbi = dpy->xkb_info;
    303     GetReq(kbLatchLockState, req);
    304     req->reqType = xkbi->codes->major_opcode;
    305     req->xkbReqType = X_kbLatchLockState;
    306     req->deviceSpec = deviceSpec;
    307     req->affectModLocks = 0;
    308     req->modLocks = 0;
    309     req->lockGroup = True;
    310     req->groupLock = group;
    311 
    312     req->affectModLatches = req->modLatches = 0;
    313     req->latchGroup = False;
    314     req->groupLatch = 0;
    315     UnlockDisplay(dpy);
    316     SyncHandle();
    317     return True;
    318 }
    319 
    320 Bool
    321 XkbLatchGroup(Display *dpy, unsigned int deviceSpec, unsigned int group)
    322 {
    323     register xkbLatchLockStateReq *req;
    324     XkbInfoPtr xkbi;
    325 
    326     if ((dpy->flags & XlibDisplayNoXkb) ||
    327         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    328         return False;
    329     LockDisplay(dpy);
    330     xkbi = dpy->xkb_info;
    331     GetReq(kbLatchLockState, req);
    332     req->reqType = xkbi->codes->major_opcode;
    333     req->xkbReqType = X_kbLatchLockState;
    334     req->deviceSpec = deviceSpec;
    335 
    336     req->affectModLatches = 0;
    337     req->modLatches = 0;
    338     req->latchGroup = True;
    339     req->groupLatch = group;
    340 
    341     req->affectModLocks = req->modLocks = 0;
    342     req->lockGroup = False;
    343     req->groupLock = 0;
    344 
    345     UnlockDisplay(dpy);
    346     SyncHandle();
    347     return True;
    348 }
    349 
    350 unsigned
    351 XkbSetXlibControls(Display *dpy, unsigned affect, unsigned values)
    352 {
    353     if (!dpy->xkb_info)
    354         XkbUseExtension(dpy, NULL, NULL);
    355     if (!dpy->xkb_info)
    356         return 0;
    357     affect &= XkbLC_AllControls;
    358     dpy->xkb_info->xlib_ctrls &= ~affect;
    359     dpy->xkb_info->xlib_ctrls |= (affect & values);
    360     return dpy->xkb_info->xlib_ctrls;
    361 }
    362 
    363 unsigned
    364 XkbGetXlibControls(Display *dpy)
    365 {
    366     if (!dpy->xkb_info)
    367         XkbUseExtension(dpy, NULL, NULL);
    368     if (!dpy->xkb_info)
    369         return 0;
    370     return dpy->xkb_info->xlib_ctrls;
    371 }
    372 
    373 unsigned int
    374 XkbXlibControlsImplemented(void)
    375 {
    376     return XkbLC_AllControls & ~XkbLC_AllComposeControls;
    377 }
    378 
    379 Bool
    380 XkbSetDebuggingFlags(Display *dpy,
    381                      unsigned int mask,
    382                      unsigned int flags,
    383                      char *msg,
    384                      unsigned int ctrls_mask,
    385                      unsigned int ctrls,
    386                      unsigned int *rtrn_flags,
    387                      unsigned int *rtrn_ctrls)
    388 {
    389     register xkbSetDebuggingFlagsReq *req;
    390     xkbSetDebuggingFlagsReply rep;
    391     XkbInfoPtr xkbi;
    392 
    393     if ((dpy->flags & XlibDisplayNoXkb) ||
    394         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    395         return False;
    396     LockDisplay(dpy);
    397     xkbi = dpy->xkb_info;
    398     GetReq(kbSetDebuggingFlags, req);
    399     req->reqType        = xkbi->codes->major_opcode;
    400     req->xkbReqType     = X_kbSetDebuggingFlags;
    401     req->affectFlags    = mask;
    402     req->flags          = flags;
    403     req->affectCtrls    = ctrls_mask;
    404     req->ctrls          = ctrls;
    405 
    406     if (msg) {
    407         char *out;
    408 
    409         req->msgLength = (CARD16) (strlen(msg) + 1);
    410         req->length += (req->msgLength + (unsigned) 3) >> 2;
    411         BufAlloc(char *, out, ((req->msgLength + (unsigned) 3) / 4) * 4);
    412         memcpy(out, msg, req->msgLength);
    413     }
    414     else
    415         req->msgLength = 0;
    416     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    417         UnlockDisplay(dpy);
    418         SyncHandle();
    419         return False;
    420     }
    421     if (rtrn_flags)
    422         *rtrn_flags = rep.currentFlags;
    423     if (rtrn_ctrls)
    424         *rtrn_ctrls = rep.currentCtrls;
    425     UnlockDisplay(dpy);
    426     SyncHandle();
    427     return True;
    428 }
    429 
    430 Bool
    431 XkbComputeEffectiveMap(XkbDescPtr xkb,
    432                        XkbKeyTypePtr type,
    433                        unsigned char *map_rtrn)
    434 {
    435     register int i;
    436     unsigned tmp;
    437     XkbKTMapEntryPtr entry = NULL;
    438 
    439     if ((!xkb) || (!type) || (!xkb->server))
    440         return False;
    441 
    442     if (type->mods.vmods != 0) {
    443         if (!XkbVirtualModsToReal(xkb, type->mods.vmods, &tmp))
    444             return False;
    445 
    446         type->mods.mask = tmp | type->mods.real_mods;
    447         entry = type->map;
    448         for (i = 0; i < type->map_count; i++, entry++) {
    449             tmp = 0;
    450             if (entry->mods.vmods != 0) {
    451                 if (!XkbVirtualModsToReal(xkb, entry->mods.vmods, &tmp))
    452                     return False;
    453                 if (tmp == 0) {
    454                     entry->active = False;
    455                     continue;
    456                 }
    457             }
    458             entry->active = True;
    459             entry->mods.mask = (entry->mods.real_mods | tmp) & type->mods.mask;
    460         }
    461     }
    462     else {
    463         type->mods.mask = type->mods.real_mods;
    464     }
    465     if (map_rtrn != NULL) {
    466         bzero(map_rtrn, type->mods.mask + 1);
    467         for (i = 0; i < type->map_count; i++) {
    468             if (entry && entry->active) {
    469                 map_rtrn[type->map[i].mods.mask] = type->map[i].level;
    470             }
    471         }
    472     }
    473     return True;
    474 }
    475 
    476 Status
    477 XkbGetState(Display *dpy, unsigned deviceSpec, XkbStatePtr rtrn)
    478 {
    479     register xkbGetStateReq *req;
    480     xkbGetStateReply rep;
    481     XkbInfoPtr xkbi;
    482 
    483     if ((dpy->flags & XlibDisplayNoXkb) ||
    484         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    485         return BadAccess;
    486     LockDisplay(dpy);
    487     xkbi = dpy->xkb_info;
    488     GetReq(kbGetState, req);
    489     req->reqType = xkbi->codes->major_opcode;
    490     req->xkbReqType = X_kbGetState;
    491     req->deviceSpec = deviceSpec;
    492     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    493         UnlockDisplay(dpy);
    494         SyncHandle();
    495         return BadImplementation;
    496     }
    497     rtrn->mods                  = rep.mods;
    498     rtrn->base_mods             = rep.baseMods;
    499     rtrn->latched_mods          = rep.latchedMods;
    500     rtrn->locked_mods           = rep.lockedMods;
    501     rtrn->group                 = rep.group;
    502     rtrn->base_group            = rep.baseGroup;
    503     rtrn->latched_group         = rep.latchedGroup;
    504     rtrn->locked_group          = rep.lockedGroup;
    505     rtrn->compat_state          = rep.compatState;
    506     rtrn->grab_mods             = rep.grabMods;
    507     rtrn->compat_grab_mods      = rep.compatGrabMods;
    508     rtrn->lookup_mods           = rep.lookupMods;
    509     rtrn->compat_lookup_mods    = rep.compatLookupMods;
    510     rtrn->ptr_buttons           = rep.ptrBtnState;
    511     UnlockDisplay(dpy);
    512     SyncHandle();
    513     return Success;
    514 }
    515 
    516 Bool
    517 XkbSetDetectableAutoRepeat(Display *dpy, Bool detectable, Bool *supported)
    518 {
    519     register xkbPerClientFlagsReq *req;
    520     xkbPerClientFlagsReply rep;
    521     XkbInfoPtr xkbi;
    522 
    523     if ((dpy->flags & XlibDisplayNoXkb) ||
    524         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    525         return False;
    526     LockDisplay(dpy);
    527     xkbi = dpy->xkb_info;
    528     GetReq(kbPerClientFlags, req);
    529     req->reqType = xkbi->codes->major_opcode;
    530     req->xkbReqType = X_kbPerClientFlags;
    531     req->deviceSpec = XkbUseCoreKbd;
    532     req->change = XkbPCF_DetectableAutoRepeatMask;
    533     if (detectable)
    534         req->value = XkbPCF_DetectableAutoRepeatMask;
    535     else
    536         req->value = 0;
    537     req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0;
    538     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    539         UnlockDisplay(dpy);
    540         SyncHandle();
    541         return False;
    542     }
    543     UnlockDisplay(dpy);
    544     SyncHandle();
    545     if (supported != NULL)
    546         *supported = ((rep.supported & XkbPCF_DetectableAutoRepeatMask) != 0);
    547     return ((rep.value & XkbPCF_DetectableAutoRepeatMask) != 0);
    548 }
    549 
    550 Bool
    551 XkbGetDetectableAutoRepeat(Display *dpy, Bool *supported)
    552 {
    553     register xkbPerClientFlagsReq *req;
    554     xkbPerClientFlagsReply rep;
    555     XkbInfoPtr xkbi;
    556 
    557     if ((dpy->flags & XlibDisplayNoXkb) ||
    558         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    559         return False;
    560     LockDisplay(dpy);
    561     xkbi = dpy->xkb_info;
    562     GetReq(kbPerClientFlags, req);
    563     req->reqType = xkbi->codes->major_opcode;
    564     req->xkbReqType = X_kbPerClientFlags;
    565     req->deviceSpec = XkbUseCoreKbd;
    566     req->change = 0;
    567     req->value = 0;
    568     req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0;
    569     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    570         UnlockDisplay(dpy);
    571         SyncHandle();
    572         return False;
    573     }
    574     UnlockDisplay(dpy);
    575     SyncHandle();
    576     if (supported != NULL)
    577         *supported = ((rep.supported & XkbPCF_DetectableAutoRepeatMask) != 0);
    578     return ((rep.value & XkbPCF_DetectableAutoRepeatMask) != 0);
    579 }
    580 
    581 Bool
    582 XkbSetAutoResetControls(Display *dpy,
    583                         unsigned changes,
    584                         unsigned *auto_ctrls,
    585                         unsigned *auto_values)
    586 {
    587     register xkbPerClientFlagsReq *req;
    588     xkbPerClientFlagsReply rep;
    589     XkbInfoPtr xkbi;
    590 
    591     if ((dpy->flags & XlibDisplayNoXkb) ||
    592         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    593         return False;
    594     LockDisplay(dpy);
    595     xkbi = dpy->xkb_info;
    596     GetReq(kbPerClientFlags, req);
    597     req->reqType = xkbi->codes->major_opcode;
    598     req->xkbReqType = X_kbPerClientFlags;
    599     req->change = XkbPCF_AutoResetControlsMask;
    600     req->deviceSpec = XkbUseCoreKbd;
    601     req->value = XkbPCF_AutoResetControlsMask;
    602     req->ctrlsToChange = changes;
    603     req->autoCtrls = *auto_ctrls;
    604     req->autoCtrlValues = *auto_values;
    605     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    606         UnlockDisplay(dpy);
    607         SyncHandle();
    608         return False;
    609     }
    610     UnlockDisplay(dpy);
    611     SyncHandle();
    612     *auto_ctrls = rep.autoCtrls;
    613     *auto_values = rep.autoCtrlValues;
    614     return ((rep.value & XkbPCF_AutoResetControlsMask) != 0);
    615 }
    616 
    617 Bool
    618 XkbGetAutoResetControls(Display *dpy,
    619                         unsigned *auto_ctrls,
    620                         unsigned *auto_ctrl_values)
    621 {
    622     register xkbPerClientFlagsReq *req;
    623     xkbPerClientFlagsReply rep;
    624     XkbInfoPtr xkbi;
    625 
    626     if ((dpy->flags & XlibDisplayNoXkb) ||
    627         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)))
    628         return False;
    629     LockDisplay(dpy);
    630     xkbi = dpy->xkb_info;
    631     GetReq(kbPerClientFlags, req);
    632     req->reqType = xkbi->codes->major_opcode;
    633     req->xkbReqType = X_kbPerClientFlags;
    634     req->deviceSpec = XkbUseCoreKbd;
    635     req->change = 0;
    636     req->value = 0;
    637     req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0;
    638     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    639         UnlockDisplay(dpy);
    640         SyncHandle();
    641         return False;
    642     }
    643     UnlockDisplay(dpy);
    644     SyncHandle();
    645     if (auto_ctrls)
    646         *auto_ctrls = rep.autoCtrls;
    647     if (auto_ctrl_values)
    648         *auto_ctrl_values = rep.autoCtrlValues;
    649     return ((rep.value & XkbPCF_AutoResetControlsMask) != 0);
    650 }
    651 
    652 Bool
    653 XkbSetPerClientControls(Display *dpy, unsigned change, unsigned *values)
    654 {
    655     register xkbPerClientFlagsReq *req;
    656     xkbPerClientFlagsReply rep;
    657     XkbInfoPtr xkbi;
    658     unsigned value_hold = *values;
    659 
    660     if ((dpy->flags & XlibDisplayNoXkb) ||
    661         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) ||
    662         (change & ~(XkbPCF_GrabsUseXKBStateMask |
    663                     XkbPCF_LookupStateWhenGrabbed |
    664                     XkbPCF_SendEventUsesXKBState)))
    665         return False;
    666     LockDisplay(dpy);
    667     xkbi = dpy->xkb_info;
    668     GetReq(kbPerClientFlags, req);
    669     req->reqType = xkbi->codes->major_opcode;
    670     req->xkbReqType = X_kbPerClientFlags;
    671     req->change = change;
    672     req->deviceSpec = XkbUseCoreKbd;
    673     req->value = *values;
    674     req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0;
    675     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    676         UnlockDisplay(dpy);
    677         SyncHandle();
    678         return False;
    679     }
    680     UnlockDisplay(dpy);
    681     SyncHandle();
    682     *values = rep.value;
    683     return ((rep.value & value_hold) != 0);
    684 }
    685 
    686 Bool
    687 XkbGetPerClientControls(Display *dpy, unsigned *ctrls)
    688 {
    689     register xkbPerClientFlagsReq *req;
    690     xkbPerClientFlagsReply rep;
    691     XkbInfoPtr xkbi;
    692 
    693     if ((dpy->flags & XlibDisplayNoXkb) ||
    694         (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) ||
    695         (ctrls == NULL))
    696         return False;
    697     LockDisplay(dpy);
    698     xkbi = dpy->xkb_info;
    699     GetReq(kbPerClientFlags, req);
    700     req->reqType = xkbi->codes->major_opcode;
    701     req->xkbReqType = X_kbPerClientFlags;
    702     req->deviceSpec = XkbUseCoreKbd;
    703     req->change = 0;
    704     req->value = 0;
    705     req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0;
    706     if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) {
    707         UnlockDisplay(dpy);
    708         SyncHandle();
    709         return False;
    710     }
    711     UnlockDisplay(dpy);
    712     SyncHandle();
    713     *ctrls = (rep.value & (XkbPCF_GrabsUseXKBStateMask |
    714                            XkbPCF_LookupStateWhenGrabbed |
    715                            XkbPCF_SendEventUsesXKBState));
    716     return (True);
    717 }
    718 
    719 Display *
    720 XkbOpenDisplay(_Xconst char *name,
    721                int *ev_rtrn,
    722                int *err_rtrn,
    723                int *major_rtrn,
    724                int *minor_rtrn,
    725                int *reason)
    726 {
    727     Display *dpy;
    728     int major_num, minor_num;
    729 
    730     if ((major_rtrn != NULL) && (minor_rtrn != NULL)) {
    731         if (!XkbLibraryVersion(major_rtrn, minor_rtrn)) {
    732             if (reason != NULL)
    733                 *reason = XkbOD_BadLibraryVersion;
    734             return NULL;
    735         }
    736     }
    737     else {
    738         major_num = XkbMajorVersion;
    739         minor_num = XkbMinorVersion;
    740         major_rtrn = &major_num;
    741         minor_rtrn = &minor_num;
    742     }
    743     dpy = XOpenDisplay(name);
    744     if (dpy == NULL) {
    745         if (reason != NULL)
    746             *reason = XkbOD_ConnectionRefused;
    747         return NULL;
    748     }
    749     if (!XkbQueryExtension(dpy, NULL, ev_rtrn, err_rtrn,
    750                            major_rtrn, minor_rtrn)) {
    751         if (reason != NULL) {
    752             if ((*major_rtrn != 0) || (*minor_rtrn != 0))
    753                 *reason = XkbOD_BadServerVersion;
    754             else
    755                 *reason = XkbOD_NonXkbServer;
    756         }
    757         XCloseDisplay(dpy);
    758         return NULL;
    759     }
    760     if (reason != NULL)
    761         *reason = XkbOD_Success;
    762     return dpy;
    763 }
    764 
    765 void
    766 XkbSetAtomFuncs(XkbInternAtomFunc getAtom, XkbGetAtomNameFunc getName)
    767 {
    768     _XkbInternAtomFunc = (getAtom ? getAtom : XInternAtom);
    769     _XkbGetAtomNameFunc = (getName ? getName : XGetAtomName);
    770     return;
    771 }
    772