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