xkb: release XTEST pointer buttons on physical releases. (#28808)

If a button release event is posted for the MD pointer, post a release event
through the matching XTEST device. This way, a client who posts a button
press through the XTEST extension cannot inadvertedly lock the button.

This behaviour is required for historical reasons, until server 1.7 the core
pointer would release a button press on physical events, regardless of the
XTEST state. Clients seem to rely on this behaviour, causing seemingly stuck
grabs.

The merged behaviour is kept for multiple keyboard PointerKey events, if two
physical keyboards hold the button down as a result of PointerKey actions,
the button is not released until the last keyboard releases the button.

X.Org Bug 28808 <http://bugs.freedesktop.org/show_bug.cgi?id=28808>

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Peter Hutterer 2010-07-01 12:44:57 +10:00
parent 339f62b1bf
commit 1432785839
3 changed files with 18 additions and 15 deletions

View File

@ -927,6 +927,12 @@ extern int XkbGetEffectiveGroup(
extern void XkbMergeLockedPtrBtns( extern void XkbMergeLockedPtrBtns(
DeviceIntPtr /* master */); DeviceIntPtr /* master */);
extern void XkbFakeDeviceButton(
DeviceIntPtr /* dev */,
int /* press */,
int /* button */);
#include "xkbfile.h" #include "xkbfile.h"
#include "xkbrules.h" #include "xkbrules.h"

View File

@ -710,19 +710,16 @@ DeviceEvent *event = &ev->device_event;
if (xkbi) { if (xkbi) {
xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7)); xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7));
/* Merge this MD's lockedPtrButtons with the one of all if (IsMaster(dev))
* attached slave devices. {
* The DIX uses a merged button state for MDs, not DeviceIntPtr source;
* releasing buttons until the last SD has released int rc;
* thenm. If we unconditionally clear the rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess);
* lockedPtrButtons bit on the MD, a PointerKeys button if (rc != Success)
* release on the SD keyboard won't generate the required fake button ErrorF("[xkb] bad sourceid '%d' on button release event.\n", event->sourceid);
* event on the XTEST pointer, thus never processing the else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER)))
* button event in the DIX and the XTEST pointer's XkbFakeDeviceButton(dev, FALSE, event->detail.key);
* buttons stay down - result is a stuck button. }
*/
if (IsMaster(dev))
XkbMergeLockedPtrBtns(dev);
} }
changed |= XkbPointerButtonMask; changed |= XkbPointerButtonMask;

View File

@ -45,7 +45,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
DevPrivateKeyRec xkbDevicePrivateKeyRec; DevPrivateKeyRec xkbDevicePrivateKeyRec;
static void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button); void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y); static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y);
void void
@ -1364,7 +1364,7 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
FreeEventList(events, GetMaximumEventsNum()); FreeEventList(events, GetMaximumEventsNum());
} }
static void void
XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
{ {
EventListPtr events; EventListPtr events;