XKB.c revision e9628295
1/************************************************************ 2Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. 3 4Permission to use, copy, modify, and distribute this 5software and its documentation for any purpose and without 6fee is hereby granted, provided that the above copyright 7notice appear in all copies and that both that copyright 8notice and this permission notice appear in supporting 9documentation, and that the name of Silicon Graphics not be 10used in advertising or publicity pertaining to distribution 11of the software without specific prior written permission. 12Silicon Graphics makes no representation about the suitability 13of this software for any purpose. It is provided "as is" 14without any express or implied warranty. 15 16SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 25********************************************************/ 26 27#ifdef HAVE_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 35XkbInternAtomFunc _XkbInternAtomFunc = XInternAtom; 36XkbGetAtomNameFunc _XkbGetAtomNameFunc = XGetAtomName; 37 38Bool 39XkbQueryExtension(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 61Bool 62XkbLibraryVersion(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 83Bool 84XkbSelectEvents(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 136Bool 137XkbSelectEventDetails(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 228Bool 229XkbLockModifiers(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 259Bool 260XkbLatchModifiers(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 292Bool 293XkbLockGroup(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 320Bool 321XkbLatchGroup(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 350unsigned 351XkbSetXlibControls(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 363unsigned 364XkbGetXlibControls(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 373unsigned int 374XkbXlibControlsImplemented(void) 375{ 376#ifdef __sgi 377 return XkbLC_AllControls; 378#else 379 return XkbLC_AllControls & ~XkbLC_AllComposeControls; 380#endif 381} 382 383Bool 384XkbSetDebuggingFlags(Display *dpy, 385 unsigned int mask, 386 unsigned int flags, 387 char *msg, 388 unsigned int ctrls_mask, 389 unsigned int ctrls, 390 unsigned int *rtrn_flags, 391 unsigned int *rtrn_ctrls) 392{ 393 register xkbSetDebuggingFlagsReq *req; 394 xkbSetDebuggingFlagsReply rep; 395 XkbInfoPtr xkbi; 396 397 if ((dpy->flags & XlibDisplayNoXkb) || 398 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 399 return False; 400 LockDisplay(dpy); 401 xkbi = dpy->xkb_info; 402 GetReq(kbSetDebuggingFlags, req); 403 req->reqType = xkbi->codes->major_opcode; 404 req->xkbReqType = X_kbSetDebuggingFlags; 405 req->affectFlags = mask; 406 req->flags = flags; 407 req->affectCtrls = ctrls_mask; 408 req->ctrls = ctrls; 409 410 if (msg) { 411 char *out; 412 413 req->msgLength = (CARD16) (strlen(msg) + 1); 414 req->length += (req->msgLength + (unsigned) 3) >> 2; 415 BufAlloc(char *, out, ((req->msgLength + (unsigned) 3) / 4) * 4); 416 memcpy(out, msg, req->msgLength); 417 } 418 else 419 req->msgLength = 0; 420 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 421 UnlockDisplay(dpy); 422 SyncHandle(); 423 return False; 424 } 425 if (rtrn_flags) 426 *rtrn_flags = rep.currentFlags; 427 if (rtrn_ctrls) 428 *rtrn_ctrls = rep.currentCtrls; 429 UnlockDisplay(dpy); 430 SyncHandle(); 431 return True; 432} 433 434Bool 435XkbComputeEffectiveMap(XkbDescPtr xkb, 436 XkbKeyTypePtr type, 437 unsigned char *map_rtrn) 438{ 439 register int i; 440 unsigned tmp; 441 XkbKTMapEntryPtr entry = NULL; 442 443 if ((!xkb) || (!type) || (!xkb->server)) 444 return False; 445 446 if (type->mods.vmods != 0) { 447 if (!XkbVirtualModsToReal(xkb, type->mods.vmods, &tmp)) 448 return False; 449 450 type->mods.mask = tmp | type->mods.real_mods; 451 entry = type->map; 452 for (i = 0; i < type->map_count; i++, entry++) { 453 tmp = 0; 454 if (entry->mods.vmods != 0) { 455 if (!XkbVirtualModsToReal(xkb, entry->mods.vmods, &tmp)) 456 return False; 457 if (tmp == 0) { 458 entry->active = False; 459 continue; 460 } 461 } 462 entry->active = True; 463 entry->mods.mask = (entry->mods.real_mods | tmp) & type->mods.mask; 464 } 465 } 466 else { 467 type->mods.mask = type->mods.real_mods; 468 } 469 if (map_rtrn != NULL) { 470 bzero(map_rtrn, type->mods.mask + 1); 471 for (i = 0; i < type->map_count; i++) { 472 if (entry && entry->active) { 473 map_rtrn[type->map[i].mods.mask] = type->map[i].level; 474 } 475 } 476 } 477 return True; 478} 479 480Status 481XkbGetState(Display *dpy, unsigned deviceSpec, XkbStatePtr rtrn) 482{ 483 register xkbGetStateReq *req; 484 xkbGetStateReply rep; 485 XkbInfoPtr xkbi; 486 487 if ((dpy->flags & XlibDisplayNoXkb) || 488 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 489 return BadAccess; 490 LockDisplay(dpy); 491 xkbi = dpy->xkb_info; 492 GetReq(kbGetState, req); 493 req->reqType = xkbi->codes->major_opcode; 494 req->xkbReqType = X_kbGetState; 495 req->deviceSpec = deviceSpec; 496 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 497 UnlockDisplay(dpy); 498 SyncHandle(); 499 return BadImplementation; 500 } 501 rtrn->mods = rep.mods; 502 rtrn->base_mods = rep.baseMods; 503 rtrn->latched_mods = rep.latchedMods; 504 rtrn->locked_mods = rep.lockedMods; 505 rtrn->group = rep.group; 506 rtrn->base_group = rep.baseGroup; 507 rtrn->latched_group = rep.latchedGroup; 508 rtrn->locked_group = rep.lockedGroup; 509 rtrn->compat_state = rep.compatState; 510 rtrn->grab_mods = rep.grabMods; 511 rtrn->compat_grab_mods = rep.compatGrabMods; 512 rtrn->lookup_mods = rep.lookupMods; 513 rtrn->compat_lookup_mods = rep.compatLookupMods; 514 rtrn->ptr_buttons = rep.ptrBtnState; 515 UnlockDisplay(dpy); 516 SyncHandle(); 517 return Success; 518} 519 520Bool 521XkbSetDetectableAutoRepeat(Display *dpy, Bool detectable, Bool *supported) 522{ 523 register xkbPerClientFlagsReq *req; 524 xkbPerClientFlagsReply rep; 525 XkbInfoPtr xkbi; 526 527 if ((dpy->flags & XlibDisplayNoXkb) || 528 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 529 return False; 530 LockDisplay(dpy); 531 xkbi = dpy->xkb_info; 532 GetReq(kbPerClientFlags, req); 533 req->reqType = xkbi->codes->major_opcode; 534 req->xkbReqType = X_kbPerClientFlags; 535 req->deviceSpec = XkbUseCoreKbd; 536 req->change = XkbPCF_DetectableAutoRepeatMask; 537 if (detectable) 538 req->value = XkbPCF_DetectableAutoRepeatMask; 539 else 540 req->value = 0; 541 req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0; 542 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 543 UnlockDisplay(dpy); 544 SyncHandle(); 545 return False; 546 } 547 UnlockDisplay(dpy); 548 SyncHandle(); 549 if (supported != NULL) 550 *supported = ((rep.supported & XkbPCF_DetectableAutoRepeatMask) != 0); 551 return ((rep.value & XkbPCF_DetectableAutoRepeatMask) != 0); 552} 553 554Bool 555XkbGetDetectableAutoRepeat(Display *dpy, Bool *supported) 556{ 557 register xkbPerClientFlagsReq *req; 558 xkbPerClientFlagsReply rep; 559 XkbInfoPtr xkbi; 560 561 if ((dpy->flags & XlibDisplayNoXkb) || 562 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 563 return False; 564 LockDisplay(dpy); 565 xkbi = dpy->xkb_info; 566 GetReq(kbPerClientFlags, req); 567 req->reqType = xkbi->codes->major_opcode; 568 req->xkbReqType = X_kbPerClientFlags; 569 req->deviceSpec = XkbUseCoreKbd; 570 req->change = 0; 571 req->value = 0; 572 req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0; 573 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 574 UnlockDisplay(dpy); 575 SyncHandle(); 576 return False; 577 } 578 UnlockDisplay(dpy); 579 SyncHandle(); 580 if (supported != NULL) 581 *supported = ((rep.supported & XkbPCF_DetectableAutoRepeatMask) != 0); 582 return ((rep.value & XkbPCF_DetectableAutoRepeatMask) != 0); 583} 584 585Bool 586XkbSetAutoResetControls(Display *dpy, 587 unsigned changes, 588 unsigned *auto_ctrls, 589 unsigned *auto_values) 590{ 591 register xkbPerClientFlagsReq *req; 592 xkbPerClientFlagsReply rep; 593 XkbInfoPtr xkbi; 594 595 if ((dpy->flags & XlibDisplayNoXkb) || 596 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 597 return False; 598 LockDisplay(dpy); 599 xkbi = dpy->xkb_info; 600 GetReq(kbPerClientFlags, req); 601 req->reqType = xkbi->codes->major_opcode; 602 req->xkbReqType = X_kbPerClientFlags; 603 req->change = XkbPCF_AutoResetControlsMask; 604 req->deviceSpec = XkbUseCoreKbd; 605 req->value = XkbPCF_AutoResetControlsMask; 606 req->ctrlsToChange = changes; 607 req->autoCtrls = *auto_ctrls; 608 req->autoCtrlValues = *auto_values; 609 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 610 UnlockDisplay(dpy); 611 SyncHandle(); 612 return False; 613 } 614 UnlockDisplay(dpy); 615 SyncHandle(); 616 *auto_ctrls = rep.autoCtrls; 617 *auto_values = rep.autoCtrlValues; 618 return ((rep.value & XkbPCF_AutoResetControlsMask) != 0); 619} 620 621Bool 622XkbGetAutoResetControls(Display *dpy, 623 unsigned *auto_ctrls, 624 unsigned *auto_ctrl_values) 625{ 626 register xkbPerClientFlagsReq *req; 627 xkbPerClientFlagsReply rep; 628 XkbInfoPtr xkbi; 629 630 if ((dpy->flags & XlibDisplayNoXkb) || 631 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL))) 632 return False; 633 LockDisplay(dpy); 634 xkbi = dpy->xkb_info; 635 GetReq(kbPerClientFlags, req); 636 req->reqType = xkbi->codes->major_opcode; 637 req->xkbReqType = X_kbPerClientFlags; 638 req->deviceSpec = XkbUseCoreKbd; 639 req->change = 0; 640 req->value = 0; 641 req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0; 642 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 643 UnlockDisplay(dpy); 644 SyncHandle(); 645 return False; 646 } 647 UnlockDisplay(dpy); 648 SyncHandle(); 649 if (auto_ctrls) 650 *auto_ctrls = rep.autoCtrls; 651 if (auto_ctrl_values) 652 *auto_ctrl_values = rep.autoCtrlValues; 653 return ((rep.value & XkbPCF_AutoResetControlsMask) != 0); 654} 655 656Bool 657XkbSetPerClientControls(Display *dpy, unsigned change, unsigned *values) 658{ 659 register xkbPerClientFlagsReq *req; 660 xkbPerClientFlagsReply rep; 661 XkbInfoPtr xkbi; 662 unsigned value_hold = *values; 663 664 if ((dpy->flags & XlibDisplayNoXkb) || 665 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) || 666 (change & ~(XkbPCF_GrabsUseXKBStateMask | 667 XkbPCF_LookupStateWhenGrabbed | 668 XkbPCF_SendEventUsesXKBState))) 669 return False; 670 LockDisplay(dpy); 671 xkbi = dpy->xkb_info; 672 GetReq(kbPerClientFlags, req); 673 req->reqType = xkbi->codes->major_opcode; 674 req->xkbReqType = X_kbPerClientFlags; 675 req->change = change; 676 req->deviceSpec = XkbUseCoreKbd; 677 req->value = *values; 678 req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0; 679 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 680 UnlockDisplay(dpy); 681 SyncHandle(); 682 return False; 683 } 684 UnlockDisplay(dpy); 685 SyncHandle(); 686 *values = rep.value; 687 return ((rep.value & value_hold) != 0); 688} 689 690Bool 691XkbGetPerClientControls(Display *dpy, unsigned *ctrls) 692{ 693 register xkbPerClientFlagsReq *req; 694 xkbPerClientFlagsReply rep; 695 XkbInfoPtr xkbi; 696 697 if ((dpy->flags & XlibDisplayNoXkb) || 698 (!dpy->xkb_info && !XkbUseExtension(dpy, NULL, NULL)) || 699 (ctrls == NULL)) 700 return False; 701 LockDisplay(dpy); 702 xkbi = dpy->xkb_info; 703 GetReq(kbPerClientFlags, req); 704 req->reqType = xkbi->codes->major_opcode; 705 req->xkbReqType = X_kbPerClientFlags; 706 req->deviceSpec = XkbUseCoreKbd; 707 req->change = 0; 708 req->value = 0; 709 req->ctrlsToChange = req->autoCtrls = req->autoCtrlValues = 0; 710 if (!_XReply(dpy, (xReply *) &rep, 0, xFalse)) { 711 UnlockDisplay(dpy); 712 SyncHandle(); 713 return False; 714 } 715 UnlockDisplay(dpy); 716 SyncHandle(); 717 *ctrls = (rep.value & (XkbPCF_GrabsUseXKBStateMask | 718 XkbPCF_LookupStateWhenGrabbed | 719 XkbPCF_SendEventUsesXKBState)); 720 return (True); 721} 722 723Display * 724XkbOpenDisplay(_Xconst char *name, 725 int *ev_rtrn, 726 int *err_rtrn, 727 int *major_rtrn, 728 int *minor_rtrn, 729 int *reason) 730{ 731 Display *dpy; 732 int major_num, minor_num; 733 734 if ((major_rtrn != NULL) && (minor_rtrn != NULL)) { 735 if (!XkbLibraryVersion(major_rtrn, minor_rtrn)) { 736 if (reason != NULL) 737 *reason = XkbOD_BadLibraryVersion; 738 return NULL; 739 } 740 } 741 else { 742 major_num = XkbMajorVersion; 743 minor_num = XkbMinorVersion; 744 major_rtrn = &major_num; 745 minor_rtrn = &minor_num; 746 } 747 dpy = XOpenDisplay(name); 748 if (dpy == NULL) { 749 if (reason != NULL) 750 *reason = XkbOD_ConnectionRefused; 751 return NULL; 752 } 753 if (!XkbQueryExtension(dpy, NULL, ev_rtrn, err_rtrn, 754 major_rtrn, minor_rtrn)) { 755 if (reason != NULL) { 756 if ((*major_rtrn != 0) || (*minor_rtrn != 0)) 757 *reason = XkbOD_BadServerVersion; 758 else 759 *reason = XkbOD_NonXkbServer; 760 } 761 XCloseDisplay(dpy); 762 return NULL; 763 } 764 if (reason != NULL) 765 *reason = XkbOD_Success; 766 return dpy; 767} 768 769void 770XkbSetAtomFuncs(XkbInternAtomFunc getAtom, XkbGetAtomNameFunc getName) 771{ 772 _XkbInternAtomFunc = (getAtom ? getAtom : XInternAtom); 773 _XkbGetAtomNameFunc = (getName ? getName : XGetAtomName); 774 return; 775} 776