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