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