#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include "inputstr.h"
#include <X11/X.h>
#include <X11/Xproto.h>
#include <X11/extensions/XI.h>
#include <X11/extensions/XIproto.h>
#include <X11/extensions/XI2proto.h>
#include <X11/extensions/geproto.h>
#include "windowstr.h"
#include "miscstruct.h"
#include "region.h"
#include "exevents.h"
#include "extnsionst.h"
#include "exglobals.h"
#include "dixevents.h"
#include "dixgrabs.h"
#include "scrnintstr.h"
#include "listdev.h"
#include "xace.h"
#include "xiquerydevice.h"
#include "eventconvert.h"
#include "eventstr.h"
#include <X11/extensions/XKBproto.h>
#include "xkbsrv.h"
#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 )
Bool ShouldFreeInputMasks(WindowPtr ,
Bool
);
static Bool MakeInputMasks(WindowPtr
);
int
XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
{
DeviceIntPtr current_ptr = PickPointer(client);
DeviceIntPtr current_kbd = GetPairedDevice(current_ptr);
if (dev == current_kbd || dev == current_ptr)
return 1;
return 0;
}
Bool
IsPointerEvent(InternalEvent* event)
{
switch(event->any.type)
{
case ET_ButtonPress:
case ET_ButtonRelease:
case ET_Motion:
return TRUE;
default:
break;
}
return FALSE;
}
DeviceIntPtr
XIGetDevice(xEvent* xE)
{
DeviceIntPtr pDev = NULL;
if (xE->u.u.type == DeviceButtonPress ||
xE->u.u.type == DeviceButtonRelease ||
xE->u.u.type == DeviceMotionNotify ||
xE->u.u.type == ProximityIn ||
xE->u.u.type == ProximityOut ||
xE->u.u.type == DevicePropertyNotify)
{
int rc;
int id;
id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
if (rc != Success)
ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
}
return pDev;
}
void
CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
{
KeyClassPtr mk = master->key;
if (device == master)
return;
mk->sourceid = device->id;
if (!XkbCopyDeviceKeymap(master, device))
FatalError("Couldn't pivot keymap from device to core!\n");
}
static void
DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
{
ClassesPtr classes;
if (from->intfeed)
{
IntegerFeedbackPtr *i, it;
if (!to->intfeed)
{
classes = to->unused_classes;
to->intfeed = classes->intfeed;
classes->intfeed = NULL;
}
i = &to->intfeed;
for (it = from->intfeed; it; it = it->next)
{
if (!(*i))
{
*i = calloc(1, sizeof(IntegerFeedbackClassRec));
if (!(*i))
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*i)->CtrlProc = it->CtrlProc;
(*i)->ctrl = it->ctrl;
i = &(*i)->next;
}
} else if (to->intfeed && !from->intfeed)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->intfeed = to->intfeed;
to->intfeed = NULL;
}
if (from->stringfeed)
{
StringFeedbackPtr *s, it;
if (!to->stringfeed)
{
classes = to->unused_classes;
to->stringfeed = classes->stringfeed;
classes->stringfeed = NULL;
}
s = &to->stringfeed;
for (it = from->stringfeed; it; it = it->next)
{
if (!(*s))
{
*s = calloc(1, sizeof(StringFeedbackClassRec));
if (!(*s))
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*s)->CtrlProc = it->CtrlProc;
(*s)->ctrl = it->ctrl;
s = &(*s)->next;
}
} else if (to->stringfeed && !from->stringfeed)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->stringfeed = to->stringfeed;
to->stringfeed = NULL;
}
if (from->bell)
{
BellFeedbackPtr *b, it;
if (!to->bell)
{
classes = to->unused_classes;
to->bell = classes->bell;
classes->bell = NULL;
}
b = &to->bell;
for (it = from->bell; it; it = it->next)
{
if (!(*b))
{
*b = calloc(1, sizeof(BellFeedbackClassRec));
if (!(*b))
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*b)->BellProc = it->BellProc;
(*b)->CtrlProc = it->CtrlProc;
(*b)->ctrl = it->ctrl;
b = &(*b)->next;
}
} else if (to->bell && !from->bell)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->bell = to->bell;
to->bell = NULL;
}
if (from->leds)
{
LedFeedbackPtr *l, it;
if (!to->leds)
{
classes = to->unused_classes;
to->leds = classes->leds;
classes->leds = NULL;
}
l = &to->leds;
for (it = from->leds; it; it = it->next)
{
if (!(*l))
{
*l = calloc(1, sizeof(LedFeedbackClassRec));
if (!(*l))
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*l)->CtrlProc = it->CtrlProc;
(*l)->ctrl = it->ctrl;
if ((*l)->xkb_sli)
XkbFreeSrvLedInfo((*l)->xkb_sli);
(*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
l = &(*l)->next;
}
} else if (to->leds && !from->leds)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->leds = to->leds;
to->leds = NULL;
}
}
static void
DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
{
ClassesPtr classes;
if (from->kbdfeed)
{
KbdFeedbackPtr *k, it;
if (!to->kbdfeed)
{
classes = to->unused_classes;
to->kbdfeed = classes->kbdfeed;
if (!to->kbdfeed)
InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
classes->kbdfeed = NULL;
}
k = &to->kbdfeed;
for(it = from->kbdfeed; it; it = it->next)
{
if (!(*k))
{
*k = calloc(1, sizeof(KbdFeedbackClassRec));
if (!*k)
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*k)->BellProc = it->BellProc;
(*k)->CtrlProc = it->CtrlProc;
(*k)->ctrl = it->ctrl;
if ((*k)->xkb_sli)
XkbFreeSrvLedInfo((*k)->xkb_sli);
(*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
k = &(*k)->next;
}
} else if (to->kbdfeed && !from->kbdfeed)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->kbdfeed = to->kbdfeed;
to->kbdfeed = NULL;
}
if (from->key)
{
if (!to->key)
{
classes = to->unused_classes;
to->key = classes->key;
if (!to->key)
InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
else
classes->key = NULL;
}
CopyKeyClass(from, to);
} else if (to->key && !from->key)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->key = to->key;
to->key = NULL;
}
if (to->kbdfeed)
{
KbdFeedbackPtr k;
for (k = to->kbdfeed; k; k = k->next)
{
if (!k->xkb_sli)
continue;
if (k->xkb_sli->flags & XkbSLI_IsDefault)
{
k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
}
}
}
if (from->focus)
{
if (!to->focus)
{
WindowPtr *oldTrace;
classes = to->unused_classes;
to->focus = classes->focus;
if (!to->focus)
{
to->focus = calloc(1, sizeof(FocusClassRec));
if (!to->focus)
FatalError("[Xi] no memory for class shift.\n");
} else
classes->focus = NULL;
oldTrace = to->focus->trace;
memcpy(to->focus, from->focus, sizeof(FocusClassRec));
to->focus->trace = realloc(oldTrace,
to->focus->traceSize * sizeof(WindowPtr));
if (!to->focus->trace && to->focus->traceSize)
FatalError("[Xi] no memory for trace.\n");
memcpy(to->focus->trace, from->focus->trace,
from->focus->traceSize * sizeof(WindowPtr));
to->focus->sourceid = from->id;
}
} else if (to->focus)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->focus = to->focus;
to->focus = NULL;
}
}
static void
DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
{
ClassesPtr classes;
if (from->ptrfeed)
{
PtrFeedbackPtr *p, it;
if (!to->ptrfeed)
{
classes = to->unused_classes;
to->ptrfeed = classes->ptrfeed;
classes->ptrfeed = NULL;
}
p = &to->ptrfeed;
for (it = from->ptrfeed; it; it = it->next)
{
if (!(*p))
{
*p = calloc(1, sizeof(PtrFeedbackClassRec));
if (!*p)
{
ErrorF("[Xi] Cannot alloc memory for class copy.");
return;
}
}
(*p)->CtrlProc = it->CtrlProc;
(*p)->ctrl = it->ctrl;
p = &(*p)->next;
}
} else if (to->ptrfeed && !from->ptrfeed)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->ptrfeed = to->ptrfeed;
to->ptrfeed = NULL;
}
if (from->valuator)
{
ValuatorClassPtr v;
if (!to->valuator)
{
classes = to->unused_classes;
to->valuator = classes->valuator;
if (to->valuator)
classes->valuator = NULL;
}
v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
if (!v)
FatalError("[Xi] no memory for class shift.\n");
to->valuator = v;
memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
v->sourceid = from->id;
} else if (to->valuator && !from->valuator)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->valuator = to->valuator;
to->valuator = NULL;
}
if (from->button)
{
if (!to->button)
{
classes = to->unused_classes;
to->button = classes->button;
if (!to->button)
{
to->button = calloc(1, sizeof(ButtonClassRec));
if (!to->button)
FatalError("[Xi] no memory for class shift.\n");
} else
classes->button = NULL;
}
if (from->button->xkb_acts)
{
if (!to->button->xkb_acts)
{
to->button->xkb_acts = calloc(1, sizeof(XkbAction));
if (!to->button->xkb_acts)
FatalError("[Xi] not enough memory for xkb_acts.\n");
}
memcpy(to->button->xkb_acts, from->button->xkb_acts,
sizeof(XkbAction));
} else
free(to->button->xkb_acts);
memcpy(to->button->labels, from->button->labels,
from->button->numButtons * sizeof(Atom));
to->button->sourceid = from->id;
} else if (to->button && !from->button)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->button = to->button;
to->button = NULL;
}
if (from->proximity)
{
if (!to->proximity)
{
classes = to->unused_classes;
to->proximity = classes->proximity;
if (!to->proximity)
{
to->proximity = calloc(1, sizeof(ProximityClassRec));
if (!to->proximity)
FatalError("[Xi] no memory for class shift.\n");
} else
classes->proximity = NULL;
}
memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
to->proximity->sourceid = from->id;
} else if (to->proximity)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->proximity = to->proximity;
to->proximity = NULL;
}
if (from->absolute)
{
if (!to->absolute)
{
classes = to->unused_classes;
to->absolute = classes->absolute;
if (!to->absolute)
{
to->absolute = calloc(1, sizeof(AbsoluteClassRec));
if (!to->absolute)
FatalError("[Xi] no memory for class shift.\n");
} else
classes->absolute = NULL;
}
memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec));
to->absolute->sourceid = from->id;
} else if (to->absolute)
{
ClassesPtr classes;
classes = to->unused_classes;
classes->absolute = to->absolute;
to->absolute = NULL;
}
}
void
DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
{
DeepCopyFeedbackClasses(from, to);
if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
DeepCopyKeyboardClasses(from, to);
if ((dce->flags & DEVCHANGE_POINTER_EVENT))
DeepCopyPointerClasses(from, to);
}
void
XISendDeviceChangedEvent(DeviceIntPtr device, DeviceIntPtr master, DeviceChangedEvent *dce)
{
xXIDeviceChangedEvent *dcce;
int rc;
rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
if (rc != Success)
{
ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
return;
}
SendEventToAllWindows(master, XI_DeviceChangedMask, (xEvent*)dcce, 1);
free(dcce);
}
static void
ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
{
DeviceIntPtr slave;
int rc;
if (!IsMaster(device))
return;
rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
if (rc != Success)
return;
if (!slave->u.master)
return;
if (slave->u.master->id != dce->masterid)
return;
device->public.devicePrivate = slave->public.devicePrivate;
DeepCopyDeviceClasses(slave, device, dce);
XISendDeviceChangedEvent(slave, device, dce);
}
#define DEFAULT 0
#define DONT_PROCESS 1
int
UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
{
int i;
int key = 0,
bit = 0,
last_valuator;
KeyClassPtr k = NULL;
ButtonClassPtr b = NULL;
ValuatorClassPtr v = NULL;
switch(event->type)
{
case ET_DeviceChanged:
ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
return DONT_PROCESS;
case ET_Motion:
case ET_ButtonPress:
case ET_ButtonRelease:
case ET_KeyPress:
case ET_KeyRelease:
case ET_ProximityIn:
case ET_ProximityOut:
break;
default:
return DEFAULT;
}
k = device->key;
v = device->valuator;
b = device->button;
key = event->detail.key;
bit = 1 << (key & 7);
last_valuator = -1;
for (i = 0; i < MAX_VALUATORS; i++)
{
if (BitIsOn(&event->valuators.mask, i))
{
if (!v)
{
ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
"Ignoring event.\n", device->name);
return DONT_PROCESS;
} else if (v->numAxes < i)
{
ErrorF("[Xi] Too many valuators reported for device '%s'. "
"Ignoring event.\n", device->name);
return DONT_PROCESS;
}
last_valuator = i;
}
}
for (i = 0; i <= last_valuator && i < v->numAxes; i++)
{
if (BitIsOn(&event->valuators.mask, i))
{
v->axisVal[i] = event->valuators.data[i];
v->axisVal[i] += (event->valuators.data_frac[i] * 1.0f / (1 << 16) / (1 << 16));
}
}
if (event->type == ET_KeyPress) {
if (!k)
return DONT_PROCESS;
if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
return DONT_PROCESS;
if (device->valuator)
device->valuator->motionHintWindow = NullWindow;
set_key_down(device, key, KEY_PROCESSED);
} else if (event->type == ET_KeyRelease) {
if (!k)
return DONT_PROCESS;
if (!key_is_down(device, key, KEY_PROCESSED))
return DONT_PROCESS;
if (device->valuator)
device->valuator->motionHintWindow = NullWindow;
set_key_up(device, key, KEY_PROCESSED);
} else if (event->type == ET_ButtonPress) {
Mask mask;
if (!b)
return DONT_PROCESS;
if (button_is_down(device, key, BUTTON_PROCESSED))
return DONT_PROCESS;
set_button_down(device, key, BUTTON_PROCESSED);
if (device->valuator)
device->valuator->motionHintWindow = NullWindow;
if (!b->map[key])
return DONT_PROCESS;
b->buttonsDown++;
b->motionMask = DeviceButtonMotionMask;
if (b->map[key] <= 5)
b->state |= (Button1Mask >> 1) << b->map[key];
mask = DevicePointerMotionMask | b->state | b->motionMask;
SetMaskForEvent(device->id, mask, DeviceMotionNotify);
mask = PointerMotionMask | b->state | b->motionMask;
SetMaskForEvent(device->id, mask, MotionNotify);
} else if (event->type == ET_ButtonRelease) {
Mask mask;
if (!b)
return DONT_PROCESS;
if (!button_is_down(device, key, BUTTON_PROCESSED))
return DONT_PROCESS;
if (IsMaster(device)) {
DeviceIntPtr sd;
for (sd = inputInfo.devices; sd; sd = sd->next) {
if (IsMaster(sd) || sd->u.master != device)
continue;
if (!sd->button)
continue;
for (i = 1; i <= sd->button->numButtons; i++)
if (sd->button->map[i] == key &&
button_is_down(sd, i, BUTTON_PROCESSED))
return DONT_PROCESS;
}
}
set_button_up(device, key, BUTTON_PROCESSED);
if (device->valuator)
device->valuator->motionHintWindow = NullWindow;
if (!b->map[key])
return DONT_PROCESS;
if (b->buttonsDown >= 1 && !--b->buttonsDown)
b->motionMask = 0;
if (b->map[key] <= 5)
b->state &= ~((Button1Mask >> 1) << b->map[key]);
mask = DevicePointerMotionMask | b->state | b->motionMask;
SetMaskForEvent(device->id, mask, DeviceMotionNotify);
mask = PointerMotionMask | b->state | b->motionMask;
SetMaskForEvent(device->id, mask, MotionNotify);
} else if (event->type == ET_ProximityIn)
device->proximity->in_proximity = TRUE;
else if (event->type == ET_ProximityOut)
device->proximity->in_proximity = FALSE;
return DEFAULT;
}
static void
ProcessRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
{
GrabPtr grab = device->deviceGrab.grab;
if (grab)
DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
else {
xEvent *xi;
int i;
i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
if (i != Success)
{
ErrorF("[Xi] %s: XI2 conversion failed in ProcessRawEvent (%d)\n",
device->name, i);
return;
}
for (i = 0; i < screenInfo.numScreens; i++)
DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
GetEventFilter(device, xi), NULL);
free(xi);
}
}
void
ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
{
GrabPtr grab;
Bool deactivateDeviceGrab = FALSE;
int key = 0, rootX, rootY;
ButtonClassPtr b;
KeyClassPtr k;
ValuatorClassPtr v;
int ret = 0;
int state, i;
DeviceIntPtr mouse = NULL, kbd = NULL;
DeviceEvent *event = &ev->device_event;
CHECKEVENT(ev);
if (ev->any.type == ET_RawKeyPress ||
ev->any.type == ET_RawKeyRelease ||
ev->any.type == ET_RawButtonPress ||
ev->any.type == ET_RawButtonRelease ||
ev->any.type == ET_RawMotion)
{
ProcessRawEvent(&ev->raw_event, device);
return;
}
if (IsPointerDevice(device))
{
kbd = GetPairedDevice(device);
mouse = device;
if (!kbd->key)
kbd = NULL;
} else
{
mouse = GetPairedDevice(device);
kbd = device;
if (!mouse->valuator || !mouse->button)
mouse = NULL;
}
state = (kbd && kbd->key) ? XkbStateFieldFromRec(&kbd->key->xkbInfo->state) : 0;
state |= (mouse && mouse->button) ? (mouse->button->state) : 0;
for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
if (BitIsOn(mouse->button->down, i))
SetBit(event->buttons, i);
if (kbd && kbd->key)
{
XkbStatePtr state;
if (event->type == ET_KeyPress || event->type == ET_KeyRelease)
state = &kbd->key->xkbInfo->prev_state;
else
state = &kbd->key->xkbInfo->state;
event->mods.base = state->base_mods;
event->mods.latched = state->latched_mods;
event->mods.locked = state->locked_mods;
event->mods.effective = state->mods;
event->group.base = state->base_group;
event->group.latched = state->latched_group;
event->group.locked = state->locked_group;
event->group.effective = state->group;
}
ret = UpdateDeviceState(device, event);
if (ret == DONT_PROCESS)
return;
v = device->valuator;
b = device->button;
k = device->key;
if (IsMaster(device) || !device->u.master)
CheckMotion(event, device);
switch (event->type)
{
case ET_Motion:
case ET_ButtonPress:
case ET_ButtonRelease:
case ET_KeyPress:
case ET_KeyRelease:
case ET_ProximityIn:
case ET_ProximityOut:
GetSpritePosition(device, &rootX, &rootY);
event->root_x = rootX;
event->root_y = rootY;
NoticeEventTime((InternalEvent*)event);
event->corestate = state;
key = event->detail.key;
break;
default:
break;
}
if (DeviceEventCallback && !syncEvents.playingEvents) {
DeviceEventInfoRec eventinfo;
SpritePtr pSprite = device->spriteInfo->sprite;
if (ev->any.type == ET_Motion)
ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
eventinfo.device = device;
eventinfo.event = ev;
CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
}
grab = device->deviceGrab.grab;
switch(event->type)
{
case ET_KeyPress:
if (!grab && CheckDeviceGrabs(device, event, 0)) {
device->deviceGrab.activatingKey = key;
return;
}
break;
case ET_KeyRelease:
if (grab && device->deviceGrab.fromPassiveGrab &&
(key == device->deviceGrab.activatingKey) &&
(device->deviceGrab.grab->type == KeyPress ||
device->deviceGrab.grab->type == DeviceKeyPress ||
device->deviceGrab.grab->type == XI_KeyPress))
deactivateDeviceGrab = TRUE;
break;
case ET_ButtonPress:
event->detail.button = b->map[key];
if (!event->detail.button) {
event->detail.button = key;
return;
}
if (!grab && CheckDeviceGrabs(device, event, 0))
{
return;
}
break;
case ET_ButtonRelease:
event->detail.button = b->map[key];
if (!event->detail.button) {
event->detail.button = key;
return;
}
if (grab && !b->buttonsDown &&
device->deviceGrab.fromPassiveGrab &&
(device->deviceGrab.grab->type == ButtonPress ||
device->deviceGrab.grab->type == DeviceButtonPress ||
device->deviceGrab.grab->type == XI_ButtonPress))
deactivateDeviceGrab = TRUE;
default:
break;
}
if (grab)
DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
else if (device->focus && !IsPointerEvent((InternalEvent*)ev))
DeliverFocusedEvent(device, (InternalEvent*)event,
GetSpriteWindow(device));
else
DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
NullGrab, NullWindow, device);
if (deactivateDeviceGrab == TRUE)
(*device->deviceGrab.DeactivateGrab) (device);
event->detail.key = key;
}
int
InitProximityClassDeviceStruct(DeviceIntPtr dev)
{
ProximityClassPtr proxc;
proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
if (!proxc)
return FALSE;
proxc->sourceid = dev->id;
proxc->in_proximity = TRUE;
dev->proximity = proxc;
return TRUE;
}
void
InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
int resolution, int min_res, int max_res, int mode)
{
AxisInfoPtr ax;
if (!dev || !dev->valuator || minval > maxval)
return;
if (axnum >= dev->valuator->numAxes)
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;
ax->label = label;
ax->mode = mode;
if (mode & OutOfProximity)
dev->proximity->in_proximity = FALSE;
}
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;
memcpy((char*)ev->buttons, (char*)b->down, 4);
} else if (k) {
ev->classes_reported |= (1 << KeyClass);
ev->num_keys = k->xkbInfo->desc->max_key_code -
k->xkbInfo->desc->min_key_code;
memmove((char *)&ev->keys[0], (char *)k->down, 4);
}
if (v) {
int nval = v->numAxes - first;
ev->classes_reported |= (1 << ValuatorClass);
ev->classes_reported |= valuator_get_mode(dev, 0) << 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;
xXIFocusInEvent *xi2event;
DeviceIntPtr mouse;
int btlen, len, i;
mouse = (IsMaster(dev) || dev->u.master) ? GetMaster(dev, MASTER_POINTER) : dev;
btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
btlen = bytes_to_int32(btlen);
len = sizeof(xXIFocusInEvent) + btlen * 4;
xi2event = calloc(1, len);
xi2event->type = GenericEvent;
xi2event->extension = IReqCode;
xi2event->evtype = type;
xi2event->length = bytes_to_int32(len - sizeof(xEvent));
xi2event->buttons_len = btlen;
xi2event->detail = detail;
xi2event->time = currentTime.milliseconds;
xi2event->deviceid = dev->id;
xi2event->sourceid = dev->id;
xi2event->mode = mode;
xi2event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
xi2event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
if (BitIsOn(mouse->button->down, i))
SetBit(&xi2event[1], i);
if (dev->key)
{
xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
xi2event->group.effective_group = dev->key->xkbInfo->state.group;
}
FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
None, FALSE);
DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
free(xi2event);
event.deviceid = dev->id;
event.mode = mode;
event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
event.detail = detail;
event.window = pWin->drawable.id;
event.time = currentTime.milliseconds;
DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
DeviceFocusChangeMask, NullGrab);
if ((event.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->xkbInfo->desc->max_key_code -
k->xkbInfo->desc->min_key_code;
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 *) malloc(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;
memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
}
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;
}
}
DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount,
DeviceStateNotifyMask, NullGrab);
free(sev);
}
}
int
CheckGrabValues(ClientPtr client, GrabParameters* param)
{
if (param->grabtype != GRABTYPE_CORE &&
param->grabtype != GRABTYPE_XI &&
param->grabtype != GRABTYPE_XI2)
{
ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
return BadImplementation;
}
if ((param->this_device_mode != GrabModeSync) &&
(param->this_device_mode != GrabModeAsync)) {
client->errorValue = param->this_device_mode;
return BadValue;
}
if ((param->other_devices_mode != GrabModeSync) &&
(param->other_devices_mode != GrabModeAsync)) {
client->errorValue = param->other_devices_mode;
return BadValue;
}
if (param->grabtype != GRABTYPE_XI2 && (param->modifiers != AnyModifier) &&
(param->modifiers & ~AllModifiersMask)) {
client->errorValue = param->modifiers;
return BadValue;
}
if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
client->errorValue = param->ownerEvents;
return BadValue;
}
return Success;
}
int
GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
int button, GrabParameters *param, GrabType grabtype,
GrabMask *mask)
{
WindowPtr pWin, confineTo;
CursorPtr cursor;
GrabPtr grab;
int rc, type = -1;
Mask access_mode = DixGrabAccess;
rc = CheckGrabValues(client, param);
if (rc != Success)
return rc;
if (param->confineTo == None)
confineTo = NullWindow;
else {
rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
if (rc != Success)
return rc;
}
if (param->cursor == None)
cursor = NullCursor;
else {
rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
RT_CURSOR, client, DixUseAccess);
if (rc != Success)
{
client->errorValue = param->cursor;
return rc;
}
access_mode |= DixForceAccess;
}
if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
access_mode |= DixFreezeAccess;
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
if (rc != Success)
return rc;
rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
if (rc != Success)
return rc;
if (grabtype == GRABTYPE_XI)
type = DeviceButtonPress;
else if (grabtype == GRABTYPE_XI2)
type = XI_ButtonPress;
grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
mask, param, type, button, confineTo, cursor);
if (!grab)
return BadAlloc;
return AddPassiveGrabToList(client, grab);
}
int
GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
int key, GrabParameters *param, GrabType grabtype, GrabMask *mask)
{
WindowPtr pWin;
GrabPtr grab;
KeyClassPtr k = dev->key;
Mask access_mode = DixGrabAccess;
int rc, type = -1;
rc = CheckGrabValues(client, param);
if (rc != Success)
return rc;
if (k == NULL)
return BadMatch;
if (grabtype == GRABTYPE_XI)
{
if ((key > k->xkbInfo->desc->max_key_code ||
key < k->xkbInfo->desc->min_key_code)
&& (key != AnyKey)) {
client->errorValue = key;
return BadValue;
}
type = DeviceKeyPress;
} else if (grabtype == GRABTYPE_XI2)
type = XI_KeyPress;
rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
if (rc != Success)
return rc;
if (param->this_device_mode == GrabModeSync || param->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, modifier_device, pWin, grabtype,
mask, param, type, key, NULL, NULL);
if (!grab)
return BadAlloc;
return AddPassiveGrabToList(client, grab);
}
int
GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
GrabParameters *param, GrabMask *mask)
{
WindowPtr pWin;
CursorPtr cursor;
GrabPtr grab;
Mask access_mode = DixGrabAccess;
int rc;
rc = CheckGrabValues(client, param);
if (rc != Success)
return rc;
rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
if (rc != Success)
return rc;
if (param->cursor == None)
cursor = NullCursor;
else {
rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
RT_CURSOR, client, DixUseAccess);
if (rc != Success)
{
client->errorValue = param->cursor;
return rc;
}
access_mode |= DixForceAccess;
}
if (param->this_device_mode == GrabModeSync || param->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, dev, pWin, GRABTYPE_XI2,
mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
0, NULL, cursor);
if (!grab)
return BadAlloc;
return AddPassiveGrabToList(client, grab);
}
int
SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
Mask mask, Mask exclusivemasks)
{
int mskidx = dev->id;
int i, ret;
Mask check;
InputClientsPtr others;
check = (mask & exclusivemasks);
if (wOtherInputMasks(pWin)) {
if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {
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->deviceGrab.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 = calloc(1, sizeof(InputClients));
if (!others)
return BadAlloc;
if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
goto bail;
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))
goto bail;
return Success;
bail:
free(others);
return BadAlloc;
}
static Bool
MakeInputMasks(WindowPtr pWin)
{
struct _OtherInputMasks *imasks;
imasks = calloc(1, sizeof(struct _OtherInputMasks));
if (!imasks)
return FALSE;
pWin->optional->inputMasks = imasks;
return TRUE;
}
void
RecalculateDeviceDeliverableEvents(WindowPtr pWin)
{
InputClientsPtr others;
struct _OtherInputMasks *inputMasks;
WindowPtr pChild, tmp;
int i, j;
pChild = pWin;
while (1) {
if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
for (i = 0; i < EMASKSIZE; i++)
memset(inputMasks->xi2mask[i], 0, sizeof(inputMasks->xi2mask[i]));
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++)
for (j = 0; j < XI2MASKSIZE; j++)
inputMasks->xi2mask[i][j] |= others->xi2mask[i][j];
}
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;
free(other);
} else if (!(other->next)) {
if (ShouldFreeInputMasks(pWin, TRUE)) {
wOtherInputMasks(pWin)->inputClients = other->next;
free(wOtherInputMasks(pWin));
pWin->optional->inputMasks = (OtherInputMasks *) NULL;
CheckWindowOptionalNeed(pWin);
free(other);
} else {
other->resource = FakeClientID(0);
if (!AddResource(other->resource, RT_INPUTCLIENT,
(pointer) pWin))
return BadAlloc;
}
} else {
wOtherInputMasks(pWin)->inputClients = other->next;
free(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;
WindowPtr spriteWin = GetSpriteWindow(d);
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 (inputFocus == PointerRootWin)
inputFocus = GetCurrentRootWindow(d);
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(d, pWin, ev, count, mask, NullGrab))
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))
DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
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
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->xkbInfo->desc->min_key_code) ||
(firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
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;
XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
serverClient);
return Success;
}
static void
DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
{
WindowPtr parent;
if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
(*dev->deviceGrab.DeactivateGrab) (dev);
if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
int focusEventMode = NotifyNormal;
if (dev->deviceGrab.grab)
focusEventMode = NotifyWhileGrabbed;
switch (dev->focus->revert) {
case RevertToNone:
if (!ActivateFocusInGrab(dev, pWin, NoneWin))
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);
if (!ActivateFocusInGrab(dev, pWin, parent))
DoFocusEvents(dev, pWin, parent, focusEventMode);
dev->focus->win = parent;
dev->focus->revert = RevertToNone;
break;
case RevertToPointerRoot:
if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
dev->focus->win = PointerRootWin;
dev->focus->traceGood = 0;
break;
case RevertToFollowKeyboard:
{
DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
kbd = inputInfo.keyboard;
if (kbd->focus->win) {
if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
dev->focus->win = FollowKeyboardWin;
dev->focus->traceGood = 0;
} else {
if (!ActivateFocusInGrab(dev, pWin, NoneWin))
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) {
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;
}
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,
DixGrabAccess);
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;
tempGrab.next = NULL;
(*dev->deviceGrab.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->deviceGrab.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;
}
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;
}
static void
FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
xEvent * ev, int count)
{
WindowPtr p2;
while (p1) {
p2 = p1->firstChild;
DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
FindInterestedChildren(dev, p2, mask, ev, count);
p1 = p1->nextSib;
}
}
void
SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
{
int i;
WindowPtr pWin, p1;
for (i = 0; i < screenInfo.numScreens; i++) {
pWin = screenInfo.screens[i]->root;
if (!pWin)
continue;
DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
p1 = pWin->firstChild;
FindInterestedChildren(dev, p1, mask, ev, count);
}
}
int
XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
unsigned int len, unsigned char* mask)
{
OtherInputMasks *masks;
InputClientsPtr others = NULL;
masks = wOtherInputMasks(win);
if (masks)
{
for (others = wOtherInputMasks(win)->inputClients; others;
others = others->next) {
if (SameClient(others, client)) {
memset(others->xi2mask[dev->id], 0,
sizeof(others->xi2mask[dev->id]));
break;
}
}
}
len = min(len, sizeof(others->xi2mask[dev->id]));
if (len && !others)
{
if (AddExtensionClient(win, client, 0, 0) != Success)
return BadAlloc;
others= wOtherInputMasks(win)->inputClients;
}
if (others)
memset(others->xi2mask[dev->id], 0, sizeof(others->xi2mask[dev->id]));
if (len)
memcpy(others->xi2mask[dev->id], mask, len);
RecalculateDeviceDeliverableEvents(win);
return Success;
}