]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/Xext/xtest.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / programs / Xserver / Xext / xtest.c
1 /* $XConsortium: xtest.c,v 1.22 94/04/17 20:32:59 dpw Exp $ */
2 /* $XFree86: xc/programs/Xserver/Xext/xtest.c,v 3.1 1996/05/06 05:55:41 dawes Exp $ */
3 /*
4
5 Copyright (c) 1992  X Consortium
6
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
14
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
25
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
30
31 */
32
33 #include "X.h"
34 #define NEED_EVENTS
35 #include "Xproto.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 #define _XTEST_SERVER_
45 #include "XTest.h"
46 #include "xteststr.h"
47 #ifdef XINPUT
48 #include "XI.h"
49 #include "XIproto.h"
50 #define EXTENSION_EVENT_BASE    64
51 #include "extinit.h"            /* LookupDeviceIntRec */
52 #endif /* XINPUT */
53
54 static unsigned char XTestReqCode;
55
56 #ifdef XINPUT
57 extern int DeviceValuator;
58 #endif /* XINPUT */
59
60 static void XTestResetProc(
61 #if NeedFunctionPrototypes
62     ExtensionEntry * /* extEntry */
63 #endif
64 );
65 static int XTestSwapFakeInput(
66 #if NeedFunctionPrototypes
67     ClientPtr /* client */,
68     xReq * /* req */
69 #endif
70 );
71
72 static DISPATCH_PROC(ProcXTestCompareCursor);
73 static DISPATCH_PROC(ProcXTestDispatch);
74 static DISPATCH_PROC(ProcXTestFakeInput);
75 static DISPATCH_PROC(ProcXTestGetVersion);
76 static DISPATCH_PROC(ProcXTestGrabControl);
77 static DISPATCH_PROC(SProcXTestCompareCursor);
78 static DISPATCH_PROC(SProcXTestDispatch);
79 static DISPATCH_PROC(SProcXTestFakeInput);
80 static DISPATCH_PROC(SProcXTestGetVersion);
81 static DISPATCH_PROC(SProcXTestGrabControl);
82
83 void
84 XTestExtensionInit()
85 {
86     ExtensionEntry *extEntry;
87
88     if ((extEntry = AddExtension(XTestExtensionName, 0, 0,
89                                  ProcXTestDispatch, SProcXTestDispatch,
90                                  XTestResetProc, StandardMinorOpcode)) != 0)
91         XTestReqCode = (unsigned char)extEntry->base;
92 }
93
94 /*ARGSUSED*/
95 static void
96 XTestResetProc (extEntry)
97 ExtensionEntry  *extEntry;
98 {
99 }
100
101 static int
102 ProcXTestGetVersion(client)
103     register ClientPtr client;
104 {
105     xXTestGetVersionReply rep;
106     register int n;
107
108     REQUEST_SIZE_MATCH(xXTestGetVersionReq);
109     rep.type = X_Reply;
110     rep.length = 0;
111     rep.sequenceNumber = client->sequence;
112     rep.majorVersion = XTestMajorVersion;
113     rep.minorVersion = XTestMinorVersion;
114     if (client->swapped) {
115         swaps(&rep.sequenceNumber, n);
116         swaps(&rep.minorVersion, n);
117     }
118     WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep);
119     return(client->noClientException);
120 }
121
122 static int
123 ProcXTestCompareCursor(client)
124     register ClientPtr client;
125 {
126     REQUEST(xXTestCompareCursorReq);
127     xXTestCompareCursorReply rep;
128     WindowPtr pWin;
129     CursorPtr pCursor;
130     register int n;
131
132     REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
133     pWin = (WindowPtr)LookupWindow(stuff->window, client);
134     if (!pWin)
135         return(BadWindow);
136     if (stuff->cursor == None)
137         pCursor = NullCursor;
138     else if (stuff->cursor == XTestCurrentCursor)
139         pCursor = GetSpriteCursor();
140     else {
141         pCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
142         if (!pCursor) 
143         {
144             client->errorValue = stuff->cursor;
145             return (BadCursor);
146         }
147     }
148     rep.type = X_Reply;
149     rep.length = 0;
150     rep.sequenceNumber = client->sequence;
151     rep.same = (wCursor(pWin) == pCursor);
152     if (client->swapped) {
153         swaps(&rep.sequenceNumber, n);
154     }
155     WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep);
156     return(client->noClientException);
157 }
158
159 static int
160 ProcXTestFakeInput(client)
161     register ClientPtr client;
162 {
163     REQUEST(xXTestFakeInputReq);
164     int nev;
165     int n;
166     xEvent *ev;
167     DeviceIntPtr dev;
168     WindowPtr root;
169     int type;
170 #ifdef XINPUT
171     Bool extension = FALSE;
172     deviceValuator *dv;
173     int base;
174     int *values;
175 #endif /* XINPUT */
176
177     nev = (stuff->length << 2) - sizeof(xReq);
178     if ((nev % sizeof(xEvent)) || !nev)
179         return BadLength;
180     nev /= sizeof(xEvent);
181     UpdateCurrentTime();
182     ev = (xEvent *)&((xReq *)stuff)[1];
183     type = ev->u.u.type & 0177;
184 #ifdef XINPUT
185     if (type >= EXTENSION_EVENT_BASE)
186     {
187         type -= DeviceValuator;
188         switch (type) {
189         case XI_DeviceKeyPress:
190         case XI_DeviceKeyRelease:
191         case XI_DeviceButtonPress:
192         case XI_DeviceButtonRelease:
193         case XI_DeviceMotionNotify:
194         case XI_ProximityIn:
195         case XI_ProximityOut:
196             break;
197         default:
198             client->errorValue = ev->u.u.type;
199             return BadValue;
200         }
201         if (nev == 1 && type == XI_DeviceMotionNotify)
202             return BadLength;
203         if (type == XI_DeviceMotionNotify)
204             base = ((deviceValuator *)(ev+1))->first_valuator;
205         else
206             base = 0;
207         for (n = 1; n < nev; n++)
208         {
209             dv = (deviceValuator *)(ev + n);
210             if (dv->type != DeviceValuator)
211             {
212                 client->errorValue = dv->type;
213                 return BadValue;
214             }
215             if (dv->first_valuator != base)
216             {
217                 client->errorValue = dv->first_valuator;
218                 return BadValue;
219             }
220             if (!dv->num_valuators || dv->num_valuators > 6)
221             {
222                 client->errorValue = dv->num_valuators;
223                 return BadValue;
224             }
225             base += dv->num_valuators;
226         }
227         type = type - XI_DeviceKeyPress + KeyPress;
228         extension = TRUE;
229     }
230     else
231 #endif /* XINPUT */
232     {
233         if (nev != 1)
234             return BadLength;
235         switch (type)
236         {
237         case KeyPress:
238         case KeyRelease:
239         case MotionNotify:
240         case ButtonPress:
241         case ButtonRelease:
242             break;
243         default:
244             client->errorValue = ev->u.u.type;
245             return BadValue;
246         }
247     }
248     if (ev->u.keyButtonPointer.time)
249     {
250         TimeStamp activateTime;
251         CARD32 ms;
252
253         activateTime = currentTime;
254         ms = activateTime.milliseconds + ev->u.keyButtonPointer.time;
255         if (ms < activateTime.milliseconds)
256             activateTime.months++;
257         activateTime.milliseconds = ms;
258         ev->u.keyButtonPointer.time = 0;
259
260         /* see mbuf.c:QueueDisplayRequest for code similar to this */
261
262         if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
263         {
264             return BadAlloc;
265         }
266         /* swap the request back so we can simply re-execute it */
267         if (client->swapped)
268         {
269             (void) XTestSwapFakeInput(client, (xReq *)stuff);
270             swaps(&stuff->length, n);
271         }
272         ResetCurrentRequest (client);
273         client->sequence--;
274         return Success;
275     }
276 #ifdef XINPUT
277     if (extension)
278     {
279         dev = LookupDeviceIntRec(stuff->deviceid & 0177);
280         if (!dev)
281         {
282             client->errorValue = stuff->deviceid & 0177;
283             return BadValue;
284         }
285         if (nev > 1)
286         {
287             dv = (deviceValuator *)(ev + 1);
288             if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes)
289             {
290                 client->errorValue = dv->first_valuator;
291                 return BadValue;
292             }
293             if (dv->first_valuator + dv->num_valuators >
294                 dev->valuator->numAxes)
295             {
296                 client->errorValue = dv->num_valuators;
297                 return BadValue;
298             }
299         }
300     }
301 #endif /* XINPUT */
302     switch (type)
303     {
304     case KeyPress:
305     case KeyRelease:
306 #ifdef XINPUT
307         if (!extension)
308 #endif /* XINPUT */
309             dev = (DeviceIntPtr)LookupKeyboardDevice();
310         if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode ||
311             ev->u.u.detail > dev->key->curKeySyms.maxKeyCode)
312         {
313             client->errorValue = ev->u.u.detail;
314             return BadValue;
315         }
316         break;
317     case MotionNotify:
318 #ifdef XINPUT
319         if (extension)
320         {
321             if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue)
322             {
323                 client->errorValue = ev->u.u.detail;
324                 return BadValue;
325             }
326             if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute)
327             {
328                 values = dev->valuator->axisVal + dv->first_valuator;
329                 for (n = 1; n < nev; n++)
330                 {
331                     dv = (deviceValuator *)(ev + n);
332                     switch (dv->num_valuators)
333                     {
334                     case 6:
335                         dv->valuator5 += values[5];
336                     case 5:
337                         dv->valuator4 += values[4];
338                     case 4:
339                         dv->valuator3 += values[3];
340                     case 3:
341                         dv->valuator2 += values[2];
342                     case 2:
343                         dv->valuator1 += values[1];
344                     case 1:
345                         dv->valuator0 += values[0];
346                     }
347                     values += 6;
348                 }
349             }
350             break;
351         }
352 #endif /* XINPUT */
353         dev = (DeviceIntPtr)LookupPointerDevice();
354         if (ev->u.keyButtonPointer.root == None)
355             root = GetCurrentRootWindow();
356         else
357         {
358             root = LookupWindow(ev->u.keyButtonPointer.root, client);
359             if (!root)
360                 return BadWindow;
361             if (root->parent)
362             {
363                 client->errorValue = ev->u.keyButtonPointer.root;
364                 return BadValue;
365             }
366         }
367         if (ev->u.u.detail == xTrue)
368         {
369             int x, y;
370             GetSpritePosition(&x, &y);
371             ev->u.keyButtonPointer.rootX += x;
372             ev->u.keyButtonPointer.rootY += y;
373         }
374         else if (ev->u.u.detail != xFalse)
375         {
376             client->errorValue = ev->u.u.detail;
377             return BadValue;
378         }
379         if (ev->u.keyButtonPointer.rootX < 0)
380             ev->u.keyButtonPointer.rootX = 0;
381         else if (ev->u.keyButtonPointer.rootX >= root->drawable.width)
382             ev->u.keyButtonPointer.rootX = root->drawable.width - 1;
383         if (ev->u.keyButtonPointer.rootY < 0)
384             ev->u.keyButtonPointer.rootY = 0;
385         else if (ev->u.keyButtonPointer.rootY >= root->drawable.height)
386             ev->u.keyButtonPointer.rootY = root->drawable.height - 1;
387         if (root != GetCurrentRootWindow())
388         {
389             NewCurrentScreen(root->drawable.pScreen,
390                              ev->u.keyButtonPointer.rootX,
391                              ev->u.keyButtonPointer.rootY);
392             return client->noClientException;
393         }
394         (*root->drawable.pScreen->SetCursorPosition)
395             (root->drawable.pScreen,
396              ev->u.keyButtonPointer.rootX,
397              ev->u.keyButtonPointer.rootY, FALSE);
398         break;
399     case ButtonPress:
400     case ButtonRelease:
401 #ifdef XINPUT
402         if (!extension)
403 #endif /* XINPUT */
404             dev = (DeviceIntPtr)LookupPointerDevice();
405         if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
406         {
407             client->errorValue = ev->u.u.detail;
408             return BadValue;
409         }
410         break;
411     }
412     if (screenIsSaved == SCREEN_SAVER_ON)
413         SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
414     ev->u.keyButtonPointer.time = currentTime.milliseconds;
415     (*dev->public.processInputProc)(ev, dev, nev);
416     return client->noClientException;
417 }
418
419 static int
420 ProcXTestGrabControl(client)
421     register ClientPtr client;
422 {
423     REQUEST(xXTestGrabControlReq);
424
425     REQUEST_SIZE_MATCH(xXTestGrabControlReq);
426     if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse))
427     {
428         client->errorValue = stuff->impervious;
429         return(BadValue);
430     }
431     if (stuff->impervious)
432         MakeClientGrabImpervious(client);
433     else
434         MakeClientGrabPervious(client);
435     return(client->noClientException);
436 }
437
438 static int
439 ProcXTestDispatch (client)
440     register ClientPtr  client;
441 {
442     REQUEST(xReq);
443     switch (stuff->data)
444     {
445     case X_XTestGetVersion:
446         return ProcXTestGetVersion(client);
447     case X_XTestCompareCursor:
448         return ProcXTestCompareCursor(client);
449     case X_XTestFakeInput:
450         return ProcXTestFakeInput(client);
451     case X_XTestGrabControl:
452         return ProcXTestGrabControl(client);
453     default:
454         return BadRequest;
455     }
456 }
457
458 static int
459 SProcXTestGetVersion(client)
460     register ClientPtr  client;
461 {
462     register int n;
463     REQUEST(xXTestGetVersionReq);
464
465     swaps(&stuff->length, n);
466     REQUEST_SIZE_MATCH(xXTestGetVersionReq);
467     swaps(&stuff->minorVersion, n);
468     return ProcXTestGetVersion(client);
469 }
470
471 static int
472 SProcXTestCompareCursor(client)
473     register ClientPtr  client;
474 {
475     register int n;
476     REQUEST(xXTestCompareCursorReq);
477
478     swaps(&stuff->length, n);
479     REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
480     swapl(&stuff->window, n);
481     swapl(&stuff->cursor, n);
482     return ProcXTestCompareCursor(client);
483 }
484
485 static int
486 XTestSwapFakeInput(client, req)
487     register ClientPtr  client;
488     xReq *req;
489 {
490     register int nev;
491     register xEvent *ev;
492     xEvent sev;
493     EventSwapPtr proc;
494
495     nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
496     for (ev = (xEvent *)&req[1]; --nev >= 0; ev++)
497     {
498         /* Swap event */
499         proc = EventSwapVector[ev->u.u.type & 0177];
500         /* no swapping proc; invalid event type? */
501         if (!proc ||  proc ==  NotImplemented) {
502             client->errorValue = ev->u.u.type;
503             return BadValue;
504         }
505         (*proc)(ev, &sev);
506         *ev = sev;
507     }
508     return Success;
509 }
510
511 static int
512 SProcXTestFakeInput(client)
513     register ClientPtr  client;
514 {
515     register int n;
516     REQUEST(xReq);
517
518     swaps(&stuff->length, n);
519     n = XTestSwapFakeInput(client, stuff);
520     if (n != Success)
521         return n;
522     return ProcXTestFakeInput(client);
523 }
524
525 static int
526 SProcXTestGrabControl(client)
527     register ClientPtr  client;
528 {
529     register int n;
530     REQUEST(xXTestGrabControlReq);
531
532     swaps(&stuff->length, n);
533     REQUEST_SIZE_MATCH(xXTestGrabControlReq);
534     return ProcXTestGrabControl(client);
535 }
536
537 static int
538 SProcXTestDispatch (client)
539     register ClientPtr  client;
540 {
541     REQUEST(xReq);
542     switch (stuff->data)
543     {
544     case X_XTestGetVersion:
545         return SProcXTestGetVersion(client);
546     case X_XTestCompareCursor:
547         return SProcXTestCompareCursor(client);
548     case X_XTestFakeInput:
549         return SProcXTestFakeInput(client);
550     case X_XTestGrabControl:
551         return SProcXTestGrabControl(client);
552     default:
553         return BadRequest;
554     }
555 }