dix: Rework Enter/Leave semaphore system.
Instead of a simple counter, use bits to keep track of which device is where etc. When device enters a window (or sets focus), the bit matching the device is set, when it leaves again, it is unset. If there are 0 bits set, then Leave/Enter/Focus events may be sent to the client. Same theory as before, but this should get around the insanity with Grab/Ungrab special cases. Those cases are basically untested though.
This commit is contained in:
parent
a88386ee27
commit
04dff74ffd
|
@ -224,8 +224,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)
|
||||||
{
|
{
|
||||||
|
|
124
dix/events.c
124
dix/events.c
|
@ -4393,7 +4393,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;
|
||||||
|
@ -4446,7 +4446,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
|
||||||
|
@ -4472,16 +4471,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)
|
||||||
{
|
{
|
||||||
|
@ -4493,6 +4491,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;
|
||||||
|
@ -4582,25 +4584,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);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4620,33 +4603,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);
|
||||||
}
|
}
|
||||||
|
@ -4656,7 +4633,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)
|
||||||
|
@ -4690,25 +4667,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)
|
||||||
{
|
{
|
||||||
|
@ -4733,6 +4703,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -6616,3 +6594,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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in New Issue