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