1 /*
2 
3    Copyright 1992, 1998  The Open Group
4 
5    Permission to use, copy, modify, distribute, and sell this software and its
6    documentation for any purpose is hereby granted without fee, provided that
7    the above copyright notice appear in all copies and that both that
8    copyright notice and this permission notice appear in supporting
9    documentation.
10 
11    The above copyright notice and this permission notice shall be included
12    in all copies or substantial portions of the Software.
13 
14    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17    IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18    OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19    ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20    OTHER DEALINGS IN THE SOFTWARE.
21 
22    Except as contained in this notice, the name of The Open Group shall
23    not be used in advertising or otherwise to promote the sale, use or
24    other dealings in this Software without prior written authorization
25    from The Open Group.
26 
27  */
28 
29 #ifdef HAVE_DIX_CONFIG_H
30 #include <dix-config.h>
31 #endif
32 
33 #include <X11/X.h>
34 #include <X11/Xproto.h>
35 #include <X11/Xatom.h>
36 #include "misc.h"
37 #include "os.h"
38 #include "dixstruct.h"
39 #include "extnsionst.h"
40 #include "windowstr.h"
41 #include "inputstr.h"
42 #include "scrnintstr.h"
43 #include "dixevents.h"
44 #include "sleepuntil.h"
45 #include "mi.h"
46 #include "xkbsrv.h"
47 #include "xkbstr.h"
48 #include <X11/extensions/xtestproto.h>
49 #include <X11/extensions/XI.h>
50 #include <X11/extensions/XIproto.h>
51 #include "exglobals.h"
52 #include "mipointer.h"
53 #include "xserver-properties.h"
54 #include "exevents.h"
55 #include "eventstr.h"
56 #include "inpututils.h"
57 
58 #include "extinit.h"
59 
60 /* XTest events are sent during request processing and may be interruped by
61  * a SIGIO. We need a separate event list to avoid events overwriting each
62  * other's memory */
63 static InternalEvent *xtest_evlist;
64 
65 /**
66  * xtestpointer
67  * is the virtual pointer for XTest. It is the first slave
68  * device of the VCP.
69  * xtestkeyboard
70  * is the virtual keyboard for XTest. It is the first slave
71  * device of the VCK
72  *
73  * Neither of these devices can be deleted.
74  */
75 DeviceIntPtr xtestpointer, xtestkeyboard;
76 
77 #ifdef PANORAMIX
78 #include "panoramiX.h"
79 #include "panoramiXsrv.h"
80 #endif
81 
82 static int XTestSwapFakeInput(ClientPtr /* client */ ,
83                               xReq *    /* req */
84     );
85 
86 static int
ProcXTestGetVersion(ClientPtr client)87 ProcXTestGetVersion(ClientPtr client)
88 {
89     xXTestGetVersionReply rep = {
90         .type = X_Reply,
91         .sequenceNumber = client->sequence,
92         .length = 0,
93         .majorVersion = XTestMajorVersion,
94         .minorVersion = XTestMinorVersion
95     };
96 
97     REQUEST_SIZE_MATCH(xXTestGetVersionReq);
98 
99     if (client->swapped) {
100         swaps(&rep.sequenceNumber);
101         swaps(&rep.minorVersion);
102     }
103     WriteToClient(client, sizeof(xXTestGetVersionReply), &rep);
104     return Success;
105 }
106 
107 static int
ProcXTestCompareCursor(ClientPtr client)108 ProcXTestCompareCursor(ClientPtr client)
109 {
110     REQUEST(xXTestCompareCursorReq);
111     xXTestCompareCursorReply rep;
112     WindowPtr pWin;
113     CursorPtr pCursor;
114     int rc;
115     DeviceIntPtr ptr = PickPointer(client);
116 
117     REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
118     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
119     if (rc != Success)
120         return rc;
121 
122     if (!ptr)
123         return BadAccess;
124 
125     if (stuff->cursor == None)
126         pCursor = NullCursor;
127     else if (stuff->cursor == XTestCurrentCursor)
128         pCursor = GetSpriteCursor(ptr);
129     else {
130         rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor,
131                                      RT_CURSOR, client, DixReadAccess);
132         if (rc != Success) {
133             client->errorValue = stuff->cursor;
134             return rc;
135         }
136     }
137     rep = (xXTestCompareCursorReply) {
138         .type = X_Reply,
139         .sequenceNumber = client->sequence,
140         .length = 0,
141         .same = (wCursor(pWin) == pCursor)
142     };
143     if (client->swapped) {
144         swaps(&rep.sequenceNumber);
145     }
146     WriteToClient(client, sizeof(xXTestCompareCursorReply), &rep);
147     return Success;
148 }
149 
150 static int
ProcXTestFakeInput(ClientPtr client)151 ProcXTestFakeInput(ClientPtr client)
152 {
153     REQUEST(xXTestFakeInputReq);
154     int nev, n, type, rc;
155     xEvent *ev;
156     DeviceIntPtr dev = NULL;
157     WindowPtr root;
158     Bool extension = FALSE;
159     ValuatorMask mask;
160     int valuators[MAX_VALUATORS] = { 0 };
161     int numValuators = 0;
162     int firstValuator = 0;
163     int nevents = 0;
164     int i;
165     int base = 0;
166     int flags = 0;
167     int need_ptr_update = 1;
168 
169     nev = (stuff->length << 2) - sizeof(xReq);
170     if ((nev % sizeof(xEvent)) || !nev)
171         return BadLength;
172     nev /= sizeof(xEvent);
173     UpdateCurrentTime();
174     ev = (xEvent *) &((xReq *) stuff)[1];
175     type = ev->u.u.type & 0177;
176 
177     if (type >= EXTENSION_EVENT_BASE) {
178         extension = TRUE;
179 
180         /* check device */
181         rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client,
182                              DixWriteAccess);
183         if (rc != Success) {
184             client->errorValue = stuff->deviceid & 0177;
185             return rc;
186         }
187 
188         /* check type */
189         type -= DeviceValuator;
190         switch (type) {
191         case XI_DeviceKeyPress:
192         case XI_DeviceKeyRelease:
193             if (!dev->key) {
194                 client->errorValue = ev->u.u.type;
195                 return BadValue;
196             }
197             break;
198         case XI_DeviceButtonPress:
199         case XI_DeviceButtonRelease:
200             if (!dev->button) {
201                 client->errorValue = ev->u.u.type;
202                 return BadValue;
203             }
204             break;
205         case XI_DeviceMotionNotify:
206             if (!dev->valuator) {
207                 client->errorValue = ev->u.u.type;
208                 return BadValue;
209             }
210             break;
211         case XI_ProximityIn:
212         case XI_ProximityOut:
213             if (!dev->proximity) {
214                 client->errorValue = ev->u.u.type;
215                 return BadValue;
216             }
217             break;
218         default:
219             client->errorValue = ev->u.u.type;
220             return BadValue;
221         }
222 
223         /* check validity */
224         if (nev == 1 && type == XI_DeviceMotionNotify)
225             return BadLength;   /* DevMotion must be followed by DevValuator */
226 
227         if (type == XI_DeviceMotionNotify) {
228             firstValuator = ((deviceValuator *) (ev + 1))->first_valuator;
229             if (firstValuator > dev->valuator->numAxes) {
230                 client->errorValue = ev->u.u.type;
231                 return BadValue;
232             }
233 
234             if (ev->u.u.detail == xFalse)
235                 flags |= POINTER_ABSOLUTE;
236         }
237         else {
238             firstValuator = 0;
239             flags |= POINTER_ABSOLUTE;
240         }
241 
242         if (nev > 1 && !dev->valuator) {
243             client->errorValue = firstValuator;
244             return BadValue;
245         }
246 
247         /* check validity of valuator events */
248         base = firstValuator;
249         for (n = 1; n < nev; n++) {
250             deviceValuator *dv = (deviceValuator *) (ev + n);
251             if (dv->type != DeviceValuator) {
252                 client->errorValue = dv->type;
253                 return BadValue;
254             }
255             if (dv->first_valuator != base) {
256                 client->errorValue = dv->first_valuator;
257                 return BadValue;
258             }
259             switch (dv->num_valuators) {
260             case 6:
261                 valuators[base + 5] = dv->valuator5;
262             case 5:
263                 valuators[base + 4] = dv->valuator4;
264             case 4:
265                 valuators[base + 3] = dv->valuator3;
266             case 3:
267                 valuators[base + 2] = dv->valuator2;
268             case 2:
269                 valuators[base + 1] = dv->valuator1;
270             case 1:
271                 valuators[base] = dv->valuator0;
272                 break;
273             default:
274                 client->errorValue = dv->num_valuators;
275                 return BadValue;
276             }
277 
278             base += dv->num_valuators;
279             numValuators += dv->num_valuators;
280 
281             if (firstValuator + numValuators > dev->valuator->numAxes) {
282                 client->errorValue = dv->num_valuators;
283                 return BadValue;
284             }
285         }
286         type = type - XI_DeviceKeyPress + KeyPress;
287 
288     }
289     else {
290         if (nev != 1)
291             return BadLength;
292         switch (type) {
293         case KeyPress:
294         case KeyRelease:
295             dev = PickKeyboard(client);
296             break;
297         case ButtonPress:
298         case ButtonRelease:
299             dev = PickPointer(client);
300             break;
301         case MotionNotify:
302             dev = PickPointer(client);
303             valuators[0] = ev->u.keyButtonPointer.rootX;
304             valuators[1] = ev->u.keyButtonPointer.rootY;
305             numValuators = 2;
306             firstValuator = 0;
307             if (ev->u.u.detail == xFalse)
308                 flags = POINTER_ABSOLUTE | POINTER_DESKTOP;
309             break;
310         default:
311             client->errorValue = ev->u.u.type;
312             return BadValue;
313         }
314 
315         /* Technically the protocol doesn't allow for BadAccess here but
316          * this can only happen when all MDs are disabled.  */
317         if (!dev)
318             return BadAccess;
319 
320         dev = GetXTestDevice(dev);
321     }
322 
323 
324     /* If the event has a time set, wait for it to pass */
325     if (ev->u.keyButtonPointer.time) {
326         TimeStamp activateTime;
327         CARD32 ms;
328 
329         activateTime = currentTime;
330         ms = activateTime.milliseconds + ev->u.keyButtonPointer.time;
331         if (ms < activateTime.milliseconds)
332             activateTime.months++;
333         activateTime.milliseconds = ms;
334         ev->u.keyButtonPointer.time = 0;
335 
336         /* see mbuf.c:QueueDisplayRequest (from the deprecated Multibuffer
337          * extension) for code similar to this */
338 
339         if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) {
340             return BadAlloc;
341         }
342         /* swap the request back so we can simply re-execute it */
343         if (client->swapped) {
344             (void) XTestSwapFakeInput(client, (xReq *) stuff);
345             swaps(&stuff->length);
346         }
347         ResetCurrentRequest(client);
348         client->sequence--;
349         return Success;
350     }
351 
352     switch (type) {
353     case KeyPress:
354     case KeyRelease:
355         if (!dev->key)
356             return BadDevice;
357 
358         if (ev->u.u.detail < dev->key->xkbInfo->desc->min_key_code ||
359             ev->u.u.detail > dev->key->xkbInfo->desc->max_key_code) {
360             client->errorValue = ev->u.u.detail;
361             return BadValue;
362         }
363 
364         need_ptr_update = 0;
365         break;
366     case MotionNotify:
367         if (!dev->valuator)
368             return BadDevice;
369 
370         if (!(extension || ev->u.keyButtonPointer.root == None)) {
371             rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root,
372                                  client, DixGetAttrAccess);
373             if (rc != Success)
374                 return rc;
375             if (root->parent) {
376                 client->errorValue = ev->u.keyButtonPointer.root;
377                 return BadValue;
378             }
379 
380             /* Add the root window's offset to the valuators */
381             if ((flags & POINTER_ABSOLUTE) && firstValuator <= 1 && numValuators > 0) {
382                 if (firstValuator == 0)
383                     valuators[0] += root->drawable.pScreen->x;
384                 if (firstValuator < 2 && firstValuator + numValuators > 1)
385                     valuators[1 - firstValuator] += root->drawable.pScreen->y;
386             }
387         }
388         if (ev->u.u.detail != xTrue && ev->u.u.detail != xFalse) {
389             client->errorValue = ev->u.u.detail;
390             return BadValue;
391         }
392 
393         /* FIXME: Xinerama! */
394 
395         break;
396     case ButtonPress:
397     case ButtonRelease:
398         if (!dev->button)
399             return BadDevice;
400 
401         if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) {
402             client->errorValue = ev->u.u.detail;
403             return BadValue;
404         }
405         break;
406     }
407     if (screenIsSaved == SCREEN_SAVER_ON)
408         dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset);
409 
410     switch (type) {
411     case MotionNotify:
412         valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
413         nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags, &mask);
414         break;
415     case ButtonPress:
416     case ButtonRelease:
417         valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
418         nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail,
419                                    flags, &mask);
420         break;
421     case KeyPress:
422     case KeyRelease:
423         nevents =
424             GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail);
425         break;
426     }
427 
428     for (i = 0; i < nevents; i++)
429         mieqProcessDeviceEvent(dev, &xtest_evlist[i], miPointerGetScreen(inputInfo.pointer));
430 
431     if (need_ptr_update)
432         miPointerUpdateSprite(dev);
433     return Success;
434 }
435 
436 static int
ProcXTestGrabControl(ClientPtr client)437 ProcXTestGrabControl(ClientPtr client)
438 {
439     REQUEST(xXTestGrabControlReq);
440 
441     REQUEST_SIZE_MATCH(xXTestGrabControlReq);
442     if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) {
443         client->errorValue = stuff->impervious;
444         return BadValue;
445     }
446     if (stuff->impervious)
447         MakeClientGrabImpervious(client);
448     else
449         MakeClientGrabPervious(client);
450     return Success;
451 }
452 
453 static int
ProcXTestDispatch(ClientPtr client)454 ProcXTestDispatch(ClientPtr client)
455 {
456     REQUEST(xReq);
457     switch (stuff->data) {
458     case X_XTestGetVersion:
459         return ProcXTestGetVersion(client);
460     case X_XTestCompareCursor:
461         return ProcXTestCompareCursor(client);
462     case X_XTestFakeInput:
463         return ProcXTestFakeInput(client);
464     case X_XTestGrabControl:
465         return ProcXTestGrabControl(client);
466     default:
467         return BadRequest;
468     }
469 }
470 
471 static int _X_COLD
SProcXTestGetVersion(ClientPtr client)472 SProcXTestGetVersion(ClientPtr client)
473 {
474     REQUEST(xXTestGetVersionReq);
475 
476     swaps(&stuff->length);
477     REQUEST_SIZE_MATCH(xXTestGetVersionReq);
478     swaps(&stuff->minorVersion);
479     return ProcXTestGetVersion(client);
480 }
481 
482 static int _X_COLD
SProcXTestCompareCursor(ClientPtr client)483 SProcXTestCompareCursor(ClientPtr client)
484 {
485     REQUEST(xXTestCompareCursorReq);
486 
487     swaps(&stuff->length);
488     REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
489     swapl(&stuff->window);
490     swapl(&stuff->cursor);
491     return ProcXTestCompareCursor(client);
492 }
493 
494 static int _X_COLD
XTestSwapFakeInput(ClientPtr client,xReq * req)495 XTestSwapFakeInput(ClientPtr client, xReq * req)
496 {
497     int nev;
498     xEvent *ev;
499     xEvent sev;
500     EventSwapPtr proc;
501 
502     nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
503     for (ev = (xEvent *) &req[1]; --nev >= 0; ev++) {
504         /* Swap event */
505         proc = EventSwapVector[ev->u.u.type & 0177];
506         /* no swapping proc; invalid event type? */
507         if (!proc || proc == NotImplemented) {
508             client->errorValue = ev->u.u.type;
509             return BadValue;
510         }
511         (*proc) (ev, &sev);
512         *ev = sev;
513     }
514     return Success;
515 }
516 
517 static int _X_COLD
SProcXTestFakeInput(ClientPtr client)518 SProcXTestFakeInput(ClientPtr client)
519 {
520     int n;
521 
522     REQUEST(xReq);
523 
524     swaps(&stuff->length);
525     n = XTestSwapFakeInput(client, stuff);
526     if (n != Success)
527         return n;
528     return ProcXTestFakeInput(client);
529 }
530 
531 static int _X_COLD
SProcXTestGrabControl(ClientPtr client)532 SProcXTestGrabControl(ClientPtr client)
533 {
534     REQUEST(xXTestGrabControlReq);
535 
536     swaps(&stuff->length);
537     REQUEST_SIZE_MATCH(xXTestGrabControlReq);
538     return ProcXTestGrabControl(client);
539 }
540 
541 static int _X_COLD
SProcXTestDispatch(ClientPtr client)542 SProcXTestDispatch(ClientPtr client)
543 {
544     REQUEST(xReq);
545     switch (stuff->data) {
546     case X_XTestGetVersion:
547         return SProcXTestGetVersion(client);
548     case X_XTestCompareCursor:
549         return SProcXTestCompareCursor(client);
550     case X_XTestFakeInput:
551         return SProcXTestFakeInput(client);
552     case X_XTestGrabControl:
553         return SProcXTestGrabControl(client);
554     default:
555         return BadRequest;
556     }
557 }
558 
559 /**
560  * Allocate an virtual slave device for xtest events, this
561  * is a slave device to inputInfo master devices
562  */
563 void
InitXTestDevices(void)564 InitXTestDevices(void)
565 {
566     if (AllocXTestDevice(serverClient, "Virtual core",
567                          &xtestpointer, &xtestkeyboard,
568                          inputInfo.pointer, inputInfo.keyboard) != Success)
569          FatalError("Failed to allocate XTest devices");
570 
571     if (ActivateDevice(xtestpointer, TRUE) != Success ||
572         ActivateDevice(xtestkeyboard, TRUE) != Success)
573         FatalError("Failed to activate XTest core devices.");
574     if (!EnableDevice(xtestpointer, TRUE) || !EnableDevice(xtestkeyboard, TRUE))
575         FatalError("Failed to enable XTest core devices.");
576 
577     AttachDevice(NULL, xtestpointer, inputInfo.pointer);
578 
579     AttachDevice(NULL, xtestkeyboard, inputInfo.keyboard);
580 }
581 
582 /**
583  * Don't allow changing the XTest property.
584  */
585 static int
DeviceSetXTestProperty(DeviceIntPtr dev,Atom property,XIPropertyValuePtr prop,BOOL checkonly)586 DeviceSetXTestProperty(DeviceIntPtr dev, Atom property,
587                        XIPropertyValuePtr prop, BOOL checkonly)
588 {
589     if (property == XIGetKnownProperty(XI_PROP_XTEST_DEVICE))
590         return BadAccess;
591 
592     return Success;
593 }
594 
595 /**
596  * Allocate a device pair that is initialised as a slave
597  * device with properties that identify the devices as belonging
598  * to XTest subsystem.
599  * This only creates the pair, Activate/Enable Device
600  * still need to be called.
601  */
602 int
AllocXTestDevice(ClientPtr client,const char * name,DeviceIntPtr * ptr,DeviceIntPtr * keybd,DeviceIntPtr master_ptr,DeviceIntPtr master_keybd)603 AllocXTestDevice(ClientPtr client, const char *name,
604                  DeviceIntPtr *ptr, DeviceIntPtr *keybd,
605                  DeviceIntPtr master_ptr, DeviceIntPtr master_keybd)
606 {
607     int retval;
608     char *xtestname;
609     char dummy = 1;
610 
611     if (asprintf(&xtestname, "%s XTEST", name) == -1)
612         return BadAlloc;
613 
614     retval =
615         AllocDevicePair(client, xtestname, ptr, keybd, CorePointerProc,
616                         CoreKeyboardProc, FALSE);
617     if (retval == Success) {
618         (*ptr)->xtest_master_id = master_ptr->id;
619         (*keybd)->xtest_master_id = master_keybd->id;
620 
621         XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
622                                XA_INTEGER, 8, PropModeReplace, 1, &dummy,
623                                FALSE);
624         XISetDevicePropertyDeletable(*ptr,
625                                      XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
626                                      FALSE);
627         XIRegisterPropertyHandler(*ptr, DeviceSetXTestProperty, NULL, NULL);
628         XIChangeDeviceProperty(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
629                                XA_INTEGER, 8, PropModeReplace, 1, &dummy,
630                                FALSE);
631         XISetDevicePropertyDeletable(*keybd,
632                                      XIGetKnownProperty(XI_PROP_XTEST_DEVICE),
633                                      FALSE);
634         XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL);
635     }
636 
637     free(xtestname);
638 
639     return retval;
640 }
641 
642 /**
643  * If master is NULL, return TRUE if the given device is an xtest device or
644  * FALSE otherwise.
645  * If master is not NULL, return TRUE if the given device is this master's
646  * xtest device.
647  */
648 BOOL
IsXTestDevice(DeviceIntPtr dev,DeviceIntPtr master)649 IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master)
650 {
651     if (IsMaster(dev))
652         return FALSE;
653 
654     /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest
655      * device */
656     if (master)
657         return dev->xtest_master_id == master->id;
658 
659     return dev->xtest_master_id != 0;
660 }
661 
662 /**
663  * @return The X Test virtual device for the given master.
664  */
665 DeviceIntPtr
GetXTestDevice(DeviceIntPtr master)666 GetXTestDevice(DeviceIntPtr master)
667 {
668     DeviceIntPtr it;
669 
670     for (it = inputInfo.devices; it; it = it->next) {
671         if (IsXTestDevice(it, master))
672             return it;
673     }
674 
675     /* This only happens if master is a slave device. don't do that */
676     return NULL;
677 }
678 
679 static void
XTestExtensionTearDown(ExtensionEntry * e)680 XTestExtensionTearDown(ExtensionEntry * e)
681 {
682     FreeEventList(xtest_evlist, GetMaximumEventsNum());
683     xtest_evlist = NULL;
684 }
685 
686 void
XTestExtensionInit(void)687 XTestExtensionInit(void)
688 {
689     AddExtension(XTestExtensionName, 0, 0,
690                  ProcXTestDispatch, SProcXTestDispatch,
691                  XTestExtensionTearDown, StandardMinorOpcode);
692 
693     xtest_evlist = InitEventList(GetMaximumEventsNum());
694 }
695