XTestExt1.c revision caade7cc
1caade7ccSmrg/* $Xorg: XTestExt1.c,v 1.4 2001/02/09 02:03:49 xorgcvs Exp $ */
2caade7ccSmrg/*
3caade7ccSmrg *	File:  xtestext1lib.c
4caade7ccSmrg *
5caade7ccSmrg *	This file contains the Xlib parts of the input synthesis extension
6caade7ccSmrg */
7caade7ccSmrg
8caade7ccSmrg/*
9caade7ccSmrg
10caade7ccSmrg
11caade7ccSmrgCopyright 1986, 1987, 1988, 1998   The Open Group
12caade7ccSmrg
13caade7ccSmrgPermission to use, copy, modify, distribute, and sell this software and its
14caade7ccSmrgdocumentation for any purpose is hereby granted without fee, provided that
15caade7ccSmrgthe above copyright notice appear in all copies and that both that
16caade7ccSmrgcopyright notice and this permission notice appear in supporting
17caade7ccSmrgdocumentation.
18caade7ccSmrg
19caade7ccSmrgThe above copyright notice and this permission notice shall be included in
20caade7ccSmrgall copies or substantial portions of the Software.
21caade7ccSmrg
22caade7ccSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23caade7ccSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24caade7ccSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
25caade7ccSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
26caade7ccSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
27caade7ccSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28caade7ccSmrg
29caade7ccSmrgExcept as contained in this notice, the name of The Open Group shall not be
30caade7ccSmrgused in advertising or otherwise to promote the sale, use or other dealings
31caade7ccSmrgin this Software without prior written authorization from The Open Group.
32caade7ccSmrg
33caade7ccSmrg
34caade7ccSmrgCopyright 1986, 1987, 1988 by Hewlett-Packard Corporation
35caade7ccSmrg
36caade7ccSmrgPermission to use, copy, modify, and distribute this
37caade7ccSmrgsoftware and its documentation for any purpose and without
38caade7ccSmrgfee is hereby granted, provided that the above copyright
39caade7ccSmrgnotice appear in all copies and that both that copyright
40caade7ccSmrgnotice and this permission notice appear in supporting
41caade7ccSmrgdocumentation, and that the name of Hewlett-Packard not be used in
42caade7ccSmrgadvertising or publicity pertaining to distribution of the
43caade7ccSmrgsoftware without specific, written prior permission.
44caade7ccSmrg
45caade7ccSmrgHewlett-Packard makes no representations about the
46caade7ccSmrgsuitability of this software for any purpose.  It is provided
47caade7ccSmrg"as is" without express or implied warranty.
48caade7ccSmrg
49caade7ccSmrgThis software is not subject to any license of the American
50caade7ccSmrgTelephone and Telegraph Company or of the Regents of the
51caade7ccSmrgUniversity of California.
52caade7ccSmrg
53caade7ccSmrg*/
54caade7ccSmrg/* $XFree86: xc/lib/Xext/XTestExt1.c,v 1.3 2001/01/17 19:42:46 dawes Exp $ */
55caade7ccSmrg
56caade7ccSmrg/******************************************************************************
57caade7ccSmrg * include files
58caade7ccSmrg *****************************************************************************/
59caade7ccSmrg
60caade7ccSmrg#define NEED_REPLIES
61caade7ccSmrg#define NEED_EVENTS
62caade7ccSmrg
63caade7ccSmrg#ifdef HAVE_CONFIG_H
64caade7ccSmrg#include <config.h>
65caade7ccSmrg#endif
66caade7ccSmrg#include <stdio.h>
67caade7ccSmrg#include <X11/Xproto.h>
68caade7ccSmrg#include <X11/Xlibint.h>
69caade7ccSmrg#include <X11/extensions/xtestext1.h>
70caade7ccSmrg
71caade7ccSmrg/******************************************************************************
72caade7ccSmrg * variables
73caade7ccSmrg *****************************************************************************/
74caade7ccSmrg
75caade7ccSmrg/*
76caade7ccSmrg * Holds the request type code for this extension.  The request type code
77caade7ccSmrg * for this extension may vary depending on how many extensions are installed
78caade7ccSmrg * already, so the initial value given below will be added to the base request
79caade7ccSmrg * code that is acquired when this extension is installed.
80caade7ccSmrg */
81caade7ccSmrgstatic int		XTestReqCode = 0;
82caade7ccSmrg/*
83caade7ccSmrg * Holds the two event type codes for this extension.  The event type codes
84caade7ccSmrg * for this extension may vary depending on how many extensions are installed
85caade7ccSmrg * already, so the initial values given below will be added to the base event
86caade7ccSmrg * code that is acquired when this extension is installed.
87caade7ccSmrg *
88caade7ccSmrg * These two variables must be available to programs that use this extension.
89caade7ccSmrg */
90caade7ccSmrgint			XTestInputActionType = 0;
91caade7ccSmrgint			XTestFakeAckType   = 1;
92caade7ccSmrg/*
93caade7ccSmrg * holds the current x and y coordinates for XTestMovePointer
94caade7ccSmrg */
95caade7ccSmrgstatic int	current_x = 0;
96caade7ccSmrgstatic int	current_y = 0;
97caade7ccSmrg/*
98caade7ccSmrg * Holds input actions being accumulated until the input action buffer is
99caade7ccSmrg * full or until XTestFlush is called.
100caade7ccSmrg */
101caade7ccSmrgstatic CARD8		action_buf[XTestMAX_ACTION_LIST_SIZE];
102caade7ccSmrg/*
103caade7ccSmrg * the index into the input action buffer
104caade7ccSmrg */
105caade7ccSmrgstatic int		action_index = 0;
106caade7ccSmrg/*
107caade7ccSmrg * the number of input actions that the server can handle at one time
108caade7ccSmrg */
109caade7ccSmrgstatic unsigned long	action_array_size = 0;
110caade7ccSmrg/*
111caade7ccSmrg * the current number of input actions
112caade7ccSmrg */
113caade7ccSmrgstatic unsigned long	action_count = 0;
114caade7ccSmrg
115caade7ccSmrg/******************************************************************************
116caade7ccSmrg * function declarations
117caade7ccSmrg *****************************************************************************/
118caade7ccSmrg
119caade7ccSmrgstatic int	XTestWireToEvent(Display *dpy, XEvent *reTemp, xEvent *eventTemp);
120caade7ccSmrgstatic int	XTestCheckExtInit(register Display *dpy);
121caade7ccSmrgstatic Bool	XTestIdentifyMyEvent(Display *display, XEvent *event_ptr, char *args);
122caade7ccSmrgstatic int	XTestInitExtension(register Display *dpy);
123caade7ccSmrgstatic int	XTestKeyOrButton(Display *display, int device_id, long unsigned int delay, unsigned int code, unsigned int action);
124caade7ccSmrgstatic int	XTestCheckDelay(Display *display, long unsigned int *delay_addr);
125caade7ccSmrgstatic int	XTestPackInputAction(Display *display, CARD8 *action_addr, int action_size);
126caade7ccSmrgstatic int	XTestWriteInputActions(Display *display, char *action_list_addr, int action_list_size, int ack_flag);
127caade7ccSmrg
128caade7ccSmrg/******************************************************************************
129caade7ccSmrg *
130caade7ccSmrg *	XTestFakeInput
131caade7ccSmrg *
132caade7ccSmrg *	Send a a request containing one or more input actions to be sent
133caade7ccSmrg *	to the server by this extension.
134caade7ccSmrg */
135caade7ccSmrgint
136caade7ccSmrgXTestFakeInput(
137caade7ccSmrg/*
138caade7ccSmrg * the connection to the X server
139caade7ccSmrg */
140caade7ccSmrgregister Display	*dpy,
141caade7ccSmrg/*
142caade7ccSmrg * the address of a list of input actions to be sent to the server
143caade7ccSmrg */
144caade7ccSmrgchar			*action_list_addr,
145caade7ccSmrg/*
146caade7ccSmrg * the size (in bytes) of the list of input actions
147caade7ccSmrg */
148caade7ccSmrgint			action_list_size,
149caade7ccSmrg/*
150caade7ccSmrg * specifies whether the server needs to send an event to indicate that its
151caade7ccSmrg * input action buffer is empty
152caade7ccSmrg */
153caade7ccSmrgint			ack_flag)
154caade7ccSmrg{
155caade7ccSmrg	/*
156caade7ccSmrg	 * pointer to xTestFakeInputReq structure
157caade7ccSmrg	 */
158caade7ccSmrg	xTestFakeInputReq	*req;
159caade7ccSmrg	/*
160caade7ccSmrg	 * loop index
161caade7ccSmrg	 */
162caade7ccSmrg	int			i;
163caade7ccSmrg
164caade7ccSmrg	LockDisplay(dpy);
165caade7ccSmrg	if ((XTestCheckExtInit(dpy) == -1) ||
166caade7ccSmrg	    (action_list_size > XTestMAX_ACTION_LIST_SIZE))
167caade7ccSmrg	{
168caade7ccSmrg		/*
169caade7ccSmrg		 * if the extension is not installed in the server or the
170caade7ccSmrg		 * action list will not fit in the request, then unlock
171caade7ccSmrg		 * the display and return -1.
172caade7ccSmrg		 */
173caade7ccSmrg		UnlockDisplay(dpy);
174caade7ccSmrg		return(-1);
175caade7ccSmrg	}
176caade7ccSmrg	else
177caade7ccSmrg	{
178caade7ccSmrg		/*
179caade7ccSmrg		 * Get the next available X request packet in the buffer.
180caade7ccSmrg		 * It sets the `length' field to the size (in 32-bit words)
181caade7ccSmrg		 * of the request.  It also sets the `reqType' field in the
182caade7ccSmrg		 * request to X_TestFakeInput, which is not what is needed.
183caade7ccSmrg		 *
184caade7ccSmrg		 * GetReq is a macro defined in Xlibint.h.
185caade7ccSmrg		 */
186caade7ccSmrg		GetReq(TestFakeInput, req);
187caade7ccSmrg		/*
188caade7ccSmrg		 * fix up the request type code to what is needed
189caade7ccSmrg		 */
190caade7ccSmrg		req->reqType = XTestReqCode;
191caade7ccSmrg		/*
192caade7ccSmrg		 * set the minor request type code to X_TestFakeInput
193caade7ccSmrg		 */
194caade7ccSmrg		req->XTestReqType = X_TestFakeInput;
195caade7ccSmrg		/*
196caade7ccSmrg		 * set the ack code
197caade7ccSmrg		 */
198caade7ccSmrg		req->ack = ack_flag;
199caade7ccSmrg		/*
200caade7ccSmrg		 * Set the action_list area to all 0's. An input action header
201caade7ccSmrg		 * value of 0 is interpreted as a flag to the input action
202caade7ccSmrg		 * list handling code in the server part of this extension
203caade7ccSmrg		 * that there are no more input actions in this request.
204caade7ccSmrg		 */
205caade7ccSmrg		for (i = 0; i < XTestMAX_ACTION_LIST_SIZE; i++)
206caade7ccSmrg		{
207caade7ccSmrg			req->action_list[i] = 0;
208caade7ccSmrg		}
209caade7ccSmrg		/*
210caade7ccSmrg		 * copy the input actions into the request
211caade7ccSmrg		 */
212caade7ccSmrg		for (i = 0; i < action_list_size; i++)
213caade7ccSmrg		{
214caade7ccSmrg			req->action_list[i] = *(action_list_addr++);
215caade7ccSmrg		}
216caade7ccSmrg		UnlockDisplay(dpy);
217caade7ccSmrg		SyncHandle();
218caade7ccSmrg		return(0);
219caade7ccSmrg	}
220caade7ccSmrg}
221caade7ccSmrg
222caade7ccSmrg/******************************************************************************
223caade7ccSmrg *
224caade7ccSmrg *	XTestGetInput
225caade7ccSmrg *
226caade7ccSmrg *	Request the server to begin putting user input actions into events
227caade7ccSmrg *	to be sent to the client that called this function.
228caade7ccSmrg */
229caade7ccSmrgint
230caade7ccSmrgXTestGetInput(
231caade7ccSmrg/*
232caade7ccSmrg * the connection to the X server
233caade7ccSmrg */
234caade7ccSmrgregister Display	*dpy,
235caade7ccSmrg/*
236caade7ccSmrg * tells the server what to do with the user input actions
237caade7ccSmrg */
238caade7ccSmrgint			action_handling)
239caade7ccSmrg{
240caade7ccSmrg	/*
241caade7ccSmrg	 * pointer to xTestGetInputReq structure
242caade7ccSmrg	 */
243caade7ccSmrg	xTestGetInputReq 	*req;
244caade7ccSmrg
245caade7ccSmrg	LockDisplay(dpy);
246caade7ccSmrg	if (XTestCheckExtInit(dpy) == -1)
247caade7ccSmrg	{
248caade7ccSmrg		/*
249caade7ccSmrg		 * if the extension is not installed in the server
250caade7ccSmrg		 * then unlock the display and return -1.
251caade7ccSmrg		 */
252caade7ccSmrg		UnlockDisplay(dpy);
253caade7ccSmrg		return(-1);
254caade7ccSmrg	}
255caade7ccSmrg	else
256caade7ccSmrg	{
257caade7ccSmrg		/*
258caade7ccSmrg		 * Get the next available X request packet in the buffer.
259caade7ccSmrg		 * It sets the `length' field to the size (in 32-bit words)
260caade7ccSmrg		 * of the request.  It also sets the `reqType' field in the
261caade7ccSmrg		 * request to X_TestGetInput, which is not what is needed.
262caade7ccSmrg		 *
263caade7ccSmrg		 * GetReq is a macro defined in Xlibint.h.
264caade7ccSmrg		 */
265caade7ccSmrg		GetReq(TestGetInput, req);
266caade7ccSmrg		/*
267caade7ccSmrg		 * fix up the request type code to what is needed
268caade7ccSmrg		 */
269caade7ccSmrg		req->reqType = XTestReqCode;
270caade7ccSmrg		/*
271caade7ccSmrg		 * set the minor request type code to X_TestGetInput
272caade7ccSmrg		 */
273caade7ccSmrg		req->XTestReqType = X_TestGetInput;
274caade7ccSmrg		/*
275caade7ccSmrg		 * set the action handling mode
276caade7ccSmrg		 */
277caade7ccSmrg		req->mode = action_handling;
278caade7ccSmrg		UnlockDisplay(dpy);
279caade7ccSmrg		SyncHandle();
280caade7ccSmrg		return(0);
281caade7ccSmrg	}
282caade7ccSmrg}
283caade7ccSmrg
284caade7ccSmrg/******************************************************************************
285caade7ccSmrg *
286caade7ccSmrg *	XTestStopInput
287caade7ccSmrg *
288caade7ccSmrg *	Tell the server to stop putting information about user input actions
289caade7ccSmrg *	into events.
290caade7ccSmrg */
291caade7ccSmrgint
292caade7ccSmrgXTestStopInput(
293caade7ccSmrg/*
294caade7ccSmrg * the connection to the X server
295caade7ccSmrg */
296caade7ccSmrgregister Display	*dpy)
297caade7ccSmrg{
298caade7ccSmrg	/*
299caade7ccSmrg	 * pointer to xTestStopInputReq structure
300caade7ccSmrg	 */
301caade7ccSmrg	xTestStopInputReq 	*req;
302caade7ccSmrg
303caade7ccSmrg	LockDisplay(dpy);
304caade7ccSmrg	if (XTestCheckExtInit(dpy) == -1)
305caade7ccSmrg	{
306caade7ccSmrg		/*
307caade7ccSmrg		 * if the extension is not installed in the server
308caade7ccSmrg		 * then unlock the display and return -1.
309caade7ccSmrg		 */
310caade7ccSmrg		UnlockDisplay(dpy);
311caade7ccSmrg		return(-1);
312caade7ccSmrg	}
313caade7ccSmrg	else
314caade7ccSmrg	{
315caade7ccSmrg		/*
316caade7ccSmrg		 * Get the next available X request packet in the buffer.
317caade7ccSmrg		 * It sets the `length' field to the size (in 32-bit words)
318caade7ccSmrg		 * of the request.  It also sets the `reqType' field in the
319caade7ccSmrg		 * request to X_TestStopInput, which is not what is needed.
320caade7ccSmrg		 *
321caade7ccSmrg		 * GetReq is a macro defined in Xlibint.h.
322caade7ccSmrg		 */
323caade7ccSmrg		GetReq(TestStopInput, req);
324caade7ccSmrg		/*
325caade7ccSmrg		 * fix up the request type code to what is needed
326caade7ccSmrg		 */
327caade7ccSmrg		req->reqType = XTestReqCode;
328caade7ccSmrg		/*
329caade7ccSmrg		 * set the minor request type code to X_TestStopInput
330caade7ccSmrg		 */
331caade7ccSmrg		req->XTestReqType = X_TestStopInput;
332caade7ccSmrg		UnlockDisplay(dpy);
333caade7ccSmrg		SyncHandle();
334caade7ccSmrg		return(0);
335caade7ccSmrg	}
336caade7ccSmrg}
337caade7ccSmrg
338caade7ccSmrg/******************************************************************************
339caade7ccSmrg *
340caade7ccSmrg *	XTestReset
341caade7ccSmrg *
342caade7ccSmrg *	Tell the server to set everything having to do with this extension
343caade7ccSmrg *	back to its initial state.
344caade7ccSmrg */
345caade7ccSmrgint
346caade7ccSmrgXTestReset(
347caade7ccSmrg/*
348caade7ccSmrg * the connection to the X server
349caade7ccSmrg */
350caade7ccSmrgregister Display	*dpy)
351caade7ccSmrg{
352caade7ccSmrg	/*
353caade7ccSmrg	 * pointer to xTestReset structure
354caade7ccSmrg	 */
355caade7ccSmrg	xTestResetReq 	*req;
356caade7ccSmrg
357caade7ccSmrg	LockDisplay(dpy);
358caade7ccSmrg	if (XTestCheckExtInit(dpy) == -1)
359caade7ccSmrg	{
360caade7ccSmrg		/*
361caade7ccSmrg		 * if the extension is not installed in the server
362caade7ccSmrg		 * then unlock the display and return -1.
363caade7ccSmrg		 */
364caade7ccSmrg		UnlockDisplay(dpy);
365caade7ccSmrg		return(-1);
366caade7ccSmrg	}
367caade7ccSmrg	else
368caade7ccSmrg	{
369caade7ccSmrg		/*
370caade7ccSmrg		 * Get the next available X request packet in the buffer.
371caade7ccSmrg		 * It sets the `length' field to the size (in 32-bit words)
372caade7ccSmrg		 * of the request.  It also sets the `reqType' field in the
373caade7ccSmrg		 * request to X_TestReset, which is not what is needed.
374caade7ccSmrg		 *
375caade7ccSmrg		 * GetReq is a macro defined in Xlibint.h.
376caade7ccSmrg		 */
377caade7ccSmrg		GetReq(TestReset, req);
378caade7ccSmrg		/*
379caade7ccSmrg		 * fix up the request type code to what is needed
380caade7ccSmrg		 */
381caade7ccSmrg		req->reqType = XTestReqCode;
382caade7ccSmrg		/*
383caade7ccSmrg		 * set the minor request type code to X_TestReset
384caade7ccSmrg		 */
385caade7ccSmrg		req->XTestReqType = X_TestReset;
386caade7ccSmrg		UnlockDisplay(dpy);
387caade7ccSmrg		SyncHandle();
388caade7ccSmrg		return(0);
389caade7ccSmrg	}
390caade7ccSmrg}
391caade7ccSmrg
392caade7ccSmrg/******************************************************************************
393caade7ccSmrg *
394caade7ccSmrg *	XTestQueryInputSize
395caade7ccSmrg *
396caade7ccSmrg *	Returns the number of input actions in the server's input action buffer.
397caade7ccSmrg */
398caade7ccSmrgint
399caade7ccSmrgXTestQueryInputSize(
400caade7ccSmrg/*
401caade7ccSmrg * the connection to the X server
402caade7ccSmrg */
403caade7ccSmrgregister Display	*dpy,
404caade7ccSmrg/*
405caade7ccSmrg * the address of the place to put the number of input actions in the
406caade7ccSmrg * server's input action buffer
407caade7ccSmrg */
408caade7ccSmrgunsigned long		*size_return)
409caade7ccSmrg{
410caade7ccSmrg	/*
411caade7ccSmrg	 * pointer to xTestQueryInputSize structure
412caade7ccSmrg	 */
413caade7ccSmrg	xTestQueryInputSizeReq 		*req;
414caade7ccSmrg	/*
415caade7ccSmrg	 * pointer to xTestQueryInputSize structure
416caade7ccSmrg	 */
417caade7ccSmrg	xTestQueryInputSizeReply 	rep;
418caade7ccSmrg
419caade7ccSmrg	LockDisplay(dpy);
420caade7ccSmrg	if (XTestCheckExtInit(dpy) == -1)
421caade7ccSmrg	{
422caade7ccSmrg		/*
423caade7ccSmrg		 * if the extension is not installed in the server
424caade7ccSmrg		 * then unlock the display and return -1.
425caade7ccSmrg		 */
426caade7ccSmrg		UnlockDisplay(dpy);
427caade7ccSmrg		return(-1);
428caade7ccSmrg	}
429caade7ccSmrg	else
430caade7ccSmrg	{
431caade7ccSmrg		/*
432caade7ccSmrg		 * Get the next available X request packet in the buffer.
433caade7ccSmrg		 * It sets the `length' field to the size (in 32-bit words)
434caade7ccSmrg		 * of the request.  It also sets the `reqType' field in the
435caade7ccSmrg		 * request to X_TestQueryInputSize, which is not what is needed.
436caade7ccSmrg		 *
437caade7ccSmrg		 * GetReq is a macro defined in Xlibint.h.
438caade7ccSmrg		 */
439caade7ccSmrg		GetReq(TestQueryInputSize, req);
440caade7ccSmrg		/*
441caade7ccSmrg		 * fix up the request type code to what is needed
442caade7ccSmrg		 */
443caade7ccSmrg		req->reqType = XTestReqCode;
444caade7ccSmrg		/*
445caade7ccSmrg		 * set the minor request type code to X_TestQueryInputSize
446caade7ccSmrg		 */
447caade7ccSmrg		req->XTestReqType = X_TestQueryInputSize;
448caade7ccSmrg		/*
449caade7ccSmrg		 * get a reply from the server
450caade7ccSmrg		 */
451caade7ccSmrg		(void) _XReply (dpy, (xReply *) &rep, 0, xTrue);
452caade7ccSmrg		/*
453caade7ccSmrg		 * put the size in the caller's variable
454caade7ccSmrg		 */
455caade7ccSmrg		*size_return = (unsigned long) rep.size_return;
456caade7ccSmrg		UnlockDisplay(dpy);
457caade7ccSmrg		SyncHandle();
458caade7ccSmrg		return(0);
459caade7ccSmrg	}
460caade7ccSmrg}
461caade7ccSmrg
462caade7ccSmrg/******************************************************************************
463caade7ccSmrg *
464caade7ccSmrg *	XTestCheckExtInit
465caade7ccSmrg *
466caade7ccSmrg *	Check to see if the XTest extension is installed in the server.
467caade7ccSmrg */
468caade7ccSmrgstatic int
469caade7ccSmrgXTestCheckExtInit(
470caade7ccSmrg/*
471caade7ccSmrg * the connection to the X server
472caade7ccSmrg */
473caade7ccSmrgregister Display	*dpy)
474caade7ccSmrg{
475caade7ccSmrg	/*
476caade7ccSmrg	 * if the extension has not been initialized, then do so
477caade7ccSmrg	 */
478caade7ccSmrg	if (!XTestReqCode)
479caade7ccSmrg	{
480caade7ccSmrg		return(XTestInitExtension(dpy));
481caade7ccSmrg	}
482caade7ccSmrg	return(0);
483caade7ccSmrg}
484caade7ccSmrg
485caade7ccSmrg/******************************************************************************
486caade7ccSmrg *
487caade7ccSmrg *	XTestInitExtension
488caade7ccSmrg *
489caade7ccSmrg *	Attempt to initialize this extension in the server.  Return 0 if it
490caade7ccSmrg *	succeeds, -1 if it does not succeed.
491caade7ccSmrg */
492caade7ccSmrgstatic int
493caade7ccSmrgXTestInitExtension(
494caade7ccSmrg/*
495caade7ccSmrg * the connection to the X server
496caade7ccSmrg */
497caade7ccSmrgregister Display	*dpy)
498caade7ccSmrg{
499caade7ccSmrg	/*
500caade7ccSmrg	 * loop index
501caade7ccSmrg	 */
502caade7ccSmrg	int			i;
503caade7ccSmrg	/*
504caade7ccSmrg	 * return value from XInitExtension
505caade7ccSmrg	 */
506caade7ccSmrg	XExtCodes		*ret;
507caade7ccSmrg
508caade7ccSmrg	/*
509caade7ccSmrg	 * attempt to initialize the extension
510caade7ccSmrg	 */
511caade7ccSmrg	ret = XInitExtension(dpy, XTestEXTENSION_NAME);
512caade7ccSmrg	/*
513caade7ccSmrg	 * if the initialize failed, return -1
514caade7ccSmrg	 */
515caade7ccSmrg	if (ret == NULL)
516caade7ccSmrg	{
517caade7ccSmrg		return (-1);
518caade7ccSmrg	}
519caade7ccSmrg	/*
520caade7ccSmrg	 * the initialize succeeded, remember the major opcode
521caade7ccSmrg	 * for this extension
522caade7ccSmrg	 */
523caade7ccSmrg	XTestReqCode = ret->major_opcode;
524caade7ccSmrg	/*
525caade7ccSmrg	 * set up the event handler for any events from
526caade7ccSmrg	 * this extension
527caade7ccSmrg	 */
528caade7ccSmrg	for (i = 0; i < XTestEVENT_COUNT; i++)
529caade7ccSmrg	{
530caade7ccSmrg		XESetWireToEvent(dpy,
531caade7ccSmrg				 ret->first_event+i,
532caade7ccSmrg				 XTestWireToEvent);
533caade7ccSmrg	}
534caade7ccSmrg	/*
535caade7ccSmrg	 * compute the event type codes for the events
536caade7ccSmrg	 * in this extension
537caade7ccSmrg	 */
538caade7ccSmrg	XTestInputActionType += ret->first_event;
539caade7ccSmrg	XTestFakeAckType += ret->first_event;
540caade7ccSmrg	/*
541caade7ccSmrg	 * everything worked ok
542caade7ccSmrg	 */
543caade7ccSmrg	return(0);
544caade7ccSmrg}
545caade7ccSmrg
546caade7ccSmrg/******************************************************************************
547caade7ccSmrg *
548caade7ccSmrg *	XTestWireToEvent
549caade7ccSmrg *
550caade7ccSmrg *	Handle XTest extension events.
551caade7ccSmrg *	Reformat a wire event into an XEvent structure of the right type.
552caade7ccSmrg */
553caade7ccSmrgstatic Bool
554caade7ccSmrgXTestWireToEvent(
555caade7ccSmrg/*
556caade7ccSmrg * the connection to the X server
557caade7ccSmrg */
558caade7ccSmrgDisplay	*dpy,
559caade7ccSmrg/*
560caade7ccSmrg * a pointer to where a host formatted event should be stored
561caade7ccSmrg * with the information copied to it
562caade7ccSmrg */
563caade7ccSmrgXEvent	*reTemp,
564caade7ccSmrg/*
565caade7ccSmrg * a pointer to the wire event
566caade7ccSmrg */
567caade7ccSmrgxEvent	*eventTemp)
568caade7ccSmrg{
569caade7ccSmrg	XTestInputActionEvent *re    = (XTestInputActionEvent *) reTemp;
570caade7ccSmrg	xTestInputActionEvent *event = (xTestInputActionEvent *) eventTemp;
571caade7ccSmrg
572caade7ccSmrg	/*
573caade7ccSmrg	 * loop index
574caade7ccSmrg	 */
575caade7ccSmrg	int	i;
576caade7ccSmrg	/*
577caade7ccSmrg	 * pointer to where the input actions go in the host format event
578caade7ccSmrg	 */
579caade7ccSmrg	CARD8	*to;
580caade7ccSmrg	/*
581caade7ccSmrg	 * pointer to the input actions in the wire event
582caade7ccSmrg	 */
583caade7ccSmrg	CARD8	*from;
584caade7ccSmrg
585caade7ccSmrg	/*
586caade7ccSmrg	 * Copy the type of the wire event to the new event.
587caade7ccSmrg	 * This will work for either event type because the type,
588caade7ccSmrg	 * display, and window fields in the events have to be the same.
589caade7ccSmrg	 */
590caade7ccSmrg	re->type = event->type;
591caade7ccSmrg	/*
592caade7ccSmrg	 * set the display parameter in case it is needed (by who?)
593caade7ccSmrg	 */
594caade7ccSmrg	re->display = dpy;
595caade7ccSmrg	if (re->type == XTestInputActionType)
596caade7ccSmrg	{
597caade7ccSmrg		/*
598caade7ccSmrg		 * point at the first byte of input actions in the wire event
599caade7ccSmrg		 */
600caade7ccSmrg		from = &(event->actions[0]);
601caade7ccSmrg		/*
602caade7ccSmrg		 * point at where the input action bytes go in the new event
603caade7ccSmrg		 */
604caade7ccSmrg		to = &(re->actions[0]);
605caade7ccSmrg		/*
606caade7ccSmrg		 * copy the input action bytes from the wire event to
607caade7ccSmrg		 * the new event
608caade7ccSmrg		 */
609caade7ccSmrg		for (i = 0; i < XTestACTIONS_SIZE; i++)
610caade7ccSmrg		{
611caade7ccSmrg			*(to++) = *(from++);
612caade7ccSmrg		}
613caade7ccSmrg	}
614caade7ccSmrg	else if (re->type == XTestFakeAckType)
615caade7ccSmrg	{
616caade7ccSmrg		/*
617caade7ccSmrg		 * nothing else needs to be done
618caade7ccSmrg		 */
619caade7ccSmrg	}
620caade7ccSmrg	else
621caade7ccSmrg	{
622caade7ccSmrg		printf("XTestWireToEvent: UNKNOWN WIRE EVENT! type=%d\n",
623caade7ccSmrg			(int) event->type);
624caade7ccSmrg		printf("%s is giving up.\n", XTestEXTENSION_NAME);
625caade7ccSmrg		exit (1);
626caade7ccSmrg	}
627caade7ccSmrg	return 1;
628caade7ccSmrg}
629caade7ccSmrg
630caade7ccSmrg/******************************************************************************
631caade7ccSmrg *
632caade7ccSmrg *	XTestPressKey
633caade7ccSmrg *
634caade7ccSmrg *	Send input actions to the server to cause the server to think
635caade7ccSmrg *	that the specified key on the keyboard was moved as specified.
636caade7ccSmrg */
637caade7ccSmrgint
638caade7ccSmrgXTestPressKey(
639caade7ccSmrgDisplay		*display,
640caade7ccSmrgint		device_id,
641caade7ccSmrgunsigned long	delay,
642caade7ccSmrgunsigned int	keycode,
643caade7ccSmrgunsigned int	key_action)
644caade7ccSmrg{
645caade7ccSmrg	/*
646caade7ccSmrg	 * bounds check the key code
647caade7ccSmrg	 */
648caade7ccSmrg	if (keycode < 8 || keycode > 255)
649caade7ccSmrg	{
650caade7ccSmrg		return(-1);
651caade7ccSmrg	}
652caade7ccSmrg	/*
653caade7ccSmrg	 * use the commmon key/button handling routine
654caade7ccSmrg	 */
655caade7ccSmrg	return(XTestKeyOrButton(display,
656caade7ccSmrg				device_id,
657caade7ccSmrg				delay,
658caade7ccSmrg				keycode,
659caade7ccSmrg				key_action));
660caade7ccSmrg}
661caade7ccSmrg
662caade7ccSmrg/******************************************************************************
663caade7ccSmrg *
664caade7ccSmrg *	XTestPressButton
665caade7ccSmrg *
666caade7ccSmrg *	Send input actions to the server to cause the server to think
667caade7ccSmrg *	that the specified button on the mouse was moved as specified.
668caade7ccSmrg */
669caade7ccSmrgint
670caade7ccSmrgXTestPressButton(
671caade7ccSmrgDisplay		*display,
672caade7ccSmrgint		device_id,
673caade7ccSmrgunsigned long	delay,
674caade7ccSmrgunsigned int	button_number,
675caade7ccSmrgunsigned int	button_action)
676caade7ccSmrg{
677caade7ccSmrg	/*
678caade7ccSmrg	 * bounds check the button number
679caade7ccSmrg	 */
680caade7ccSmrg	if (button_number > 7)
681caade7ccSmrg	{
682caade7ccSmrg		return(-1);
683caade7ccSmrg	}
684caade7ccSmrg	/*
685caade7ccSmrg	 * use the commmon key/button handling routine
686caade7ccSmrg	 */
687caade7ccSmrg	return(XTestKeyOrButton(display,
688caade7ccSmrg				device_id,
689caade7ccSmrg				delay,
690caade7ccSmrg				button_number,
691caade7ccSmrg				button_action));
692caade7ccSmrg}
693caade7ccSmrg
694caade7ccSmrg/******************************************************************************
695caade7ccSmrg *
696caade7ccSmrg *	XTestKeyOrButton
697caade7ccSmrg *
698caade7ccSmrg *	Send input actions to the server to cause the server to think
699caade7ccSmrg *	that the specified key/button was moved as specified.
700caade7ccSmrg */
701caade7ccSmrgstatic int
702caade7ccSmrgXTestKeyOrButton(
703caade7ccSmrgDisplay		*display,
704caade7ccSmrgint		device_id,
705caade7ccSmrgunsigned long	delay,
706caade7ccSmrgunsigned int	code,
707caade7ccSmrgunsigned int	action)
708caade7ccSmrg{
709caade7ccSmrg	/*
710caade7ccSmrg	 * holds a key input action to be filled out and sent to the server
711caade7ccSmrg	 */
712caade7ccSmrg	XTestKeyInfo	keyinfo;
713caade7ccSmrg
714caade7ccSmrg	/*
715caade7ccSmrg	 * bounds check the device id
716caade7ccSmrg	 */
717caade7ccSmrg	if (device_id < 0 || device_id > XTestMAX_DEVICE_ID)
718caade7ccSmrg	{
719caade7ccSmrg		return(-1);
720caade7ccSmrg	}
721caade7ccSmrg	/*
722caade7ccSmrg	 * fill out the key input action(s) as appropriate
723caade7ccSmrg	 */
724caade7ccSmrg	switch(action)
725caade7ccSmrg	{
726caade7ccSmrg	case XTestPRESS:
727caade7ccSmrg		/*
728caade7ccSmrg		 * Check the delay.  If it is larger than will fit in the
729caade7ccSmrg		 * key input action, send a delay input action.
730caade7ccSmrg		 */
731caade7ccSmrg		if(XTestCheckDelay(display, &delay) == -1)
732caade7ccSmrg		{
733caade7ccSmrg			/*
734caade7ccSmrg			 * an error occurred, return -1
735caade7ccSmrg			 */
736caade7ccSmrg			return(-1);
737caade7ccSmrg		}
738caade7ccSmrg		/*
739caade7ccSmrg		 * create the header
740caade7ccSmrg		 */
741caade7ccSmrg		keyinfo.header = XTestPackDeviceID(device_id) |
742caade7ccSmrg				 XTestKEY_ACTION |
743caade7ccSmrg				 XTestKEY_DOWN;
744caade7ccSmrg		/*
745caade7ccSmrg		 * set the key/button code
746caade7ccSmrg		 */
747caade7ccSmrg		keyinfo.keycode = code;
748caade7ccSmrg		/*
749caade7ccSmrg		 * set the delay time
750caade7ccSmrg		 */
751caade7ccSmrg		keyinfo.delay_time = delay;
752caade7ccSmrg		/*
753caade7ccSmrg		 * pack the input action into a request to be sent to the
754caade7ccSmrg		 * server when the request is full or XTestFlush is called
755caade7ccSmrg		 */
756caade7ccSmrg		return(XTestPackInputAction(display,
757caade7ccSmrg					    (CARD8 *) &keyinfo,
758caade7ccSmrg					    sizeof(XTestKeyInfo)));
759caade7ccSmrg	case XTestRELEASE:
760caade7ccSmrg		/*
761caade7ccSmrg		 * Check the delay.  If it is larger than will fit in the
762caade7ccSmrg		 * key input action, send a delay input action.
763caade7ccSmrg		 */
764caade7ccSmrg		if(XTestCheckDelay(display, &delay) == -1)
765caade7ccSmrg		{
766caade7ccSmrg			/*
767caade7ccSmrg			 * an error occurred, return -1
768caade7ccSmrg			 */
769caade7ccSmrg			return(-1);
770caade7ccSmrg		}
771caade7ccSmrg		/*
772caade7ccSmrg		 * create the header
773caade7ccSmrg		 */
774caade7ccSmrg		keyinfo.header = XTestPackDeviceID(device_id) |
775caade7ccSmrg				 XTestKEY_ACTION |
776caade7ccSmrg				 XTestKEY_UP;
777caade7ccSmrg		/*
778caade7ccSmrg		 * set the key/button code
779caade7ccSmrg		 */
780caade7ccSmrg		keyinfo.keycode = code;
781caade7ccSmrg		/*
782caade7ccSmrg		 * set the delay time
783caade7ccSmrg		 */
784caade7ccSmrg		keyinfo.delay_time = delay;
785caade7ccSmrg		/*
786caade7ccSmrg		 * pack the input action into a request to be sent to the
787caade7ccSmrg		 * server when the request is full or XTestFlush is called
788caade7ccSmrg		 */
789caade7ccSmrg		return(XTestPackInputAction(display,
790caade7ccSmrg					    (CARD8 *) &keyinfo,
791caade7ccSmrg					    sizeof(XTestKeyInfo)));
792caade7ccSmrg	case XTestSTROKE:
793caade7ccSmrg		/*
794caade7ccSmrg		 * Check the delay.  If it is larger than will fit in the
795caade7ccSmrg		 * key input action, send a delay input action.
796caade7ccSmrg		 */
797caade7ccSmrg		if(XTestCheckDelay(display, &delay) == -1)
798caade7ccSmrg		{
799caade7ccSmrg			/*
800caade7ccSmrg			 * an error occurred, return -1
801caade7ccSmrg			 */
802caade7ccSmrg			return(-1);
803caade7ccSmrg		}
804caade7ccSmrg		/*
805caade7ccSmrg		 * create a key/button-down input action header
806caade7ccSmrg		 */
807caade7ccSmrg		keyinfo.header = XTestPackDeviceID(device_id) |
808caade7ccSmrg				 XTestKEY_ACTION |
809caade7ccSmrg				 XTestKEY_DOWN;
810caade7ccSmrg		/*
811caade7ccSmrg		 * set the key/button code
812caade7ccSmrg		 */
813caade7ccSmrg		keyinfo.keycode = code;
814caade7ccSmrg		/*
815caade7ccSmrg		 * set the delay time
816caade7ccSmrg		 */
817caade7ccSmrg		keyinfo.delay_time = delay;
818caade7ccSmrg		/*
819caade7ccSmrg		 * pack the input action into a request to be sent to the
820caade7ccSmrg		 * server when the request is full or XTestFlush is called
821caade7ccSmrg		 */
822caade7ccSmrg		if (XTestPackInputAction(display,
823caade7ccSmrg					 (CARD8 *) &keyinfo,
824caade7ccSmrg					 sizeof(XTestKeyInfo)) == -1)
825caade7ccSmrg		{
826caade7ccSmrg			/*
827caade7ccSmrg			 * an error occurred, return -1
828caade7ccSmrg			 */
829caade7ccSmrg			return(-1);
830caade7ccSmrg		}
831caade7ccSmrg		/*
832caade7ccSmrg		 * set the delay to XTestSTROKE_DELAY_TIME
833caade7ccSmrg		 */
834caade7ccSmrg		delay = XTestSTROKE_DELAY_TIME;
835caade7ccSmrg		/*
836caade7ccSmrg		 * Check the delay.  If it is larger than will fit in the
837caade7ccSmrg		 * key input action, send a delay input action.
838caade7ccSmrg		 */
839caade7ccSmrg		if(XTestCheckDelay(display, &delay) == -1)
840caade7ccSmrg		{
841caade7ccSmrg			/*
842caade7ccSmrg			 * an error occurred, return -1
843caade7ccSmrg			 */
844caade7ccSmrg			return(-1);
845caade7ccSmrg		}
846caade7ccSmrg		/*
847caade7ccSmrg		 * create a key/button-up input action header
848caade7ccSmrg		 */
849caade7ccSmrg		keyinfo.header = XTestPackDeviceID(device_id) |
850caade7ccSmrg				 XTestKEY_ACTION |
851caade7ccSmrg				 XTestKEY_UP;
852caade7ccSmrg		/*
853caade7ccSmrg		 * set the key/button code
854caade7ccSmrg		 */
855caade7ccSmrg		keyinfo.keycode = code;
856caade7ccSmrg		/*
857caade7ccSmrg		 * set the delay time
858caade7ccSmrg		 */
859caade7ccSmrg		keyinfo.delay_time = delay;
860caade7ccSmrg		/*
861caade7ccSmrg		 * pack the input action into a request to be sent to the
862caade7ccSmrg		 * server when the request is full or XTestFlush is called
863caade7ccSmrg		 */
864caade7ccSmrg		return(XTestPackInputAction(display,
865caade7ccSmrg					    (CARD8 *) &keyinfo,
866caade7ccSmrg					    sizeof(XTestKeyInfo)));
867caade7ccSmrg	default:
868caade7ccSmrg		/*
869caade7ccSmrg		 * invalid action value, return -1
870caade7ccSmrg		 */
871caade7ccSmrg		 return(-1);
872caade7ccSmrg	}
873caade7ccSmrg}
874caade7ccSmrg
875caade7ccSmrg/******************************************************************************
876caade7ccSmrg *
877caade7ccSmrg *	XTestMovePointer
878caade7ccSmrg *
879caade7ccSmrg *	Send input actions to the server to cause the server to think
880caade7ccSmrg *	that the mouse was moved as specified.
881caade7ccSmrg */
882caade7ccSmrgint
883caade7ccSmrgXTestMovePointer(
884caade7ccSmrgDisplay		*display,
885caade7ccSmrgint		device_id,
886caade7ccSmrgunsigned long	delay[],
887caade7ccSmrgint		x[],
888caade7ccSmrgint		y[],
889caade7ccSmrgunsigned int	count)
890caade7ccSmrg{
891caade7ccSmrg	/*
892caade7ccSmrg	 * holds a motion input action to be filled out and sent to the server
893caade7ccSmrg	 */
894caade7ccSmrg	XTestMotionInfo	motioninfo;
895caade7ccSmrg	/*
896caade7ccSmrg	 * holds a jump input action to be filled out and sent to the server
897caade7ccSmrg	 */
898caade7ccSmrg	XTestJumpInfo	jumpinfo;
899caade7ccSmrg	/*
900caade7ccSmrg	 * loop index
901caade7ccSmrg	 */
902caade7ccSmrg	unsigned int	i;
903caade7ccSmrg	/*
904caade7ccSmrg	 * holds the change in x and y directions from the current x and y
905caade7ccSmrg	 * coordinates
906caade7ccSmrg	 */
907caade7ccSmrg	int	dx;
908caade7ccSmrg	int	dy;
909caade7ccSmrg
910caade7ccSmrg	/*
911caade7ccSmrg	 * bounds check the device id
912caade7ccSmrg	 */
913caade7ccSmrg	if (device_id < 0 || device_id > XTestMAX_DEVICE_ID)
914caade7ccSmrg	{
915caade7ccSmrg		return(-1);
916caade7ccSmrg	}
917caade7ccSmrg	/*
918caade7ccSmrg	 * if the count is 0, there is nothing to do.  return 0
919caade7ccSmrg	 */
920caade7ccSmrg	if (count == 0)
921caade7ccSmrg	{
922caade7ccSmrg		return(0);
923caade7ccSmrg	}
924caade7ccSmrg	/*
925caade7ccSmrg	 * loop through the pointer motions, creating the appropriate
926caade7ccSmrg	 * input actions for each motion
927caade7ccSmrg	 */
928caade7ccSmrg	for (i = 0; i < count; i++)
929caade7ccSmrg	{
930caade7ccSmrg		/*
931caade7ccSmrg		 * Check the delay.  If it is larger than will fit in the
932caade7ccSmrg		 * input action, send a delay input action.
933caade7ccSmrg		 */
934caade7ccSmrg		if(XTestCheckDelay(display, &(delay[i])) == -1)
935caade7ccSmrg		{
936caade7ccSmrg			/*
937caade7ccSmrg			 * an error occurred, return -1
938caade7ccSmrg			 */
939caade7ccSmrg			return(-1);
940caade7ccSmrg		}
941caade7ccSmrg		/*
942caade7ccSmrg		 * compute the change from the current x and y coordinates
943caade7ccSmrg		 * to the new x and y coordinates
944caade7ccSmrg		 */
945caade7ccSmrg		dx = x[i] - current_x;
946caade7ccSmrg		dy = y[i] - current_y;
947caade7ccSmrg		/*
948caade7ccSmrg		 * update the current x and y coordinates
949caade7ccSmrg		 */
950caade7ccSmrg		current_x = x[i];
951caade7ccSmrg		current_y = y[i];
952caade7ccSmrg		/*
953caade7ccSmrg		 * If the pointer motion range is too large to fit into
954caade7ccSmrg		 * a motion input action, then use a jump input action.
955caade7ccSmrg		 * Otherwise, use a motion input action.
956caade7ccSmrg		 */
957caade7ccSmrg		 if ((dx > XTestMOTION_MAX) || (dx < XTestMOTION_MIN) ||
958caade7ccSmrg		     (dy > XTestMOTION_MAX) || (dy < XTestMOTION_MIN))
959caade7ccSmrg		{
960caade7ccSmrg			/*
961caade7ccSmrg			 * create a jump input action header
962caade7ccSmrg			 */
963caade7ccSmrg			jumpinfo.header = XTestPackDeviceID(device_id) |
964caade7ccSmrg					  XTestJUMP_ACTION;
965caade7ccSmrg			/*
966caade7ccSmrg			 * set the x and y coordinates to jump to
967caade7ccSmrg			 */
968caade7ccSmrg			jumpinfo.jumpx = x[i];
969caade7ccSmrg			jumpinfo.jumpy = y[i];
970caade7ccSmrg			/*
971caade7ccSmrg			 * set the delay time
972caade7ccSmrg			 */
973caade7ccSmrg			jumpinfo.delay_time = delay[i];
974caade7ccSmrg			/*
975caade7ccSmrg			 * pack the jump input action into a request to be
976caade7ccSmrg			 * sent to the server when the request is full
977caade7ccSmrg			 * or XTestFlush is called
978caade7ccSmrg			 */
979caade7ccSmrg			if (XTestPackInputAction(display,
980caade7ccSmrg						 (CARD8 *) &jumpinfo,
981caade7ccSmrg						 sizeof(XTestJumpInfo)) == -1)
982caade7ccSmrg			{
983caade7ccSmrg				/*
984caade7ccSmrg				 * an error occurred, return -1
985caade7ccSmrg				 */
986caade7ccSmrg				return(-1);
987caade7ccSmrg			}
988caade7ccSmrg		}
989caade7ccSmrg		else
990caade7ccSmrg		{
991caade7ccSmrg			/*
992caade7ccSmrg			 * create a motion input action header
993caade7ccSmrg			 */
994caade7ccSmrg			motioninfo.header = XTestPackDeviceID(device_id) |
995caade7ccSmrg					    XTestMOTION_ACTION;
996caade7ccSmrg			/*
997caade7ccSmrg			 * compute the motion data byte
998caade7ccSmrg			 */
999caade7ccSmrg			if (dx < 0)
1000caade7ccSmrg			{
1001caade7ccSmrg				motioninfo.header |= XTestX_NEGATIVE;
1002caade7ccSmrg				dx = abs(dx);
1003caade7ccSmrg			}
1004caade7ccSmrg			if (dy < 0)
1005caade7ccSmrg			{
1006caade7ccSmrg				motioninfo.header |= XTestY_NEGATIVE;
1007caade7ccSmrg				dy = abs(dy);
1008caade7ccSmrg			}
1009caade7ccSmrg			motioninfo.motion_data = XTestPackXMotionValue(dx);
1010caade7ccSmrg			motioninfo.motion_data |= XTestPackYMotionValue(dy);
1011caade7ccSmrg			/*
1012caade7ccSmrg			 * set the delay time
1013caade7ccSmrg			 */
1014caade7ccSmrg			motioninfo.delay_time = delay[i];
1015caade7ccSmrg			/*
1016caade7ccSmrg			 * pack the motion input action into a request to be
1017caade7ccSmrg			 * sent to the server when the request is full
1018caade7ccSmrg			 * or XTestFlush is called
1019caade7ccSmrg			 */
1020caade7ccSmrg			if (XTestPackInputAction(display,
1021caade7ccSmrg						 (CARD8 *) &motioninfo,
1022caade7ccSmrg						 sizeof(XTestMotionInfo)) == -1)
1023caade7ccSmrg			{
1024caade7ccSmrg				/*
1025caade7ccSmrg				 * an error occurred, return -1
1026caade7ccSmrg				 */
1027caade7ccSmrg				return(-1);
1028caade7ccSmrg			}
1029caade7ccSmrg		}
1030caade7ccSmrg	}
1031caade7ccSmrg	/*
1032caade7ccSmrg	 * if you get here, everything went ok
1033caade7ccSmrg	 */
1034caade7ccSmrg	return(0);
1035caade7ccSmrg}
1036caade7ccSmrg
1037caade7ccSmrg/******************************************************************************
1038caade7ccSmrg *
1039caade7ccSmrg *	XTestCheckDelay
1040caade7ccSmrg *
1041caade7ccSmrg *	Check the delay value at the passed-in address.  If it is larger than
1042caade7ccSmrg *	will fit in a normal input action, then send a delay input action.
1043caade7ccSmrg */
1044caade7ccSmrgstatic int
1045caade7ccSmrgXTestCheckDelay(
1046caade7ccSmrgDisplay		*display,
1047caade7ccSmrgunsigned long	*delay_addr)
1048caade7ccSmrg{
1049caade7ccSmrg	/*
1050caade7ccSmrg	 * holds a delay input action to be filled out and sent to the server
1051caade7ccSmrg	 */
1052caade7ccSmrg	XTestDelayInfo	delayinfo;
1053caade7ccSmrg
1054caade7ccSmrg	/*
1055caade7ccSmrg	 * if the delay value will fit in the input action,
1056caade7ccSmrg	 * then there is no need for a delay input action
1057caade7ccSmrg	 */
1058caade7ccSmrg	if (*delay_addr <= XTestSHORT_DELAY_TIME)
1059caade7ccSmrg	{
1060caade7ccSmrg		return(0);
1061caade7ccSmrg	}
1062caade7ccSmrg	/*
1063caade7ccSmrg	 * fill out a delay input action
1064caade7ccSmrg	 */
1065caade7ccSmrg	delayinfo.header = XTestPackDeviceID(XTestDELAY_DEVICE_ID);
1066caade7ccSmrg	delayinfo.delay_time = *delay_addr;
1067caade7ccSmrg	/*
1068caade7ccSmrg	 * all of the delay time will be accounted for in the
1069caade7ccSmrg	 * delay input action, so set the original delay value to 0
1070caade7ccSmrg	 */
1071caade7ccSmrg	*delay_addr = 0;
1072caade7ccSmrg	/*
1073caade7ccSmrg	 * pack the delay input action into a request to be sent to the
1074caade7ccSmrg	 * server when the request is full or XTestFlush is called
1075caade7ccSmrg	 */
1076caade7ccSmrg	return(XTestPackInputAction(display,
1077caade7ccSmrg				    (CARD8 *) &delayinfo,
1078caade7ccSmrg				    sizeof(XTestDelayInfo)));
1079caade7ccSmrg}
1080caade7ccSmrg
1081caade7ccSmrg/******************************************************************************
1082caade7ccSmrg *
1083caade7ccSmrg *	XTestPackInputAction
1084caade7ccSmrg *
1085caade7ccSmrg *	If the input action buffer is full or the number of input actions
1086caade7ccSmrg *	has reached the maximum that the server can handle at one time,
1087caade7ccSmrg *	then send the input actions to the server using XTestFakeInput.
1088caade7ccSmrg */
1089caade7ccSmrgstatic int
1090caade7ccSmrgXTestPackInputAction(
1091caade7ccSmrgDisplay	*display,
1092caade7ccSmrgCARD8	*action_addr,
1093caade7ccSmrgint	action_size)
1094caade7ccSmrg{
1095caade7ccSmrg	/*
1096caade7ccSmrg	 * loop index
1097caade7ccSmrg	 */
1098caade7ccSmrg	int	i;
1099caade7ccSmrg	/*
1100caade7ccSmrg	 * acknowledge flag
1101caade7ccSmrg	 */
1102caade7ccSmrg	int	ack_flag;
1103caade7ccSmrg
1104caade7ccSmrg	/*
1105caade7ccSmrg	 * if we don't already know it, find out how many input actions
1106caade7ccSmrg	 * the server can handle at one time
1107caade7ccSmrg	 */
1108caade7ccSmrg	if (action_array_size == 0)
1109caade7ccSmrg	{
1110caade7ccSmrg		if(XTestQueryInputSize(display, &action_array_size) == -1)
1111caade7ccSmrg		{
1112caade7ccSmrg			/*
1113caade7ccSmrg			 * if an error, return -1
1114caade7ccSmrg			 */
1115caade7ccSmrg			return(-1);
1116caade7ccSmrg		}
1117caade7ccSmrg	}
1118caade7ccSmrg	/*
1119caade7ccSmrg	 * if the specified input action will fit in the the input
1120caade7ccSmrg	 * action buffer and won't exceed the server's capacity, then
1121caade7ccSmrg	 * put the input action into the input buffer
1122caade7ccSmrg	 */
1123caade7ccSmrg	if(((action_index + action_size) <= XTestMAX_ACTION_LIST_SIZE) &&
1124caade7ccSmrg	   ((action_count + 1) < action_array_size))
1125caade7ccSmrg	{
1126caade7ccSmrg		/*
1127caade7ccSmrg		 * copy the input action into the buffer
1128caade7ccSmrg		 */
1129caade7ccSmrg		for (i = 0; i < action_size; i++)
1130caade7ccSmrg		{
1131caade7ccSmrg			action_buf[action_index++] = *(action_addr++);
1132caade7ccSmrg		}
1133caade7ccSmrg		/*
1134caade7ccSmrg		 * increment the action count
1135caade7ccSmrg		 */
1136caade7ccSmrg		action_count++;
1137caade7ccSmrg		/*
1138caade7ccSmrg		 * everything went ok, return 0
1139caade7ccSmrg		 */
1140caade7ccSmrg		return(0);
1141caade7ccSmrg	}
1142caade7ccSmrg	/*
1143caade7ccSmrg	 * We have to write input actions to the server.  If the server's
1144caade7ccSmrg	 * input action capacity will be reached, then ask for an
1145caade7ccSmrg	 * acknowledge event when the server has processed all of the
1146caade7ccSmrg	 * input actions.  Otherwise, an acknowledge event is not needed.
1147caade7ccSmrg	 */
1148caade7ccSmrg	if (action_count >= action_array_size)
1149caade7ccSmrg	{
1150caade7ccSmrg		ack_flag = XTestFAKE_ACK_REQUEST;
1151caade7ccSmrg	}
1152caade7ccSmrg	else
1153caade7ccSmrg	{
1154caade7ccSmrg		ack_flag = XTestFAKE_ACK_NOT_NEEDED;
1155caade7ccSmrg	}
1156caade7ccSmrg	/*
1157caade7ccSmrg	 * write the input actions to the server
1158caade7ccSmrg	 */
1159caade7ccSmrg	if (XTestWriteInputActions(display,
1160caade7ccSmrg				   (char *) &(action_buf[0]),
1161caade7ccSmrg				   action_index,
1162caade7ccSmrg				   ack_flag) == -1)
1163caade7ccSmrg	{
1164caade7ccSmrg		/*
1165caade7ccSmrg		 * error, return -1
1166caade7ccSmrg		 */
1167caade7ccSmrg		return(-1);
1168caade7ccSmrg	}
1169caade7ccSmrg	/*
1170caade7ccSmrg	 * copy the input action into the buffer
1171caade7ccSmrg	 */
1172caade7ccSmrg	for (i = 0; i < action_size; i++)
1173caade7ccSmrg	{
1174caade7ccSmrg		action_buf[action_index++] = *(action_addr++);
1175caade7ccSmrg	}
1176caade7ccSmrg	/*
1177caade7ccSmrg	 * increment the action count
1178caade7ccSmrg	 */
1179caade7ccSmrg	action_count++;
1180caade7ccSmrg	return(0);
1181caade7ccSmrg}
1182caade7ccSmrg
1183caade7ccSmrg/******************************************************************************
1184caade7ccSmrg *
1185caade7ccSmrg *	XTestWriteInputActions
1186caade7ccSmrg *
1187caade7ccSmrg *	Send input actions to the server.
1188caade7ccSmrg */
1189caade7ccSmrgstatic int
1190caade7ccSmrgXTestWriteInputActions(
1191caade7ccSmrgDisplay	*display,
1192caade7ccSmrgchar	*action_list_addr,
1193caade7ccSmrgint	action_list_size,
1194caade7ccSmrgint	ack_flag)
1195caade7ccSmrg{
1196caade7ccSmrg	/*
1197caade7ccSmrg	 * Holds an event.  Used while waiting for an acknowledge event
1198caade7ccSmrg	 */
1199caade7ccSmrg	XEvent	event;
1200caade7ccSmrg	/*
1201caade7ccSmrg	 * points to XTestIdentifyMyEvent
1202caade7ccSmrg	 */
1203caade7ccSmrg	Bool	(*func_ptr)(Display *, XEvent *, XPointer);
1204caade7ccSmrg
1205caade7ccSmrg	/*
1206caade7ccSmrg	 * write the input actions to the server
1207caade7ccSmrg	 */
1208caade7ccSmrg	if (XTestFakeInput(display,
1209caade7ccSmrg			   action_list_addr,
1210caade7ccSmrg			   action_list_size,
1211caade7ccSmrg			   ack_flag) == -1)
1212caade7ccSmrg	{
1213caade7ccSmrg		/*
1214caade7ccSmrg		 * if an error, return -1
1215caade7ccSmrg		 */
1216caade7ccSmrg		return(-1);
1217caade7ccSmrg	}
1218caade7ccSmrg	/*
1219caade7ccSmrg	 * flush X's buffers to make sure that the server really gets
1220caade7ccSmrg	 * the input actions
1221caade7ccSmrg	 */
1222caade7ccSmrg	XFlush(display);
1223caade7ccSmrg	/*
1224caade7ccSmrg	 * mark the input action buffer as empty
1225caade7ccSmrg	 */
1226caade7ccSmrg	action_index = 0;
1227caade7ccSmrg	/*
1228caade7ccSmrg	 * if we asked for an acknowledge event, then wait for it
1229caade7ccSmrg	 */
1230caade7ccSmrg	if (ack_flag == XTestFAKE_ACK_REQUEST)
1231caade7ccSmrg	{
1232caade7ccSmrg		/*
1233caade7ccSmrg		 * point func_ptr at XTestIdentifyMyEvent
1234caade7ccSmrg		 */
1235caade7ccSmrg		func_ptr = XTestIdentifyMyEvent;
1236caade7ccSmrg		/*
1237caade7ccSmrg		 * Wait until the acknowledge event comes.  When the
1238caade7ccSmrg		 * acknowledge event comes, it is removed from the event
1239caade7ccSmrg		 * queue without disturbing any other events that might
1240caade7ccSmrg		 * be in the queue.
1241caade7ccSmrg		 */
1242caade7ccSmrg		XIfEvent(display, &event, func_ptr, NULL);
1243caade7ccSmrg		/*
1244caade7ccSmrg		 * set the input action count back to 0
1245caade7ccSmrg		 */
1246caade7ccSmrg		action_count = 0;
1247caade7ccSmrg	}
1248caade7ccSmrg	/*
1249caade7ccSmrg	 * if we got here, then everything is ok, return 0
1250caade7ccSmrg	 */
1251caade7ccSmrg	return(0);
1252caade7ccSmrg}
1253caade7ccSmrg
1254caade7ccSmrg/******************************************************************************
1255caade7ccSmrg *
1256caade7ccSmrg *	XTestIdentifyMyEvent
1257caade7ccSmrg *
1258caade7ccSmrg *	This function is called by XIfEvent to look at an event and see if
1259caade7ccSmrg *	it is of XTestFakeAckType.
1260caade7ccSmrg */
1261caade7ccSmrgstatic	Bool
1262caade7ccSmrgXTestIdentifyMyEvent(
1263caade7ccSmrgDisplay	*display,
1264caade7ccSmrg/*
1265caade7ccSmrg * Holds the event that this routine is supposed to look at.
1266caade7ccSmrg */
1267caade7ccSmrgXEvent	*event_ptr,
1268caade7ccSmrg/*
1269caade7ccSmrg * this points to any user-specified arguments (ignored)
1270caade7ccSmrg */
1271caade7ccSmrgchar	*args)
1272caade7ccSmrg{
1273caade7ccSmrg	/*
1274caade7ccSmrg	 * if the event if of the correct type, return the Bool True,
1275caade7ccSmrg	 * otherwise return the Bool False.
1276caade7ccSmrg	 */
1277caade7ccSmrg	if (event_ptr->type == XTestFakeAckType)
1278caade7ccSmrg	{
1279caade7ccSmrg		return(True);
1280caade7ccSmrg	}
1281caade7ccSmrg	else
1282caade7ccSmrg	{
1283caade7ccSmrg		return(False);
1284caade7ccSmrg	}
1285caade7ccSmrg}
1286caade7ccSmrg
1287caade7ccSmrg/******************************************************************************
1288caade7ccSmrg *
1289caade7ccSmrg *	XTestFlush
1290caade7ccSmrg *
1291caade7ccSmrg *	Send any input actions in the input action buffer to the server.
1292caade7ccSmrg */
1293caade7ccSmrgint
1294caade7ccSmrgXTestFlush(Display *display)
1295caade7ccSmrg{
1296caade7ccSmrg	/*
1297caade7ccSmrg	 * acknowledge flag
1298caade7ccSmrg	 */
1299caade7ccSmrg	int	ack_flag;
1300caade7ccSmrg
1301caade7ccSmrg	/*
1302caade7ccSmrg	 * if there are no input actions in the input action buffer,
1303caade7ccSmrg	 * then return 0
1304caade7ccSmrg	 */
1305caade7ccSmrg	if (action_index == 0)
1306caade7ccSmrg	{
1307caade7ccSmrg		return(0);
1308caade7ccSmrg	}
1309caade7ccSmrg	/*
1310caade7ccSmrg	 * We have input actions to write to the server.  We will
1311caade7ccSmrg	 * wait until the server has finished processing the input actions.
1312caade7ccSmrg	 */
1313caade7ccSmrg	ack_flag = XTestFAKE_ACK_REQUEST;
1314caade7ccSmrg	/*
1315caade7ccSmrg	 * write the input actions to the server
1316caade7ccSmrg	 */
1317caade7ccSmrg	return(XTestWriteInputActions(display,
1318caade7ccSmrg				      (char *) &(action_buf[0]),
1319caade7ccSmrg				      action_index,
1320caade7ccSmrg				      ack_flag));
1321caade7ccSmrg}
1322