1 From deab888bb3bb2a56963da50ff551bd66fbd858a1 Mon Sep 17 00:00:00 2001
2 From: Peter Hutterer <peter.hutterer@who-t.net>
3 Date: Tue, 29 Jun 2010 13:49:27 +1000
4 Subject: [PATCH 1/5] xkb: Mark switch case fallthrough with comment.
6 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
8 xkb/xkbActions.c | 2 ++
9 1 files changed, 2 insertions(+), 0 deletions(-)
11 diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
12 index 4c7bce2..6a7f36d 100644
13 --- a/xkb/xkbActions.c
14 +++ b/xkb/xkbActions.c
15 @@ -625,6 +625,8 @@ _XkbFilterPointerBtn( XkbSrvInfoPtr xkbi,
18 xkbi->lockedPtrButtons&= ~(1<<button);
22 XkbDDXFakeDeviceButton(xkbi->device, 0, button);
27 From 50b6311dbd2594acc36d6856fdde8623459f1374 Mon Sep 17 00:00:00 2001
28 From: Peter Hutterer <peter.hutterer@who-t.net>
29 Date: Tue, 29 Jun 2010 12:12:53 +1000
30 Subject: [PATCH 2/5] xkb: merge lockedPtrButtons state from all attached SDs.
32 Content-Type: text/plain; charset=UTF-8
33 Content-Transfer-Encoding: 8bit
36 lockedPtrButtons keeps the state of the buttons locked by a PointerKeys button
37 press. Unconditionally clearing the bits may cause stuck buttons in this
40 1. type Shift + NumLock to enable PointerKeys
41 2. type 0/Ins on keypad to emulate Button 1 press
42 → button1 press event to client
43 3. press and release button 1 on physical mouse
44 → button1 release event to client
46 Button 1 on the MD is now stuck and cannot be released.
49 XKB PointerKeys button events are posted through the XTEST pointer device.
50 Once a press is generated, the XTEST device's button is down. The DIX merges
51 the button state of all attached SDs, hence the MD will have a button down
52 while the XTEST device has a button down.
54 PointerKey button events are only generated on the master device to avoid
55 duplicate events (see XkbFakeDeviceButton()). If the MD has the
56 lockedPtrButtons bit cleared by a release event on a physical device, no
57 such event is generated when a keyboard device triggers the PointerKey
58 ButtonRelease trigger. Since the event - if generated - is posted through
59 the XTEST pointer device, lack of a generated ButtonRelease event on the
60 XTEST pointer device means the button is never released, resulting in the
61 stuck button observed above.
64 This patch merges the MD's lockedPtrButtons with the one of all attached
65 slave devices on release events. Thus, as long as one attached keyboard has
66 a lockedPtrButtons bit set, this bit is kept in the MD. Once a PointerKey
67 button is released on all keyboards, the matching release event is emulated
68 from the MD through the XTEST pointer device, thus also releasing the button
71 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
73 include/xkbsrv.h | 3 +++
74 xkb/xkbAccessX.c | 18 +++++++++++++++++-
75 xkb/xkbActions.c | 8 ++++++++
76 xkb/xkbUtils.c | 26 ++++++++++++++++++++++++++
77 4 files changed, 54 insertions(+), 1 deletions(-)
79 diff --git a/include/xkbsrv.h b/include/xkbsrv.h
80 index c0cd501..f0db0e4 100644
81 --- a/include/xkbsrv.h
82 +++ b/include/xkbsrv.h
83 @@ -933,6 +933,9 @@ extern int XkbGetEffectiveGroup(
84 XkbStatePtr /* xkbstate */,
87 +extern void XkbMergeLockedPtrBtns(
88 + DeviceIntPtr /* master */);
93 diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
94 index be1dcee..e3fdc06 100644
95 --- a/xkb/xkbAccessX.c
96 +++ b/xkb/xkbAccessX.c
97 @@ -707,8 +707,24 @@ DeviceEvent *event = &ev->device_event;
98 changed |= XkbPointerButtonMask;
100 else if (event->type == ET_ButtonRelease) {
103 xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7));
105 + /* Merge this MD's lockedPtrButtons with the one of all
106 + * attached slave devices.
107 + * The DIX uses a merged button state for MDs, not
108 + * releasing buttons until the last SD has released
109 + * thenm. If we unconditionally clear the
110 + * lockedPtrButtons bit on the MD, a PointerKeys button
111 + * release on the SD keyboard won't generate the required fake button
112 + * event on the XTEST pointer, thus never processing the
113 + * button event in the DIX and the XTEST pointer's
114 + * buttons stay down - result is a stuck button.
117 + XkbMergeLockedPtrBtns(dev);
120 changed |= XkbPointerButtonMask;
123 diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
124 index 6a7f36d..ab52b6a 100644
125 --- a/xkb/xkbActions.c
126 +++ b/xkb/xkbActions.c
127 @@ -626,6 +626,14 @@ _XkbFilterPointerBtn( XkbSrvInfoPtr xkbi,
129 xkbi->lockedPtrButtons&= ~(1<<button);
131 + if (IsMaster(xkbi->device))
133 + XkbMergeLockedPtrBtns(xkbi->device);
134 + /* One SD still has lock set, don't post event */
135 + if ((xkbi->lockedPtrButtons & (1 << button)) != 0)
141 XkbDDXFakeDeviceButton(xkbi->device, 0, button);
142 diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c
143 index b1e0e55..d7d1935 100644
146 @@ -2190,3 +2190,29 @@ XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode)
148 return effectiveGroup;
151 +/* Merge the lockedPtrButtons from all attached SDs for the given master
152 + * device into the MD's state.
155 +XkbMergeLockedPtrBtns(DeviceIntPtr master)
157 + DeviceIntPtr d = inputInfo.devices;
158 + XkbSrvInfoPtr xkbi = NULL;
160 + if (!IsMaster(master))
166 + xkbi = master->key->xkbInfo;
167 + xkbi->lockedPtrButtons = 0;
169 + for (; d; d = d->next) {
170 + if (IsMaster(d) || GetMaster(d, MASTER_KEYBOARD) != master || !d->key)
173 + xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons;
179 From 4a4224f5d786035af88c251a9ee177217e8f77fd Mon Sep 17 00:00:00 2001
180 From: Peter Hutterer <peter.hutterer@who-t.net>
181 Date: Wed, 14 Apr 2010 10:54:29 +1000
182 Subject: [PATCH 3/5] xkb: rename XkbFakeDeviceButton and XkbFakeDeviceMotion, move into xkbActions.c
184 The name XkbDDXFakeDeviceButton and XkbDDXFakeDeviceMotion is somewhat
185 misleading, there's no DDX involved in the game at all anymore.
187 This removes XkbFakeDeviceMotion and XkbFakeDeviceButton from the API where
188 it arguably shouldn't have been in the first place.
190 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
191 Reviewed-by: Daniel Stone <daniel@fooishbar.org>
192 Reviewed-by: Dan Nicholson <dbn.lists@gmail.com>
194 include/xkbsrv.h | 13 -------
195 xkb/Makefile.am | 4 +--
196 xkb/ddxDevBtn.c | 69 --------------------------------------
197 xkb/ddxFakeMtn.c | 64 -----------------------------------
198 xkb/xkbActions.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++-------
199 5 files changed, 85 insertions(+), 162 deletions(-)
200 delete mode 100644 xkb/ddxDevBtn.c
201 delete mode 100644 xkb/ddxFakeMtn.c
203 diff --git a/include/xkbsrv.h b/include/xkbsrv.h
204 index f0db0e4..d1cbd1a 100644
205 --- a/include/xkbsrv.h
206 +++ b/include/xkbsrv.h
207 @@ -768,19 +768,6 @@ extern _X_EXPORT void XkbDDXUpdateDeviceIndicators(
208 CARD32 /* newState */
211 -extern _X_EXPORT void XkbDDXFakePointerMotion(
212 - DeviceIntPtr /* dev */,
213 - unsigned int /* flags */,
218 -extern _X_EXPORT void XkbDDXFakeDeviceButton(
219 - DeviceIntPtr /* dev */,
224 extern _X_EXPORT int XkbDDXTerminateServer(
225 DeviceIntPtr /* dev */,
227 diff --git a/xkb/Makefile.am b/xkb/Makefile.am
228 index e54ce59..fb3ccbf 100644
229 --- a/xkb/Makefile.am
230 +++ b/xkb/Makefile.am
231 @@ -5,11 +5,9 @@ AM_CFLAGS = $(DIX_CFLAGS)
244 diff --git a/xkb/ddxDevBtn.c b/xkb/ddxDevBtn.c
245 deleted file mode 100644
246 index b8a1255..0000000
247 --- a/xkb/ddxDevBtn.c
250 -/************************************************************
251 -Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc.
253 -Permission to use, copy, modify, and distribute this
254 -software and its documentation for any purpose and without
255 -fee is hereby granted, provided that the above copyright
256 -notice appear in all copies and that both that copyright
257 -notice and this permission notice appear in supporting
258 -documentation, and that the name of Silicon Graphics not be
259 -used in advertising or publicity pertaining to distribution
260 -of the software without specific prior written permission.
261 -Silicon Graphics makes no representation about the suitability
262 -of this software for any purpose. It is provided "as is"
263 -without any express or implied warranty.
265 -SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
266 -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
267 -AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
268 -GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
269 -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
270 -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
271 -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
272 -THE USE OR PERFORMANCE OF THIS SOFTWARE.
274 -********************************************************/
276 -#ifdef HAVE_DIX_CONFIG_H
277 -#include <dix-config.h>
280 -#include "inputstr.h"
285 -XkbDDXFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
287 - EventListPtr events;
291 - /* If dev is a slave device, and the SD is attached, do nothing. If we'd
292 - * post through the attached master pointer we'd get duplicate events.
294 - * if dev is a master keyboard, post through the XTEST device
296 - * if dev is a floating slave, post through the device itself.
300 - ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
301 - else if (!dev->u.master)
306 - events = InitEventList(GetMaximumEventsNum());
308 - nevents = GetPointerEvents(events, ptr,
309 - press ? ButtonPress : ButtonRelease, button,
310 - 0 /* flags */, 0 /* first */,
311 - 0 /* num_val */, NULL);
312 - OsReleaseSignals();
314 - for (i = 0; i < nevents; i++)
315 - mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
317 - FreeEventList(events, GetMaximumEventsNum());
319 diff --git a/xkb/ddxFakeMtn.c b/xkb/ddxFakeMtn.c
320 deleted file mode 100644
321 index b383716..0000000
322 --- a/xkb/ddxFakeMtn.c
325 -/************************************************************
326 -Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc.
328 -Permission to use, copy, modify, and distribute this
329 -software and its documentation for any purpose and without
330 -fee is hereby granted, provided that the above copyright
331 -notice appear in all copies and that both that copyright
332 -notice and this permission notice appear in supporting
333 -documentation, and that the name of Silicon Graphics not be
334 -used in advertising or publicity pertaining to distribution
335 -of the software without specific prior written permission.
336 -Silicon Graphics makes no representation about the suitability
337 -of this software for any purpose. It is provided "as is"
338 -without any express or implied warranty.
340 -SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
341 -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
342 -AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
343 -GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
344 -DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
345 -DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
346 -OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH
347 -THE USE OR PERFORMANCE OF THIS SOFTWARE.
349 -********************************************************/
351 -#ifdef HAVE_DIX_CONFIG_H
352 -#include <dix-config.h>
355 -#include "inputstr.h"
360 -XkbDDXFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
362 - EventListPtr events;
367 - if (!dev->u.master)
370 - ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
372 - if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
373 - gpe_flags = POINTER_ABSOLUTE;
375 - gpe_flags = POINTER_RELATIVE;
377 - events = InitEventList(GetMaximumEventsNum());
379 - nevents = GetPointerEvents(events, ptr,
381 - gpe_flags, 0, 2, (int[]){x, y});
382 - OsReleaseSignals();
384 - for (i = 0; i < nevents; i++)
385 - mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
387 - FreeEventList(events, GetMaximumEventsNum());
389 diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
390 index ab52b6a..2817e39 100644
391 --- a/xkb/xkbActions.c
392 +++ b/xkb/xkbActions.c
393 @@ -40,11 +40,15 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
398 #define EXTENSION_EVENT_BASE 64
400 static int xkbDevicePrivateKeyIndex;
401 DevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKeyIndex;
403 +static void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
404 +static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y);
407 xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc,
409 @@ -479,7 +483,7 @@ int dx,dy;
410 dx= xkbi->mouseKeysDX;
411 dy= xkbi->mouseKeysDY;
413 - XkbDDXFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy);
414 + XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy);
415 return xkbi->desc->ctrls->mk_interval;
418 @@ -507,7 +511,7 @@ Bool accel;
419 accel= ((pAction->ptr.flags&XkbSA_NoAcceleration)==0);
420 x= XkbPtrActionX(&pAction->ptr);
421 y= XkbPtrActionY(&pAction->ptr);
422 - XkbDDXFakePointerMotion(xkbi->device, pAction->ptr.flags,x,y);
423 + XkbFakePointerMotion(xkbi->device, pAction->ptr.flags,x,y);
424 AccessXCancelRepeatKey(xkbi,keycode);
425 xkbi->mouseKeysAccel= accel&&
426 (xkbi->desc->ctrls->enabled_ctrls&XkbMouseKeysAccelMask);
427 @@ -554,7 +558,7 @@ _XkbFilterPointerBtn( XkbSrvInfoPtr xkbi,
428 ((pAction->btn.flags&XkbSA_LockNoLock)==0)) {
429 xkbi->lockedPtrButtons|= (1<<button);
430 AccessXCancelRepeatKey(xkbi,keycode);
431 - XkbDDXFakeDeviceButton(xkbi->device, 1, button);
432 + XkbFakeDeviceButton(xkbi->device, 1, button);
433 filter->upAction.type= XkbSA_NoAction;
436 @@ -565,12 +569,12 @@ _XkbFilterPointerBtn( XkbSrvInfoPtr xkbi,
437 if (pAction->btn.count>0) {
438 nClicks= pAction->btn.count;
439 for (i=0;i<nClicks;i++) {
440 - XkbDDXFakeDeviceButton(xkbi->device, 1, button);
441 - XkbDDXFakeDeviceButton(xkbi->device, 0, button);
442 + XkbFakeDeviceButton(xkbi->device, 1, button);
443 + XkbFakeDeviceButton(xkbi->device, 0, button);
445 filter->upAction.type= XkbSA_NoAction;
447 - else XkbDDXFakeDeviceButton(xkbi->device, 1, button);
448 + else XkbFakeDeviceButton(xkbi->device, 1, button);
451 case XkbSA_SetPtrDflt:
452 @@ -636,7 +640,7 @@ _XkbFilterPointerBtn( XkbSrvInfoPtr xkbi,
456 - XkbDDXFakeDeviceButton(xkbi->device, 0, button);
457 + XkbFakeDeviceButton(xkbi->device, 0, button);
461 @@ -974,7 +978,7 @@ int button;
462 if ((pAction->devbtn.flags&XkbSA_LockNoLock)||
463 BitIsOn(dev->button->down, button))
465 - XkbDDXFakeDeviceButton(dev,TRUE,button);
466 + XkbFakeDeviceButton(dev,TRUE,button);
467 filter->upAction.type= XkbSA_NoAction;
469 case XkbSA_DeviceBtn:
470 @@ -982,12 +986,12 @@ int button;
472 nClicks= pAction->btn.count;
473 for (i=0;i<nClicks;i++) {
474 - XkbDDXFakeDeviceButton(dev,TRUE,button);
475 - XkbDDXFakeDeviceButton(dev,FALSE,button);
476 + XkbFakeDeviceButton(dev,TRUE,button);
477 + XkbFakeDeviceButton(dev,FALSE,button);
479 filter->upAction.type= XkbSA_NoAction;
481 - else XkbDDXFakeDeviceButton(dev,TRUE,button);
482 + else XkbFakeDeviceButton(dev,TRUE,button);
486 @@ -1006,10 +1010,10 @@ int button;
487 if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)||
488 !BitIsOn(dev->button->down, button))
490 - XkbDDXFakeDeviceButton(dev,FALSE,button);
491 + XkbFakeDeviceButton(dev,FALSE,button);
493 case XkbSA_DeviceBtn:
494 - XkbDDXFakeDeviceButton(dev,FALSE,button);
495 + XkbFakeDeviceButton(dev,FALSE,button);
499 @@ -1326,3 +1330,70 @@ xkbStateNotify sn;
504 +XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
506 + EventListPtr events;
511 + if (!dev->u.master)
514 + ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
516 + if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
517 + gpe_flags = POINTER_ABSOLUTE;
519 + gpe_flags = POINTER_RELATIVE;
521 + events = InitEventList(GetMaximumEventsNum());
523 + nevents = GetPointerEvents(events, ptr,
525 + gpe_flags, 0, 2, (int[]){x, y});
526 + OsReleaseSignals();
528 + for (i = 0; i < nevents; i++)
529 + mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
531 + FreeEventList(events, GetMaximumEventsNum());
535 +XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
537 + EventListPtr events;
541 + /* If dev is a slave device, and the SD is attached, do nothing. If we'd
542 + * post through the attached master pointer we'd get duplicate events.
544 + * if dev is a master keyboard, post through the XTEST device
546 + * if dev is a floating slave, post through the device itself.
550 + ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
551 + else if (!dev->u.master)
556 + events = InitEventList(GetMaximumEventsNum());
558 + nevents = GetPointerEvents(events, ptr,
559 + press ? ButtonPress : ButtonRelease, button,
560 + 0 /* flags */, 0 /* first */,
561 + 0 /* num_val */, NULL);
562 + OsReleaseSignals();
565 + for (i = 0; i < nevents; i++)
566 + mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
568 + FreeEventList(events, GetMaximumEventsNum());
573 From dcb46252f959893f1934232698e2ae26390a8a5b Mon Sep 17 00:00:00 2001
574 From: Peter Hutterer <peter.hutterer@who-t.net>
575 Date: Tue, 29 Jun 2010 15:24:51 +1000
576 Subject: [PATCH 4/5] xkb: emulate PointerKeys events only on the master device.
578 This patch replicates the behaviour for button events. Only generate a
579 PointerKeys motion event on the master device, not on the slave device.
580 Fixes the current issue of PointerKey motion events generating key events as
583 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
585 xkb/xkbActions.c | 9 ++++-----
586 1 files changed, 4 insertions(+), 5 deletions(-)
588 diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
589 index 2817e39..391c375 100644
590 --- a/xkb/xkbActions.c
591 +++ b/xkb/xkbActions.c
592 @@ -496,9 +496,6 @@ _XkbFilterPointerMove( XkbSrvInfoPtr xkbi,
596 - if (xkbi->device == inputInfo.keyboard)
599 if (filter->keycode==0) { /* initial press */
600 filter->keycode = keycode;
602 @@ -1338,10 +1335,12 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
606 - if (!dev->u.master)
608 + ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
609 + else if (!dev->u.master)
612 - ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
615 if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY)
616 gpe_flags = POINTER_ABSOLUTE;
620 From 40941fb2e9ae763add7b74850e8a0471ac754db6 Mon Sep 17 00:00:00 2001
621 From: Peter Hutterer <peter.hutterer@who-t.net>
622 Date: Thu, 1 Jul 2010 12:44:57 +1000
623 Subject: [PATCH 5/5] xkb: release XTEST pointer buttons on physical releases. (#28808)
625 If a button release event is posted for the MD pointer, post a release event
626 through the matching XTEST device. This way, a client who posts a button
627 press through the XTEST extension cannot inadvertedly lock the button.
629 This behaviour is required for historical reasons, until server 1.7 the core
630 pointer would release a button press on physical events, regardless of the
631 XTEST state. Clients seem to rely on this behaviour, causing seemingly stuck
634 The merged behaviour is kept for multiple keyboard PointerKey events, if two
635 physical keyboards hold the button down as a result of PointerKey actions,
636 the button is not released until the last keyboard releases the button.
638 X.Org Bug 28808 <http://bugs.freedesktop.org/show_bug.cgi?id=28808>
640 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
642 include/xkbsrv.h | 6 ++++++
643 xkb/xkbAccessX.c | 23 ++++++++++-------------
644 xkb/xkbActions.c | 4 ++--
645 3 files changed, 18 insertions(+), 15 deletions(-)
647 diff --git a/include/xkbsrv.h b/include/xkbsrv.h
648 index d1cbd1a..a96ca56 100644
649 --- a/include/xkbsrv.h
650 +++ b/include/xkbsrv.h
651 @@ -923,6 +923,12 @@ extern int XkbGetEffectiveGroup(
652 extern void XkbMergeLockedPtrBtns(
653 DeviceIntPtr /* master */);
655 +extern void XkbFakeDeviceButton(
656 + DeviceIntPtr /* dev */,
662 #include "xkbrules.h"
664 diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c
665 index e3fdc06..d3f9652 100644
666 --- a/xkb/xkbAccessX.c
667 +++ b/xkb/xkbAccessX.c
668 @@ -710,19 +710,16 @@ DeviceEvent *event = &ev->device_event;
670 xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7));
672 - /* Merge this MD's lockedPtrButtons with the one of all
673 - * attached slave devices.
674 - * The DIX uses a merged button state for MDs, not
675 - * releasing buttons until the last SD has released
676 - * thenm. If we unconditionally clear the
677 - * lockedPtrButtons bit on the MD, a PointerKeys button
678 - * release on the SD keyboard won't generate the required fake button
679 - * event on the XTEST pointer, thus never processing the
680 - * button event in the DIX and the XTEST pointer's
681 - * buttons stay down - result is a stuck button.
684 - XkbMergeLockedPtrBtns(dev);
687 + DeviceIntPtr source;
689 + rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess);
691 + ErrorF("[xkb] bad sourceid '%d' on button release event.\n", event->sourceid);
692 + else if (!IsXTestDevice(source, GetMaster(dev, MASTER_POINTER)))
693 + XkbFakeDeviceButton(dev, FALSE, event->detail.key);
697 changed |= XkbPointerButtonMask;
698 diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
699 index 391c375..5d40199 100644
700 --- a/xkb/xkbActions.c
701 +++ b/xkb/xkbActions.c
702 @@ -46,7 +46,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
703 static int xkbDevicePrivateKeyIndex;
704 DevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKeyIndex;
706 -static void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
707 +void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button);
708 static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y);
711 @@ -1360,7 +1360,7 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
712 FreeEventList(events, GetMaximumEventsNum());
717 XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
723 From 7273832bcdc6f43e9a5a8fdbb56844466efb710a Mon Sep 17 00:00:00 2001
724 From: Peter Hutterer <peter.hutterer@who-t.net>
725 Date: Fri, 23 Jul 2010 11:46:30 +1000
726 Subject: [PATCH 1/3] xkb: post-fix PointerKeys button events with a DeviceChangedEvent.
728 commit 14327858391ebe929b806efb53ad79e789361883
729 xkb: release XTEST pointer buttons on physical releases. (#28808)
730 revealed a bug with the XTEST/PointerKeys interaction.
732 Events resulting from PointerKeys are injected into the event processing
733 stream, not appended to the event queue. The events generated for the fake
734 button press include a DeviceChangedEvent (DCE), a raw button event and the
735 button event itself. The DCE causes the master to switch classes to the
736 attached XTEST pointer device.
738 Once the fake button is processed, normal event processing continues with
739 events in the EQ. The master still contains the XTEST classes, causing some
740 events to be dropped if e.g. the number of valuators of the event in the
741 queue exceeds the XTEST device's number of valuators.
743 Example: the EQ contains the following events, processed one-by-one, left to
746 [DCE (dev)][Btn down][Btn up][Motion][Motion][...]
747 ^ XkbFakeDeviceButton injects [DCE (XTEST)][Btn up]
749 Thus the event sequence processed looks like this:
751 [DCE (dev)][Btn down][Btn up][DCE (XTEST)][Btn up][Motion][Motion][...]
753 The first DCE causes the master to switch to the device. The button up event
754 injects a DCE to the XTEST device, causing the following Motion events to be
755 processed with the master still being on XTEST classes.
757 This patch post-fixes the injected event sequence with a DCE to restore the
758 classes of the original slave device, resulting in an event sequence like
760 [DCE (dev)][Btn down][Btn up][DCE (XTEST)][Btn up][DCE (dev)][Motion][Motion]
762 Note that this is a simplified description. The event sequence injected by
763 the PointerKeys code is injected for the master device only and the matching
764 slave device that caused the injection has already finished processing on
765 the slave. Furthermore, the injection happens as part of the the XKB layer,
766 before the unwrapping of the processInputProc takes us into the DIX where
767 the DCE is actually handled.
769 Bug reproducible with a device that reports more than 2 valuators. Simply
770 cause button releases on the device and wait for a "too many valuators"
773 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
775 xkb/xkbActions.c | 26 +++++++++++++++++++-------
776 1 files changed, 19 insertions(+), 7 deletions(-)
778 diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
779 index 5d40199..2afd46d 100644
780 --- a/xkb/xkbActions.c
781 +++ b/xkb/xkbActions.c
782 @@ -1365,34 +1365,46 @@ XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
787 + DeviceIntPtr ptr, mpointer, lastSlave;
789 /* If dev is a slave device, and the SD is attached, do nothing. If we'd
790 * post through the attached master pointer we'd get duplicate events.
792 * if dev is a master keyboard, post through the XTEST device
794 * if dev is a floating slave, post through the device itself.
796 + * The event is injected into the event processing, not the EQ. Thus,
797 + * ensure that we restore the master after the event sequence to the
798 + * original set of classes. Otherwise, the master remains on the XTEST
799 + * classes and drops events that don't fit into the XTEST layout (e.g.
800 + * events with more than 2 valuators).
801 + * To do so, we remember the lastSlave that posted through the master
802 + * and add a DeviceChangedEvent to the end of the list.
806 - ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER));
807 - else if (!dev->u.master)
808 + if (IsMaster(dev)) {
809 + mpointer = GetMaster(dev, MASTER_POINTER);
810 + lastSlave = mpointer->u.lastSlave;
811 + ptr = GetXTestDevice(mpointer);
812 + } else if (!dev->u.master)
817 - events = InitEventList(GetMaximumEventsNum());
818 + events = InitEventList(GetMaximumEventsNum() + 1);
820 nevents = GetPointerEvents(events, ptr,
821 press ? ButtonPress : ButtonRelease, button,
822 0 /* flags */, 0 /* first */,
823 0 /* num_val */, NULL);
824 + if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
825 + CreateClassesChangedEvent(&events[nevents++], mpointer,
826 + lastSlave, DEVCHANGE_POINTER_EVENT);
830 for (i = 0; i < nevents; i++)
831 mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL);
833 - FreeEventList(events, GetMaximumEventsNum());
834 + FreeEventList(events, GetMaximumEventsNum() + 1);
839 From 817e031a996a5f5aa16fc789d7e570cc589d96cb Mon Sep 17 00:00:00 2001
840 From: Peter Hutterer <peter.hutterer@who-t.net>
841 Date: Wed, 28 Jul 2010 14:24:59 +1000
842 Subject: [PATCH 3/3] Xi: reset the unused classes pointer after copying
844 After copying the unused_classes into the device, reset the original
845 pointer. Otherwise we have two pointers pointing to the same field and both
846 get freed on device removal.
848 Some classes already have this behaviour since 51c8fd69.
850 Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
852 Xi/exevents.c | 6 ++++++
853 1 files changed, 6 insertions(+), 0 deletions(-)
855 diff --git a/Xi/exevents.c b/Xi/exevents.c
856 index 566b0ef..a6160dd 100644
859 @@ -227,6 +227,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
860 classes = dixLookupPrivate(&to->devPrivates,
861 UnusedClassesPrivateKey);
862 to->intfeed = classes->intfeed;
863 + classes->intfeed = NULL;
867 @@ -263,6 +264,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
868 classes = dixLookupPrivate(&to->devPrivates,
869 UnusedClassesPrivateKey);
870 to->stringfeed = classes->stringfeed;
871 + classes->stringfeed = NULL;
875 @@ -299,6 +301,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
876 classes = dixLookupPrivate(&to->devPrivates,
877 UnusedClassesPrivateKey);
878 to->bell = classes->bell;
879 + classes->bell = NULL;
883 @@ -336,6 +339,7 @@ DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
884 classes = dixLookupPrivate(&to->devPrivates,
885 UnusedClassesPrivateKey);
886 to->leds = classes->leds;
887 + classes->leds = NULL;
891 @@ -387,6 +391,7 @@ DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
892 to->kbdfeed = classes->kbdfeed;
894 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
895 + classes->kbdfeed = NULL;
899 @@ -517,6 +522,7 @@ DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
900 classes = dixLookupPrivate(&to->devPrivates,
901 UnusedClassesPrivateKey);
902 to->ptrfeed = classes->ptrfeed;
903 + classes->ptrfeed = NULL;