]>
Commit | Line | Data |
---|---|---|
313ed234 SS |
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. | |
5 | ||
6 | Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> | |
7 | --- | |
8 | xkb/xkbActions.c | 2 ++ | |
9 | 1 files changed, 2 insertions(+), 0 deletions(-) | |
10 | ||
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, | |
16 | break; | |
17 | } | |
18 | xkbi->lockedPtrButtons&= ~(1<<button); | |
19 | + | |
20 | + /* fallthrough */ | |
21 | case XkbSA_PtrBtn: | |
22 | XkbDDXFakeDeviceButton(xkbi->device, 0, button); | |
23 | break; | |
24 | -- | |
25 | 1.7.1 | |
26 | ||
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. | |
31 | MIME-Version: 1.0 | |
32 | Content-Type: text/plain; charset=UTF-8 | |
33 | Content-Transfer-Encoding: 8bit | |
34 | ||
35 | Problem: | |
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 | |
38 | sequence of events: | |
39 | ||
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 | |
45 | ||
46 | Button 1 on the MD is now stuck and cannot be released. | |
47 | ||
48 | Cause: | |
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. | |
53 | ||
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. | |
62 | ||
63 | Solution: | |
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 | |
69 | in the DIX. | |
70 | ||
71 | Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> | |
72 | --- | |
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(-) | |
78 | ||
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 */, | |
85 | CARD8 /* keycode */); | |
86 | ||
87 | +extern void XkbMergeLockedPtrBtns( | |
88 | + DeviceIntPtr /* master */); | |
89 | + | |
90 | #include "xkbfile.h" | |
91 | #include "xkbrules.h" | |
92 | ||
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; | |
99 | } | |
100 | else if (event->type == ET_ButtonRelease) { | |
101 | - if (xkbi) | |
102 | + if (xkbi) { | |
103 | xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7)); | |
104 | + | |
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. | |
115 | + */ | |
116 | + if (IsMaster(dev)) | |
117 | + XkbMergeLockedPtrBtns(dev); | |
118 | + } | |
119 | + | |
120 | changed |= XkbPointerButtonMask; | |
121 | } | |
122 | ||
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, | |
128 | } | |
129 | xkbi->lockedPtrButtons&= ~(1<<button); | |
130 | ||
131 | + if (IsMaster(xkbi->device)) | |
132 | + { | |
133 | + XkbMergeLockedPtrBtns(xkbi->device); | |
134 | + /* One SD still has lock set, don't post event */ | |
135 | + if ((xkbi->lockedPtrButtons & (1 << button)) != 0) | |
136 | + break; | |
137 | + } | |
138 | + | |
139 | /* fallthrough */ | |
140 | case XkbSA_PtrBtn: | |
141 | XkbDDXFakeDeviceButton(xkbi->device, 0, button); | |
142 | diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c | |
143 | index b1e0e55..d7d1935 100644 | |
144 | --- a/xkb/xkbUtils.c | |
145 | +++ b/xkb/xkbUtils.c | |
146 | @@ -2190,3 +2190,29 @@ XkbGetEffectiveGroup(XkbSrvInfoPtr xkbi, XkbStatePtr xkbState, CARD8 keycode) | |
147 | ||
148 | return effectiveGroup; | |
149 | } | |
150 | + | |
151 | +/* Merge the lockedPtrButtons from all attached SDs for the given master | |
152 | + * device into the MD's state. | |
153 | + */ | |
154 | +void | |
155 | +XkbMergeLockedPtrBtns(DeviceIntPtr master) | |
156 | +{ | |
157 | + DeviceIntPtr d = inputInfo.devices; | |
158 | + XkbSrvInfoPtr xkbi = NULL; | |
159 | + | |
160 | + if (!IsMaster(master)) | |
161 | + return; | |
162 | + | |
163 | + if (!master->key) | |
164 | + return; | |
165 | + | |
166 | + xkbi = master->key->xkbInfo; | |
167 | + xkbi->lockedPtrButtons = 0; | |
168 | + | |
169 | + for (; d; d = d->next) { | |
170 | + if (IsMaster(d) || GetMaster(d, MASTER_KEYBOARD) != master || !d->key) | |
171 | + continue; | |
172 | + | |
173 | + xkbi->lockedPtrButtons |= d->key->xkbInfo->lockedPtrButtons; | |
174 | + } | |
175 | +} | |
176 | -- | |
177 | 1.7.1 | |
178 | ||
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 | |
183 | ||
184 | The name XkbDDXFakeDeviceButton and XkbDDXFakeDeviceMotion is somewhat | |
185 | misleading, there's no DDX involved in the game at all anymore. | |
186 | ||
187 | This removes XkbFakeDeviceMotion and XkbFakeDeviceButton from the API where | |
188 | it arguably shouldn't have been in the first place. | |
189 | ||
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> | |
193 | --- | |
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 | |
202 | ||
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 */ | |
209 | ); | |
210 | ||
211 | -extern _X_EXPORT void XkbDDXFakePointerMotion( | |
212 | - DeviceIntPtr /* dev */, | |
213 | - unsigned int /* flags */, | |
214 | - int /* x */, | |
215 | - int /* y */ | |
216 | -); | |
217 | - | |
218 | -extern _X_EXPORT void XkbDDXFakeDeviceButton( | |
219 | - DeviceIntPtr /* dev */, | |
220 | - Bool /* press */, | |
221 | - int /* button */ | |
222 | -); | |
223 | - | |
224 | extern _X_EXPORT int XkbDDXTerminateServer( | |
225 | DeviceIntPtr /* dev */, | |
226 | KeyCode /* key */, | |
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) | |
232 | DDX_SRCS = \ | |
233 | ddxBeep.c \ | |
234 | ddxCtrls.c \ | |
235 | - ddxFakeMtn.c \ | |
236 | ddxLEDs.c \ | |
237 | ddxLoad.c \ | |
238 | - ddxList.c \ | |
239 | - ddxDevBtn.c | |
240 | + ddxList.c | |
241 | ||
242 | DIX_SRCS = \ | |
243 | xkb.c \ | |
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 | |
248 | +++ /dev/null | |
249 | @@ -1,69 +0,0 @@ | |
250 | -/************************************************************ | |
251 | -Copyright (c) 1995 by Silicon Graphics Computer Systems, Inc. | |
252 | - | |
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. | |
264 | - | |
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. | |
273 | - | |
274 | -********************************************************/ | |
275 | - | |
276 | -#ifdef HAVE_DIX_CONFIG_H | |
277 | -#include <dix-config.h> | |
278 | -#endif | |
279 | - | |
280 | -#include "inputstr.h" | |
281 | -#include <xkbsrv.h> | |
282 | -#include "mi.h" | |
283 | - | |
284 | -void | |
285 | -XkbDDXFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) | |
286 | -{ | |
287 | - EventListPtr events; | |
288 | - int nevents, i; | |
289 | - DeviceIntPtr ptr; | |
290 | - | |
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. | |
293 | - * | |
294 | - * if dev is a master keyboard, post through the XTEST device | |
295 | - * | |
296 | - * if dev is a floating slave, post through the device itself. | |
297 | - */ | |
298 | - | |
299 | - if (IsMaster(dev)) | |
300 | - ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER)); | |
301 | - else if (!dev->u.master) | |
302 | - ptr = dev; | |
303 | - else | |
304 | - return; | |
305 | - | |
306 | - events = InitEventList(GetMaximumEventsNum()); | |
307 | - OsBlockSignals(); | |
308 | - nevents = GetPointerEvents(events, ptr, | |
309 | - press ? ButtonPress : ButtonRelease, button, | |
310 | - 0 /* flags */, 0 /* first */, | |
311 | - 0 /* num_val */, NULL); | |
312 | - OsReleaseSignals(); | |
313 | - | |
314 | - for (i = 0; i < nevents; i++) | |
315 | - mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); | |
316 | - | |
317 | - FreeEventList(events, GetMaximumEventsNum()); | |
318 | -} | |
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 | |
323 | +++ /dev/null | |
324 | @@ -1,64 +0,0 @@ | |
325 | -/************************************************************ | |
326 | -Copyright (c) 1993 by Silicon Graphics Computer Systems, Inc. | |
327 | - | |
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. | |
339 | - | |
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. | |
348 | - | |
349 | -********************************************************/ | |
350 | - | |
351 | -#ifdef HAVE_DIX_CONFIG_H | |
352 | -#include <dix-config.h> | |
353 | -#endif | |
354 | - | |
355 | -#include "inputstr.h" | |
356 | -#include <xkbsrv.h> | |
357 | -#include "mi.h" | |
358 | - | |
359 | -void | |
360 | -XkbDDXFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) | |
361 | -{ | |
362 | - EventListPtr events; | |
363 | - int nevents, i; | |
364 | - DeviceIntPtr ptr; | |
365 | - int gpe_flags = 0; | |
366 | - | |
367 | - if (!dev->u.master) | |
368 | - ptr = dev; | |
369 | - else | |
370 | - ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER)); | |
371 | - | |
372 | - if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY) | |
373 | - gpe_flags = POINTER_ABSOLUTE; | |
374 | - else | |
375 | - gpe_flags = POINTER_RELATIVE; | |
376 | - | |
377 | - events = InitEventList(GetMaximumEventsNum()); | |
378 | - OsBlockSignals(); | |
379 | - nevents = GetPointerEvents(events, ptr, | |
380 | - MotionNotify, 0, | |
381 | - gpe_flags, 0, 2, (int[]){x, y}); | |
382 | - OsReleaseSignals(); | |
383 | - | |
384 | - for (i = 0; i < nevents; i++) | |
385 | - mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); | |
386 | - | |
387 | - FreeEventList(events, GetMaximumEventsNum()); | |
388 | -} | |
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. | |
394 | #include <xkbsrv.h> | |
395 | #include "xkb.h" | |
396 | #include <ctype.h> | |
397 | +#include "mi.h" | |
398 | #define EXTENSION_EVENT_BASE 64 | |
399 | ||
400 | static int xkbDevicePrivateKeyIndex; | |
401 | DevPrivateKey xkbDevicePrivateKey = &xkbDevicePrivateKeyIndex; | |
402 | ||
403 | +static void XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button); | |
404 | +static void XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y); | |
405 | + | |
406 | void | |
407 | xkbUnwrapProc(DeviceIntPtr device, DeviceHandleProc proc, | |
408 | pointer data) | |
409 | @@ -479,7 +483,7 @@ int dx,dy; | |
410 | dx= xkbi->mouseKeysDX; | |
411 | dy= xkbi->mouseKeysDY; | |
412 | } | |
413 | - XkbDDXFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy); | |
414 | + XkbFakePointerMotion(xkbi->device, xkbi->mouseKeysFlags,dx,dy); | |
415 | return xkbi->desc->ctrls->mk_interval; | |
416 | } | |
417 | ||
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; | |
434 | } | |
435 | break; | |
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); | |
444 | } | |
445 | filter->upAction.type= XkbSA_NoAction; | |
446 | } | |
447 | - else XkbDDXFakeDeviceButton(xkbi->device, 1, button); | |
448 | + else XkbFakeDeviceButton(xkbi->device, 1, button); | |
449 | } | |
450 | break; | |
451 | case XkbSA_SetPtrDflt: | |
452 | @@ -636,7 +640,7 @@ _XkbFilterPointerBtn( XkbSrvInfoPtr xkbi, | |
453 | ||
454 | /* fallthrough */ | |
455 | case XkbSA_PtrBtn: | |
456 | - XkbDDXFakeDeviceButton(xkbi->device, 0, button); | |
457 | + XkbFakeDeviceButton(xkbi->device, 0, button); | |
458 | break; | |
459 | } | |
460 | filter->active = 0; | |
461 | @@ -974,7 +978,7 @@ int button; | |
462 | if ((pAction->devbtn.flags&XkbSA_LockNoLock)|| | |
463 | BitIsOn(dev->button->down, button)) | |
464 | return 0; | |
465 | - XkbDDXFakeDeviceButton(dev,TRUE,button); | |
466 | + XkbFakeDeviceButton(dev,TRUE,button); | |
467 | filter->upAction.type= XkbSA_NoAction; | |
468 | break; | |
469 | case XkbSA_DeviceBtn: | |
470 | @@ -982,12 +986,12 @@ int button; | |
471 | int nClicks,i; | |
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); | |
478 | } | |
479 | filter->upAction.type= XkbSA_NoAction; | |
480 | } | |
481 | - else XkbDDXFakeDeviceButton(dev,TRUE,button); | |
482 | + else XkbFakeDeviceButton(dev,TRUE,button); | |
483 | break; | |
484 | } | |
485 | } | |
486 | @@ -1006,10 +1010,10 @@ int button; | |
487 | if ((filter->upAction.devbtn.flags&XkbSA_LockNoUnlock)|| | |
488 | !BitIsOn(dev->button->down, button)) | |
489 | return 0; | |
490 | - XkbDDXFakeDeviceButton(dev,FALSE,button); | |
491 | + XkbFakeDeviceButton(dev,FALSE,button); | |
492 | break; | |
493 | case XkbSA_DeviceBtn: | |
494 | - XkbDDXFakeDeviceButton(dev,FALSE,button); | |
495 | + XkbFakeDeviceButton(dev,FALSE,button); | |
496 | break; | |
497 | } | |
498 | filter->active = 0; | |
499 | @@ -1326,3 +1330,70 @@ xkbStateNotify sn; | |
500 | return; | |
501 | } | |
502 | ||
503 | +static void | |
504 | +XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) | |
505 | +{ | |
506 | + EventListPtr events; | |
507 | + int nevents, i; | |
508 | + DeviceIntPtr ptr; | |
509 | + int gpe_flags = 0; | |
510 | + | |
511 | + if (!dev->u.master) | |
512 | + ptr = dev; | |
513 | + else | |
514 | + ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER)); | |
515 | + | |
516 | + if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY) | |
517 | + gpe_flags = POINTER_ABSOLUTE; | |
518 | + else | |
519 | + gpe_flags = POINTER_RELATIVE; | |
520 | + | |
521 | + events = InitEventList(GetMaximumEventsNum()); | |
522 | + OsBlockSignals(); | |
523 | + nevents = GetPointerEvents(events, ptr, | |
524 | + MotionNotify, 0, | |
525 | + gpe_flags, 0, 2, (int[]){x, y}); | |
526 | + OsReleaseSignals(); | |
527 | + | |
528 | + for (i = 0; i < nevents; i++) | |
529 | + mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); | |
530 | + | |
531 | + FreeEventList(events, GetMaximumEventsNum()); | |
532 | +} | |
533 | + | |
534 | +static void | |
535 | +XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) | |
536 | +{ | |
537 | + EventListPtr events; | |
538 | + int nevents, i; | |
539 | + DeviceIntPtr ptr; | |
540 | + | |
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. | |
543 | + * | |
544 | + * if dev is a master keyboard, post through the XTEST device | |
545 | + * | |
546 | + * if dev is a floating slave, post through the device itself. | |
547 | + */ | |
548 | + | |
549 | + if (IsMaster(dev)) | |
550 | + ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER)); | |
551 | + else if (!dev->u.master) | |
552 | + ptr = dev; | |
553 | + else | |
554 | + return; | |
555 | + | |
556 | + events = InitEventList(GetMaximumEventsNum()); | |
557 | + OsBlockSignals(); | |
558 | + nevents = GetPointerEvents(events, ptr, | |
559 | + press ? ButtonPress : ButtonRelease, button, | |
560 | + 0 /* flags */, 0 /* first */, | |
561 | + 0 /* num_val */, NULL); | |
562 | + OsReleaseSignals(); | |
563 | + | |
564 | + | |
565 | + for (i = 0; i < nevents; i++) | |
566 | + mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); | |
567 | + | |
568 | + FreeEventList(events, GetMaximumEventsNum()); | |
569 | +} | |
570 | -- | |
571 | 1.7.1 | |
572 | ||
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. | |
577 | ||
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 | |
581 | well. | |
582 | ||
583 | Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> | |
584 | --- | |
585 | xkb/xkbActions.c | 9 ++++----- | |
586 | 1 files changed, 4 insertions(+), 5 deletions(-) | |
587 | ||
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, | |
593 | int x,y; | |
594 | Bool accel; | |
595 | ||
596 | - if (xkbi->device == inputInfo.keyboard) | |
597 | - return 0; | |
598 | - | |
599 | if (filter->keycode==0) { /* initial press */ | |
600 | filter->keycode = keycode; | |
601 | filter->active = 1; | |
602 | @@ -1338,10 +1335,12 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) | |
603 | DeviceIntPtr ptr; | |
604 | int gpe_flags = 0; | |
605 | ||
606 | - if (!dev->u.master) | |
607 | + if (IsMaster(dev)) | |
608 | + ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER)); | |
609 | + else if (!dev->u.master) | |
610 | ptr = dev; | |
611 | else | |
612 | - ptr = GetXTestDevice(GetMaster(dev, MASTER_POINTER)); | |
613 | + return; | |
614 | ||
615 | if (flags & XkbSA_MoveAbsoluteX || flags & XkbSA_MoveAbsoluteY) | |
616 | gpe_flags = POINTER_ABSOLUTE; | |
617 | -- | |
618 | 1.7.1 | |
619 | ||
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) | |
624 | ||
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. | |
628 | ||
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 | |
632 | grabs. | |
633 | ||
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. | |
637 | ||
638 | X.Org Bug 28808 <http://bugs.freedesktop.org/show_bug.cgi?id=28808> | |
639 | ||
640 | Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> | |
641 | --- | |
642 | include/xkbsrv.h | 6 ++++++ | |
643 | xkb/xkbAccessX.c | 23 ++++++++++------------- | |
644 | xkb/xkbActions.c | 4 ++-- | |
645 | 3 files changed, 18 insertions(+), 15 deletions(-) | |
646 | ||
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 */); | |
654 | ||
655 | +extern void XkbFakeDeviceButton( | |
656 | + DeviceIntPtr /* dev */, | |
657 | + int /* press */, | |
658 | + int /* button */); | |
659 | + | |
660 | + | |
661 | #include "xkbfile.h" | |
662 | #include "xkbrules.h" | |
663 | ||
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; | |
669 | if (xkbi) { | |
670 | xkbi->lockedPtrButtons&= ~(1 << (event->detail.key & 0x7)); | |
671 | ||
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. | |
682 | - */ | |
683 | - if (IsMaster(dev)) | |
684 | - XkbMergeLockedPtrBtns(dev); | |
685 | + if (IsMaster(dev)) | |
686 | + { | |
687 | + DeviceIntPtr source; | |
688 | + int rc; | |
689 | + rc = dixLookupDevice(&source, event->sourceid, serverClient, DixWriteAccess); | |
690 | + if (rc != Success) | |
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); | |
694 | + } | |
695 | } | |
696 | ||
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; | |
705 | ||
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); | |
709 | ||
710 | void | |
711 | @@ -1360,7 +1360,7 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y) | |
712 | FreeEventList(events, GetMaximumEventsNum()); | |
713 | } | |
714 | ||
715 | -static void | |
716 | +void | |
717 | XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button) | |
718 | { | |
719 | EventListPtr events; | |
720 | -- | |
721 | 1.7.1 | |
722 | ||
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. | |
727 | ||
728 | commit 14327858391ebe929b806efb53ad79e789361883 | |
729 | xkb: release XTEST pointer buttons on physical releases. (#28808) | |
730 | revealed a bug with the XTEST/PointerKeys interaction. | |
731 | ||
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. | |
737 | ||
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. | |
742 | ||
743 | Example: the EQ contains the following events, processed one-by-one, left to | |
744 | right. | |
745 | ||
746 | [DCE (dev)][Btn down][Btn up][Motion][Motion][...] | |
747 | ^ XkbFakeDeviceButton injects [DCE (XTEST)][Btn up] | |
748 | ||
749 | Thus the event sequence processed looks like this: | |
750 | ||
751 | [DCE (dev)][Btn down][Btn up][DCE (XTEST)][Btn up][Motion][Motion][...] | |
752 | ||
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. | |
756 | ||
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 | |
759 | this: | |
760 | [DCE (dev)][Btn down][Btn up][DCE (XTEST)][Btn up][DCE (dev)][Motion][Motion] | |
761 | ||
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. | |
768 | ||
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" | |
771 | warning message. | |
772 | ||
773 | Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> | |
774 | --- | |
775 | xkb/xkbActions.c | 26 +++++++++++++++++++------- | |
776 | 1 files changed, 19 insertions(+), 7 deletions(-) | |
777 | ||
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) | |
783 | { | |
784 | EventListPtr events; | |
785 | int nevents, i; | |
786 | - DeviceIntPtr ptr; | |
787 | + DeviceIntPtr ptr, mpointer, lastSlave; | |
788 | ||
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. | |
791 | * | |
792 | * if dev is a master keyboard, post through the XTEST device | |
793 | - * | |
794 | * if dev is a floating slave, post through the device itself. | |
795 | + * | |
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. | |
803 | */ | |
804 | ||
805 | - if (IsMaster(dev)) | |
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) | |
813 | ptr = dev; | |
814 | else | |
815 | return; | |
816 | ||
817 | - events = InitEventList(GetMaximumEventsNum()); | |
818 | + events = InitEventList(GetMaximumEventsNum() + 1); | |
819 | OsBlockSignals(); | |
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); | |
827 | OsReleaseSignals(); | |
828 | ||
829 | ||
830 | for (i = 0; i < nevents; i++) | |
831 | mieqProcessDeviceEvent(ptr, (InternalEvent*)events[i].event, NULL); | |
832 | ||
833 | - FreeEventList(events, GetMaximumEventsNum()); | |
834 | + FreeEventList(events, GetMaximumEventsNum() + 1); | |
835 | } | |
836 | -- | |
837 | 1.7.2 | |
838 | ||
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 | |
843 | ||
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. | |
847 | ||
848 | Some classes already have this behaviour since 51c8fd69. | |
849 | ||
850 | Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> | |
851 | --- | |
852 | Xi/exevents.c | 6 ++++++ | |
853 | 1 files changed, 6 insertions(+), 0 deletions(-) | |
854 | ||
855 | diff --git a/Xi/exevents.c b/Xi/exevents.c | |
856 | index 566b0ef..a6160dd 100644 | |
857 | --- a/Xi/exevents.c | |
858 | +++ b/Xi/exevents.c | |
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; | |
864 | } | |
865 | ||
866 | i = &to->intfeed; | |
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; | |
872 | } | |
873 | ||
874 | s = &to->stringfeed; | |
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; | |
880 | } | |
881 | ||
882 | b = &to->bell; | |
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; | |
888 | } | |
889 | ||
890 | l = &to->leds; | |
891 | @@ -387,6 +391,7 @@ DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to) | |
892 | to->kbdfeed = classes->kbdfeed; | |
893 | if (!to->kbdfeed) | |
894 | InitKeyboardDeviceStruct(to, NULL, NULL, NULL); | |
895 | + classes->kbdfeed = NULL; | |
896 | } | |
897 | ||
898 | k = &to->kbdfeed; | |
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; | |
904 | } | |
905 | ||
906 | p = &to->ptrfeed; | |
907 | -- | |
908 | 1.7.2 | |
909 |