1059 lines
31 KiB
C
1059 lines
31 KiB
C
/************************************************************
|
|
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>
|
|
#define NEED_EVENTS 1
|
|
#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 "windowstr.h"
|
|
#include "exevents.h"
|
|
#include <xkbsrv.h>
|
|
#include "xkb.h"
|
|
|
|
/***====================================================================***/
|
|
|
|
void
|
|
XkbSendNewKeyboardNotify(DeviceIntPtr kbd,xkbNewKeyboardNotify *pNKN)
|
|
{
|
|
register int i;
|
|
Time time;
|
|
CARD16 changed;
|
|
|
|
pNKN->type = XkbEventCode + XkbEventBase;
|
|
pNKN->xkbType = XkbNewKeyboardNotify;
|
|
pNKN->time = time = GetTimeInMillis();
|
|
changed = pNKN->changed;
|
|
|
|
for (i=1; i<currentMaxClients; i++) {
|
|
if ((!clients[i]) || clients[i]->clientGone ||
|
|
(clients[i]->requestVector==InitialVector)) {
|
|
continue;
|
|
}
|
|
|
|
if (clients[i]->xkbClientFlags&_XkbClientInitialized) {
|
|
if (clients[i]->newKeyboardNotifyMask&changed) {
|
|
pNKN->sequenceNumber = clients[i]->sequence;
|
|
pNKN->time = time;
|
|
pNKN->changed = changed;
|
|
if ( clients[i]->swapped ) {
|
|
register int n;
|
|
swaps(&pNKN->sequenceNumber,n);
|
|
swapl(&pNKN->time,n);
|
|
swaps(&pNKN->changed,n);
|
|
}
|
|
WriteToClient(clients[i],sizeof(xEvent),(char *)pNKN);
|
|
if (changed&XkbNKN_KeycodesMask) {
|
|
clients[i]->minKC= pNKN->minKeyCode;
|
|
clients[i]->maxKC= pNKN->maxKeyCode;
|
|
}
|
|
}
|
|
}
|
|
else if (changed&XkbNKN_KeycodesMask) {
|
|
xEvent event;
|
|
event.u.u.type= MappingNotify;
|
|
event.u.mappingNotify.request= MappingKeyboard;
|
|
event.u.mappingNotify.firstKeyCode= clients[i]->minKC;
|
|
event.u.mappingNotify.count= clients[i]->maxKC-clients[i]->minKC+1;
|
|
event.u.u.sequenceNumber= clients[i]->sequence;
|
|
if (clients[i]->swapped) {
|
|
int n;
|
|
swaps(&event.u.u.sequenceNumber,n);
|
|
}
|
|
WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event);
|
|
event.u.mappingNotify.request= MappingModifier;
|
|
WriteToClient(clients[i],SIZEOF(xEvent), (char *)&event);
|
|
}
|
|
}
|
|
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;
|
|
}
|
|
|
|
/***====================================================================***/
|
|
|
|
void
|
|
XkbSendMapNotify(DeviceIntPtr kbd,xkbMapNotify *pMN)
|
|
{
|
|
int i;
|
|
XkbSrvInfoPtr xkbi;
|
|
unsigned time = 0,initialized;
|
|
CARD16 changed;
|
|
|
|
if (!kbd->key || !kbd->key->xkbInfo)
|
|
return;
|
|
|
|
xkbi = kbd->key->xkbInfo;
|
|
initialized= 0;
|
|
|
|
changed = pMN->changed;
|
|
pMN->minKeyCode= xkbi->desc->min_key_code;
|
|
pMN->maxKeyCode= xkbi->desc->max_key_code;
|
|
for (i=1; i<currentMaxClients; i++) {
|
|
if (clients[i] && ! clients[i]->clientGone &&
|
|
(clients[i]->requestVector != InitialVector) &&
|
|
(clients[i]->xkbClientFlags&_XkbClientInitialized) &&
|
|
(clients[i]->mapNotifyMask&changed))
|
|
{
|
|
if (!initialized) {
|
|
pMN->type = XkbEventCode + XkbEventBase;
|
|
pMN->xkbType = XkbMapNotify;
|
|
pMN->deviceID = kbd->id;
|
|
time = GetTimeInMillis();
|
|
initialized= 1;
|
|
}
|
|
pMN->time= time;
|
|
pMN->sequenceNumber = clients[i]->sequence;
|
|
pMN->changed = changed;
|
|
if ( clients[i]->swapped ) {
|
|
register int n;
|
|
swaps(&pMN->sequenceNumber,n);
|
|
swapl(&pMN->time,n);
|
|
swaps(&pMN->changed,n);
|
|
}
|
|
WriteToClient(clients[i],sizeof(xEvent),(char *)pMN);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
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, supported = 0;
|
|
|
|
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();
|
|
supported= pEv->supported;
|
|
initialized= 1;
|
|
}
|
|
else {
|
|
pEv->sequenceNumber = interest->client->sequence;
|
|
pEv->time = time;
|
|
pEv->ledsDefined= defined;
|
|
pEv->ledState= state;
|
|
pEv->reason= reason;
|
|
pEv->supported= supported;
|
|
}
|
|
if (client!=interest->client) {
|
|
/* only report UnsupportedFeature to the client that */
|
|
/* issued the failing request */
|
|
pEv->reason&= ~XkbXI_UnsupportedFeatureMask;
|
|
if ((interest->extDevNotifyMask&reason)==0)
|
|
continue;
|
|
}
|
|
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;
|
|
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;
|
|
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);
|
|
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);
|
|
in.state= sli->effectiveState;
|
|
in.changed= pChanges->indicators.state_changes;
|
|
XkbSendIndicatorNotify(kbd,XkbIndicatorStateNotify,&in);
|
|
}
|
|
if (pChanges->names.changed) {
|
|
xkbNamesNotify nn;
|
|
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;
|
|
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;
|
|
}
|
|
|
|
/***====================================================================***/
|
|
|
|
Bool
|
|
XkbFilterEvents(ClientPtr pClient,int nEvents,xEvent *xE)
|
|
{
|
|
int i, button_mask;
|
|
DeviceIntPtr pXDev = inputInfo.keyboard;
|
|
XkbSrvInfoPtr xkbi;
|
|
|
|
if (xE->u.u.type & EXTENSION_EVENT_BASE)
|
|
{
|
|
pXDev = XIGetDevice(xE);
|
|
if (!pXDev)
|
|
pXDev = inputInfo.keyboard;
|
|
}
|
|
|
|
xkbi= (pXDev->key) ? pXDev->key->xkbInfo : NULL;
|
|
|
|
if ( pClient->xkbClientFlags & _XkbClientInitialized ) {
|
|
if ((xkbDebugFlags&0x10)&&
|
|
((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:\n");
|
|
DebugF("[xkb] Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state);
|
|
DebugF("[xkb] XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n",
|
|
XkbLastRepeatEvent,xE,
|
|
((XkbLastRepeatEvent!=(pointer)xE)?"True":"False"));
|
|
DebugF("[xkb] (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n",
|
|
pClient->xkbClientFlags,
|
|
(_XkbWantsDetectableAutoRepeat(pClient)?"True":"False"));
|
|
DebugF("[xkb] !IsRelease(%d) %s\n",xE[0].u.u.type,
|
|
(!_XkbIsReleaseEvent(xE[0].u.u.type))?"True":"False");
|
|
}
|
|
if ( (XkbLastRepeatEvent==(pointer)xE) &&
|
|
(_XkbWantsDetectableAutoRepeat(pClient)) &&
|
|
(_XkbIsReleaseEvent(xE[0].u.u.type)) ) {
|
|
return False;
|
|
}
|
|
|
|
if (!xkbi)
|
|
return True;
|
|
|
|
if ((pXDev->deviceGrab.grab != NullGrab)
|
|
&& pXDev->deviceGrab.fromPassiveGrab &&
|
|
((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)||
|
|
(xE[0].u.u.type==DeviceKeyPress)||
|
|
(xE[0].u.u.type == DeviceKeyRelease))) {
|
|
register unsigned state,flags;
|
|
|
|
flags= pClient->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;
|
|
}
|
|
button_mask = 1 << xE[0].u.u.detail;
|
|
if (xE[0].u.u.type == ButtonPress &&
|
|
((xE[0].u.keyButtonPointer.state >> 7) & button_mask) == button_mask &&
|
|
(xkbi->lockedPtrButtons & button_mask) == button_mask) {
|
|
/* If the MouseKeys is pressed, and the "real" mouse is also pressed
|
|
* when the mouse is released, the server does not behave properly.
|
|
* Faking a release of the button here solves the problem.
|
|
*/
|
|
DebugF("[xkb] Faking release of button %d\n", xE[0].u.u.detail);
|
|
XkbDDXFakeDeviceButton(xkbi->device, 0, xE[0].u.u.detail);
|
|
}
|
|
}
|
|
else {
|
|
register CARD8 type;
|
|
|
|
if (!xkbi)
|
|
return True;
|
|
|
|
for (i=0;i<nEvents;i++) {
|
|
type= xE[i].u.u.type;
|
|
if ((xkbDebugFlags&0x4)&&
|
|
((xE[i].u.u.type==KeyPress)||(xE[i].u.u.type==KeyRelease)||
|
|
(xE[i].u.u.type==DeviceKeyPress)||
|
|
(xE[i].u.u.type == DeviceKeyRelease))) {
|
|
DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n");
|
|
DebugF("[xkb] event= 0x%04x\n",xE[i].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[i].u.keyButtonPointer.state&(~0x1f00);
|
|
new= xE[i].u.keyButtonPointer.state&0x1F00;
|
|
|
|
if (old==XkbStateFieldFromRec(&xkbi->state))
|
|
new|= xkbi->state.compat_lookup_mods;
|
|
else new|= xkbi->state.compat_grab_mods;
|
|
xE[i].u.keyButtonPointer.state= new;
|
|
}
|
|
else if ((type==EnterNotify)||(type==LeaveNotify)) {
|
|
xE[i].u.enterLeave.state&= 0x1F00;
|
|
xE[i].u.enterLeave.state|= xkbi->state.compat_grab_mods;
|
|
} else if ((type>=DeviceKeyPress)&&(type<=DeviceMotionNotify)) {
|
|
CARD16 old, new;
|
|
deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer*)&xE[i];
|
|
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;
|
|
}
|
|
button_mask = 1 << xE[i].u.u.detail;
|
|
if (type == ButtonPress &&
|
|
((xE[i].u.keyButtonPointer.state >> 7) & button_mask) == button_mask &&
|
|
(xkbi->lockedPtrButtons & button_mask) == button_mask) {
|
|
DebugF("[xkb] Faking release of button %d\n", xE[i].u.u.detail);
|
|
XkbDDXFakeDeviceButton(xkbi->device, 0, xE[i].u.u.detail);
|
|
} else if (type == DeviceButtonPress &&
|
|
((((deviceKeyButtonPointer*)&xE[i])->state >> 7) & button_mask) == button_mask &&
|
|
(xkbi->lockedPtrButtons & button_mask) == button_mask) {
|
|
DebugF("[xkb] Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state);
|
|
XkbDDXFakeDeviceButton(xkbi->device, 0, ((deviceKeyButtonPointer*)&xE[i])->state);
|
|
}
|
|
}
|
|
}
|
|
return True;
|
|
}
|
|
|
|
/***====================================================================***/
|
|
|
|
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 = _XkbTypedAlloc(XkbInterestRec);
|
|
bzero(interest,sizeof(XkbInterestRec));
|
|
if (interest) {
|
|
interest->dev = dev;
|
|
interest->client = client;
|
|
interest->resource = id;
|
|
interest->stateNotifyMask= 0;
|
|
interest->ctrlsNotifyMask= 0;
|
|
interest->namesNotifyMask= 0;
|
|
interest->compatNotifyMask= 0;
|
|
interest->bellNotifyMask= FALSE;
|
|
interest->accessXNotifyMask= 0;
|
|
interest->iStateNotifyMask= 0;
|
|
interest->iMapNotifyMask= 0;
|
|
interest->altSymsNotifyMask= 0;
|
|
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;
|
|
_XkbFree(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;
|
|
_XkbFree(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;
|
|
}
|