XTest.c revision ea133fd7
1/* $Xorg: XTest.c,v 1.5 2001/02/09 02:04:00 xorgcvs Exp $ */
2/*
3Copyright 1990, 1991 by UniSoft Group Limited
4*/
5
6/*
7
8Copyright 1992, 1993, 1998  The Open Group
9
10Permission to use, copy, modify, distribute, and sell this software and its
11documentation for any purpose is hereby granted without fee, provided that
12the above copyright notice appear in all copies and that both that
13copyright notice and this permission notice appear in supporting
14documentation.
15
16The above copyright notice and this permission notice shall be included
17in all copies or substantial portions of the Software.
18
19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
23OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25OTHER DEALINGS IN THE SOFTWARE.
26
27Except as contained in this notice, the name of The Open Group shall
28not be used in advertising or otherwise to promote the sale, use or
29other dealings in this Software without prior written authorization
30from The Open Group.
31
32*/
33/* $XFree86: xc/lib/Xtst/XTest.c,v 1.5 2001/12/14 19:56:40 dawes Exp $ */
34
35#define NEED_REPLIES
36#include <X11/Xlibint.h>
37#include <X11/extensions/XTest.h>
38#include <X11/extensions/xtestproto.h>
39#include <X11/extensions/Xext.h>
40#include <X11/extensions/extutil.h>
41#include <X11/extensions/XInput.h>
42#include <X11/extensions/XIproto.h>
43
44static XExtensionInfo _xtest_info_data;
45static XExtensionInfo *xtest_info = &_xtest_info_data;
46static /* const */ char *xtest_extension_name = XTestExtensionName;
47
48#define XTestCheckExtension(dpy,i,val) \
49  XextCheckExtension (dpy, i, xtest_extension_name, val)
50
51#define XTestICheckExtension(dpy,i,val) \
52  XextCheckExtension (dpy, i, xtest_extension_name, val); \
53  if (!i->data) return val
54
55/*****************************************************************************
56 *                                                                           *
57 *			   private utility routines                          *
58 *                                                                           *
59 *****************************************************************************/
60
61static int close_display(Display *dpy, XExtCodes *codes);
62static /* const */ XExtensionHooks xtest_extension_hooks = {
63    NULL,				/* create_gc */
64    NULL,				/* copy_gc */
65    NULL,				/* flush_gc */
66    NULL,				/* free_gc */
67    NULL,				/* create_font */
68    NULL,				/* free_font */
69    close_display,			/* close_display */
70    NULL,				/* wire_to_event */
71    NULL,				/* event_to_wire */
72    NULL,				/* error */
73    NULL				/* error_string */
74};
75
76static XPointer
77get_xinput_base(Display *dpy)
78{
79    int major_opcode, first_event, first_error;
80    first_event = 0;
81
82    XQueryExtension(dpy, INAME, &major_opcode, &first_event, &first_error);
83    return (XPointer)(long)first_event;
84}
85
86static XEXT_GENERATE_FIND_DISPLAY (find_display, xtest_info,
87				   xtest_extension_name,
88				   &xtest_extension_hooks, XTestNumberEvents,
89				   get_xinput_base(dpy))
90
91static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xtest_info)
92
93/*****************************************************************************
94 *                                                                           *
95 *		    public routines               			     *
96 *                                                                           *
97 *****************************************************************************/
98
99Bool
100XTestQueryExtension (Display *dpy,
101		     int *event_base_return, int *error_base_return,
102		     int *major_return, int *minor_return)
103{
104    XExtDisplayInfo *info = find_display (dpy);
105    register xXTestGetVersionReq *req;
106    xXTestGetVersionReply rep;
107
108    if (XextHasExtension(info)) {
109	LockDisplay(dpy);
110	GetReq(XTestGetVersion, req);
111	req->reqType = info->codes->major_opcode;
112	req->xtReqType = X_XTestGetVersion;
113	req->majorVersion = XTestMajorVersion;
114	req->minorVersion = XTestMinorVersion;
115	if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
116	    UnlockDisplay(dpy);
117	    SyncHandle();
118	    return False;
119	}
120	UnlockDisplay(dpy);
121	SyncHandle();
122	*event_base_return = info->codes->first_event;
123	*error_base_return = info->codes->first_error;
124	*major_return = rep.majorVersion;
125	*minor_return = rep.minorVersion;
126	return True;
127    } else {
128	return False;
129    }
130}
131
132Bool
133XTestCompareCursorWithWindow(Display *dpy, Window window, Cursor cursor)
134{
135    XExtDisplayInfo *info = find_display (dpy);
136    register xXTestCompareCursorReq *req;
137    xXTestCompareCursorReply rep;
138
139    XTestCheckExtension (dpy, info, 0);
140
141    LockDisplay(dpy);
142    GetReq(XTestCompareCursor, req);
143    req->reqType = info->codes->major_opcode;
144    req->xtReqType = X_XTestCompareCursor;
145    req->window = window;
146    req->cursor = cursor;
147    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
148	UnlockDisplay(dpy);
149	SyncHandle();
150	return False;
151    }
152    UnlockDisplay(dpy);
153    SyncHandle();
154    return rep.same;
155}
156
157Bool
158XTestCompareCurrentCursorWithWindow(Display *dpy, Window window)
159{
160    return XTestCompareCursorWithWindow(dpy, window, XTestCurrentCursor);
161}
162
163int
164XTestFakeKeyEvent(Display *dpy, unsigned int keycode,
165		  Bool is_press, unsigned long delay)
166{
167    XExtDisplayInfo *info = find_display (dpy);
168    register xXTestFakeInputReq *req;
169
170    XTestCheckExtension (dpy, info, 0);
171
172    LockDisplay(dpy);
173    GetReq(XTestFakeInput, req);
174    req->reqType = info->codes->major_opcode;
175    req->xtReqType = X_XTestFakeInput;
176    req->type = is_press ? KeyPress : KeyRelease;
177    req->detail = keycode;
178    req->time = delay;
179    UnlockDisplay(dpy);
180    SyncHandle();
181    return 1;
182}
183
184int
185XTestFakeButtonEvent(Display *dpy, unsigned int button,
186		     Bool is_press, unsigned long delay)
187{
188    XExtDisplayInfo *info = find_display (dpy);
189    register xXTestFakeInputReq *req;
190
191    XTestCheckExtension (dpy, info, 0);
192
193    LockDisplay(dpy);
194    GetReq(XTestFakeInput, req);
195    req->reqType = info->codes->major_opcode;
196    req->xtReqType = X_XTestFakeInput;
197    req->type = is_press ? ButtonPress : ButtonRelease;
198    req->detail = button;
199    req->time = delay;
200    UnlockDisplay(dpy);
201    SyncHandle();
202    return 1;
203}
204
205int
206XTestFakeMotionEvent(Display *dpy, int screen, int x, int y, unsigned long delay)
207{
208    XExtDisplayInfo *info = find_display (dpy);
209    register xXTestFakeInputReq *req;
210
211    XTestCheckExtension (dpy, info, 0);
212
213    LockDisplay(dpy);
214    GetReq(XTestFakeInput, req);
215    req->reqType = info->codes->major_opcode;
216    req->xtReqType = X_XTestFakeInput;
217    req->type = MotionNotify;
218    req->detail = False;
219    if (screen == -1)
220	req->root = None;
221    else
222	req->root = RootWindow(dpy, screen);
223    req->rootX = x;
224    req->rootY = y;
225    req->time = delay;
226    UnlockDisplay(dpy);
227    SyncHandle();
228    return 1;
229}
230
231int
232XTestFakeRelativeMotionEvent(Display *dpy, int dx, int dy, unsigned long delay)
233{
234    XExtDisplayInfo *info = find_display (dpy);
235    register xXTestFakeInputReq *req;
236
237    XTestCheckExtension (dpy, info, 0);
238
239    LockDisplay(dpy);
240    GetReq(XTestFakeInput, req);
241    req->reqType = info->codes->major_opcode;
242    req->xtReqType = X_XTestFakeInput;
243    req->type = MotionNotify;
244    req->detail = True;
245    req->root = None;
246    req->rootX = dx;
247    req->rootY = dy;
248    req->time = delay;
249    UnlockDisplay(dpy);
250    SyncHandle();
251    return 1;
252}
253
254static void
255send_axes(
256    Display *dpy,
257    XExtDisplayInfo *info,
258    xXTestFakeInputReq *req,
259    XDevice *dev,
260    int first_axis,
261    int *axes,
262    int n_axes)
263{
264    deviceValuator ev;
265    int n;
266
267    req->deviceid |= MORE_EVENTS;
268    req->length += ((n_axes + 5) / 6) * (SIZEOF(xEvent) >> 2);
269    ev.type = XI_DeviceValuator + (long)info->data;
270    ev.deviceid = dev->device_id;
271    ev.num_valuators = n_axes;
272    ev.first_valuator = first_axis;
273    while (n_axes > 0) {
274	n = n_axes;
275	if (n > 6)
276	    n = 6;
277	switch (n) {
278	case 6:
279	    ev.valuator5 = *(axes+5);
280	case 5:
281	    ev.valuator4 = *(axes+4);
282	case 4:
283	    ev.valuator3 = *(axes+3);
284	case 3:
285	    ev.valuator2 = *(axes+2);
286	case 2:
287	    ev.valuator1 = *(axes+1);
288	case 1:
289	    ev.valuator0 = *axes;
290	}
291	Data(dpy, (char *)&ev, SIZEOF(xEvent));
292	axes += n;
293	n_axes -= n;
294	ev.first_valuator += n;
295    }
296}
297
298int
299XTestFakeDeviceKeyEvent(Display *dpy, XDevice *dev,
300			unsigned int keycode, Bool is_press,
301			int *axes, int n_axes, unsigned long delay)
302{
303    XExtDisplayInfo *info = find_display (dpy);
304    register xXTestFakeInputReq *req;
305
306    XTestICheckExtension (dpy, info, 0);
307
308    LockDisplay(dpy);
309    GetReq(XTestFakeInput, req);
310    req->reqType = info->codes->major_opcode;
311    req->xtReqType = X_XTestFakeInput;
312    req->type = is_press ? XI_DeviceKeyPress : XI_DeviceKeyRelease;
313    req->type += (int)(long)info->data;
314    req->detail = keycode;
315    req->time = delay;
316    req->deviceid = dev->device_id;
317    if (n_axes)
318	send_axes(dpy, info, req, dev, 0, axes, n_axes);
319    UnlockDisplay(dpy);
320    SyncHandle();
321    return 1;
322}
323
324int
325XTestFakeDeviceButtonEvent(Display *dpy, XDevice *dev,
326			   unsigned int button, Bool is_press,
327			   int *axes, int n_axes, unsigned long delay)
328{
329    XExtDisplayInfo *info = find_display (dpy);
330    register xXTestFakeInputReq *req;
331
332    XTestICheckExtension (dpy, info, 0);
333
334    LockDisplay(dpy);
335    GetReq(XTestFakeInput, req);
336    req->reqType = info->codes->major_opcode;
337    req->xtReqType = X_XTestFakeInput;
338    req->type = is_press ? XI_DeviceButtonPress : XI_DeviceButtonRelease;
339    req->type += (int)(long)info->data;
340    req->detail = button;
341    req->time = delay;
342    req->deviceid = dev->device_id;
343    if (n_axes)
344	send_axes(dpy, info, req, dev, 0, axes, n_axes);
345    UnlockDisplay(dpy);
346    SyncHandle();
347    return 1;
348}
349
350int
351XTestFakeProximityEvent(Display *dpy, XDevice *dev, Bool in_prox,
352			int *axes, int n_axes, unsigned long delay)
353{
354    XExtDisplayInfo *info = find_display (dpy);
355    register xXTestFakeInputReq *req;
356
357    XTestICheckExtension (dpy, info, 0);
358
359    LockDisplay(dpy);
360    GetReq(XTestFakeInput, req);
361    req->reqType = info->codes->major_opcode;
362    req->xtReqType = X_XTestFakeInput;
363    req->type = in_prox ? XI_ProximityIn : XI_ProximityOut;
364    req->type += (int)(long)info->data;
365    req->time = delay;
366    req->deviceid = dev->device_id;
367    if (n_axes)
368	send_axes(dpy, info, req, dev, 0, axes, n_axes);
369    UnlockDisplay(dpy);
370    SyncHandle();
371    return 1;
372}
373
374int
375XTestFakeDeviceMotionEvent(Display *dpy, XDevice *dev,
376			   Bool is_relative, int first_axis,
377			   int *axes, int n_axes, unsigned long delay)
378{
379    XExtDisplayInfo *info = find_display (dpy);
380    register xXTestFakeInputReq *req;
381
382    XTestICheckExtension (dpy, info, 0);
383
384    LockDisplay(dpy);
385    GetReq(XTestFakeInput, req);
386    req->reqType = info->codes->major_opcode;
387    req->xtReqType = X_XTestFakeInput;
388    req->type = XI_DeviceMotionNotify + (int)(long)info->data;
389    req->detail = is_relative;
390    req->time = delay;
391    req->deviceid = dev->device_id;
392    send_axes(dpy, info, req, dev, first_axis, axes, n_axes);
393    UnlockDisplay(dpy);
394    SyncHandle();
395    return 1;
396}
397
398int
399XTestGrabControl(Display *dpy, Bool impervious)
400{
401    XExtDisplayInfo *info = find_display (dpy);
402    register xXTestGrabControlReq *req;
403
404    XTestCheckExtension (dpy, info, 0);
405
406    LockDisplay(dpy);
407    GetReq(XTestGrabControl, req);
408    req->reqType = info->codes->major_opcode;
409    req->xtReqType = X_XTestGrabControl;
410    req->impervious = impervious;
411    UnlockDisplay(dpy);
412    SyncHandle();
413    return 1;
414}
415
416void
417XTestSetGContextOfGC(GC gc, GContext gid)
418{
419    gc->gid = gid;
420}
421
422void
423XTestSetVisualIDOfVisual(Visual *visual, VisualID visualid)
424{
425    visual->visualid = visualid;
426}
427
428static xReq _dummy_request = {
429	0, 0, 0
430};
431
432Status
433XTestDiscard(Display *dpy)
434{
435    Bool something;
436    register char *ptr;
437
438    LockDisplay(dpy);
439    if ((something = (dpy->bufptr != dpy->buffer))) {
440	for (ptr = dpy->buffer;
441	     ptr < dpy->bufptr;
442	     ptr += (((xReq *)ptr)->length << 2))
443	    dpy->request--;
444	dpy->bufptr = dpy->buffer;
445	dpy->last_req = (char *)&_dummy_request;
446    }
447    UnlockDisplay(dpy);
448    SyncHandle();
449    return something;
450}
451