diff options
Diffstat (limited to 'xorg-server/xkb/xkbEvents.c')
-rw-r--r-- | xorg-server/xkb/xkbEvents.c | 2180 |
1 files changed, 1090 insertions, 1090 deletions
diff --git a/xorg-server/xkb/xkbEvents.c b/xorg-server/xkb/xkbEvents.c index 132ccd302..dfbf7f2b3 100644 --- a/xorg-server/xkb/xkbEvents.c +++ b/xorg-server/xkb/xkbEvents.c @@ -1,1090 +1,1090 @@ -/************************************************************
-Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
-
-Permission to use, copy, modify, and distribute this
-software and its documentation for any purpose and without
-fee is hereby granted, provided that the above copyright
-notice appear in all copies and that both that copyright
-notice and this permission notice appear in supporting
-documentation, and that the name of Silicon Graphics not be
-used in advertising or publicity pertaining to distribution
-of the software without specific prior written permission.
-Silicon Graphics makes no representation about the suitability
-of this software for any purpose. It is provided "as is"
-without any express or implied warranty.
-
-SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
-SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
-GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
-DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
-DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
-OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
-THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-********************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdio.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <X11/keysym.h>
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "inputstr.h"
-#include "exevents.h"
-#include "exglobals.h"
-#include "windowstr.h"
-#include <xkbsrv.h>
-#include "xkb.h"
-
-/***====================================================================***/
-
-/*
- * This function sends out two kinds of notification:
- * - Core mapping notify events sent to clients for whom kbd is the
- * current core ('picked') keyboard _and_ have not explicitly
- * selected for XKB mapping notify events;
- * - Xi mapping events, sent unconditionally to all clients who have
- * explicitly selected for them (including those who have explicitly
- * selected for XKB mapping notify events!).
- */
-static void
-XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed,
- int first_key, int num_keys)
-{
- int i;
- int keymap_changed = 0;
- int modmap_changed = 0;
- xEvent core_mn;
- deviceMappingNotify xi_mn;
- CARD32 time = GetTimeInMillis();
-
- if (xkb_event == XkbNewKeyboardNotify) {
- if (changed & XkbNKN_KeycodesMask) {
- keymap_changed = 1;
- modmap_changed = 1;
- }
- }
- else if (xkb_event == XkbMapNotify) {
- if (changed & XkbKeySymsMask)
- keymap_changed = 1;
- if (changed & XkbModifierMapMask)
- modmap_changed = 1;
- }
- if (!keymap_changed && !modmap_changed)
- return;
-
- core_mn.u.u.type = MappingNotify;
- xi_mn.type = DeviceMappingNotify;
- xi_mn.deviceid = kbd->id;
- xi_mn.time = time;
-
- /* 0 is serverClient. */
- for (i = 1; i < currentMaxClients; i++) {
- if (!clients[i] || clients[i]->clientState != ClientStateRunning)
- continue;
-
- /* XKB allows clients to restrict the MappingNotify events sent to
- * them. This was broken for three years. Sorry. */
- if (xkb_event == XkbMapNotify &&
- (clients[i]->xkbClientFlags & _XkbClientInitialized) &&
- !(clients[i]->mapNotifyMask & changed))
- continue;
- /* Emulate previous server behaviour: any client which has activated
- * XKB will not receive core events emulated from a NewKeyboardNotify
- * at all. */
- if (xkb_event == XkbNewKeyboardNotify &&
- (clients[i]->xkbClientFlags & _XkbClientInitialized))
- continue;
-
- /* Don't send core events to clients who don't know about us. */
- if (!XIShouldNotify(clients[i], kbd))
- continue;
-
- if (keymap_changed) {
- core_mn.u.mappingNotify.request = MappingKeyboard;
-
- /* Clip the keycode range to what the client knows about, so it
- * doesn't freak out. */
- if (first_key >= clients[i]->minKC)
- core_mn.u.mappingNotify.firstKeyCode = first_key;
- else
- core_mn.u.mappingNotify.firstKeyCode = clients[i]->minKC;
- if (first_key + num_keys - 1 <= clients[i]->maxKC)
- core_mn.u.mappingNotify.count = num_keys;
- else
- core_mn.u.mappingNotify.count = clients[i]->maxKC -
- clients[i]->minKC + 1;
-
- WriteEventsToClient(clients[i], 1, &core_mn);
- }
- if (modmap_changed) {
- core_mn.u.mappingNotify.request = MappingModifier;
- core_mn.u.mappingNotify.firstKeyCode = 0;
- core_mn.u.mappingNotify.count = 0;
- WriteEventsToClient(clients[i], 1, &core_mn);
- }
- }
-
- /* Hmm, maybe we can accidentally generate Xi events for core devices
- * here? Clients might be upset, but that seems better than the
- * alternative of stale keymaps. -ds */
- if (keymap_changed) {
- xi_mn.request = MappingKeyboard;
- xi_mn.firstKeyCode = first_key;
- xi_mn.count = num_keys;
- SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
- 1);
- }
- if (modmap_changed) {
- xi_mn.request = MappingModifier;
- xi_mn.firstKeyCode = 0;
- xi_mn.count = 0;
- SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn,
- 1);
- }
-}
-
-/***====================================================================***/
-
-void
-XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN)
-{
- int i;
- Time time = GetTimeInMillis();
- CARD16 changed = pNKN->changed;
-
- pNKN->type = XkbEventCode + XkbEventBase;
- pNKN->xkbType = XkbNewKeyboardNotify;
-
- for (i=1; i<currentMaxClients; i++) {
- if (!clients[i] || clients[i]->clientState != ClientStateRunning)
- continue;
-
- if (!(clients[i]->newKeyboardNotifyMask & changed))
- continue;
-
- pNKN->sequenceNumber = clients[i]->sequence;
- pNKN->time = time;
- pNKN->changed = changed;
- if (clients[i]->swapped) {
- int n;
- swaps(&pNKN->sequenceNumber,n);
- swapl(&pNKN->time,n);
- swaps(&pNKN->changed,n);
- }
- WriteToClient(clients[i], sizeof(xEvent), pNKN);
-
- if (changed & XkbNKN_KeycodesMask) {
- clients[i]->minKC = pNKN->minKeyCode;
- clients[i]->maxKC = pNKN->maxKeyCode;
- }
- }
-
- XkbSendLegacyMapNotify(kbd, XkbNewKeyboardNotify, changed, pNKN->minKeyCode,
- pNKN->maxKeyCode - pNKN->minKeyCode + 1);
-
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify *pSN)
-{
-XkbSrvInfoPtr xkbi;
-XkbStatePtr state;
-XkbInterestPtr interest;
-Time time;
-register CARD16 changed,bState;
-
- interest = kbd->xkb_interest;
- if (!interest || !kbd->key || !kbd->key->xkbInfo)
- return;
- xkbi = kbd->key->xkbInfo;
- state= &xkbi->state;
-
- pSN->type = XkbEventCode + XkbEventBase;
- pSN->xkbType = XkbStateNotify;
- pSN->deviceID = kbd->id;
- pSN->time = time = GetTimeInMillis();
- pSN->mods = state->mods;
- pSN->baseMods = state->base_mods;
- pSN->latchedMods = state->latched_mods;
- pSN->lockedMods = state->locked_mods;
- pSN->group = state->group;
- pSN->baseGroup = state->base_group;
- pSN->latchedGroup = state->latched_group;
- pSN->lockedGroup = state->locked_group;
- pSN->compatState = state->compat_state;
- pSN->grabMods = state->grab_mods;
- pSN->compatGrabMods = state->compat_grab_mods;
- pSN->lookupMods = state->lookup_mods;
- pSN->compatLookupMods = state->compat_lookup_mods;
- pSN->ptrBtnState = state->ptr_buttons;
- changed = pSN->changed;
- bState= pSN->ptrBtnState;
-
- while (interest) {
- if ((!interest->client->clientGone) &&
- (interest->client->requestVector != InitialVector) &&
- (interest->client->xkbClientFlags&_XkbClientInitialized) &&
- (interest->stateNotifyMask&changed)) {
- pSN->sequenceNumber = interest->client->sequence;
- pSN->time = time;
- pSN->changed = changed;
- pSN->ptrBtnState = bState;
- if ( interest->client->swapped ) {
- register int n;
- swaps(&pSN->sequenceNumber,n);
- swapl(&pSN->time,n);
- swaps(&pSN->changed,n);
- swaps(&pSN->ptrBtnState,n);
- }
- WriteToClient(interest->client, sizeof(xEvent), (char *)pSN);
- }
- interest= interest->next;
- }
- return;
-}
-
-/***====================================================================***/
-
-/*
- * This function sends out XKB mapping notify events to clients which
- * have explicitly selected for them. Core and Xi events are handled by
- * XkbSendLegacyMapNotify. */
-void
-XkbSendMapNotify(DeviceIntPtr kbd, xkbMapNotify *pMN)
-{
- int i;
- CARD32 time = GetTimeInMillis();
- CARD16 changed = pMN->changed;
- XkbSrvInfoPtr xkbi = kbd->key->xkbInfo;
-
- pMN->minKeyCode = xkbi->desc->min_key_code;
- pMN->maxKeyCode = xkbi->desc->max_key_code;
- pMN->type = XkbEventCode + XkbEventBase;
- pMN->xkbType = XkbMapNotify;
- pMN->deviceID = kbd->id;
-
- /* 0 is serverClient. */
- for (i = 1; i < currentMaxClients; i++) {
- if (!clients[i] || clients[i]->clientState != ClientStateRunning)
- continue;
-
- if (!(clients[i]->mapNotifyMask & changed))
- continue;
-
- pMN->time = time;
- pMN->sequenceNumber = clients[i]->sequence;
- pMN->changed = changed;
-
- if (clients[i]->swapped) {
- int n;
- swaps(&pMN->sequenceNumber, n);
- swapl(&pMN->time, n);
- swaps(&pMN->changed, n);
- }
- WriteToClient(clients[i], sizeof(xEvent), pMN);
- }
-
- XkbSendLegacyMapNotify(kbd, XkbMapNotify, changed, pMN->firstKeySym,
- pMN->nKeySyms);
-}
-
-int
-XkbComputeControlsNotify( DeviceIntPtr kbd,
- XkbControlsPtr old,
- XkbControlsPtr new,
- xkbControlsNotify * pCN,
- Bool forceCtrlProc)
-{
-int i;
-CARD32 changedControls;
-
- changedControls= 0;
-
- if (!kbd || !kbd->kbdfeed)
- return 0;
-
- if (old->enabled_ctrls!=new->enabled_ctrls)
- changedControls|= XkbControlsEnabledMask;
- if ((old->repeat_delay!=new->repeat_delay)||
- (old->repeat_interval!=new->repeat_interval))
- changedControls|= XkbRepeatKeysMask;
- for (i = 0; i < XkbPerKeyBitArraySize; i++)
- if (old->per_key_repeat[i] != new->per_key_repeat[i])
- changedControls|= XkbPerKeyRepeatMask;
- if (old->slow_keys_delay!=new->slow_keys_delay)
- changedControls|= XkbSlowKeysMask;
- if (old->debounce_delay!=new->debounce_delay)
- changedControls|= XkbBounceKeysMask;
- if ((old->mk_delay!=new->mk_delay)||
- (old->mk_interval!=new->mk_interval)||
- (old->mk_dflt_btn!=new->mk_dflt_btn))
- changedControls|= XkbMouseKeysMask;
- if ((old->mk_time_to_max!=new->mk_time_to_max)||
- (old->mk_curve!=new->mk_curve)||
- (old->mk_max_speed!=new->mk_max_speed))
- changedControls|= XkbMouseKeysAccelMask;
- if (old->ax_options!=new->ax_options)
- changedControls|= XkbAccessXKeysMask;
- if ((old->ax_options^new->ax_options) & XkbAX_SKOptionsMask)
- changedControls|= XkbStickyKeysMask;
- if ((old->ax_options^new->ax_options) & XkbAX_FBOptionsMask)
- changedControls|= XkbAccessXFeedbackMask;
- if ((old->ax_timeout!=new->ax_timeout)||
- (old->axt_ctrls_mask!=new->axt_ctrls_mask)||
- (old->axt_ctrls_values!=new->axt_ctrls_values)||
- (old->axt_opts_mask!=new->axt_opts_mask)||
- (old->axt_opts_values!= new->axt_opts_values)) {
- changedControls|= XkbAccessXTimeoutMask;
- }
- if ((old->internal.mask!=new->internal.mask)||
- (old->internal.real_mods!=new->internal.real_mods)||
- (old->internal.vmods!=new->internal.vmods))
- changedControls|= XkbInternalModsMask;
- if ((old->ignore_lock.mask!=new->ignore_lock.mask)||
- (old->ignore_lock.real_mods!=new->ignore_lock.real_mods)||
- (old->ignore_lock.vmods!=new->ignore_lock.vmods))
- changedControls|= XkbIgnoreLockModsMask;
-
- if (new->enabled_ctrls&XkbRepeatKeysMask)
- kbd->kbdfeed->ctrl.autoRepeat=TRUE;
- else kbd->kbdfeed->ctrl.autoRepeat=FALSE;
-
- if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc &&
- (changedControls || forceCtrlProc))
- (*kbd->kbdfeed->CtrlProc)(kbd, &kbd->kbdfeed->ctrl);
-
- if ((!changedControls)&&(old->num_groups==new->num_groups))
- return 0;
-
- if (!kbd->xkb_interest)
- return 0;
-
- pCN->changedControls = changedControls;
- pCN->enabledControls = new->enabled_ctrls;
- pCN->enabledControlChanges = (new->enabled_ctrls^old->enabled_ctrls);
- pCN->numGroups = new->num_groups;
-
- return 1;
-}
-
-void
-XkbSendControlsNotify(DeviceIntPtr kbd,xkbControlsNotify *pCN)
-{
-int initialized;
-CARD32 changedControls, enabledControls, enabledChanges = 0;
-XkbSrvInfoPtr xkbi;
-XkbInterestPtr interest;
-Time time = 0;
-
- interest = kbd->xkb_interest;
- if (!interest || !kbd->key || !kbd->key->xkbInfo)
- return;
- xkbi = kbd->key->xkbInfo;
-
- initialized = 0;
- enabledControls = xkbi->desc->ctrls->enabled_ctrls;
- changedControls = pCN->changedControls;
- pCN->numGroups= xkbi->desc->ctrls->num_groups;
- while (interest) {
- if ((!interest->client->clientGone) &&
- (interest->client->requestVector != InitialVector) &&
- (interest->client->xkbClientFlags&_XkbClientInitialized) &&
- (interest->ctrlsNotifyMask&changedControls)) {
- if (!initialized) {
- pCN->type = XkbEventCode + XkbEventBase;
- pCN->xkbType = XkbControlsNotify;
- pCN->deviceID = kbd->id;
- pCN->time = time = GetTimeInMillis();
- enabledChanges = pCN->enabledControlChanges;
- initialized= 1;
- }
- pCN->changedControls = changedControls;
- pCN->enabledControls = enabledControls;
- pCN->enabledControlChanges = enabledChanges;
- pCN->sequenceNumber = interest->client->sequence;
- pCN->time = time;
- if ( interest->client->swapped ) {
- register int n;
- swaps(&pCN->sequenceNumber,n);
- swapl(&pCN->changedControls,n);
- swapl(&pCN->enabledControls,n);
- swapl(&pCN->enabledControlChanges,n);
- swapl(&pCN->time,n);
- }
- WriteToClient(interest->client, sizeof(xEvent), (char *)pCN);
- }
- interest= interest->next;
- }
- return;
-}
-
-static void
-XkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify *pEv)
-{
-int initialized;
-XkbInterestPtr interest;
-Time time = 0;
-CARD32 state,changed;
-
- interest = kbd->xkb_interest;
- if (!interest)
- return;
-
- initialized = 0;
- state = pEv->state;
- changed = pEv->changed;
- while (interest) {
- if ((!interest->client->clientGone) &&
- (interest->client->requestVector != InitialVector) &&
- (interest->client->xkbClientFlags&_XkbClientInitialized) &&
- (((xkbType==XkbIndicatorStateNotify)&&
- (interest->iStateNotifyMask&changed))||
- ((xkbType==XkbIndicatorMapNotify)&&
- (interest->iMapNotifyMask&changed)))) {
- if (!initialized) {
- pEv->type = XkbEventCode + XkbEventBase;
- pEv->xkbType = xkbType;
- pEv->deviceID = kbd->id;
- pEv->time = time = GetTimeInMillis();
- initialized= 1;
- }
- pEv->sequenceNumber = interest->client->sequence;
- pEv->time = time;
- pEv->changed = changed;
- pEv->state = state;
- if ( interest->client->swapped ) {
- register int n;
- swaps(&pEv->sequenceNumber,n);
- swapl(&pEv->time,n);
- swapl(&pEv->changed,n);
- swapl(&pEv->state,n);
- }
- WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
- }
- interest= interest->next;
- }
- return;
-}
-
-
-void
-XkbHandleBell( BOOL force,
- BOOL eventOnly,
- DeviceIntPtr kbd,
- CARD8 percent,
- pointer pCtrl,
- CARD8 class,
- Atom name,
- WindowPtr pWin,
- ClientPtr pClient)
-{
-xkbBellNotify bn;
-int initialized;
-XkbSrvInfoPtr xkbi;
-XkbInterestPtr interest;
-CARD8 id;
-CARD16 pitch,duration;
-Time time = 0;
-XID winID = 0;
-
- if (!kbd->key || !kbd->key->xkbInfo)
- return;
-
- xkbi = kbd->key->xkbInfo;
-
- if ((force||(xkbi->desc->ctrls->enabled_ctrls&XkbAudibleBellMask))&&
- (!eventOnly)) {
- if (kbd->kbdfeed->BellProc)
- (*kbd->kbdfeed->BellProc)(percent,kbd,(pointer)pCtrl,class);
- }
- interest = kbd->xkb_interest;
- if ((!interest)||(force))
- return;
-
- if ((class==0)||(class==KbdFeedbackClass)) {
- KeybdCtrl *pKeyCtrl= (KeybdCtrl *)pCtrl;
- id= pKeyCtrl->id;
- pitch= pKeyCtrl->bell_pitch;
- duration= pKeyCtrl->bell_duration;
- }
- else if (class==BellFeedbackClass) {
- BellCtrl *pBellCtrl= (BellCtrl *)pCtrl;
- id= pBellCtrl->id;
- pitch= pBellCtrl->pitch;
- duration= pBellCtrl->duration;
- }
- else return;
-
- initialized = 0;
- while (interest) {
- if ((!interest->client->clientGone) &&
- (interest->client->requestVector != InitialVector) &&
- (interest->client->xkbClientFlags&_XkbClientInitialized) &&
- (interest->bellNotifyMask)) {
- if (!initialized) {
- time = GetTimeInMillis();
- bn.type = XkbEventCode + XkbEventBase;
- bn.xkbType = XkbBellNotify;
- bn.deviceID = kbd->id;
- bn.bellClass = class;
- bn.bellID = id;
- bn.percent= percent;
- bn.eventOnly = (eventOnly!=0);
- winID= (pWin?pWin->drawable.id:None);
- initialized= 1;
- }
- bn.sequenceNumber = interest->client->sequence;
- bn.time = time;
- bn.pitch = pitch;
- bn.duration = duration;
- bn.name = name;
- bn.window= winID;
- if ( interest->client->swapped ) {
- register int n;
- swaps(&bn.sequenceNumber,n);
- swapl(&bn.time,n);
- swaps(&bn.pitch,n);
- swaps(&bn.duration,n);
- swapl(&bn.name,n);
- swapl(&bn.window,n);
- }
- WriteToClient(interest->client, sizeof(xEvent), (char *)&bn);
- }
- interest= interest->next;
- }
- return;
-}
-
-void
-XkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify *pEv)
-{
-int initialized;
-XkbInterestPtr interest;
-Time time = 0;
-CARD16 sk_delay,db_delay;
-
- interest = kbd->xkb_interest;
- if (!interest)
- return;
-
- initialized = 0;
- sk_delay= pEv->slowKeysDelay;
- db_delay= pEv->debounceDelay;
- while (interest) {
- if ((!interest->client->clientGone) &&
- (interest->client->requestVector != InitialVector) &&
- (interest->client->xkbClientFlags&_XkbClientInitialized) &&
- (interest->accessXNotifyMask&(1<<pEv->detail))) {
- if (!initialized) {
- pEv->type = XkbEventCode + XkbEventBase;
- pEv->xkbType = XkbAccessXNotify;
- pEv->deviceID = kbd->id;
- pEv->time = time = GetTimeInMillis();
- initialized= 1;
- }
- pEv->sequenceNumber = interest->client->sequence;
- pEv->time = time;
- pEv->slowKeysDelay = sk_delay;
- pEv->debounceDelay = db_delay;
- if ( interest->client->swapped ) {
- register int n;
- swaps(&pEv->sequenceNumber,n);
- swapl(&pEv->time,n);
- swaps(&pEv->slowKeysDelay,n);
- swaps(&pEv->debounceDelay,n);
- }
- WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
- }
- interest= interest->next;
- }
- return;
-}
-
-void
-XkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify *pEv)
-{
-int initialized;
-XkbInterestPtr interest;
-Time time = 0;
-CARD16 changed,changedVirtualMods;
-CARD32 changedIndicators;
-
- interest = kbd->xkb_interest;
- if (!interest)
- return;
-
- initialized = 0;
- changed= pEv->changed;
- changedIndicators= pEv->changedIndicators;
- changedVirtualMods= pEv->changedVirtualMods;
- while (interest) {
- if ((!interest->client->clientGone) &&
- (interest->client->requestVector != InitialVector) &&
- (interest->client->xkbClientFlags&_XkbClientInitialized) &&
- (interest->namesNotifyMask&pEv->changed)) {
- if (!initialized) {
- pEv->type = XkbEventCode + XkbEventBase;
- pEv->xkbType = XkbNamesNotify;
- pEv->deviceID = kbd->id;
- pEv->time = time = GetTimeInMillis();
- initialized= 1;
- }
- pEv->sequenceNumber = interest->client->sequence;
- pEv->time = time;
- pEv->changed = changed;
- pEv->changedIndicators = changedIndicators;
- pEv->changedVirtualMods= changedVirtualMods;
- if ( interest->client->swapped ) {
- register int n;
- swaps(&pEv->sequenceNumber,n);
- swapl(&pEv->time,n);
- swaps(&pEv->changed,n);
- swapl(&pEv->changedIndicators,n);
- swaps(&pEv->changedVirtualMods,n);
- }
- WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
- }
- interest= interest->next;
- }
- return;
-}
-
-void
-XkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify *pEv)
-{
-int initialized;
-XkbInterestPtr interest;
-Time time = 0;
-CARD16 firstSI = 0, nSI = 0, nTotalSI = 0;
-
- interest = kbd->xkb_interest;
- if (!interest)
- return;
-
- initialized = 0;
- while (interest) {
- if ((!interest->client->clientGone) &&
- (interest->client->requestVector != InitialVector) &&
- (interest->client->xkbClientFlags&_XkbClientInitialized) &&
- (interest->compatNotifyMask)) {
- if (!initialized) {
- pEv->type = XkbEventCode + XkbEventBase;
- pEv->xkbType = XkbCompatMapNotify;
- pEv->deviceID = kbd->id;
- pEv->time = time = GetTimeInMillis();
- firstSI= pEv->firstSI;
- nSI= pEv->nSI;
- nTotalSI= pEv->nTotalSI;
- initialized= 1;
- }
- pEv->sequenceNumber = interest->client->sequence;
- pEv->time = time;
- pEv->firstSI = firstSI;
- pEv->nSI = nSI;
- pEv->nTotalSI = nTotalSI;
- if ( interest->client->swapped ) {
- register int n;
- swaps(&pEv->sequenceNumber,n);
- swapl(&pEv->time,n);
- swaps(&pEv->firstSI,n);
- swaps(&pEv->nSI,n);
- swaps(&pEv->nTotalSI,n);
- }
- WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
- }
- interest= interest->next;
- }
- return;
-}
-
-void
-XkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage *pEv)
-{
-int initialized;
-XkbSrvInfoPtr xkbi;
-XkbInterestPtr interest;
-Time time = 0;
-
- interest = kbd->xkb_interest;
- if (!interest || !kbd->key || !kbd->key->xkbInfo)
- return;
-
- xkbi = kbd->key->xkbInfo;
-
- initialized = 0;
- pEv->mods= xkbi->state.mods;
- pEv->group= xkbi->state.group;
- while (interest) {
- if ((!interest->client->clientGone) &&
- (interest->client->requestVector != InitialVector) &&
- (interest->client->xkbClientFlags&_XkbClientInitialized) &&
- (interest->actionMessageMask)) {
- if (!initialized) {
- pEv->type = XkbEventCode + XkbEventBase;
- pEv->xkbType = XkbActionMessage;
- pEv->deviceID = kbd->id;
- pEv->sequenceNumber = interest->client->sequence;
- pEv->time = time = GetTimeInMillis();
- initialized= 1;
- }
- pEv->sequenceNumber = interest->client->sequence;
- pEv->time = time;
- if ( interest->client->swapped ) {
- register int n;
- swaps(&pEv->sequenceNumber,n);
- swapl(&pEv->time,n);
- }
- WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
- }
- interest= interest->next;
- }
- return;
-}
-
-void
-XkbSendExtensionDeviceNotify( DeviceIntPtr dev,
- ClientPtr client,
- xkbExtensionDeviceNotify * pEv)
-{
-int initialized;
-XkbInterestPtr interest;
-Time time = 0;
-CARD32 defined, state;
-CARD16 reason;
-
- interest = dev->xkb_interest;
- if (!interest)
- return;
-
- initialized = 0;
- reason= pEv->reason;
- defined= pEv->ledsDefined;
- state= pEv->ledState;
- while (interest) {
- if ((!interest->client->clientGone) &&
- (interest->client->requestVector != InitialVector) &&
- (interest->client->xkbClientFlags&_XkbClientInitialized) &&
- (interest->extDevNotifyMask&reason)) {
- if (!initialized) {
- pEv->type = XkbEventCode + XkbEventBase;
- pEv->xkbType = XkbExtensionDeviceNotify;
- pEv->deviceID = dev->id;
- pEv->sequenceNumber = interest->client->sequence;
- pEv->time = time = GetTimeInMillis();
- initialized= 1;
- }
- else {
- pEv->sequenceNumber = interest->client->sequence;
- pEv->time = time;
- pEv->ledsDefined= defined;
- pEv->ledState= state;
- pEv->reason= reason;
- pEv->supported= XkbXI_AllFeaturesMask;
- }
- if ( interest->client->swapped ) {
- register int n;
- swaps(&pEv->sequenceNumber,n);
- swapl(&pEv->time,n);
- swapl(&pEv->ledsDefined,n);
- swapl(&pEv->ledState,n);
- swaps(&pEv->reason,n);
- swaps(&pEv->supported,n);
- }
- WriteToClient(interest->client, sizeof(xEvent), (char *)pEv);
- }
- interest= interest->next;
- }
- return;
-}
-
-void
-XkbSendNotification( DeviceIntPtr kbd,
- XkbChangesPtr pChanges,
- XkbEventCausePtr cause)
-{
-XkbSrvLedInfoPtr sli;
-
- sli= NULL;
- if (pChanges->state_changes) {
- xkbStateNotify sn;
- sn.changed= pChanges->state_changes;
- sn.keycode= cause->kc;
- sn.eventType= cause->event;
- sn.requestMajor= cause->mjr;
- sn.requestMinor= cause->mnr;
- XkbSendStateNotify(kbd,&sn);
- }
- if (pChanges->map.changed) {
- xkbMapNotify mn;
- memset(&mn, 0, sizeof(xkbMapNotify));
- mn.changed= pChanges->map.changed;
- mn.firstType= pChanges->map.first_type;
- mn.nTypes= pChanges->map.num_types;
- mn.firstKeySym= pChanges->map.first_key_sym;
- mn.nKeySyms= pChanges->map.num_key_syms;
- mn.firstKeyAct= pChanges->map.first_key_act;
- mn.nKeyActs= pChanges->map.num_key_acts;
- mn.firstKeyBehavior= pChanges->map.first_key_behavior;
- mn.nKeyBehaviors= pChanges->map.num_key_behaviors;
- mn.virtualMods= pChanges->map.vmods;
- mn.firstKeyExplicit= pChanges->map.first_key_explicit;
- mn.nKeyExplicit= pChanges->map.num_key_explicit;
- mn.firstModMapKey= pChanges->map.first_modmap_key;
- mn.nModMapKeys= pChanges->map.num_modmap_keys;
- mn.firstVModMapKey= pChanges->map.first_vmodmap_key;
- mn.nVModMapKeys= pChanges->map.num_vmodmap_keys;
- XkbSendMapNotify(kbd,&mn);
- }
- if ((pChanges->ctrls.changed_ctrls)||
- (pChanges->ctrls.enabled_ctrls_changes)) {
- xkbControlsNotify cn;
- memset(&cn, 0, sizeof(xkbControlsNotify));
- cn.changedControls= pChanges->ctrls.changed_ctrls;
- cn.enabledControlChanges= pChanges->ctrls.enabled_ctrls_changes;
- cn.keycode= cause->kc;
- cn.eventType= cause->event;
- cn.requestMajor= cause->mjr;
- cn.requestMinor= cause->mnr;
- XkbSendControlsNotify(kbd,&cn);
- }
- if (pChanges->indicators.map_changes) {
- xkbIndicatorNotify in;
- if (sli==NULL)
- sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
- memset(&in, 0, sizeof(xkbIndicatorNotify));
- in.state= sli->effectiveState;
- in.changed= pChanges->indicators.map_changes;
- XkbSendIndicatorNotify(kbd,XkbIndicatorMapNotify,&in);
- }
- if (pChanges->indicators.state_changes) {
- xkbIndicatorNotify in;
- if (sli==NULL)
- sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0);
- memset(&in, 0, sizeof(xkbIndicatorNotify));
- in.state= sli->effectiveState;
- in.changed= pChanges->indicators.state_changes;
- XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in);
- }
- if (pChanges->names.changed) {
- xkbNamesNotify nn;
- memset(&nn, 0, sizeof(xkbNamesNotify));
- nn.changed= pChanges->names.changed;
- nn.firstType= pChanges->names.first_type;
- nn.nTypes= pChanges->names.num_types;
- nn.firstLevelName= pChanges->names.first_lvl;
- nn.nLevelNames= pChanges->names.num_lvls;
- nn.nRadioGroups= pChanges->names.num_rg;
- nn.changedVirtualMods= pChanges->names.changed_vmods;
- nn.changedIndicators= pChanges->names.changed_indicators;
- XkbSendNamesNotify(kbd,&nn);
- }
- if ((pChanges->compat.changed_groups)||(pChanges->compat.num_si>0)) {
- xkbCompatMapNotify cmn;
- memset(&cmn, 0, sizeof(xkbCompatMapNotify));
- cmn.changedGroups= pChanges->compat.changed_groups;
- cmn.firstSI= pChanges->compat.first_si;
- cmn.nSI= pChanges->compat.num_si;
- cmn.nTotalSI= kbd->key->xkbInfo->desc->compat->num_si;
- XkbSendCompatMapNotify(kbd,&cmn);
- }
- return;
-}
-
-/***====================================================================***/
-
-void
-XkbFilterEvents(ClientPtr client,int nEvents,xEvent *xE)
-{
- DeviceIntPtr dev = NULL;
- XkbSrvInfoPtr xkbi;
- CARD8 type = xE[0].u.u.type;
-
- if (xE->u.u.type & EXTENSION_EVENT_BASE)
- dev = XIGetDevice(xE);
-
- if (!dev)
- dev = PickKeyboard(client);
-
- if (!dev->key)
- return;
-
- xkbi = dev->key->xkbInfo;
-
- if (client->xkbClientFlags & _XkbClientInitialized) {
- if ((xkbDebugFlags&0x10)&&
- (type == KeyPress || type == KeyRelease ||
- type == DeviceKeyPress || type == DeviceKeyRelease))
- DebugF("[xkb] XkbFilterWriteEvents (XKB client): state 0x%04x\n",
- xE[0].u.keyButtonPointer.state);
-
- if (dev->deviceGrab.grab != NullGrab && dev->deviceGrab.fromPassiveGrab &&
- (type == KeyPress || type == KeyRelease ||
- type == DeviceKeyPress || type == DeviceKeyRelease)) {
- unsigned int state, flags;
-
- flags = client->xkbClientFlags;
- state = xkbi->state.compat_grab_mods;
- if (flags & XkbPCF_GrabsUseXKBStateMask) {
- int group;
- if (flags & XkbPCF_LookupStateWhenGrabbed) {
- group = xkbi->state.group;
- state = xkbi->state.lookup_mods;
- }
- else {
- state = xkbi->state.grab_mods;
- group = xkbi->state.base_group + xkbi->state.latched_group;
- if (group < 0 || group >= xkbi->desc->ctrls->num_groups)
- group = XkbAdjustGroup(group, xkbi->desc->ctrls);
- }
- state = XkbBuildCoreState(state, group);
- }
- else if (flags & XkbPCF_LookupStateWhenGrabbed) {
- state = xkbi->state.compat_lookup_mods;
- }
- xE[0].u.keyButtonPointer.state = state;
- }
- }
- else {
- if ((xkbDebugFlags & 0x4) &&
- (xE[0].u.u.type == KeyPress || xE[0].u.u.type==KeyRelease ||
- xE[0].u.u.type == DeviceKeyPress ||
- xE[0].u.u.type == DeviceKeyRelease)) {
- DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
- DebugF("[xkb] event= 0x%04x\n",xE[0].u.keyButtonPointer.state);
- DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",
- xkbi->state.lookup_mods, xkbi->state.grab_mods);
- DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n",
- xkbi->state.compat_lookup_mods, xkbi->state.compat_grab_mods);
- }
- if (type >= KeyPress && type <= MotionNotify) {
- CARD16 old, new;
-
- old = xE[0].u.keyButtonPointer.state & ~0x1f00;
- new = xE[0].u.keyButtonPointer.state & 0x1F00;
-
- if (old == XkbStateFieldFromRec(&xkbi->state))
- new |= xkbi->state.compat_lookup_mods;
- else
- new |= xkbi->state.compat_grab_mods;
- xE[0].u.keyButtonPointer.state = new;
- }
- else if (type == EnterNotify || type == LeaveNotify) {
- xE[0].u.enterLeave.state &= 0x1F00;
- xE[0].u.enterLeave.state |= xkbi->state.compat_grab_mods;
- }
- else if (type >= DeviceKeyPress && type <= DeviceMotionNotify) {
- CARD16 old, new;
- deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*) &xE[0];
-
- old = kbp->state & ~0x1F00;
- new = kbp->state & 0x1F00;
- if (old == XkbStateFieldFromRec(&xkbi->state))
- new |= xkbi->state.compat_lookup_mods;
- else
- new |= xkbi->state.compat_grab_mods;
- kbp->state = new;
- }
- }
-}
-
-/***====================================================================***/
-
-XkbInterestPtr
-XkbFindClientResource(DevicePtr inDev,ClientPtr client)
-{
-DeviceIntPtr dev = (DeviceIntPtr)inDev;
-XkbInterestPtr interest;
-
- if ( dev->xkb_interest ) {
- interest = dev->xkb_interest;
- while (interest){
- if (interest->client==client) {
- return interest;
- }
- interest = interest->next;
- }
- }
- return NULL;
-}
-
-XkbInterestPtr
-XkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id)
-{
-DeviceIntPtr dev = (DeviceIntPtr)inDev;
-XkbInterestPtr interest;
-
- interest = dev->xkb_interest;
- while (interest) {
- if (interest->client==client)
- return ((interest->resource==id)?interest:NULL);
- interest = interest->next;
- }
- interest = calloc(1, sizeof(XkbInterestRec));
- if (interest) {
- interest->dev = dev;
- interest->client = client;
- interest->resource = id;
- interest->next = dev->xkb_interest;
- dev->xkb_interest= interest;
- return interest;
- }
- return NULL;
-}
-
-int
-XkbRemoveResourceClient(DevicePtr inDev,XID id)
-{
-XkbSrvInfoPtr xkbi;
-DeviceIntPtr dev = (DeviceIntPtr)inDev;
-XkbInterestPtr interest;
-Bool found;
-unsigned long autoCtrls,autoValues;
-ClientPtr client = NULL;
-
- found= FALSE;
-
- if (!dev->key || !dev->key->xkbInfo)
- return found;
-
- autoCtrls= autoValues= 0;
- if ( dev->xkb_interest ) {
- interest = dev->xkb_interest;
- if (interest && (interest->resource==id)){
- dev->xkb_interest = interest->next;
- autoCtrls= interest->autoCtrls;
- autoValues= interest->autoCtrlValues;
- client= interest->client;
- free(interest);
- found= TRUE;
- }
- while ((!found)&&(interest->next)) {
- if (interest->next->resource==id) {
- XkbInterestPtr victim = interest->next;
- interest->next = victim->next;
- autoCtrls= victim->autoCtrls;
- autoValues= victim->autoCtrlValues;
- client= victim->client;
- free(victim);
- found= TRUE;
- }
- interest = interest->next;
- }
- }
- if (found && autoCtrls && dev->key && dev->key->xkbInfo ) {
- XkbEventCauseRec cause;
-
- xkbi= dev->key->xkbInfo;
- XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client);
- XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause);
- }
- return found;
-}
+/************************************************************ +Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. + +Permission to use, copy, modify, and distribute this +software and its documentation for any purpose and without +fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting +documentation, and that the name of Silicon Graphics not be +used in advertising or publicity pertaining to distribution +of the software without specific prior written permission. +Silicon Graphics makes no representation about the suitability +of this software for any purpose. It is provided "as is" +without any express or implied warranty. + +SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON +GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, +DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH +THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <stdio.h> +#include <X11/X.h> +#include <X11/Xproto.h> +#include <X11/keysym.h> +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "inputstr.h" +#include "exevents.h" +#include "exglobals.h" +#include "windowstr.h" +#include <xkbsrv.h> +#include "xkb.h" + +/***====================================================================***/ + +/* + * This function sends out two kinds of notification: + * - Core mapping notify events sent to clients for whom kbd is the + * current core ('picked') keyboard _and_ have not explicitly + * selected for XKB mapping notify events; + * - Xi mapping events, sent unconditionally to all clients who have + * explicitly selected for them (including those who have explicitly + * selected for XKB mapping notify events!). + */ +static void +XkbSendLegacyMapNotify(DeviceIntPtr kbd, CARD16 xkb_event, CARD16 changed, + int first_key, int num_keys) +{ + int i; + int keymap_changed = 0; + int modmap_changed = 0; + xEvent core_mn; + deviceMappingNotify xi_mn; + CARD32 time = GetTimeInMillis(); + + if (xkb_event == XkbNewKeyboardNotify) { + if (changed & XkbNKN_KeycodesMask) { + keymap_changed = 1; + modmap_changed = 1; + } + } + else if (xkb_event == XkbMapNotify) { + if (changed & XkbKeySymsMask) + keymap_changed = 1; + if (changed & XkbModifierMapMask) + modmap_changed = 1; + } + if (!keymap_changed && !modmap_changed) + return; + + core_mn.u.u.type = MappingNotify; + xi_mn.type = DeviceMappingNotify; + xi_mn.deviceid = kbd->id; + xi_mn.time = time; + + /* 0 is serverClient. */ + for (i = 1; i < currentMaxClients; i++) { + if (!clients[i] || clients[i]->clientState != ClientStateRunning) + continue; + + /* XKB allows clients to restrict the MappingNotify events sent to + * them. This was broken for three years. Sorry. */ + if (xkb_event == XkbMapNotify && + (clients[i]->xkbClientFlags & _XkbClientInitialized) && + !(clients[i]->mapNotifyMask & changed)) + continue; + /* Emulate previous server behaviour: any client which has activated + * XKB will not receive core events emulated from a NewKeyboardNotify + * at all. */ + if (xkb_event == XkbNewKeyboardNotify && + (clients[i]->xkbClientFlags & _XkbClientInitialized)) + continue; + + /* Don't send core events to clients who don't know about us. */ + if (!XIShouldNotify(clients[i], kbd)) + continue; + + if (keymap_changed) { + core_mn.u.mappingNotify.request = MappingKeyboard; + + /* Clip the keycode range to what the client knows about, so it + * doesn't freak out. */ + if (first_key >= clients[i]->minKC) + core_mn.u.mappingNotify.firstKeyCode = first_key; + else + core_mn.u.mappingNotify.firstKeyCode = clients[i]->minKC; + if (first_key + num_keys - 1 <= clients[i]->maxKC) + core_mn.u.mappingNotify.count = num_keys; + else + core_mn.u.mappingNotify.count = clients[i]->maxKC - + clients[i]->minKC + 1; + + WriteEventsToClient(clients[i], 1, &core_mn); + } + if (modmap_changed) { + core_mn.u.mappingNotify.request = MappingModifier; + core_mn.u.mappingNotify.firstKeyCode = 0; + core_mn.u.mappingNotify.count = 0; + WriteEventsToClient(clients[i], 1, &core_mn); + } + } + + /* Hmm, maybe we can accidentally generate Xi events for core devices + * here? Clients might be upset, but that seems better than the + * alternative of stale keymaps. -ds */ + if (keymap_changed) { + xi_mn.request = MappingKeyboard; + xi_mn.firstKeyCode = first_key; + xi_mn.count = num_keys; + SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn, + 1); + } + if (modmap_changed) { + xi_mn.request = MappingModifier; + xi_mn.firstKeyCode = 0; + xi_mn.count = 0; + SendEventToAllWindows(kbd, DeviceMappingNotifyMask, (xEvent *) &xi_mn, + 1); + } +} + +/***====================================================================***/ + +void +XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN) +{ + int i; + Time time = GetTimeInMillis(); + CARD16 changed = pNKN->changed; + + pNKN->type = XkbEventCode + XkbEventBase; + pNKN->xkbType = XkbNewKeyboardNotify; + + for (i=1; i<currentMaxClients; i++) { + if (!clients[i] || clients[i]->clientState != ClientStateRunning) + continue; + + if (!(clients[i]->newKeyboardNotifyMask & changed)) + continue; + + pNKN->sequenceNumber = clients[i]->sequence; + pNKN->time = time; + pNKN->changed = changed; + if (clients[i]->swapped) { + int n; + swaps(&pNKN->sequenceNumber,n); + swapl(&pNKN->time,n); + swaps(&pNKN->changed,n); + } + WriteToClient(clients[i], sizeof(xEvent), pNKN); + + if (changed & XkbNKN_KeycodesMask) { + clients[i]->minKC = pNKN->minKeyCode; + clients[i]->maxKC = pNKN->maxKeyCode; + } + } + + XkbSendLegacyMapNotify(kbd, XkbNewKeyboardNotify, changed, pNKN->minKeyCode, + pNKN->maxKeyCode - pNKN->minKeyCode + 1); + + return; +} + +/***====================================================================***/ + +void +XkbSendStateNotify(DeviceIntPtr kbd,xkbStateNotify *pSN) +{ +XkbSrvInfoPtr xkbi; +XkbStatePtr state; +XkbInterestPtr interest; +Time time; +register CARD16 changed,bState; + + interest = kbd->xkb_interest; + if (!interest || !kbd->key || !kbd->key->xkbInfo) + return; + xkbi = kbd->key->xkbInfo; + state= &xkbi->state; + + pSN->type = XkbEventCode + XkbEventBase; + pSN->xkbType = XkbStateNotify; + pSN->deviceID = kbd->id; + pSN->time = time = GetTimeInMillis(); + pSN->mods = state->mods; + pSN->baseMods = state->base_mods; + pSN->latchedMods = state->latched_mods; + pSN->lockedMods = state->locked_mods; + pSN->group = state->group; + pSN->baseGroup = state->base_group; + pSN->latchedGroup = state->latched_group; + pSN->lockedGroup = state->locked_group; + pSN->compatState = state->compat_state; + pSN->grabMods = state->grab_mods; + pSN->compatGrabMods = state->compat_grab_mods; + pSN->lookupMods = state->lookup_mods; + pSN->compatLookupMods = state->compat_lookup_mods; + pSN->ptrBtnState = state->ptr_buttons; + changed = pSN->changed; + bState= pSN->ptrBtnState; + + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->stateNotifyMask&changed)) { + pSN->sequenceNumber = interest->client->sequence; + pSN->time = time; + pSN->changed = changed; + pSN->ptrBtnState = bState; + if ( interest->client->swapped ) { + register int n; + swaps(&pSN->sequenceNumber,n); + swapl(&pSN->time,n); + swaps(&pSN->changed,n); + swaps(&pSN->ptrBtnState,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pSN); + } + interest= interest->next; + } + return; +} + +/***====================================================================***/ + +/* + * This function sends out XKB mapping notify events to clients which + * have explicitly selected for them. Core and Xi events are handled by + * XkbSendLegacyMapNotify. */ +void +XkbSendMapNotify(DeviceIntPtr kbd, xkbMapNotify *pMN) +{ + int i; + CARD32 time = GetTimeInMillis(); + CARD16 changed = pMN->changed; + XkbSrvInfoPtr xkbi = kbd->key->xkbInfo; + + pMN->minKeyCode = xkbi->desc->min_key_code; + pMN->maxKeyCode = xkbi->desc->max_key_code; + pMN->type = XkbEventCode + XkbEventBase; + pMN->xkbType = XkbMapNotify; + pMN->deviceID = kbd->id; + + /* 0 is serverClient. */ + for (i = 1; i < currentMaxClients; i++) { + if (!clients[i] || clients[i]->clientState != ClientStateRunning) + continue; + + if (!(clients[i]->mapNotifyMask & changed)) + continue; + + pMN->time = time; + pMN->sequenceNumber = clients[i]->sequence; + pMN->changed = changed; + + if (clients[i]->swapped) { + int n; + swaps(&pMN->sequenceNumber, n); + swapl(&pMN->time, n); + swaps(&pMN->changed, n); + } + WriteToClient(clients[i], sizeof(xEvent), pMN); + } + + XkbSendLegacyMapNotify(kbd, XkbMapNotify, changed, pMN->firstKeySym, + pMN->nKeySyms); +} + +int +XkbComputeControlsNotify( DeviceIntPtr kbd, + XkbControlsPtr old, + XkbControlsPtr new, + xkbControlsNotify * pCN, + Bool forceCtrlProc) +{ +int i; +CARD32 changedControls; + + changedControls= 0; + + if (!kbd || !kbd->kbdfeed) + return 0; + + if (old->enabled_ctrls!=new->enabled_ctrls) + changedControls|= XkbControlsEnabledMask; + if ((old->repeat_delay!=new->repeat_delay)|| + (old->repeat_interval!=new->repeat_interval)) + changedControls|= XkbRepeatKeysMask; + for (i = 0; i < XkbPerKeyBitArraySize; i++) + if (old->per_key_repeat[i] != new->per_key_repeat[i]) + changedControls|= XkbPerKeyRepeatMask; + if (old->slow_keys_delay!=new->slow_keys_delay) + changedControls|= XkbSlowKeysMask; + if (old->debounce_delay!=new->debounce_delay) + changedControls|= XkbBounceKeysMask; + if ((old->mk_delay!=new->mk_delay)|| + (old->mk_interval!=new->mk_interval)|| + (old->mk_dflt_btn!=new->mk_dflt_btn)) + changedControls|= XkbMouseKeysMask; + if ((old->mk_time_to_max!=new->mk_time_to_max)|| + (old->mk_curve!=new->mk_curve)|| + (old->mk_max_speed!=new->mk_max_speed)) + changedControls|= XkbMouseKeysAccelMask; + if (old->ax_options!=new->ax_options) + changedControls|= XkbAccessXKeysMask; + if ((old->ax_options^new->ax_options) & XkbAX_SKOptionsMask) + changedControls|= XkbStickyKeysMask; + if ((old->ax_options^new->ax_options) & XkbAX_FBOptionsMask) + changedControls|= XkbAccessXFeedbackMask; + if ((old->ax_timeout!=new->ax_timeout)|| + (old->axt_ctrls_mask!=new->axt_ctrls_mask)|| + (old->axt_ctrls_values!=new->axt_ctrls_values)|| + (old->axt_opts_mask!=new->axt_opts_mask)|| + (old->axt_opts_values!= new->axt_opts_values)) { + changedControls|= XkbAccessXTimeoutMask; + } + if ((old->internal.mask!=new->internal.mask)|| + (old->internal.real_mods!=new->internal.real_mods)|| + (old->internal.vmods!=new->internal.vmods)) + changedControls|= XkbInternalModsMask; + if ((old->ignore_lock.mask!=new->ignore_lock.mask)|| + (old->ignore_lock.real_mods!=new->ignore_lock.real_mods)|| + (old->ignore_lock.vmods!=new->ignore_lock.vmods)) + changedControls|= XkbIgnoreLockModsMask; + + if (new->enabled_ctrls&XkbRepeatKeysMask) + kbd->kbdfeed->ctrl.autoRepeat=TRUE; + else kbd->kbdfeed->ctrl.autoRepeat=FALSE; + + if (kbd->kbdfeed && kbd->kbdfeed->CtrlProc && + (changedControls || forceCtrlProc)) + (*kbd->kbdfeed->CtrlProc)(kbd, &kbd->kbdfeed->ctrl); + + if ((!changedControls)&&(old->num_groups==new->num_groups)) + return 0; + + if (!kbd->xkb_interest) + return 0; + + pCN->changedControls = changedControls; + pCN->enabledControls = new->enabled_ctrls; + pCN->enabledControlChanges = (new->enabled_ctrls^old->enabled_ctrls); + pCN->numGroups = new->num_groups; + + return 1; +} + +void +XkbSendControlsNotify(DeviceIntPtr kbd,xkbControlsNotify *pCN) +{ +int initialized; +CARD32 changedControls, enabledControls, enabledChanges = 0; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +Time time = 0; + + interest = kbd->xkb_interest; + if (!interest || !kbd->key || !kbd->key->xkbInfo) + return; + xkbi = kbd->key->xkbInfo; + + initialized = 0; + enabledControls = xkbi->desc->ctrls->enabled_ctrls; + changedControls = pCN->changedControls; + pCN->numGroups= xkbi->desc->ctrls->num_groups; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->ctrlsNotifyMask&changedControls)) { + if (!initialized) { + pCN->type = XkbEventCode + XkbEventBase; + pCN->xkbType = XkbControlsNotify; + pCN->deviceID = kbd->id; + pCN->time = time = GetTimeInMillis(); + enabledChanges = pCN->enabledControlChanges; + initialized= 1; + } + pCN->changedControls = changedControls; + pCN->enabledControls = enabledControls; + pCN->enabledControlChanges = enabledChanges; + pCN->sequenceNumber = interest->client->sequence; + pCN->time = time; + if ( interest->client->swapped ) { + register int n; + swaps(&pCN->sequenceNumber,n); + swapl(&pCN->changedControls,n); + swapl(&pCN->enabledControls,n); + swapl(&pCN->enabledControlChanges,n); + swapl(&pCN->time,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pCN); + } + interest= interest->next; + } + return; +} + +static void +XkbSendIndicatorNotify(DeviceIntPtr kbd,int xkbType,xkbIndicatorNotify *pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD32 state,changed; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + state = pEv->state; + changed = pEv->changed; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (((xkbType==XkbIndicatorStateNotify)&& + (interest->iStateNotifyMask&changed))|| + ((xkbType==XkbIndicatorMapNotify)&& + (interest->iMapNotifyMask&changed)))) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = xkbType; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->changed = changed; + pEv->state = state; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swapl(&pEv->changed,n); + swapl(&pEv->state,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + + +void +XkbHandleBell( BOOL force, + BOOL eventOnly, + DeviceIntPtr kbd, + CARD8 percent, + pointer pCtrl, + CARD8 class, + Atom name, + WindowPtr pWin, + ClientPtr pClient) +{ +xkbBellNotify bn; +int initialized; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +CARD8 id; +CARD16 pitch,duration; +Time time = 0; +XID winID = 0; + + if (!kbd->key || !kbd->key->xkbInfo) + return; + + xkbi = kbd->key->xkbInfo; + + if ((force||(xkbi->desc->ctrls->enabled_ctrls&XkbAudibleBellMask))&& + (!eventOnly)) { + if (kbd->kbdfeed->BellProc) + (*kbd->kbdfeed->BellProc)(percent,kbd,(pointer)pCtrl,class); + } + interest = kbd->xkb_interest; + if ((!interest)||(force)) + return; + + if ((class==0)||(class==KbdFeedbackClass)) { + KeybdCtrl *pKeyCtrl= (KeybdCtrl *)pCtrl; + id= pKeyCtrl->id; + pitch= pKeyCtrl->bell_pitch; + duration= pKeyCtrl->bell_duration; + } + else if (class==BellFeedbackClass) { + BellCtrl *pBellCtrl= (BellCtrl *)pCtrl; + id= pBellCtrl->id; + pitch= pBellCtrl->pitch; + duration= pBellCtrl->duration; + } + else return; + + initialized = 0; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->bellNotifyMask)) { + if (!initialized) { + time = GetTimeInMillis(); + bn.type = XkbEventCode + XkbEventBase; + bn.xkbType = XkbBellNotify; + bn.deviceID = kbd->id; + bn.bellClass = class; + bn.bellID = id; + bn.percent= percent; + bn.eventOnly = (eventOnly!=0); + winID= (pWin?pWin->drawable.id:None); + initialized= 1; + } + bn.sequenceNumber = interest->client->sequence; + bn.time = time; + bn.pitch = pitch; + bn.duration = duration; + bn.name = name; + bn.window= winID; + if ( interest->client->swapped ) { + register int n; + swaps(&bn.sequenceNumber,n); + swapl(&bn.time,n); + swaps(&bn.pitch,n); + swaps(&bn.duration,n); + swapl(&bn.name,n); + swapl(&bn.window,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)&bn); + } + interest= interest->next; + } + return; +} + +void +XkbSendAccessXNotify(DeviceIntPtr kbd,xkbAccessXNotify *pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD16 sk_delay,db_delay; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + sk_delay= pEv->slowKeysDelay; + db_delay= pEv->debounceDelay; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->accessXNotifyMask&(1<<pEv->detail))) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbAccessXNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->slowKeysDelay = sk_delay; + pEv->debounceDelay = db_delay; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->slowKeysDelay,n); + swaps(&pEv->debounceDelay,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendNamesNotify(DeviceIntPtr kbd,xkbNamesNotify *pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD16 changed,changedVirtualMods; +CARD32 changedIndicators; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + changed= pEv->changed; + changedIndicators= pEv->changedIndicators; + changedVirtualMods= pEv->changedVirtualMods; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->namesNotifyMask&pEv->changed)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbNamesNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->changed = changed; + pEv->changedIndicators = changedIndicators; + pEv->changedVirtualMods= changedVirtualMods; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->changed,n); + swapl(&pEv->changedIndicators,n); + swaps(&pEv->changedVirtualMods,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendCompatMapNotify(DeviceIntPtr kbd,xkbCompatMapNotify *pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD16 firstSI = 0, nSI = 0, nTotalSI = 0; + + interest = kbd->xkb_interest; + if (!interest) + return; + + initialized = 0; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->compatNotifyMask)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbCompatMapNotify; + pEv->deviceID = kbd->id; + pEv->time = time = GetTimeInMillis(); + firstSI= pEv->firstSI; + nSI= pEv->nSI; + nTotalSI= pEv->nTotalSI; + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->firstSI = firstSI; + pEv->nSI = nSI; + pEv->nTotalSI = nTotalSI; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swaps(&pEv->firstSI,n); + swaps(&pEv->nSI,n); + swaps(&pEv->nTotalSI,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendActionMessage(DeviceIntPtr kbd,xkbActionMessage *pEv) +{ +int initialized; +XkbSrvInfoPtr xkbi; +XkbInterestPtr interest; +Time time = 0; + + interest = kbd->xkb_interest; + if (!interest || !kbd->key || !kbd->key->xkbInfo) + return; + + xkbi = kbd->key->xkbInfo; + + initialized = 0; + pEv->mods= xkbi->state.mods; + pEv->group= xkbi->state.group; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->actionMessageMask)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbActionMessage; + pEv->deviceID = kbd->id; + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendExtensionDeviceNotify( DeviceIntPtr dev, + ClientPtr client, + xkbExtensionDeviceNotify * pEv) +{ +int initialized; +XkbInterestPtr interest; +Time time = 0; +CARD32 defined, state; +CARD16 reason; + + interest = dev->xkb_interest; + if (!interest) + return; + + initialized = 0; + reason= pEv->reason; + defined= pEv->ledsDefined; + state= pEv->ledState; + while (interest) { + if ((!interest->client->clientGone) && + (interest->client->requestVector != InitialVector) && + (interest->client->xkbClientFlags&_XkbClientInitialized) && + (interest->extDevNotifyMask&reason)) { + if (!initialized) { + pEv->type = XkbEventCode + XkbEventBase; + pEv->xkbType = XkbExtensionDeviceNotify; + pEv->deviceID = dev->id; + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time = GetTimeInMillis(); + initialized= 1; + } + else { + pEv->sequenceNumber = interest->client->sequence; + pEv->time = time; + pEv->ledsDefined= defined; + pEv->ledState= state; + pEv->reason= reason; + pEv->supported= XkbXI_AllFeaturesMask; + } + if ( interest->client->swapped ) { + register int n; + swaps(&pEv->sequenceNumber,n); + swapl(&pEv->time,n); + swapl(&pEv->ledsDefined,n); + swapl(&pEv->ledState,n); + swaps(&pEv->reason,n); + swaps(&pEv->supported,n); + } + WriteToClient(interest->client, sizeof(xEvent), (char *)pEv); + } + interest= interest->next; + } + return; +} + +void +XkbSendNotification( DeviceIntPtr kbd, + XkbChangesPtr pChanges, + XkbEventCausePtr cause) +{ +XkbSrvLedInfoPtr sli; + + sli= NULL; + if (pChanges->state_changes) { + xkbStateNotify sn; + sn.changed= pChanges->state_changes; + sn.keycode= cause->kc; + sn.eventType= cause->event; + sn.requestMajor= cause->mjr; + sn.requestMinor= cause->mnr; + XkbSendStateNotify(kbd,&sn); + } + if (pChanges->map.changed) { + xkbMapNotify mn; + memset(&mn, 0, sizeof(xkbMapNotify)); + mn.changed= pChanges->map.changed; + mn.firstType= pChanges->map.first_type; + mn.nTypes= pChanges->map.num_types; + mn.firstKeySym= pChanges->map.first_key_sym; + mn.nKeySyms= pChanges->map.num_key_syms; + mn.firstKeyAct= pChanges->map.first_key_act; + mn.nKeyActs= pChanges->map.num_key_acts; + mn.firstKeyBehavior= pChanges->map.first_key_behavior; + mn.nKeyBehaviors= pChanges->map.num_key_behaviors; + mn.virtualMods= pChanges->map.vmods; + mn.firstKeyExplicit= pChanges->map.first_key_explicit; + mn.nKeyExplicit= pChanges->map.num_key_explicit; + mn.firstModMapKey= pChanges->map.first_modmap_key; + mn.nModMapKeys= pChanges->map.num_modmap_keys; + mn.firstVModMapKey= pChanges->map.first_vmodmap_key; + mn.nVModMapKeys= pChanges->map.num_vmodmap_keys; + XkbSendMapNotify(kbd,&mn); + } + if ((pChanges->ctrls.changed_ctrls)|| + (pChanges->ctrls.enabled_ctrls_changes)) { + xkbControlsNotify cn; + memset(&cn, 0, sizeof(xkbControlsNotify)); + cn.changedControls= pChanges->ctrls.changed_ctrls; + cn.enabledControlChanges= pChanges->ctrls.enabled_ctrls_changes; + cn.keycode= cause->kc; + cn.eventType= cause->event; + cn.requestMajor= cause->mjr; + cn.requestMinor= cause->mnr; + XkbSendControlsNotify(kbd,&cn); + } + if (pChanges->indicators.map_changes) { + xkbIndicatorNotify in; + if (sli==NULL) + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + memset(&in, 0, sizeof(xkbIndicatorNotify)); + in.state= sli->effectiveState; + in.changed= pChanges->indicators.map_changes; + XkbSendIndicatorNotify(kbd,XkbIndicatorMapNotify,&in); + } + if (pChanges->indicators.state_changes) { + xkbIndicatorNotify in; + if (sli==NULL) + sli= XkbFindSrvLedInfo(kbd,XkbDfltXIClass,XkbDfltXIId,0); + memset(&in, 0, sizeof(xkbIndicatorNotify)); + in.state= sli->effectiveState; + in.changed= pChanges->indicators.state_changes; + XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in); + } + if (pChanges->names.changed) { + xkbNamesNotify nn; + memset(&nn, 0, sizeof(xkbNamesNotify)); + nn.changed= pChanges->names.changed; + nn.firstType= pChanges->names.first_type; + nn.nTypes= pChanges->names.num_types; + nn.firstLevelName= pChanges->names.first_lvl; + nn.nLevelNames= pChanges->names.num_lvls; + nn.nRadioGroups= pChanges->names.num_rg; + nn.changedVirtualMods= pChanges->names.changed_vmods; + nn.changedIndicators= pChanges->names.changed_indicators; + XkbSendNamesNotify(kbd,&nn); + } + if ((pChanges->compat.changed_groups)||(pChanges->compat.num_si>0)) { + xkbCompatMapNotify cmn; + memset(&cmn, 0, sizeof(xkbCompatMapNotify)); + cmn.changedGroups= pChanges->compat.changed_groups; + cmn.firstSI= pChanges->compat.first_si; + cmn.nSI= pChanges->compat.num_si; + cmn.nTotalSI= kbd->key->xkbInfo->desc->compat->num_si; + XkbSendCompatMapNotify(kbd,&cmn); + } + return; +} + +/***====================================================================***/ + +void +XkbFilterEvents(ClientPtr client,int nEvents,xEvent *xE) +{ + DeviceIntPtr dev = NULL; + XkbSrvInfoPtr xkbi; + CARD8 type = xE[0].u.u.type; + + if (xE->u.u.type & EXTENSION_EVENT_BASE) + dev = XIGetDevice(xE); + + if (!dev) + dev = PickKeyboard(client); + + if (!dev->key) + return; + + xkbi = dev->key->xkbInfo; + + if (client->xkbClientFlags & _XkbClientInitialized) { + if ((xkbDebugFlags&0x10)&& + (type == KeyPress || type == KeyRelease || + type == DeviceKeyPress || type == DeviceKeyRelease)) + DebugF("[xkb] XkbFilterWriteEvents (XKB client): state 0x%04x\n", + xE[0].u.keyButtonPointer.state); + + if (dev->deviceGrab.grab != NullGrab && dev->deviceGrab.fromPassiveGrab && + (type == KeyPress || type == KeyRelease || + type == DeviceKeyPress || type == DeviceKeyRelease)) { + unsigned int state, flags; + + flags = client->xkbClientFlags; + state = xkbi->state.compat_grab_mods; + if (flags & XkbPCF_GrabsUseXKBStateMask) { + int group; + if (flags & XkbPCF_LookupStateWhenGrabbed) { + group = xkbi->state.group; + state = xkbi->state.lookup_mods; + } + else { + state = xkbi->state.grab_mods; + group = xkbi->state.base_group + xkbi->state.latched_group; + if (group < 0 || group >= xkbi->desc->ctrls->num_groups) + group = XkbAdjustGroup(group, xkbi->desc->ctrls); + } + state = XkbBuildCoreState(state, group); + } + else if (flags & XkbPCF_LookupStateWhenGrabbed) { + state = xkbi->state.compat_lookup_mods; + } + xE[0].u.keyButtonPointer.state = state; + } + } + else { + if ((xkbDebugFlags & 0x4) && + (xE[0].u.u.type == KeyPress || xE[0].u.u.type==KeyRelease || + xE[0].u.u.type == DeviceKeyPress || + xE[0].u.u.type == DeviceKeyRelease)) { + DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n"); + DebugF("[xkb] event= 0x%04x\n",xE[0].u.keyButtonPointer.state); + DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n", + xkbi->state.lookup_mods, xkbi->state.grab_mods); + DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n", + xkbi->state.compat_lookup_mods, xkbi->state.compat_grab_mods); + } + if (type >= KeyPress && type <= MotionNotify) { + CARD16 old, new; + + old = xE[0].u.keyButtonPointer.state & ~0x1f00; + new = xE[0].u.keyButtonPointer.state & 0x1F00; + + if (old == XkbStateFieldFromRec(&xkbi->state)) + new |= xkbi->state.compat_lookup_mods; + else + new |= xkbi->state.compat_grab_mods; + xE[0].u.keyButtonPointer.state = new; + } + else if (type == EnterNotify || type == LeaveNotify) { + xE[0].u.enterLeave.state &= 0x1F00; + xE[0].u.enterLeave.state |= xkbi->state.compat_grab_mods; + } + else if (type >= DeviceKeyPress && type <= DeviceMotionNotify) { + CARD16 old, new; + deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*) &xE[0]; + + old = kbp->state & ~0x1F00; + new = kbp->state & 0x1F00; + if (old == XkbStateFieldFromRec(&xkbi->state)) + new |= xkbi->state.compat_lookup_mods; + else + new |= xkbi->state.compat_grab_mods; + kbp->state = new; + } + } +} + +/***====================================================================***/ + +XkbInterestPtr +XkbFindClientResource(DevicePtr inDev,ClientPtr client) +{ +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; + + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + while (interest){ + if (interest->client==client) { + return interest; + } + interest = interest->next; + } + } + return NULL; +} + +XkbInterestPtr +XkbAddClientResource(DevicePtr inDev,ClientPtr client,XID id) +{ +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; + + interest = dev->xkb_interest; + while (interest) { + if (interest->client==client) + return ((interest->resource==id)?interest:NULL); + interest = interest->next; + } + interest = calloc(1, sizeof(XkbInterestRec)); + if (interest) { + interest->dev = dev; + interest->client = client; + interest->resource = id; + interest->next = dev->xkb_interest; + dev->xkb_interest= interest; + return interest; + } + return NULL; +} + +int +XkbRemoveResourceClient(DevicePtr inDev,XID id) +{ +XkbSrvInfoPtr xkbi; +DeviceIntPtr dev = (DeviceIntPtr)inDev; +XkbInterestPtr interest; +Bool found; +unsigned long autoCtrls,autoValues; +ClientPtr client = NULL; + + found= FALSE; + + if (!dev->key || !dev->key->xkbInfo) + return found; + + autoCtrls= autoValues= 0; + if ( dev->xkb_interest ) { + interest = dev->xkb_interest; + if (interest && (interest->resource==id)){ + dev->xkb_interest = interest->next; + autoCtrls= interest->autoCtrls; + autoValues= interest->autoCtrlValues; + client= interest->client; + free(interest); + found= TRUE; + } + while ((!found)&&(interest->next)) { + if (interest->next->resource==id) { + XkbInterestPtr victim = interest->next; + interest->next = victim->next; + autoCtrls= victim->autoCtrls; + autoValues= victim->autoCtrlValues; + client= victim->client; + free(victim); + found= TRUE; + } + interest = interest->next; + } + } + if (found && autoCtrls && dev->key && dev->key->xkbInfo ) { + XkbEventCauseRec cause; + + xkbi= dev->key->xkbInfo; + XkbSetCauseXkbReq(&cause,X_kbPerClientFlags,client); + XkbEnableDisableControls(xkbi,autoCtrls,autoValues,NULL,&cause); + } + return found; +} |