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