diff options
author | Peter Hutterer <peter@cs.unisa.edu.au> | 2008-04-10 19:22:59 +0930 |
---|---|---|
committer | Peter Hutterer <peter@cs.unisa.edu.au> | 2008-04-10 19:22:59 +0930 |
commit | 04dff74ffdf727015e3721aae4ea13acc498cd1c (patch) | |
tree | 9003f77c5163bcf49f7b903527f7dcf906180388 | |
parent | a88386ee277d136caaaeec305f8753f23f9b6274 (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.c | 3 | ||||
-rw-r--r-- | dix/events.c | 124 | ||||
-rw-r--r-- | dix/window.c | 2 | ||||
-rw-r--r-- | include/input.h | 35 | ||||
-rw-r--r-- | include/windowstr.h | 12 |
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; /* |