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