summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter@cs.unisa.edu.au>2008-04-10 19:22:59 +0930
committerPeter Hutterer <peter@cs.unisa.edu.au>2008-04-10 19:22:59 +0930
commit04dff74ffdf727015e3721aae4ea13acc498cd1c (patch)
tree9003f77c5163bcf49f7b903527f7dcf906180388
parenta88386ee277d136caaaeec305f8753f23f9b6274 (diff)
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.
-rw-r--r--dix/devices.c3
-rw-r--r--dix/events.c124
-rw-r--r--dix/window.c2
-rw-r--r--include/input.h35
-rw-r--r--include/windowstr.h12
5 files changed, 114 insertions, 62 deletions
diff --git a/dix/devices.c b/dix/devices.c
index df194de17..2d7885e28 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -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)
{
diff --git a/dix/events.c b/dix/events.c
index 144591469..1b62db05f 100644
--- a/dix/events.c
+++ b/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;
+}
+
diff --git a/dix/window.c b/dix/window.c
index ee4c75649..d3160c903 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -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;
}
diff --git a/include/input.h b/include/input.h
index 9ba12db79..0c993eed0 100644
--- a/include/input.h
+++ b/include/input.h
@@ -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);
diff --git a/include/windowstr.h b/include/windowstr.h
index 406087e17..a36dc2972 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -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;
/*