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(
DeviceIntPtr /* master */);
extern void XkbFakeDeviceButton(
DeviceIntPtr /* dev */,
int /* press */,
int /* button */);
#include "xkbfile.h"
#include "xkbrules.h"

View File

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

View File

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