XERqsts.c revision 9384b2f3
1/* $XFree86$ */
2/*****************************************************************************
3Copyright 1987, 1988, 1989, 1990, 1991 by Digital Equipment Corp., Maynard, MA
4
5Permission to use, copy, modify, and distribute this software and its
6documentation for any purpose and without fee is hereby granted,
7provided that the above copyright notice appear in all copies and that
8both that copyright notice and this permission notice appear in
9supporting documentation, and that the name of Digital not be
10used in advertising or publicity pertaining to distribution of the
11software without specific, written prior permission.
12
13DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
14ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
15DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
16ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
17WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
18ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
19SOFTWARE.
20
21*****************************************************************************/
22#ifndef NO_DEC_ADDED_VALUE
23#ifdef SMT
24#define NEED_EVENTS
25#define NEED_REPLIES
26#endif
27#include <X11/Xlib.h>
28#define NEED_REPLIES
29#define NEED_EVENTS
30#include <X11/Xproto.h>
31#else /* NO_DEC_BUG_FIX */
32#include <X11/Xlib.h>
33#define NEED_REPLIES
34#define NEED_EVENTS
35#include <X11/Xproto.h>
36#endif /* NO_DEC_BUG_FIX */
37/* the following's a hack to support V3.1 protocol */
38#if defined(__STDC__) && !defined(UNIXCPP)
39#define GetOldReq(name, req, old_length) \
40        WORD64ALIGN\
41        if ((dpy->bufptr + SIZEOF(x##name##Req)) > dpy->bufmax)\
42                _XFlush(dpy);\
43        req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\
44        req->reqType = X_##name;\
45        req->length = old_length>>2;\
46        dpy->bufptr += old_length;\
47        dpy->request++
48
49#else  /* non-ANSI C uses empty comment instead of "##" for token concat */
50#define GetOldReq(name, req, old_length) \
51        WORD64ALIGN\
52        if ((dpy->bufptr + SIZEOF(x/**/name/**/Req)) > dpy->bufmax)\
53                _XFlush(dpy);\
54        req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\
55        req->reqType = X_/**/name;\
56        req->length = old_length>>2;\
57        dpy->bufptr += old_length;\
58        dpy->request++
59#endif
60
61#ifndef vms
62#include <X11/Xlibint.h>
63#else   /* vms */
64#define SyncHandle() \
65    if (dpy->synchandler) (*dpy->synchandler)(dpy)
66/*
67 * LockDisplay uses an undocumented feature in V5 of VMS that allows
68 * disabling ASTs without calling $SETAST.  A bit is set in P1 space
69 * that disables a user mode AST from being delivered to this process.
70 *
71 */
72#define LockDisplay(dis)             \
73{   globalref char ctl$gb_soft_ast_disable;    \
74    globalref char ctl$gb_lib_lock;        \
75    globalref short ctl$gw_soft_ast_lock_depth;    \
76    if ( ctl$gb_soft_ast_disable == 0 ) {    \
77    ctl$gb_soft_ast_disable = 1;        \
78    ctl$gb_lib_lock = 1;            \
79    ctl$gw_soft_ast_lock_depth = 1;        \
80    }                        \
81    else ctl$gw_soft_ast_lock_depth++;        \
82}
83
84/*
85 * UnlockDisplay clears the AST disable bit, then checks to see if an
86 * AST delivery attempt was made during the critical section.  If so,
87 * reenable_ASTs is set, and $SETAST must be called to turn AST delivery
88 * back on.
89 *
90 * Note that it assumed that LockDisplay and UnlockDisplay appear in
91 * matched sets within a single routine.
92 */
93#define UnlockDisplay(dis)             \
94{   globalref char ctl$gb_reenable_asts;    \
95    globalref char ctl$gb_soft_ast_disable;    \
96    globalref char ctl$gb_lib_lock;        \
97    globalref short ctl$gw_soft_ast_lock_depth;    \
98    if (!--ctl$gw_soft_ast_lock_depth)         \
99    if ( ctl$gb_lib_lock ) {        \
100        ctl$gb_lib_lock = 0;        \
101            ctl$gb_soft_ast_disable = 0;    \
102        if (ctl$gb_reenable_asts != 0)    \
103        sys$setast(1);            \
104        }                    \
105}
106
107#define WORD64ALIGN
108#if defined(__STDC__) && !defined(UNIXCPP)
109#define GetReq(name, req) \
110        WORD64ALIGN\
111        if ((dpy->bufptr + SIZEOF(x##name##Req)) > dpy->bufmax)\
112                _XFlush(dpy);\
113        req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\
114        req->reqType = X_##name;\
115        req->length = (SIZEOF(x##name##Req))>>2;\
116        dpy->bufptr += SIZEOF(x##name##Req);\
117        dpy->request++
118
119#else  /* non-ANSI C uses empty comment instead of "##" for token concat */
120#define GetReq(name, req) \
121        WORD64ALIGN\
122        if ((dpy->bufptr + SIZEOF(x/**/name/**/Req)) > dpy->bufmax)\
123                _XFlush(dpy);\
124        req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\
125        req->reqType = X_/**/name;\
126        req->length = (SIZEOF(x/**/name/**/Req))>>2;\
127        dpy->bufptr += SIZEOF(x/**/name/**/Req);\
128        dpy->request++
129#endif
130#endif /* vms */
131
132#include <X11/extensions/xtraplib.h>
133#include <X11/extensions/xtraplibp.h>
134
135/* Returns the all important protocol number to be used.
136 * The only request guaranteed to be of the same request/reply
137 * size is XEGetVersionRequest.  All others need the protocol
138 * number to determine how to communicate.
139 * Unfortunately, this was broken for V3.1 so GetAvailable will
140 * have to be used to determine the protocol version.
141 */
142int XEGetVersionRequest(XETC *tc, XETrapGetVersRep *ret)
143{
144    int status = True;
145    Display *dpy = tc->dpy;
146    CARD32 X_XTrapGet = tc->extOpcode;
147    xXTrapGetReq *reqptr;
148    xXTrapGetVersReply rep;
149    int numlongs = (SIZEOF(xXTrapGetVersReply) -
150        SIZEOF(xReply) + SIZEOF(CARD32) -1 ) / SIZEOF(CARD32);
151    LockDisplay(dpy);
152    GetReq(XTrapGet,reqptr);
153    reqptr->minor_opcode = XETrap_GetVersion;
154    reqptr->protocol = XETrapProtocol;
155    status = _XReply(dpy,(xReply *)&rep,numlongs,xTrue);
156    UnlockDisplay(dpy);
157    SyncHandle();
158    memcpy((char *)ret,&(rep.data),sizeof(XETrapGetVersRep));
159    return(status);
160}
161
162int XEGetAvailableRequest(XETC *tc, XETrapGetAvailRep *ret)
163{
164    int status = True;
165    Display *dpy = tc->dpy;
166    CARD32 X_XTrapGet = tc->extOpcode;
167    xXTrapGetReq *reqptr;
168    xXTrapGetAvailReply rep;
169    int numlongs = (SIZEOF(xXTrapGetAvailReply) -
170        SIZEOF(xReply) + SIZEOF(CARD32) -1 ) / SIZEOF(CARD32);
171    LockDisplay(dpy);
172    GetReq(XTrapGet,reqptr);
173    reqptr->minor_opcode = XETrap_GetAvailable;
174    reqptr->protocol = XETrapProtocol;
175    status = _XReply(dpy,(xReply *)&rep,numlongs,xTrue);
176    UnlockDisplay(dpy);
177    SyncHandle();
178    memcpy((char *)ret,&(rep.data),sizeof(XETrapGetAvailRep));
179    return(status);
180}
181
182/* should not be called directly by clients */
183static int XEConfigRequest(XETC *tc)
184{   /* protocol changed between V3.1 and V3.2! */
185    int status = True;
186    Display *dpy = tc->dpy;
187    CARD32 X_XTrapConfig = tc->extOpcode;
188    xXTrapConfigReq *reqptr;
189    if (tc->protocol == 31)
190    {   /* hack to allocate the old request length */
191        GetOldReq(XTrapConfig,reqptr,276);
192    }
193    else
194    {
195        GetReq(XTrapConfig,reqptr);
196    }
197    reqptr->minor_opcode = XETrap_Config;
198
199    memcpy((char *)reqptr->config_flags_valid,
200        (char *)tc->values.v.flags.valid,4);
201    memcpy((char *)reqptr->config_flags_data,
202        (char *)tc->values.v.flags.data,4);
203    memcpy((char *)reqptr->config_flags_req,
204        (char *)tc->values.v.flags.req,XETrapMaxRequest);
205    memcpy((char *)reqptr->config_flags_event,
206        (char *)tc->values.v.flags.event,XETrapMaxEvent);
207    reqptr->config_max_pkt_size=tc->values.v.max_pkt_size;
208    reqptr->config_cmd_key=tc->values.v.cmd_key;
209
210    XFlush(dpy);
211    SyncHandle();
212    tc->dirty = 0L; /* Configuration is no longer dirty */
213    return(status);
214}
215
216/* Flush out any pending configuration */
217int XEFlushConfig(XETC *tc)
218{
219    return((tc->dirty) ? XEConfigRequest(tc) : True);
220}
221int XEResetRequest(XETC *tc)
222{
223    int status = True;
224    Display *dpy = tc->dpy;
225    CARD32 X_XTrap = tc->extOpcode;
226    xXTrapReq *reqptr;
227    status = XEFlushConfig(tc); /* Flushout any pending configuration first */
228    if (status == True)
229    {
230        GetReq(XTrap,reqptr);
231        reqptr->minor_opcode = XETrap_Reset;
232        XFlush(dpy);
233        SyncHandle();
234    }
235    return(status);
236}
237
238
239int XEGetLastInpTimeRequest(XETC *tc, XETrapGetLastInpTimeRep *ret)
240{   /* this was broken in V3.1! */
241    int status = True;
242    Display *dpy = tc->dpy;
243    CARD32 X_XTrap = tc->extOpcode;
244    xXTrapReq *reqptr;
245    xXTrapGetLITimReply rep;
246    int numlongs = (SIZEOF(xXTrapGetLITimReply) -
247        SIZEOF(xReply) + SIZEOF(CARD32) - 1) / SIZEOF(CARD32);
248    LockDisplay(dpy);
249    GetReq(XTrap,reqptr);
250    reqptr->minor_opcode = XETrap_GetLastInpTime;
251    status = _XReply(dpy,(xReply *)&rep,numlongs,xTrue);
252    UnlockDisplay(dpy);
253    SyncHandle();
254
255    ret->last_time=rep.data_last_time;
256
257    return(status);
258}
259
260int XEStartTrapRequest(XETC *tc)
261{
262    int status = True;
263    Display *dpy = tc->dpy;
264    CARD32 X_XTrap = tc->extOpcode;
265    xXTrapReq *reqptr;
266    status = XEFlushConfig(tc); /* Flushout any pending configuration first */
267    if (status == True)
268    {
269        /* Add our event handler for the XLib transport */
270        XETrapSetEventHandler(tc, XETrapData, XETrapDispatchXLib);
271        GetReq(XTrap,reqptr);
272        reqptr->minor_opcode = XETrap_StartTrap;
273        XFlush(dpy);
274        SyncHandle();
275        BitTrue(tc->values.tc_flags, XETCTrapActive);
276    }
277    return(status);
278}
279int XEStopTrapRequest(XETC *tc)
280{
281    int status = True;
282    Display *dpy = tc->dpy;
283    CARD32 X_XTrap = tc->extOpcode;
284    xXTrapReq *reqptr;
285    status = XEFlushConfig(tc); /* Flushout any pending configuration first */
286    if (status == True)
287    {
288        GetReq(XTrap,reqptr);
289        reqptr->minor_opcode = XETrap_StopTrap;
290        XFlush(dpy);
291        SyncHandle();
292        BitFalse(tc->values.tc_flags, XETCTrapActive);
293        /* Remove our event handler for the XLib transport */
294	XETrapSetEventHandler(tc, XETrapData, NULL);
295    }
296
297    return(status);
298}
299
300#ifndef _XINPUT
301int XESimulateXEventRequest(XETC *tc, CARD8 type, CARD8 detail,
302    CARD16 x, CARD16 y, CARD8 screen)
303{
304    int status = True;
305    Display *dpy = tc->dpy;
306    CARD32 X_XTrapInput = tc->extOpcode;
307    xXTrapInputReq *reqptr;
308    status = XEFlushConfig(tc); /* Flushout any pending configuration first */
309    if (status == True)
310    {   /* write out the input event */
311        GetReq(XTrapInput,reqptr);
312        reqptr->minor_opcode = XETrap_SimulateXEvent;
313        reqptr->input.type   = type;
314        reqptr->input.detail = detail;
315        reqptr->input.x      = x;
316        reqptr->input.y      = y;
317        reqptr->input.screen = screen;
318        XFlush(dpy);
319    }
320    return(status);
321}
322#endif
323int XEGetCurrentRequest(XETC *tc, XETrapGetCurRep *ret)
324{
325    int status = True;
326    Display *dpy = tc->dpy;
327    CARD32 X_XTrap = tc->extOpcode;
328    xXTrapReq *reqptr;
329    xXTrapGetCurReply rep;
330    int numlongs = (SIZEOF(xXTrapGetCurReply) -
331        SIZEOF(xReply) + SIZEOF(CARD32) -1 ) / SIZEOF(CARD32);
332    status = XEFlushConfig(tc); /* Flushout any pending configuration first */
333    if (status == True)
334    {
335        LockDisplay(dpy);
336        GetReq(XTrap,reqptr);
337        reqptr->minor_opcode = XETrap_GetCurrent;
338        /* to support comm. w/ V3.1 extensions */
339        if (tc->protocol == 31)
340        {
341            char tmp[284];  /* need space for the big *old* reply */
342            numlongs = (284-sizeof(xReply)+sizeof(long)-1)/sizeof(long);
343            status = _XReply(dpy,(xReply *)tmp,numlongs,xTrue);
344            memcpy(&rep,tmp,sizeof(rep));   /* move just what's needed */
345        }
346        else
347        {
348            status = _XReply(dpy,(xReply *)&rep,numlongs,xTrue);
349        }
350        UnlockDisplay(dpy);
351        SyncHandle();
352
353    memcpy((char *)ret->state_flags,rep.data_state_flags,2);
354    memcpy((char *)ret->config.flags.valid,rep.data_config_flags_valid,4);
355    memcpy((char *)ret->config.flags.data,rep.data_config_flags_data,4);
356    memcpy((char *)ret->config.flags.req,rep.data_config_flags_req,
357        XETrapMaxRequest);
358    memcpy((char *)ret->config.flags.event,rep.data_config_flags_event,
359        XETrapMaxEvent);
360    ret->config.max_pkt_size=rep.data_config_max_pkt_size;
361    ret->config.cmd_key=rep.data_config_cmd_key;
362
363    }
364    return(status);
365}
366
367int XEGetStatisticsRequest(XETC *tc, XETrapGetStatsRep *ret)
368{
369    int status = True;
370    Display *dpy = tc->dpy;
371    CARD32 X_XTrap = tc->extOpcode;
372    xXTrapReq *reqptr;
373    xXTrapGetStatsReply rep;
374    status = XEFlushConfig(tc); /* Flushout any pending configuration first */
375    if (status == True)
376    {
377        LockDisplay(dpy);
378        GetReq(XTrap,reqptr);
379        reqptr->minor_opcode = XETrap_GetStatistics;
380        /* to support comm. w/ V3.1 extensions */
381#ifndef CRAY
382        if (tc->protocol == 31)
383        {   /* this is the way we used to do it which breaks Cray's */
384#ifndef VECTORED_EVENTS
385            int numlongs = (1060-sizeof(xReply)+sizeof(long)-1)/sizeof(long);
386#else
387            int numlongs = (1544-sizeof(xReply)+sizeof(long)-1)/sizeof(long);
388#endif
389            status = _XReply(dpy,(xReply *)&rep,numlongs,xTrue);
390            if (status == True)
391            {   /* need to shift it back into the data struct */
392                xXTrapGetStatsReply tmp;
393                tmp = rep;
394                memcpy(&(rep.data),&(tmp.pad0), sizeof(rep.data));
395            }
396        }
397        else
398#endif /* CRAY */
399        {   /* this is the way we do it for V3.2 */
400            int numbytes = SIZEOF(xXTrapGetStatsReply) - SIZEOF(xReply);
401            status = _XReply(dpy, (xReply *)&rep, 0, xFalse);
402            if (status == True)
403            {
404                status = _XRead(dpy, (char *)&rep.data, numbytes);
405            }
406        }
407        UnlockDisplay(dpy);
408        SyncHandle();
409        memcpy(ret,&(rep.data),sizeof(XETrapGetStatsRep));
410    }
411    return(status);
412}
413