Merge whot@wombat:~/potoroo/xserver into mpx

This commit is contained in:
Peter Hutterer 2008-04-11 08:29:52 +09:30
commit 90f491cf8e
9 changed files with 204 additions and 180 deletions

View File

@ -272,10 +272,10 @@ ProcXChangeDeviceHierarchy(ClientPtr client)
goto unwind; goto unwind;
} }
if ((IsPointerDevice(newmaster) && if (!((IsPointerDevice(newmaster) &&
!IsPointerDevice(ptr)) || IsPointerDevice(ptr)) ||
(IsKeyboardDevice(newmaster) && (IsKeyboardDevice(newmaster) &&
!IsKeyboardDevice(ptr))) IsKeyboardDevice(ptr))))
{ {
rc = BadDevice; rc = BadDevice;
goto unwind; goto unwind;

View File

@ -104,6 +104,32 @@ RegisterOtherDevice(DeviceIntPtr device)
device->public.realInputProc = ProcessOtherEvent; device->public.realInputProc = ProcessOtherEvent;
} }
_X_EXPORT Bool
IsPointerEvent(xEvent* xE)
{
switch(xE->u.u.type)
{
case ButtonPress:
case ButtonRelease:
case MotionNotify:
case EnterNotify:
case LeaveNotify:
return TRUE;
default:
if (xE->u.u.type == DeviceButtonPress ||
xE->u.u.type == DeviceButtonRelease ||
xE->u.u.type == DeviceMotionNotify ||
xE->u.u.type == DeviceEnterNotify ||
xE->u.u.type == DeviceLeaveNotify ||
xE->u.u.type == ProximityIn ||
xE->u.u.type == ProximityOut)
{
return TRUE;
}
}
return FALSE;
}
/** /**
* Copy the device->key into master->key and send a mapping notify to the * Copy the device->key into master->key and send a mapping notify to the
* clients if appropriate. * clients if appropriate.
@ -459,11 +485,29 @@ DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to)
} }
ALLOC_COPY_CLASS_IF(focus, FocusClassRec); /* We can't just copy over the focus class. When an app sets the focus,
if (to->focus && !from->focus) * it'll do so on the master device. Copying the SDs focus means losing
* the focus.
* So we only copy the focus class if the device didn't have one,
* otherwise we leave it as it is.
*/
if (from->focus)
{ {
FreeDeviceClass(FocusClass, (pointer)&to->focus); if (!to->focus)
{
to->focus = xcalloc(1, sizeof(FocusClassRec));
if (!to->focus)
FatalError("[Xi] no memory for class shift.\n");
memcpy(to->focus->trace, from->focus->trace,
from->focus->traceSize * sizeof(WindowPtr));
}
} else if (to->focus)
{
/* properly freeing the class would also free the sprite trace, which
* is still in use by the SD. just xfree the struct. */
xfree(to->focus);
} }
ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec); ALLOC_COPY_CLASS_IF(proximity, ProximityClassRec);
if (to->proximity && !from->proximity) if (to->proximity && !from->proximity)
{ {
@ -730,11 +774,15 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
{ {
kbd = GetPairedDevice(device); kbd = GetPairedDevice(device);
mouse = device; mouse = device;
if (!kbd->key) /* can happen with floating SDs */
kbd = NULL;
} }
else else
{ {
mouse = GetPairedDevice(device); mouse = GetPairedDevice(device);
kbd = device; kbd = device;
if (!mouse->valuator || !mouse->button) /* may be float. SDs */
mouse = NULL;
} }
xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0; xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0;
xE->u.keyButtonPointer.state |= (mouse) ? (mouse->button->state) : 0; xE->u.keyButtonPointer.state |= (mouse) ? (mouse->button->state) : 0;
@ -808,7 +856,7 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count)
if (grab) if (grab)
DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count); DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count);
else if (device->focus) else if (device->focus && !IsPointerEvent(xE))
DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count); DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count);
else else
DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow, DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow,

View File

@ -88,8 +88,6 @@ SOFTWARE.
/* The client that is allowed to change pointer-keyboard pairings. */ /* The client that is allowed to change pointer-keyboard pairings. */
static ClientPtr pairingClient = NULL; static ClientPtr pairingClient = NULL;
DevPrivateKey MasterDevClassesPrivateKey = &MasterDevClassesPrivateKey;
DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey; DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey;
/** /**
@ -224,8 +222,7 @@ EnableDevice(DeviceIntPtr dev)
if (dev->spriteInfo->spriteOwner) if (dev->spriteInfo->spriteOwner)
{ {
InitializeSprite(dev, WindowTable[0]); InitializeSprite(dev, WindowTable[0]);
((FocusSemaphoresPtr)dixLookupPrivate(&(WindowTable[0])->devPrivates, ENTER_LEAVE_SEMAPHORE_SET(WindowTable[0], dev);
FocusPrivatesKey))->enterleave++;
} }
else if ((other = NextFreePointerDevice()) == NULL) else if ((other = NextFreePointerDevice()) == NULL)
{ {
@ -410,7 +407,6 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
XkbComponentNamesRec names; XkbComponentNamesRec names;
#endif #endif
ClassesPtr classes; ClassesPtr classes;
DeviceIntRec dummy;
switch (what) { switch (what) {
case DEVICE_INIT: case DEVICE_INIT:
@ -420,8 +416,6 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
return BadAlloc; return BadAlloc;
} }
dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, NULL);
keySyms.minKeyCode = 8; keySyms.minKeyCode = 8;
keySyms.maxKeyCode = 255; keySyms.maxKeyCode = 255;
keySyms.mapWidth = 4; keySyms.mapWidth = 4;
@ -460,53 +454,9 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what)
xfree(keySyms.map); xfree(keySyms.map);
xfree(modMap); xfree(modMap);
classes->key = pDev->key;
classes->valuator = pDev->valuator;
classes->button = pDev->button;
classes->focus = pDev->focus;
classes->proximity = pDev->proximity;
classes->absolute = pDev->absolute;
classes->kbdfeed = pDev->kbdfeed;
classes->ptrfeed = pDev->ptrfeed;
classes->intfeed = pDev->intfeed;
classes->stringfeed = pDev->stringfeed;
classes->bell = pDev->bell;
classes->leds = pDev->leds;
/* Each time we switch classes we free the MD's classes and copy the
* SD's classes into the MD. We mustn't lose the first set of classes
* though as we need it to restore them when the last SD disconnects.
*
* So we create a fake device, seem to copy from the fake to the real
* one, thus ending up with a copy of the original ones in our MD.
*
* If we don't do that, we're in SIGABRT territory (double-frees, etc)
*/
memcpy(&dummy, pDev, sizeof(DeviceIntRec));
/* Need to set them to NULL. Otherwise, Xkb does some weird stuff and
* the dev->key->xkbInfo->kbdProc starts calling itself. This can
* probably be fixed in a better way, but I don't know how. (whot) */
pDev->key = NULL;
pDev->valuator = NULL;
pDev->button = NULL;
pDev->focus = NULL;
pDev->proximity = NULL;
pDev->absolute = NULL;
pDev->kbdfeed = NULL;
pDev->ptrfeed = NULL;
pDev->intfeed = NULL;
pDev->stringfeed = NULL;
pDev->bell = NULL;
pDev->leds = NULL;
DeepCopyDeviceClasses(&dummy, pDev);
dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey,
classes);
break; break;
case DEVICE_CLOSE: case DEVICE_CLOSE:
dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL);
break; break;
default: default:
@ -527,16 +477,12 @@ CorePointerProc(DeviceIntPtr pDev, int what)
BYTE map[33]; BYTE map[33];
int i = 0; int i = 0;
ClassesPtr classes; ClassesPtr classes;
DeviceIntRec dummy;
switch (what) { switch (what) {
case DEVICE_INIT: case DEVICE_INIT:
if (!(classes = xcalloc(1, sizeof(ClassesRec)))) if (!(classes = xcalloc(1, sizeof(ClassesRec))))
return BadAlloc; return BadAlloc;
dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, NULL);
for (i = 1; i <= 32; i++) for (i = 1; i <= 32; i++)
map[i] = i; map[i] = i;
InitPointerDeviceStruct((DevicePtr)pDev, map, 32, InitPointerDeviceStruct((DevicePtr)pDev, map, 32,
@ -546,43 +492,9 @@ CorePointerProc(DeviceIntPtr pDev, int what)
pDev->lastx = pDev->valuator->axisVal[0]; pDev->lastx = pDev->valuator->axisVal[0];
pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
pDev->lasty = pDev->valuator->axisVal[1]; pDev->lasty = pDev->valuator->axisVal[1];
classes->key = pDev->key;
classes->valuator = pDev->valuator;
classes->button = pDev->button;
classes->focus = pDev->focus;
classes->proximity = pDev->proximity;
classes->absolute = pDev->absolute;
classes->kbdfeed = pDev->kbdfeed;
classes->ptrfeed = pDev->ptrfeed;
classes->intfeed = pDev->intfeed;
classes->stringfeed = pDev->stringfeed;
classes->bell = pDev->bell;
classes->leds = pDev->leds;
/* See comment in CoreKeyboardProc. */
memcpy(&dummy, pDev, sizeof(DeviceIntRec));
/* Need to set them to NULL for the VCK (see CoreKeyboardProc). Not
* sure if also necessary for the VCP, but it doesn't seem to hurt */
pDev->key = NULL;
pDev->valuator = NULL;
pDev->button = NULL;
pDev->focus = NULL;
pDev->proximity = NULL;
pDev->absolute = NULL;
pDev->kbdfeed = NULL;
pDev->ptrfeed = NULL;
pDev->intfeed = NULL;
pDev->stringfeed = NULL;
pDev->bell = NULL;
pDev->leds = NULL;
DeepCopyDeviceClasses(&dummy, pDev);
dixSetPrivate(&pDev->devPrivates, MasterDevClassesPrivateKey, classes);
break; break;
case DEVICE_CLOSE: case DEVICE_CLOSE:
dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL);
break; break;
default: default:
@ -858,13 +770,6 @@ CloseDevice(DeviceIntPtr dev)
xfree(dev->name); xfree(dev->name);
if (dev->isMaster)
{
classes = (ClassesPtr)dixLookupPrivate(&dev->devPrivates,
MasterDevClassesPrivateKey);
FreeAllDeviceClasses(classes);
}
classes = (ClassesPtr)&dev->key; classes = (ClassesPtr)&dev->key;
FreeAllDeviceClasses(classes); FreeAllDeviceClasses(classes);
@ -2506,7 +2411,7 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
return Success; return Success;
/* free the existing sprite. */ /* free the existing sprite. */
if (!dev->u.master && dev->spriteInfo->sprite) if (!dev->u.master && dev->spriteInfo->paired == dev)
xfree(dev->spriteInfo->sprite); xfree(dev->spriteInfo->sprite);
oldmaster = dev->u.master; oldmaster = dev->u.master;
@ -2515,15 +2420,22 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
/* If device is set to floating, we need to create a sprite for it, /* If device is set to floating, we need to create a sprite for it,
* otherwise things go bad. However, we don't want to render the cursor, * otherwise things go bad. However, we don't want to render the cursor,
* so we reset spriteOwner. * so we reset spriteOwner.
* Sprite has to be forced to NULL first, otherwise InitializeSprite won't
* alloc new memory but overwrite the previous one.
*/ */
if (!master) if (!master)
{ {
/* current root window */ WindowPtr currentRoot = dev->spriteInfo->sprite->spriteTrace[0];
InitializeSprite(dev, dev->spriteInfo->sprite->spriteTrace[0]); dev->spriteInfo->sprite = NULL;
InitializeSprite(dev, currentRoot);
dev->spriteInfo->spriteOwner = FALSE; dev->spriteInfo->spriteOwner = FALSE;
dev->spriteInfo->paired = dev;
} else } else
{
dev->spriteInfo->sprite = master->spriteInfo->sprite; dev->spriteInfo->sprite = master->spriteInfo->sprite;
dev->spriteInfo->paired = master;
dev->spriteInfo->spriteOwner = FALSE;
}
/* If we were connected to master device before, this MD may need to /* If we were connected to master device before, this MD may need to
* change back to it's original classes. * change back to it's original classes.
@ -2537,16 +2449,9 @@ AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master)
if (!it) /* no dev is paired with old master */ if (!it) /* no dev is paired with old master */
{ {
ClassesPtr classes; /* XXX: reset to defaults */
EventList event = { NULL, 0}; EventList event = { NULL, 0};
char* classbuf; char* classbuf;
DeviceIntRec dummy;
FreeAllDeviceClasses((ClassesPtr)&oldmaster->key);
classes = (ClassesPtr)dixLookupPrivate(&oldmaster->devPrivates,
MasterDevClassesPrivateKey);
memcpy(&dummy.key, classes, sizeof(ClassesRec));
DeepCopyDeviceClasses(&dummy, oldmaster);
/* Send event to clients */ /* Send event to clients */
CreateClassesChangedEvent(&event, oldmaster, oldmaster); CreateClassesChangedEvent(&event, oldmaster, oldmaster);

View File

@ -331,11 +331,14 @@ IsPointerDevice(DeviceIntPtr dev)
/* /*
* Return true if a device is a keyboard, check is the same as used by XI to * Return true if a device is a keyboard, check is the same as used by XI to
* fill the 'use' field. * fill the 'use' field.
*
* Some pointer devices have keys as well (e.g. multimedia keys). Try to not
* count them as keyboard devices.
*/ */
_X_EXPORT Bool _X_EXPORT Bool
IsKeyboardDevice(DeviceIntPtr dev) IsKeyboardDevice(DeviceIntPtr dev)
{ {
return (dev->key && dev->kbdfeed); return (dev->key && dev->kbdfeed) && !IsPointerDevice(dev);;
} }
#ifdef XEVIE #ifdef XEVIE
@ -1394,7 +1397,7 @@ ComputeFreezes(void)
replayDev->spriteInfo->sprite->spriteTrace[i]) replayDev->spriteInfo->sprite->spriteTrace[i])
{ {
if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
if (replayDev->focus) if (replayDev->focus && !IsPointerEvent(xE))
DeliverFocusedEvent(replayDev, xE, w, count); DeliverFocusedEvent(replayDev, xE, w, count);
else else
DeliverDeviceEvents(w, xE, NullGrab, NullWindow, DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
@ -1404,7 +1407,7 @@ ComputeFreezes(void)
} }
} }
/* must not still be in the same stack */ /* must not still be in the same stack */
if (replayDev->focus) if (replayDev->focus && !IsPointerEvent(xE))
DeliverFocusedEvent(replayDev, xE, w, count); DeliverFocusedEvent(replayDev, xE, w, count);
else else
DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
@ -3688,7 +3691,18 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
{ {
WindowPtr focus; WindowPtr focus;
if (thisDev->focus) /* Hack: Some pointer device have a focus class. So we need to check
* for the type of event, to see if we really want to deliver it to
* the focus window. For pointer events, the answer is no.
*/
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)
{
focus = PointerRootWin;
} else if (thisDev->focus)
{ {
focus = thisDev->focus->win; focus = thisDev->focus->win;
if (focus == FollowKeyboardWin) if (focus == FollowKeyboardWin)
@ -4383,7 +4397,7 @@ EnterLeaveEvent(
GrabPtr grab = mouse->deviceGrab.grab; GrabPtr grab = mouse->deviceGrab.grab;
GrabPtr devgrab = mouse->deviceGrab.grab; GrabPtr devgrab = mouse->deviceGrab.grab;
Mask mask; Mask mask;
int* inWindow; /* no of sprites inside pWin */ int inWindow; /* zero if no sprites are in window */
Bool sendevent = FALSE; Bool sendevent = FALSE;
deviceEnterNotify *devEnterLeave; deviceEnterNotify *devEnterLeave;
@ -4436,7 +4450,6 @@ EnterLeaveEvent(
IsParent(focus, pWin))) IsParent(focus, pWin)))
event.u.enterLeave.flags |= ELFlagFocus; event.u.enterLeave.flags |= ELFlagFocus;
inWindow = &((FocusSemaphoresPtr)dixLookupPrivate(&pWin->devPrivates, FocusPrivatesKey))->enterleave;
/* /*
* Sending multiple core enter/leave events to the same window confuse the * Sending multiple core enter/leave events to the same window confuse the
@ -4462,16 +4475,15 @@ EnterLeaveEvent(
* NotifyNonlinearVirtual to C and nothing to B. * NotifyNonlinearVirtual to C and nothing to B.
*/ */
if (event.u.u.detail != NotifyVirtual && /* Clear bit for device, but don't worry about SDs. */
event.u.u.detail != NotifyNonlinearVirtual) if (mouse->isMaster && type == LeaveNotify &&
{ (mode != NotifyVirtual && mode != NotifyNonlinearVirtual))
if (((*inWindow) == (LeaveNotify - type))) ENTER_LEAVE_SEMAPHORE_UNSET(pWin, mouse);
sendevent = TRUE;
} else inWindow = EnterLeaveSemaphoresIsset(pWin);
{
if (!(*inWindow)) if (!inWindow)
sendevent = TRUE; sendevent = TRUE;
}
if ((mask & filters[mouse->id][type]) && sendevent) if ((mask & filters[mouse->id][type]) && sendevent)
{ {
@ -4483,6 +4495,10 @@ EnterLeaveEvent(
filters[mouse->id][type], NullGrab, 0); filters[mouse->id][type], NullGrab, 0);
} }
if (mouse->isMaster && type == EnterNotify &&
(mode != NotifyVirtual && mode != NotifyNonlinearVirtual))
ENTER_LEAVE_SEMAPHORE_SET(pWin, mouse);
/* we don't have enough bytes, so we squash flags and mode into /* we don't have enough bytes, so we squash flags and mode into
one byte, and use the last byte for the deviceid. */ one byte, and use the last byte for the deviceid. */
devEnterLeave = (deviceEnterNotify*)&event; devEnterLeave = (deviceEnterNotify*)&event;
@ -4572,25 +4588,6 @@ LeaveNotifies(DeviceIntPtr pDev,
} }
} }
/* welcome to insanity */
#define FOCUS_SEMAPHORE_MODIFY(win, field, mode, val) \
{ \
FocusSemaphoresPtr sem;\
sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); \
if (mode != NotifyGrab && mode != NotifyUngrab) { \
sem->field += val; \
} else if (mode == NotifyUngrab) { \
if (sem->field == 0 && val > 0) \
sem->field += val; \
else if (sem->field == 1 && val < 0) \
sem->field += val; \
} \
}
#define ENTER_LEAVE_SEMAPHORE_UP(win, mode) \
FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode, 1);
#define ENTER_LEAVE_SEMAPHORE_DOWN(win, mode) \
FOCUS_SEMAPHORE_MODIFY(win, enterleave, mode, -1);
/** /**
@ -4610,33 +4607,27 @@ DoEnterLeaveEvents(DeviceIntPtr pDev,
return; return;
if (IsParent(fromWin, toWin)) if (IsParent(fromWin, toWin))
{ {
ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin, EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin,
None); None);
EnterNotifies(pDev, fromWin, toWin, mode, EnterNotifies(pDev, fromWin, toWin, mode,
NotifyVirtual); NotifyVirtual);
ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None); EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None);
} }
else if (IsParent(toWin, fromWin)) else if (IsParent(toWin, fromWin))
{ {
ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin, EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin,
None); None);
LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual); LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual);
ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None); EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None);
} }
else else
{ /* neither fromWin nor toWin is descendent of the other */ { /* neither fromWin nor toWin is descendent of the other */
WindowPtr common = CommonAncestor(toWin, fromWin); WindowPtr common = CommonAncestor(toWin, fromWin);
/* common == NullWindow ==> different screens */ /* common == NullWindow ==> different screens */
ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin, EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin,
None); None);
LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual); LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual);
EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual); EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual);
ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin, EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin,
None); None);
} }
@ -4646,7 +4637,7 @@ static void
FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
{ {
xEvent event; xEvent event;
int* numFoci; /* no of foci the window has already */ int numFoci; /* zero if no device has focus on window */
Bool sendevent = FALSE; Bool sendevent = FALSE;
if (dev != inputInfo.keyboard) if (dev != inputInfo.keyboard)
@ -4680,25 +4671,18 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
* NotifyNonlinearVirtual to C and nothing to B. * NotifyNonlinearVirtual to C and nothing to B.
*/ */
numFoci = if (dev->isMaster && type == FocusOut &&
&((FocusSemaphoresPtr)dixLookupPrivate(&pWin->devPrivates, (detail != NotifyVirtual &&
FocusPrivatesKey))->focusinout; detail != NotifyNonlinearVirtual &&
if (mode == NotifyGrab || mode == NotifyUngrab) detail != NotifyPointer &&
detail != NotifyPointerRoot &&
detail != NotifyDetailNone))
FOCUS_SEMAPHORE_UNSET(pWin, dev);
numFoci = FocusSemaphoresIsset(pWin);
if (!numFoci)
sendevent = TRUE; sendevent = TRUE;
else if (detail != NotifyVirtual &&
detail != NotifyNonlinearVirtual &&
detail != NotifyPointer &&
detail != NotifyPointerRoot &&
detail != NotifyDetailNone)
{
(type == FocusIn) ? (*numFoci)++ : (*numFoci)--;
if (((*numFoci) == (FocusOut - type)))
sendevent = TRUE;
} else
{
if (!(*numFoci))
sendevent = TRUE;
}
if (sendevent) if (sendevent)
{ {
@ -4723,6 +4707,14 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
KeymapStateMask, NullGrab, 0); KeymapStateMask, NullGrab, 0);
} }
} }
if (dev->isMaster && type == FocusIn &&
(detail != NotifyVirtual &&
detail != NotifyNonlinearVirtual &&
detail != NotifyPointer &&
detail != NotifyPointerRoot &&
detail != NotifyDetailNone))
FOCUS_SEMAPHORE_SET(pWin, dev);
} }
/* /*
@ -6606,3 +6598,37 @@ ExtGrabDevice(ClientPtr client,
return GrabSuccess; return GrabSuccess;
} }
/*
* @return Zero if no device is currently in window, non-zero otherwise.
*/
int
EnterLeaveSemaphoresIsset(WindowPtr win)
{
FocusSemaphoresPtr sem;
int set = 0;
int i;
sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey);
for (i = 0; i < (MAX_DEVICES + 7)/8; i++)
set += sem->enterleave[i];
return set;
}
/*
* @return Zero if no devices has focus on the window, non-zero otherwise.
*/
int
FocusSemaphoresIsset(WindowPtr win)
{
FocusSemaphoresPtr sem;
int set = 0;
int i;
sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey);
for (i = 0; i < (MAX_DEVICES + 7)/8; i++)
set += sem->focusinout[i];
return set;
}

View File

@ -366,6 +366,7 @@ CreateRootWindow(ScreenPtr pScreen)
WindowPtr pWin; WindowPtr pWin;
BoxRec box; BoxRec box;
PixmapFormatRec *format; PixmapFormatRec *format;
FocusSemaphoresPtr sem;
pWin = (WindowPtr)xalloc(sizeof(WindowRec)); pWin = (WindowPtr)xalloc(sizeof(WindowRec));
if (!pWin) if (!pWin)
@ -484,6 +485,7 @@ CreateRootWindow(ScreenPtr pScreen)
if (disableSaveUnders) if (disableSaveUnders)
pScreen->saveUnderSupport = NotUseful; pScreen->saveUnderSupport = NotUseful;
return TRUE; return TRUE;
} }

View File

@ -722,7 +722,10 @@ xf86PostKeyboardEvent(DeviceIntPtr device,
int index; int index;
#if XFreeXDGA #if XFreeXDGA
DeviceIntPtr pointer = GetPairedDevice(device); DeviceIntPtr pointer;
/* Some pointers send key events, paired device is wrong then. */
pointer = IsPointerDevice(device) ? device : GetPairedDevice(device);
if (miPointerGetScreen(pointer)) { if (miPointerGetScreen(pointer)) {
index = miPointerGetScreen(pointer)->myNum; index = miPointerGetScreen(pointer)->myNum;

View File

@ -615,6 +615,7 @@ extern int XItoCoreType(int xi_type);
extern Bool DevHasCursor(DeviceIntPtr pDev); extern Bool DevHasCursor(DeviceIntPtr pDev);
extern Bool IsPointerDevice( DeviceIntPtr dev); extern Bool IsPointerDevice( DeviceIntPtr dev);
extern Bool IsKeyboardDevice(DeviceIntPtr dev); extern Bool IsKeyboardDevice(DeviceIntPtr dev);
extern Bool IsPointerEvent(xEvent* xE);
/* /*
* These are deprecated compatibility functions and will be removed soon! * These are deprecated compatibility functions and will be removed soon!

View File

@ -80,6 +80,39 @@ SOFTWARE.
#define RevertToFollowKeyboard 3 #define RevertToFollowKeyboard 3
#endif #endif
/* Used for enter/leave and focus in/out semaphores */
#define SEMAPHORE_FIELD_SET(win, dev, field) \
{ \
FocusSemaphoresPtr sem; \
sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); \
sem->field[dev->id/8] |= (1 << (dev->id % 8)); \
}
#define SEMAPHORE_FIELD_UNSET(win, dev, field) \
{ \
FocusSemaphoresPtr sem; \
sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); \
sem->field[dev->id/8] &= ~(1 << (dev->id % 8)); \
}
#define ENTER_LEAVE_SEMAPHORE_SET(win, dev) \
SEMAPHORE_FIELD_SET(win, dev, enterleave);
#define ENTER_LEAVE_SEMAPHORE_UNSET(win, dev) \
SEMAPHORE_FIELD_UNSET(win, dev, enterleave);
#define ENTER_LEAVE_SEMAPHORE_ISSET(win, dev) \
((FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey))->enterleave[dev->id/8] & (1 << (dev->id % 8))
#define FOCUS_SEMAPHORE_SET(win, dev) \
SEMAPHORE_FIELD_SET(win, dev, focusinout);
#define FOCUS_SEMAPHORE_UNSET(win, dev) \
SEMAPHORE_FIELD_UNSET(win, dev, focusinout);
#define FOCUS_SEMAPHORE_ISSET(win, dev) \
((FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey))->focusinout[dev->id/8] & (1 << (dev->id % 8))
typedef unsigned long Leds; typedef unsigned long Leds;
typedef struct _OtherClients *OtherClientsPtr; typedef struct _OtherClients *OtherClientsPtr;
typedef struct _InputClients *InputClientsPtr; typedef struct _InputClients *InputClientsPtr;
@ -488,6 +521,8 @@ extern void DeepCopyDeviceClasses(DeviceIntPtr from,
extern void FreeDeviceClass(int type, pointer* class); extern void FreeDeviceClass(int type, pointer* class);
extern void FreeFeedbackClass(int type, pointer* class); extern void FreeFeedbackClass(int type, pointer* class);
extern void FreeAllDeviceClasses(ClassesPtr classes); extern void FreeAllDeviceClasses(ClassesPtr classes);
extern int EnterLeaveSemaphoresIsset(WindowPtr win);
extern int FocusSemaphoresIsset(WindowPtr win);
/* Window/device based access control */ /* Window/device based access control */
extern Bool ACRegisterClient(ClientPtr client); extern Bool ACRegisterClient(ClientPtr client);

View File

@ -59,6 +59,7 @@ SOFTWARE.
#include "miscstruct.h" #include "miscstruct.h"
#include <X11/Xprotostr.h> #include <X11/Xprotostr.h>
#include "opaque.h" #include "opaque.h"
#include "inputstr.h"
#define GuaranteeNothing 0 #define GuaranteeNothing 0
#define GuaranteeVisBack 1 #define GuaranteeVisBack 1
@ -257,11 +258,14 @@ extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
extern DevPrivateKey FocusPrivatesKey; extern DevPrivateKey FocusPrivatesKey;
/* Used to maintain semantics of core protocol for Enter/LeaveNotifies and /* Used to maintain semantics of core protocol for Enter/LeaveNotifies and
* FocusIn/Out events for multiple pointers/keyboards. * FocusIn/Out events for multiple pointers/keyboards.
*/ *
* Each device ID corresponds to one bit. If set, the device is in the
* window/has focus.
*/
typedef struct _FocusSemaphores { typedef struct _FocusSemaphores {
int enterleave; char enterleave[(MAX_DEVICES + 7)/8];
int focusinout; char focusinout[(MAX_DEVICES + 7)/8];
} FocusSemaphoresRec, *FocusSemaphoresPtr; } FocusSemaphoresRec, *FocusSemaphoresPtr;
/* /*