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)
|
||||
{
|
||||
InitializeSprite(dev, WindowTable[0]);
|
||||
((FocusSemaphoresPtr)dixLookupPrivate(&(WindowTable[0])->devPrivates,
|
||||
FocusPrivatesKey))->enterleave++;
|
||||
ENTER_LEAVE_SEMAPHORE_SET(WindowTable[0], dev);
|
||||
}
|
||||
else if ((other = NextFreePointerDevice()) == NULL)
|
||||
{
|
||||
|
|
124
dix/events.c
124
dix/events.c
|
@ -4393,7 +4393,7 @@ EnterLeaveEvent(
|
|||
GrabPtr grab = mouse->deviceGrab.grab;
|
||||
GrabPtr devgrab = mouse->deviceGrab.grab;
|
||||
Mask mask;
|
||||
int* inWindow; /* no of sprites inside pWin */
|
||||
int inWindow; /* zero if no sprites are in window */
|
||||
Bool sendevent = FALSE;
|
||||
|
||||
deviceEnterNotify *devEnterLeave;
|
||||
|
@ -4446,7 +4446,6 @@ EnterLeaveEvent(
|
|||
IsParent(focus, pWin)))
|
||||
event.u.enterLeave.flags |= ELFlagFocus;
|
||||
|
||||
inWindow = &((FocusSemaphoresPtr)dixLookupPrivate(&pWin->devPrivates, FocusPrivatesKey))->enterleave;
|
||||
|
||||
/*
|
||||
* Sending multiple core enter/leave events to the same window confuse the
|
||||
|
@ -4472,16 +4471,15 @@ EnterLeaveEvent(
|
|||
* NotifyNonlinearVirtual to C and nothing to B.
|
||||
*/
|
||||
|
||||
if (event.u.u.detail != NotifyVirtual &&
|
||||
event.u.u.detail != NotifyNonlinearVirtual)
|
||||
{
|
||||
if (((*inWindow) == (LeaveNotify - type)))
|
||||
sendevent = TRUE;
|
||||
} else
|
||||
{
|
||||
if (!(*inWindow))
|
||||
sendevent = TRUE;
|
||||
}
|
||||
/* Clear bit for device, but don't worry about SDs. */
|
||||
if (mouse->isMaster && type == LeaveNotify &&
|
||||
(mode != NotifyVirtual && mode != NotifyNonlinearVirtual))
|
||||
ENTER_LEAVE_SEMAPHORE_UNSET(pWin, mouse);
|
||||
|
||||
inWindow = EnterLeaveSemaphoresIsset(pWin);
|
||||
|
||||
if (!inWindow)
|
||||
sendevent = TRUE;
|
||||
|
||||
if ((mask & filters[mouse->id][type]) && sendevent)
|
||||
{
|
||||
|
@ -4493,6 +4491,10 @@ EnterLeaveEvent(
|
|||
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
|
||||
one byte, and use the last byte for the deviceid. */
|
||||
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;
|
||||
if (IsParent(fromWin, toWin))
|
||||
{
|
||||
ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
|
||||
EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin,
|
||||
None);
|
||||
EnterNotifies(pDev, fromWin, toWin, mode,
|
||||
NotifyVirtual);
|
||||
ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
|
||||
EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None);
|
||||
}
|
||||
else if (IsParent(toWin, fromWin))
|
||||
{
|
||||
ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
|
||||
EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin,
|
||||
None);
|
||||
LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual);
|
||||
ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
|
||||
EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None);
|
||||
}
|
||||
else
|
||||
{ /* neither fromWin nor toWin is descendent of the other */
|
||||
WindowPtr common = CommonAncestor(toWin, fromWin);
|
||||
/* common == NullWindow ==> different screens */
|
||||
ENTER_LEAVE_SEMAPHORE_DOWN(fromWin, mode);
|
||||
EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin,
|
||||
None);
|
||||
LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual);
|
||||
EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual);
|
||||
ENTER_LEAVE_SEMAPHORE_UP(toWin, mode);
|
||||
EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin,
|
||||
None);
|
||||
}
|
||||
|
@ -4656,7 +4633,7 @@ static void
|
|||
FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
|
||||
{
|
||||
xEvent event;
|
||||
int* numFoci; /* no of foci the window has already */
|
||||
int numFoci; /* zero if no device has focus on window */
|
||||
Bool sendevent = FALSE;
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
numFoci =
|
||||
&((FocusSemaphoresPtr)dixLookupPrivate(&pWin->devPrivates,
|
||||
FocusPrivatesKey))->focusinout;
|
||||
if (mode == NotifyGrab || mode == NotifyUngrab)
|
||||
if (dev->isMaster && type == FocusOut &&
|
||||
(detail != NotifyVirtual &&
|
||||
detail != NotifyNonlinearVirtual &&
|
||||
detail != NotifyPointer &&
|
||||
detail != NotifyPointerRoot &&
|
||||
detail != NotifyDetailNone))
|
||||
FOCUS_SEMAPHORE_UNSET(pWin, dev);
|
||||
|
||||
numFoci = FocusSemaphoresIsset(pWin);
|
||||
|
||||
if (!numFoci)
|
||||
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)
|
||||
{
|
||||
|
@ -4733,6 +4703,14 @@ FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
|
|||
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 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;
|
||||
BoxRec box;
|
||||
PixmapFormatRec *format;
|
||||
FocusSemaphoresPtr sem;
|
||||
|
||||
pWin = (WindowPtr)xalloc(sizeof(WindowRec));
|
||||
if (!pWin)
|
||||
|
@ -484,6 +485,7 @@ CreateRootWindow(ScreenPtr pScreen)
|
|||
|
||||
if (disableSaveUnders)
|
||||
pScreen->saveUnderSupport = NotUseful;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,39 @@ SOFTWARE.
|
|||
#define RevertToFollowKeyboard 3
|
||||
#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 struct _OtherClients *OtherClientsPtr;
|
||||
typedef struct _InputClients *InputClientsPtr;
|
||||
|
@ -488,6 +521,8 @@ extern void DeepCopyDeviceClasses(DeviceIntPtr from,
|
|||
extern void FreeDeviceClass(int type, pointer* class);
|
||||
extern void FreeFeedbackClass(int type, pointer* class);
|
||||
extern void FreeAllDeviceClasses(ClassesPtr classes);
|
||||
extern int EnterLeaveSemaphoresIsset(WindowPtr win);
|
||||
extern int FocusSemaphoresIsset(WindowPtr win);
|
||||
|
||||
/* Window/device based access control */
|
||||
extern Bool ACRegisterClient(ClientPtr client);
|
||||
|
|
|
@ -59,6 +59,7 @@ SOFTWARE.
|
|||
#include "miscstruct.h"
|
||||
#include <X11/Xprotostr.h>
|
||||
#include "opaque.h"
|
||||
#include "inputstr.h"
|
||||
|
||||
#define GuaranteeNothing 0
|
||||
#define GuaranteeVisBack 1
|
||||
|
@ -257,11 +258,14 @@ extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS];
|
|||
extern DevPrivateKey FocusPrivatesKey;
|
||||
|
||||
/* 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 {
|
||||
int enterleave;
|
||||
int focusinout;
|
||||
char enterleave[(MAX_DEVICES + 7)/8];
|
||||
char focusinout[(MAX_DEVICES + 7)/8];
|
||||
} FocusSemaphoresRec, *FocusSemaphoresPtr;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue
Block a user