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