1289 lines
35 KiB
C
1289 lines
35 KiB
C
/************************************************************
|
|
|
|
Copyright 1989, 1998 The Open Group
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
the above copyright notice appear in all copies and that both that
|
|
copyright notice and this permission notice appear in supporting
|
|
documentation.
|
|
|
|
The above copyright notice and this permission notice shall be included in
|
|
all copies or substantial portions of the Software.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
Except as contained in this notice, the name of The Open Group shall not be
|
|
used in advertising or otherwise to promote the sale, use or other dealings
|
|
in this Software without prior written authorization from The Open Group.
|
|
|
|
Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
|
|
|
|
All Rights Reserved
|
|
|
|
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 Hewlett-Packard not be
|
|
used in advertising or publicity pertaining to distribution of the
|
|
software without specific, written prior permission.
|
|
|
|
HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
|
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
|
HEWLETT-PACKARD 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.
|
|
|
|
********************************************************/
|
|
|
|
/********************************************************************
|
|
*
|
|
* Routines to register and initialize extension input devices.
|
|
* This also contains ProcessOtherEvent, the routine called from DDX
|
|
* to route extension events.
|
|
*
|
|
*/
|
|
|
|
#define NEED_EVENTS
|
|
#ifdef HAVE_DIX_CONFIG_H
|
|
#include <dix-config.h>
|
|
#endif
|
|
|
|
#include <X11/X.h>
|
|
#include <X11/Xproto.h>
|
|
#include <X11/extensions/XI.h>
|
|
#include <X11/extensions/XIproto.h>
|
|
#include "inputstr.h"
|
|
#include "windowstr.h"
|
|
#include "miscstruct.h"
|
|
#include "region.h"
|
|
#include "exevents.h"
|
|
#include "extnsionst.h"
|
|
#include "exglobals.h"
|
|
#include "dixevents.h" /* DeliverFocusedEvent */
|
|
#include "dixgrabs.h" /* CreateGrab() */
|
|
#include "scrnintstr.h"
|
|
#include "xace.h"
|
|
|
|
#ifdef XKB
|
|
#include "xkbsrv.h"
|
|
#endif
|
|
|
|
#define WID(w) ((w) ? ((w)->drawable.id) : 0)
|
|
#define AllModifiersMask ( \
|
|
ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
|
|
Mod3Mask | Mod4Mask | Mod5Mask )
|
|
#define AllButtonsMask ( \
|
|
Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
|
|
#define Motion_Filter(class) (DevicePointerMotionMask | \
|
|
(class)->state | (class)->motionMask)
|
|
|
|
static Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
|
|
Bool /* ignoreSelectedEvents */
|
|
);
|
|
static Bool MakeInputMasks(WindowPtr /* pWin */
|
|
);
|
|
|
|
/**************************************************************************
|
|
*
|
|
* Procedures for extension device event routing.
|
|
*
|
|
*/
|
|
|
|
void
|
|
RegisterOtherDevice(DeviceIntPtr device)
|
|
{
|
|
device->public.processInputProc = ProcessOtherEvent;
|
|
device->public.realInputProc = ProcessOtherEvent;
|
|
(device)->ActivateGrab = ActivateKeyboardGrab;
|
|
(device)->DeactivateGrab = DeactivateKeyboardGrab;
|
|
}
|
|
|
|
/*ARGSUSED*/ void
|
|
ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count)
|
|
{
|
|
BYTE *kptr;
|
|
int i;
|
|
CARD16 modifiers;
|
|
CARD16 mask;
|
|
GrabPtr grab = other->grab;
|
|
Bool deactivateDeviceGrab = FALSE;
|
|
int key = 0, bit = 0, rootX, rootY;
|
|
ButtonClassPtr b = other->button;
|
|
KeyClassPtr k = other->key;
|
|
ValuatorClassPtr v = other->valuator;
|
|
deviceValuator *xV = (deviceValuator *) xE;
|
|
|
|
if (xE->u.u.type != DeviceValuator) {
|
|
GetSpritePosition(&rootX, &rootY);
|
|
xE->u.keyButtonPointer.rootX = rootX;
|
|
xE->u.keyButtonPointer.rootY = rootY;
|
|
key = xE->u.u.detail;
|
|
NoticeEventTime(xE);
|
|
xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state |
|
|
inputInfo.pointer->button->state;
|
|
bit = 1 << (key & 7);
|
|
}
|
|
if (DeviceEventCallback) {
|
|
DeviceEventInfoRec eventinfo;
|
|
|
|
eventinfo.events = (xEventPtr) xE;
|
|
eventinfo.count = count;
|
|
CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
|
|
}
|
|
for (i = 1; i < count; i++)
|
|
if ((++xV)->type == DeviceValuator) {
|
|
int first = xV->first_valuator;
|
|
int *axisvals;
|
|
|
|
if (xV->num_valuators
|
|
&& (!v
|
|
|| (xV->num_valuators
|
|
&& (first + xV->num_valuators > v->numAxes))))
|
|
FatalError("Bad valuators reported for device %s\n",
|
|
other->name);
|
|
xV->device_state = 0;
|
|
if (k)
|
|
xV->device_state |= k->state;
|
|
if (b)
|
|
xV->device_state |= b->state;
|
|
if (v && v->axisVal) {
|
|
axisvals = v->axisVal;
|
|
switch (xV->num_valuators) {
|
|
case 6:
|
|
*(axisvals + first + 5) = xV->valuator5;
|
|
case 5:
|
|
*(axisvals + first + 4) = xV->valuator4;
|
|
case 4:
|
|
*(axisvals + first + 3) = xV->valuator3;
|
|
case 3:
|
|
*(axisvals + first + 2) = xV->valuator2;
|
|
case 2:
|
|
*(axisvals + first + 1) = xV->valuator1;
|
|
case 1:
|
|
*(axisvals + first) = xV->valuator0;
|
|
case 0:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (xE->u.u.type == DeviceKeyPress) {
|
|
if (!k)
|
|
return;
|
|
|
|
modifiers = k->modifierMap[key];
|
|
kptr = &k->down[key >> 3];
|
|
if (*kptr & bit) { /* allow ddx to generate multiple downs */
|
|
if (!modifiers) {
|
|
xE->u.u.type = DeviceKeyRelease;
|
|
ProcessOtherEvent(xE, other, count);
|
|
xE->u.u.type = DeviceKeyPress;
|
|
/* release can have side effects, don't fall through */
|
|
ProcessOtherEvent(xE, other, count);
|
|
}
|
|
return;
|
|
}
|
|
if (other->valuator)
|
|
other->valuator->motionHintWindow = NullWindow;
|
|
*kptr |= bit;
|
|
k->prev_state = k->state;
|
|
for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
|
|
if (mask & modifiers) {
|
|
/* This key affects modifier "i" */
|
|
k->modifierKeyCount[i]++;
|
|
k->state |= mask;
|
|
modifiers &= ~mask;
|
|
}
|
|
}
|
|
if (!grab && CheckDeviceGrabs(other, xE, 0, count)) {
|
|
other->activatingKey = key;
|
|
return;
|
|
}
|
|
} else if (xE->u.u.type == DeviceKeyRelease) {
|
|
if (!k)
|
|
return;
|
|
|
|
kptr = &k->down[key >> 3];
|
|
if (!(*kptr & bit)) /* guard against duplicates */
|
|
return;
|
|
modifiers = k->modifierMap[key];
|
|
if (other->valuator)
|
|
other->valuator->motionHintWindow = NullWindow;
|
|
*kptr &= ~bit;
|
|
k->prev_state = k->state;
|
|
for (i = 0, mask = 1; modifiers; i++, mask <<= 1) {
|
|
if (mask & modifiers) {
|
|
/* This key affects modifier "i" */
|
|
if (--k->modifierKeyCount[i] <= 0) {
|
|
k->modifierKeyCount[i] = 0;
|
|
k->state &= ~mask;
|
|
}
|
|
modifiers &= ~mask;
|
|
}
|
|
}
|
|
|
|
if (other->fromPassiveGrab && (key == other->activatingKey))
|
|
deactivateDeviceGrab = TRUE;
|
|
} else if (xE->u.u.type == DeviceButtonPress) {
|
|
if (!b)
|
|
return;
|
|
|
|
kptr = &b->down[key >> 3];
|
|
*kptr |= bit;
|
|
if (other->valuator)
|
|
other->valuator->motionHintWindow = NullWindow;
|
|
b->buttonsDown++;
|
|
b->motionMask = DeviceButtonMotionMask;
|
|
xE->u.u.detail = key;
|
|
if (xE->u.u.detail == 0)
|
|
return;
|
|
if (xE->u.u.detail <= 5)
|
|
b->state |= (Button1Mask >> 1) << xE->u.u.detail;
|
|
SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
|
|
if (!grab)
|
|
if (CheckDeviceGrabs(other, xE, 0, count))
|
|
/* if a passive grab was activated, the event has been sent
|
|
* already */
|
|
return;
|
|
|
|
} else if (xE->u.u.type == DeviceButtonRelease) {
|
|
if (!b)
|
|
return;
|
|
|
|
kptr = &b->down[key >> 3];
|
|
*kptr &= ~bit;
|
|
if (other->valuator)
|
|
other->valuator->motionHintWindow = NullWindow;
|
|
if (b->buttonsDown >= 1 && !--b->buttonsDown)
|
|
b->motionMask = 0;
|
|
xE->u.u.detail = key;
|
|
if (xE->u.u.detail == 0)
|
|
return;
|
|
if (xE->u.u.detail <= 5)
|
|
b->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
|
|
SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify);
|
|
if (!b->state && other->fromPassiveGrab)
|
|
deactivateDeviceGrab = TRUE;
|
|
} else if (xE->u.u.type == ProximityIn)
|
|
other->valuator->mode &= ~OutOfProximity;
|
|
else if (xE->u.u.type == ProximityOut)
|
|
other->valuator->mode |= OutOfProximity;
|
|
|
|
if (grab)
|
|
DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count);
|
|
else if (other->focus)
|
|
DeliverFocusedEvent(other, xE, GetSpriteWindow(), count);
|
|
else
|
|
DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow,
|
|
other, count);
|
|
|
|
if (deactivateDeviceGrab == TRUE)
|
|
(*other->DeactivateGrab) (other);
|
|
}
|
|
|
|
_X_EXPORT int
|
|
InitProximityClassDeviceStruct(DeviceIntPtr dev)
|
|
{
|
|
ProximityClassPtr proxc;
|
|
|
|
proxc = (ProximityClassPtr) xalloc(sizeof(ProximityClassRec));
|
|
if (!proxc)
|
|
return FALSE;
|
|
dev->proximity = proxc;
|
|
return TRUE;
|
|
}
|
|
|
|
_X_EXPORT void
|
|
InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval,
|
|
int resolution, int min_res, int max_res)
|
|
{
|
|
AxisInfoPtr ax;
|
|
|
|
if (!dev || !dev->valuator)
|
|
return;
|
|
|
|
ax = dev->valuator->axes + axnum;
|
|
|
|
ax->min_value = minval;
|
|
ax->max_value = maxval;
|
|
ax->resolution = resolution;
|
|
ax->min_resolution = min_res;
|
|
ax->max_resolution = max_res;
|
|
}
|
|
|
|
static void
|
|
FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
|
|
ButtonClassPtr b, ValuatorClassPtr v, int first)
|
|
{
|
|
ev->type = DeviceStateNotify;
|
|
ev->deviceid = dev->id;
|
|
ev->time = currentTime.milliseconds;
|
|
ev->classes_reported = 0;
|
|
ev->num_keys = 0;
|
|
ev->num_buttons = 0;
|
|
ev->num_valuators = 0;
|
|
|
|
if (b) {
|
|
ev->classes_reported |= (1 << ButtonClass);
|
|
ev->num_buttons = b->numButtons;
|
|
memmove((char *)&ev->buttons[0], (char *)b->down, 4);
|
|
} else if (k) {
|
|
ev->classes_reported |= (1 << KeyClass);
|
|
ev->num_keys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
|
|
memmove((char *)&ev->keys[0], (char *)k->down, 4);
|
|
}
|
|
if (v) {
|
|
int nval = v->numAxes - first;
|
|
|
|
ev->classes_reported |= (1 << ValuatorClass);
|
|
ev->classes_reported |= (dev->valuator->mode << ModeBitsShift);
|
|
ev->num_valuators = nval < 3 ? nval : 3;
|
|
switch (ev->num_valuators) {
|
|
case 3:
|
|
ev->valuator2 = v->axisVal[first + 2];
|
|
case 2:
|
|
ev->valuator1 = v->axisVal[first + 1];
|
|
case 1:
|
|
ev->valuator0 = v->axisVal[first];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
|
|
int first)
|
|
{
|
|
int nval = v->numAxes - first;
|
|
|
|
ev->type = DeviceValuator;
|
|
ev->deviceid = dev->id;
|
|
ev->num_valuators = nval < 3 ? nval : 3;
|
|
ev->first_valuator = first;
|
|
switch (ev->num_valuators) {
|
|
case 3:
|
|
ev->valuator2 = v->axisVal[first + 2];
|
|
case 2:
|
|
ev->valuator1 = v->axisVal[first + 1];
|
|
case 1:
|
|
ev->valuator0 = v->axisVal[first];
|
|
break;
|
|
}
|
|
first += ev->num_valuators;
|
|
}
|
|
|
|
void
|
|
DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
|
|
WindowPtr pWin)
|
|
{
|
|
deviceFocus event;
|
|
|
|
if (type == FocusIn)
|
|
type = DeviceFocusIn;
|
|
else
|
|
type = DeviceFocusOut;
|
|
|
|
event.deviceid = dev->id;
|
|
event.mode = mode;
|
|
event.type = type;
|
|
event.detail = detail;
|
|
event.window = pWin->drawable.id;
|
|
event.time = currentTime.milliseconds;
|
|
|
|
(void)DeliverEventsToWindow(pWin, (xEvent *) & event, 1,
|
|
DeviceFocusChangeMask, NullGrab, dev->id);
|
|
|
|
if ((type == DeviceFocusIn) &&
|
|
(wOtherInputMasks(pWin)) &&
|
|
(wOtherInputMasks(pWin)->inputEvents[dev->id] & DeviceStateNotifyMask))
|
|
{
|
|
int evcount = 1;
|
|
deviceStateNotify *ev, *sev;
|
|
deviceKeyStateNotify *kev;
|
|
deviceButtonStateNotify *bev;
|
|
|
|
KeyClassPtr k;
|
|
ButtonClassPtr b;
|
|
ValuatorClassPtr v;
|
|
int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
|
|
|
|
if ((b = dev->button) != NULL) {
|
|
nbuttons = b->numButtons;
|
|
if (nbuttons > 32)
|
|
evcount++;
|
|
}
|
|
if ((k = dev->key) != NULL) {
|
|
nkeys = k->curKeySyms.maxKeyCode - k->curKeySyms.minKeyCode;
|
|
if (nkeys > 32)
|
|
evcount++;
|
|
if (nbuttons > 0) {
|
|
evcount++;
|
|
}
|
|
}
|
|
if ((v = dev->valuator) != NULL) {
|
|
nval = v->numAxes;
|
|
|
|
if (nval > 3)
|
|
evcount++;
|
|
if (nval > 6) {
|
|
if (!(k && b))
|
|
evcount++;
|
|
if (nval > 9)
|
|
evcount += ((nval - 7) / 3);
|
|
}
|
|
}
|
|
|
|
sev = ev = (deviceStateNotify *) xalloc(evcount * sizeof(xEvent));
|
|
FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
|
|
|
|
if (b != NULL) {
|
|
FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
|
|
first += 3;
|
|
nval -= 3;
|
|
if (nbuttons > 32) {
|
|
(ev - 1)->deviceid |= MORE_EVENTS;
|
|
bev = (deviceButtonStateNotify *) ev++;
|
|
bev->type = DeviceButtonStateNotify;
|
|
bev->deviceid = dev->id;
|
|
memmove((char *)&bev->buttons[0], (char *)&b->down[4], 28);
|
|
}
|
|
if (nval > 0) {
|
|
(ev - 1)->deviceid |= MORE_EVENTS;
|
|
FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
|
|
first += 3;
|
|
nval -= 3;
|
|
}
|
|
}
|
|
|
|
if (k != NULL) {
|
|
FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
|
|
first += 3;
|
|
nval -= 3;
|
|
if (nkeys > 32) {
|
|
(ev - 1)->deviceid |= MORE_EVENTS;
|
|
kev = (deviceKeyStateNotify *) ev++;
|
|
kev->type = DeviceKeyStateNotify;
|
|
kev->deviceid = dev->id;
|
|
memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
|
|
}
|
|
if (nval > 0) {
|
|
(ev - 1)->deviceid |= MORE_EVENTS;
|
|
FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
|
|
first += 3;
|
|
nval -= 3;
|
|
}
|
|
}
|
|
|
|
while (nval > 0) {
|
|
FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
|
|
first += 3;
|
|
nval -= 3;
|
|
if (nval > 0) {
|
|
(ev - 1)->deviceid |= MORE_EVENTS;
|
|
FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
|
|
first += 3;
|
|
nval -= 3;
|
|
}
|
|
}
|
|
|
|
(void)DeliverEventsToWindow(pWin, (xEvent *) sev, evcount,
|
|
DeviceStateNotifyMask, NullGrab, dev->id);
|
|
xfree(sev);
|
|
}
|
|
}
|
|
|
|
int
|
|
GrabButton(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
|
|
BYTE other_devices_mode, CARD16 modifiers,
|
|
DeviceIntPtr modifier_device, CARD8 button, Window grabWindow,
|
|
BOOL ownerEvents, Cursor rcursor, Window rconfineTo, Mask eventMask)
|
|
{
|
|
WindowPtr pWin, confineTo;
|
|
CursorPtr cursor;
|
|
GrabPtr grab;
|
|
Mask access_mode = DixGrabAccess;
|
|
int rc;
|
|
|
|
if ((this_device_mode != GrabModeSync) &&
|
|
(this_device_mode != GrabModeAsync)) {
|
|
client->errorValue = this_device_mode;
|
|
return BadValue;
|
|
}
|
|
if ((other_devices_mode != GrabModeSync) &&
|
|
(other_devices_mode != GrabModeAsync)) {
|
|
client->errorValue = other_devices_mode;
|
|
return BadValue;
|
|
}
|
|
if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
|
|
client->errorValue = modifiers;
|
|
return BadValue;
|
|
}
|
|
if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
|
|
client->errorValue = ownerEvents;
|
|
return BadValue;
|
|
}
|
|
rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
|
|
if (rc != Success)
|
|
return rc;
|
|
if (rconfineTo == None)
|
|
confineTo = NullWindow;
|
|
else {
|
|
rc = dixLookupWindow(&confineTo, rconfineTo, client, DixSetAttrAccess);
|
|
if (rc != Success)
|
|
return rc;
|
|
}
|
|
if (rcursor == None)
|
|
cursor = NullCursor;
|
|
else {
|
|
rc = dixLookupResource((pointer *)&cursor, rcursor, RT_CURSOR,
|
|
client, DixUseAccess);
|
|
if (rc != Success)
|
|
{
|
|
client->errorValue = rcursor;
|
|
return (rc == BadValue) ? BadCursor : rc;
|
|
}
|
|
access_mode |= DixForceAccess;
|
|
}
|
|
if (this_device_mode == GrabModeSync || other_devices_mode == GrabModeSync)
|
|
access_mode |= DixFreezeAccess;
|
|
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
|
|
if (rc != Success)
|
|
return rc;
|
|
|
|
grab = CreateGrab(client->index, dev, pWin, eventMask,
|
|
(Bool) ownerEvents, (Bool) this_device_mode,
|
|
(Bool) other_devices_mode, modifier_device, modifiers,
|
|
DeviceButtonPress, button, confineTo, cursor);
|
|
if (!grab)
|
|
return BadAlloc;
|
|
return AddPassiveGrabToList(client, grab);
|
|
}
|
|
|
|
int
|
|
GrabKey(ClientPtr client, DeviceIntPtr dev, BYTE this_device_mode,
|
|
BYTE other_devices_mode, CARD16 modifiers,
|
|
DeviceIntPtr modifier_device, CARD8 key, Window grabWindow,
|
|
BOOL ownerEvents, Mask mask)
|
|
{
|
|
WindowPtr pWin;
|
|
GrabPtr grab;
|
|
KeyClassPtr k = dev->key;
|
|
Mask access_mode = DixGrabAccess;
|
|
int rc;
|
|
|
|
if (k == NULL)
|
|
return BadMatch;
|
|
if ((other_devices_mode != GrabModeSync) &&
|
|
(other_devices_mode != GrabModeAsync)) {
|
|
client->errorValue = other_devices_mode;
|
|
return BadValue;
|
|
}
|
|
if ((this_device_mode != GrabModeSync) &&
|
|
(this_device_mode != GrabModeAsync)) {
|
|
client->errorValue = this_device_mode;
|
|
return BadValue;
|
|
}
|
|
if (((key > k->curKeySyms.maxKeyCode) || (key < k->curKeySyms.minKeyCode))
|
|
&& (key != AnyKey)) {
|
|
client->errorValue = key;
|
|
return BadValue;
|
|
}
|
|
if ((modifiers != AnyModifier) && (modifiers & ~AllModifiersMask)) {
|
|
client->errorValue = modifiers;
|
|
return BadValue;
|
|
}
|
|
if ((ownerEvents != xTrue) && (ownerEvents != xFalse)) {
|
|
client->errorValue = ownerEvents;
|
|
return BadValue;
|
|
}
|
|
rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
|
|
if (rc != Success)
|
|
return rc;
|
|
if (this_device_mode == GrabModeSync || other_devices_mode == GrabModeSync)
|
|
access_mode |= DixFreezeAccess;
|
|
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
|
|
if (rc != Success)
|
|
return rc;
|
|
|
|
grab = CreateGrab(client->index, dev, pWin,
|
|
mask, ownerEvents, this_device_mode, other_devices_mode,
|
|
modifier_device, modifiers, DeviceKeyPress, key,
|
|
NullWindow, NullCursor);
|
|
if (!grab)
|
|
return BadAlloc;
|
|
return AddPassiveGrabToList(client, grab);
|
|
}
|
|
|
|
int
|
|
SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
|
|
Mask mask, Mask exclusivemasks, Mask validmasks)
|
|
{
|
|
int mskidx = dev->id;
|
|
int i, ret;
|
|
Mask check;
|
|
InputClientsPtr others;
|
|
|
|
if (mask & ~validmasks) {
|
|
client->errorValue = mask;
|
|
return BadValue;
|
|
}
|
|
check = (mask & exclusivemasks);
|
|
if (wOtherInputMasks(pWin)) {
|
|
if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { /* It is illegal for two different
|
|
* clients to select on any of the
|
|
* events for maskcheck. However,
|
|
* it is OK, for some client to
|
|
* continue selecting on one of those
|
|
* events. */
|
|
for (others = wOtherInputMasks(pWin)->inputClients; others;
|
|
others = others->next) {
|
|
if (!SameClient(others, client) && (check &
|
|
others->mask[mskidx]))
|
|
return BadAccess;
|
|
}
|
|
}
|
|
for (others = wOtherInputMasks(pWin)->inputClients; others;
|
|
others = others->next) {
|
|
if (SameClient(others, client)) {
|
|
check = others->mask[mskidx];
|
|
others->mask[mskidx] = mask;
|
|
if (mask == 0) {
|
|
for (i = 0; i < EMASKSIZE; i++)
|
|
if (i != mskidx && others->mask[i] != 0)
|
|
break;
|
|
if (i == EMASKSIZE) {
|
|
RecalculateDeviceDeliverableEvents(pWin);
|
|
if (ShouldFreeInputMasks(pWin, FALSE))
|
|
FreeResource(others->resource, RT_NONE);
|
|
return Success;
|
|
}
|
|
}
|
|
goto maskSet;
|
|
}
|
|
}
|
|
}
|
|
check = 0;
|
|
if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
|
|
return ret;
|
|
maskSet:
|
|
if (dev->valuator)
|
|
if ((dev->valuator->motionHintWindow == pWin) &&
|
|
(mask & DevicePointerMotionHintMask) &&
|
|
!(check & DevicePointerMotionHintMask) && !dev->grab)
|
|
dev->valuator->motionHintWindow = NullWindow;
|
|
RecalculateDeviceDeliverableEvents(pWin);
|
|
return Success;
|
|
}
|
|
|
|
int
|
|
AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
|
|
{
|
|
InputClientsPtr others;
|
|
|
|
if (!pWin->optional && !MakeWindowOptional(pWin))
|
|
return BadAlloc;
|
|
others = (InputClients *) xalloc(sizeof(InputClients));
|
|
if (!others)
|
|
return BadAlloc;
|
|
if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
|
|
return BadAlloc;
|
|
bzero((char *)&others->mask[0], sizeof(Mask) * EMASKSIZE);
|
|
others->mask[mskidx] = mask;
|
|
others->resource = FakeClientID(client->index);
|
|
others->next = pWin->optional->inputMasks->inputClients;
|
|
pWin->optional->inputMasks->inputClients = others;
|
|
if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
|
|
return BadAlloc;
|
|
return Success;
|
|
}
|
|
|
|
static Bool
|
|
MakeInputMasks(WindowPtr pWin)
|
|
{
|
|
struct _OtherInputMasks *imasks;
|
|
|
|
imasks = (struct _OtherInputMasks *)
|
|
xalloc(sizeof(struct _OtherInputMasks));
|
|
if (!imasks)
|
|
return FALSE;
|
|
bzero((char *)imasks, sizeof(struct _OtherInputMasks));
|
|
pWin->optional->inputMasks = imasks;
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
RecalculateDeviceDeliverableEvents(WindowPtr pWin)
|
|
{
|
|
InputClientsPtr others;
|
|
struct _OtherInputMasks *inputMasks; /* default: NULL */
|
|
WindowPtr pChild, tmp;
|
|
int i;
|
|
|
|
pChild = pWin;
|
|
while (1) {
|
|
if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
|
|
for (others = inputMasks->inputClients; others;
|
|
others = others->next) {
|
|
for (i = 0; i < EMASKSIZE; i++)
|
|
inputMasks->inputEvents[i] |= others->mask[i];
|
|
}
|
|
for (i = 0; i < EMASKSIZE; i++)
|
|
inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
|
|
for (tmp = pChild->parent; tmp; tmp = tmp->parent)
|
|
if (wOtherInputMasks(tmp))
|
|
for (i = 0; i < EMASKSIZE; i++)
|
|
inputMasks->deliverableEvents[i] |=
|
|
(wOtherInputMasks(tmp)->deliverableEvents[i]
|
|
& ~inputMasks->
|
|
dontPropagateMask[i] & PropagateMask[i]);
|
|
}
|
|
if (pChild->firstChild) {
|
|
pChild = pChild->firstChild;
|
|
continue;
|
|
}
|
|
while (!pChild->nextSib && (pChild != pWin))
|
|
pChild = pChild->parent;
|
|
if (pChild == pWin)
|
|
break;
|
|
pChild = pChild->nextSib;
|
|
}
|
|
}
|
|
|
|
int
|
|
InputClientGone(WindowPtr pWin, XID id)
|
|
{
|
|
InputClientsPtr other, prev;
|
|
|
|
if (!wOtherInputMasks(pWin))
|
|
return (Success);
|
|
prev = 0;
|
|
for (other = wOtherInputMasks(pWin)->inputClients; other;
|
|
other = other->next) {
|
|
if (other->resource == id) {
|
|
if (prev) {
|
|
prev->next = other->next;
|
|
xfree(other);
|
|
} else if (!(other->next)) {
|
|
if (ShouldFreeInputMasks(pWin, TRUE)) {
|
|
wOtherInputMasks(pWin)->inputClients = other->next;
|
|
xfree(wOtherInputMasks(pWin));
|
|
pWin->optional->inputMasks = (OtherInputMasks *) NULL;
|
|
CheckWindowOptionalNeed(pWin);
|
|
xfree(other);
|
|
} else {
|
|
other->resource = FakeClientID(0);
|
|
if (!AddResource(other->resource, RT_INPUTCLIENT,
|
|
(pointer) pWin))
|
|
return BadAlloc;
|
|
}
|
|
} else {
|
|
wOtherInputMasks(pWin)->inputClients = other->next;
|
|
xfree(other);
|
|
}
|
|
RecalculateDeviceDeliverableEvents(pWin);
|
|
return (Success);
|
|
}
|
|
prev = other;
|
|
}
|
|
FatalError("client not on device event list");
|
|
}
|
|
|
|
int
|
|
SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
|
|
xEvent * ev, Mask mask, int count)
|
|
{
|
|
WindowPtr pWin;
|
|
WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
|
|
WindowPtr spriteWin = GetSpriteWindow();
|
|
|
|
if (dest == PointerWindow)
|
|
pWin = spriteWin;
|
|
else if (dest == InputFocus) {
|
|
WindowPtr inputFocus;
|
|
|
|
if (!d->focus)
|
|
inputFocus = spriteWin;
|
|
else
|
|
inputFocus = d->focus->win;
|
|
|
|
if (inputFocus == FollowKeyboardWin)
|
|
inputFocus = inputInfo.keyboard->focus->win;
|
|
|
|
if (inputFocus == NoneWin)
|
|
return Success;
|
|
|
|
/* If the input focus is PointerRootWin, send the event to where
|
|
* the pointer is if possible, then perhaps propogate up to root. */
|
|
if (inputFocus == PointerRootWin)
|
|
inputFocus = GetCurrentRootWindow();
|
|
|
|
if (IsParent(inputFocus, spriteWin)) {
|
|
effectiveFocus = inputFocus;
|
|
pWin = spriteWin;
|
|
} else
|
|
effectiveFocus = pWin = inputFocus;
|
|
} else
|
|
dixLookupWindow(&pWin, dest, client, DixSendAccess);
|
|
if (!pWin)
|
|
return BadWindow;
|
|
if ((propagate != xFalse) && (propagate != xTrue)) {
|
|
client->errorValue = propagate;
|
|
return BadValue;
|
|
}
|
|
ev->u.u.type |= 0x80;
|
|
if (propagate) {
|
|
for (; pWin; pWin = pWin->parent) {
|
|
if (DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id))
|
|
return Success;
|
|
if (pWin == effectiveFocus)
|
|
return Success;
|
|
if (wOtherInputMasks(pWin))
|
|
mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
|
|
if (!mask)
|
|
break;
|
|
}
|
|
} else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
|
|
(void)(DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id));
|
|
return Success;
|
|
}
|
|
|
|
int
|
|
SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
|
|
{
|
|
int i;
|
|
ButtonClassPtr b = dev->button;
|
|
|
|
if (b == NULL)
|
|
return BadMatch;
|
|
|
|
if (nElts != b->numButtons) {
|
|
client->errorValue = nElts;
|
|
return BadValue;
|
|
}
|
|
if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
|
|
return BadValue;
|
|
for (i = 0; i < nElts; i++)
|
|
if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
|
|
return MappingBusy;
|
|
for (i = 0; i < nElts; i++)
|
|
b->map[i + 1] = map[i];
|
|
return Success;
|
|
}
|
|
|
|
int
|
|
SetModifierMapping(ClientPtr client, DeviceIntPtr dev, int len, int rlen,
|
|
int numKeyPerModifier, KeyCode * inputMap, KeyClassPtr * k)
|
|
{
|
|
KeyCode *map = NULL;
|
|
int inputMapLen;
|
|
int i;
|
|
|
|
*k = dev->key;
|
|
if (*k == NULL)
|
|
return BadMatch;
|
|
if (len != ((numKeyPerModifier << 1) + rlen))
|
|
return BadLength;
|
|
|
|
inputMapLen = 8 * numKeyPerModifier;
|
|
|
|
/*
|
|
* Now enforce the restriction that "all of the non-zero keycodes must be
|
|
* in the range specified by min-keycode and max-keycode in the
|
|
* connection setup (else a Value error)"
|
|
*/
|
|
i = inputMapLen;
|
|
while (i--) {
|
|
if (inputMap[i]
|
|
&& (inputMap[i] < (*k)->curKeySyms.minKeyCode
|
|
|| inputMap[i] > (*k)->curKeySyms.maxKeyCode)) {
|
|
client->errorValue = inputMap[i];
|
|
return -1; /* BadValue collides with MappingFailed */
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Now enforce the restriction that none of the old or new
|
|
* modifier keys may be down while we change the mapping, and
|
|
* that the DDX layer likes the choice.
|
|
*/
|
|
if (!AllModifierKeysAreUp(dev, (*k)->modifierKeyMap,
|
|
(int)(*k)->maxKeysPerModifier, inputMap,
|
|
(int)numKeyPerModifier)
|
|
|| !AllModifierKeysAreUp(dev, inputMap, (int)numKeyPerModifier,
|
|
(*k)->modifierKeyMap,
|
|
(int)(*k)->maxKeysPerModifier)) {
|
|
return MappingBusy;
|
|
} else {
|
|
for (i = 0; i < inputMapLen; i++) {
|
|
if (inputMap[i] && !LegalModifier(inputMap[i], dev)) {
|
|
return MappingFailed;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Now build the keyboard's modifier bitmap from the
|
|
* list of keycodes.
|
|
*/
|
|
if (inputMapLen) {
|
|
map = (KeyCode *) xalloc(inputMapLen);
|
|
if (!map)
|
|
return BadAlloc;
|
|
}
|
|
if ((*k)->modifierKeyMap)
|
|
xfree((*k)->modifierKeyMap);
|
|
if (inputMapLen) {
|
|
(*k)->modifierKeyMap = map;
|
|
memmove((char *)(*k)->modifierKeyMap, (char *)inputMap, inputMapLen);
|
|
} else
|
|
(*k)->modifierKeyMap = NULL;
|
|
|
|
(*k)->maxKeysPerModifier = numKeyPerModifier;
|
|
for (i = 0; i < MAP_LENGTH; i++)
|
|
(*k)->modifierMap[i] = 0;
|
|
for (i = 0; i < inputMapLen; i++)
|
|
if (inputMap[i]) {
|
|
(*k)->modifierMap[inputMap[i]]
|
|
|= (1 << (i / (*k)->maxKeysPerModifier));
|
|
}
|
|
|
|
return (MappingSuccess);
|
|
}
|
|
|
|
void
|
|
SendDeviceMappingNotify(ClientPtr client, CARD8 request,
|
|
KeyCode firstKeyCode, CARD8 count, DeviceIntPtr dev)
|
|
{
|
|
xEvent event;
|
|
deviceMappingNotify *ev = (deviceMappingNotify *) & event;
|
|
|
|
ev->type = DeviceMappingNotify;
|
|
ev->request = request;
|
|
ev->deviceid = dev->id;
|
|
ev->time = currentTime.milliseconds;
|
|
if (request == MappingKeyboard) {
|
|
ev->firstKeyCode = firstKeyCode;
|
|
ev->count = count;
|
|
}
|
|
|
|
#ifdef XKB
|
|
if (request == MappingKeyboard || request == MappingModifier)
|
|
XkbApplyMappingChange(dev, request, firstKeyCode, count, client);
|
|
#endif
|
|
|
|
SendEventToAllWindows(dev, DeviceMappingNotifyMask, (xEvent *) ev, 1);
|
|
}
|
|
|
|
int
|
|
ChangeKeyMapping(ClientPtr client,
|
|
DeviceIntPtr dev,
|
|
unsigned len,
|
|
int type,
|
|
KeyCode firstKeyCode,
|
|
CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
|
|
{
|
|
KeySymsRec keysyms;
|
|
KeyClassPtr k = dev->key;
|
|
|
|
if (k == NULL)
|
|
return (BadMatch);
|
|
|
|
if (len != (keyCodes * keySymsPerKeyCode))
|
|
return BadLength;
|
|
|
|
if ((firstKeyCode < k->curKeySyms.minKeyCode) ||
|
|
(firstKeyCode + keyCodes - 1 > k->curKeySyms.maxKeyCode)) {
|
|
client->errorValue = firstKeyCode;
|
|
return BadValue;
|
|
}
|
|
if (keySymsPerKeyCode == 0) {
|
|
client->errorValue = 0;
|
|
return BadValue;
|
|
}
|
|
keysyms.minKeyCode = firstKeyCode;
|
|
keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
|
|
keysyms.mapWidth = keySymsPerKeyCode;
|
|
keysyms.map = map;
|
|
if (!SetKeySymsMap(&k->curKeySyms, &keysyms))
|
|
return BadAlloc;
|
|
SendDeviceMappingNotify(client, MappingKeyboard, firstKeyCode, keyCodes, dev);
|
|
return client->noClientException;
|
|
}
|
|
|
|
static void
|
|
DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
|
|
{
|
|
WindowPtr parent;
|
|
|
|
/* Deactivate any grabs performed on this window, before making
|
|
* any input focus changes.
|
|
* Deactivating a device grab should cause focus events. */
|
|
|
|
if (dev->grab && (dev->grab->window == pWin))
|
|
(*dev->DeactivateGrab) (dev);
|
|
|
|
/* If the focus window is a root window (ie. has no parent)
|
|
* then don't delete the focus from it. */
|
|
|
|
if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
|
|
int focusEventMode = NotifyNormal;
|
|
|
|
/* If a grab is in progress, then alter the mode of focus events. */
|
|
|
|
if (dev->grab)
|
|
focusEventMode = NotifyWhileGrabbed;
|
|
|
|
switch (dev->focus->revert) {
|
|
case RevertToNone:
|
|
DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
|
|
dev->focus->win = NoneWin;
|
|
dev->focus->traceGood = 0;
|
|
break;
|
|
case RevertToParent:
|
|
parent = pWin;
|
|
do {
|
|
parent = parent->parent;
|
|
dev->focus->traceGood--;
|
|
}
|
|
while (!parent->realized);
|
|
DoFocusEvents(dev, pWin, parent, focusEventMode);
|
|
dev->focus->win = parent;
|
|
dev->focus->revert = RevertToNone;
|
|
break;
|
|
case RevertToPointerRoot:
|
|
DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
|
|
dev->focus->win = PointerRootWin;
|
|
dev->focus->traceGood = 0;
|
|
break;
|
|
case RevertToFollowKeyboard:
|
|
if (inputInfo.keyboard->focus->win) {
|
|
DoFocusEvents(dev, pWin, inputInfo.keyboard->focus->win,
|
|
focusEventMode);
|
|
dev->focus->win = FollowKeyboardWin;
|
|
dev->focus->traceGood = 0;
|
|
} else {
|
|
DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
|
|
dev->focus->win = NoneWin;
|
|
dev->focus->traceGood = 0;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dev->valuator)
|
|
if (dev->valuator->motionHintWindow == pWin)
|
|
dev->valuator->motionHintWindow = NullWindow;
|
|
}
|
|
|
|
void
|
|
DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
|
|
{
|
|
int i;
|
|
DeviceIntPtr dev;
|
|
InputClientsPtr ic;
|
|
struct _OtherInputMasks *inputMasks;
|
|
|
|
for (dev = inputInfo.devices; dev; dev = dev->next) {
|
|
if (dev == inputInfo.pointer || dev == inputInfo.keyboard)
|
|
continue;
|
|
DeleteDeviceFromAnyExtEvents(pWin, dev);
|
|
}
|
|
|
|
for (dev = inputInfo.off_devices; dev; dev = dev->next)
|
|
DeleteDeviceFromAnyExtEvents(pWin, dev);
|
|
|
|
if (freeResources)
|
|
while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
|
|
ic = inputMasks->inputClients;
|
|
for (i = 0; i < EMASKSIZE; i++)
|
|
inputMasks->dontPropagateMask[i] = 0;
|
|
FreeResource(ic->resource, RT_NONE);
|
|
}
|
|
}
|
|
|
|
int
|
|
MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
|
|
{
|
|
DeviceIntPtr dev;
|
|
|
|
dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
|
|
DixReadAccess);
|
|
if (!dev)
|
|
return 0;
|
|
|
|
if (pEvents->type == DeviceMotionNotify) {
|
|
if (mask & DevicePointerMotionHintMask) {
|
|
if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
|
|
return 1; /* don't send, but pretend we did */
|
|
}
|
|
pEvents->detail = NotifyHint;
|
|
} else {
|
|
pEvents->detail = NotifyNormal;
|
|
}
|
|
}
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
|
|
deviceKeyButtonPointer * xE, GrabPtr grab,
|
|
ClientPtr client, Mask deliveryMask)
|
|
{
|
|
DeviceIntPtr dev;
|
|
|
|
dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
|
|
DixReadAccess);
|
|
if (!dev)
|
|
return;
|
|
|
|
if (type == DeviceMotionNotify)
|
|
dev->valuator->motionHintWindow = pWin;
|
|
else if ((type == DeviceButtonPress) && (!grab) &&
|
|
(deliveryMask & DeviceButtonGrabMask)) {
|
|
GrabRec tempGrab;
|
|
|
|
tempGrab.device = dev;
|
|
tempGrab.resource = client->clientAsMask;
|
|
tempGrab.window = pWin;
|
|
tempGrab.ownerEvents =
|
|
(deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
|
|
tempGrab.eventMask = deliveryMask;
|
|
tempGrab.keyboardMode = GrabModeAsync;
|
|
tempGrab.pointerMode = GrabModeAsync;
|
|
tempGrab.confineTo = NullWindow;
|
|
tempGrab.cursor = NullCursor;
|
|
(*dev->ActivateGrab) (dev, &tempGrab, currentTime, TRUE);
|
|
}
|
|
}
|
|
|
|
static Mask
|
|
DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
|
|
{
|
|
InputClientsPtr other;
|
|
|
|
if (!wOtherInputMasks(pWin))
|
|
return 0;
|
|
for (other = wOtherInputMasks(pWin)->inputClients; other;
|
|
other = other->next) {
|
|
if (SameClient(other, client))
|
|
return other->mask[dev->id];
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
|
|
{
|
|
WindowPtr pWin;
|
|
GrabPtr grab = dev->grab;
|
|
|
|
pWin = dev->valuator->motionHintWindow;
|
|
|
|
if ((grab && SameClient(grab, client) &&
|
|
((grab->eventMask & DevicePointerMotionHintMask) ||
|
|
(grab->ownerEvents &&
|
|
(DeviceEventMaskForClient(dev, pWin, client) &
|
|
DevicePointerMotionHintMask)))) ||
|
|
(!grab &&
|
|
(DeviceEventMaskForClient(dev, pWin, client) &
|
|
DevicePointerMotionHintMask)))
|
|
dev->valuator->motionHintWindow = NullWindow;
|
|
}
|
|
|
|
int
|
|
DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
|
|
int maskndx)
|
|
{
|
|
struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
|
|
|
|
if (mask & ~PropagateMask[maskndx]) {
|
|
client->errorValue = mask;
|
|
return BadValue;
|
|
}
|
|
|
|
if (mask == 0) {
|
|
if (inputMasks)
|
|
inputMasks->dontPropagateMask[maskndx] = mask;
|
|
} else {
|
|
if (!inputMasks)
|
|
AddExtensionClient(pWin, client, 0, 0);
|
|
inputMasks = wOtherInputMasks(pWin);
|
|
inputMasks->dontPropagateMask[maskndx] = mask;
|
|
}
|
|
RecalculateDeviceDeliverableEvents(pWin);
|
|
if (ShouldFreeInputMasks(pWin, FALSE))
|
|
FreeResource(inputMasks->inputClients->resource, RT_NONE);
|
|
return Success;
|
|
}
|
|
|
|
static Bool
|
|
ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
|
|
{
|
|
int i;
|
|
Mask allInputEventMasks = 0;
|
|
struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
|
|
|
|
for (i = 0; i < EMASKSIZE; i++)
|
|
allInputEventMasks |= inputMasks->dontPropagateMask[i];
|
|
if (!ignoreSelectedEvents)
|
|
for (i = 0; i < EMASKSIZE; i++)
|
|
allInputEventMasks |= inputMasks->inputEvents[i];
|
|
if (allInputEventMasks == 0)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Walk through the window tree, finding all clients that want to know
|
|
* about the Event.
|
|
*
|
|
*/
|
|
|
|
static void
|
|
FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
|
|
xEvent * ev, int count)
|
|
{
|
|
WindowPtr p2;
|
|
|
|
while (p1) {
|
|
p2 = p1->firstChild;
|
|
(void)DeliverEventsToWindow(p1, ev, count, mask, NullGrab, dev->id);
|
|
FindInterestedChildren(dev, p2, mask, ev, count);
|
|
p1 = p1->nextSib;
|
|
}
|
|
}
|
|
|
|
/***********************************************************************
|
|
*
|
|
* Send an event to interested clients in all windows on all screens.
|
|
*
|
|
*/
|
|
|
|
void
|
|
SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
|
|
{
|
|
int i;
|
|
WindowPtr pWin, p1;
|
|
|
|
for (i = 0; i < screenInfo.numScreens; i++) {
|
|
pWin = WindowTable[i];
|
|
if (!pWin)
|
|
continue;
|
|
(void)DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, dev->id);
|
|
p1 = pWin->firstChild;
|
|
FindInterestedChildren(dev, p1, mask, ev, count);
|
|
}
|
|
}
|