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