geext.c revision 35c4bbdf
1/*
2 * Copyright 2007-2008 Peter Hutterer
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Author: Peter Hutterer, University of South Australia, NICTA
24 */
25
26#ifdef HAVE_DIX_CONFIG_H
27#include <dix-config.h>
28#endif
29#include "windowstr.h"
30#include <X11/extensions/ge.h>
31
32#include "geint.h"
33#include "geext.h"
34#include "protocol-versions.h"
35#include "extinit.h"
36
37DevPrivateKeyRec GEClientPrivateKeyRec;
38
39GEExtension GEExtensions[MAXEXTENSIONS];
40
41/* Major available requests */
42static const int version_requests[] = {
43    X_GEQueryVersion,           /* before client sends QueryVersion */
44    X_GEQueryVersion,           /* must be set to last request in version 1 */
45};
46
47/* Forward declarations */
48static void SGEGenericEvent(xEvent *from, xEvent *to);
49
50#define NUM_VERSION_REQUESTS	(sizeof (version_requests) / sizeof (version_requests[0]))
51#define EXT_MASK(ext) ((ext) & 0x7F)
52
53/************************************************************/
54/*                request handlers                          */
55/************************************************************/
56
57static int
58ProcGEQueryVersion(ClientPtr client)
59{
60    GEClientInfoPtr pGEClient = GEGetClient(client);
61    xGEQueryVersionReply rep;
62
63    REQUEST(xGEQueryVersionReq);
64
65    REQUEST_SIZE_MATCH(xGEQueryVersionReq);
66
67    rep = (xGEQueryVersionReply) {
68        .repType = X_Reply,
69        .RepType = X_GEQueryVersion,
70        .sequenceNumber = client->sequence,
71        .length = 0,
72
73        /* return the supported version by the server */
74        .majorVersion = SERVER_GE_MAJOR_VERSION,
75        .minorVersion = SERVER_GE_MINOR_VERSION
76    };
77
78    /* Remember version the client requested */
79    pGEClient->major_version = stuff->majorVersion;
80    pGEClient->minor_version = stuff->minorVersion;
81
82    if (client->swapped) {
83        swaps(&rep.sequenceNumber);
84        swapl(&rep.length);
85        swaps(&rep.majorVersion);
86        swaps(&rep.minorVersion);
87    }
88
89    WriteToClient(client, sizeof(xGEQueryVersionReply), &rep);
90    return Success;
91}
92
93static int (*ProcGEVector[GENumberRequests]) (ClientPtr) = {
94    /* Version 1.0 */
95    ProcGEQueryVersion,
96};
97
98/************************************************************/
99/*                swapped request handlers                  */
100/************************************************************/
101static int
102SProcGEQueryVersion(ClientPtr client)
103{
104    REQUEST(xGEQueryVersionReq);
105
106    swaps(&stuff->length);
107    REQUEST_SIZE_MATCH(xGEQueryVersionReq);
108    swaps(&stuff->majorVersion);
109    swaps(&stuff->minorVersion);
110    return (*ProcGEVector[stuff->ReqType]) (client);
111}
112
113static int (*SProcGEVector[GENumberRequests]) (ClientPtr) = {
114    /* Version 1.0 */
115    SProcGEQueryVersion
116};
117
118/************************************************************/
119/*                callbacks                                 */
120/************************************************************/
121
122/* dispatch requests */
123static int
124ProcGEDispatch(ClientPtr client)
125{
126    GEClientInfoPtr pGEClient = GEGetClient(client);
127
128    REQUEST(xGEReq);
129
130    if (pGEClient->major_version >= NUM_VERSION_REQUESTS)
131        return BadRequest;
132    if (stuff->ReqType > version_requests[pGEClient->major_version])
133        return BadRequest;
134
135    return (ProcGEVector[stuff->ReqType]) (client);
136}
137
138/* dispatch swapped requests */
139static int
140SProcGEDispatch(ClientPtr client)
141{
142    REQUEST(xGEReq);
143    if (stuff->ReqType >= GENumberRequests)
144        return BadRequest;
145    return (*SProcGEVector[stuff->ReqType]) (client);
146}
147
148/**
149 * Called when a new client inits a connection to the X server.
150 *
151 * We alloc a simple struct to store the client's major/minor version. Can be
152 * used in the furture for versioning support.
153 */
154static void
155GEClientCallback(CallbackListPtr *list, void *closure, void *data)
156{
157    NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
158    ClientPtr pClient = clientinfo->client;
159    GEClientInfoPtr pGEClient = GEGetClient(pClient);
160
161    pGEClient->major_version = 0;
162    pGEClient->minor_version = 0;
163}
164
165/* Reset extension. Called on server shutdown. */
166static void
167GEResetProc(ExtensionEntry * extEntry)
168{
169    DeleteCallback(&ClientStateCallback, GEClientCallback, 0);
170    EventSwapVector[GenericEvent] = NotImplemented;
171}
172
173/*  Calls the registered event swap function for the extension.
174 *
175 *  Each extension can register a swap function to handle GenericEvents being
176 *  swapped properly. The server calls SGEGenericEvent() before the event is
177 *  written on the wire, this one calls the registered swap function to do the
178 *  work.
179 */
180static void
181SGEGenericEvent(xEvent *from, xEvent *to)
182{
183    xGenericEvent *gefrom = (xGenericEvent *) from;
184    xGenericEvent *geto = (xGenericEvent *) to;
185
186    if ((gefrom->extension & 0x7f) > MAXEXTENSIONS) {
187        ErrorF("GE: Invalid extension offset for event.\n");
188        return;
189    }
190
191    if (GEExtensions[EXT_MASK(gefrom->extension)].evswap)
192        GEExtensions[EXT_MASK(gefrom->extension)].evswap(gefrom, geto);
193}
194
195/* Init extension, register at server.
196 * Since other extensions may rely on XGE (XInput does already), it is a good
197 * idea to init XGE first, before any other extension.
198 */
199void
200GEExtensionInit(void)
201{
202    ExtensionEntry *extEntry;
203
204    if (!dixRegisterPrivateKey
205        (&GEClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(GEClientInfoRec)))
206        FatalError("GEExtensionInit: GE private request failed.\n");
207
208    if (!AddCallback(&ClientStateCallback, GEClientCallback, 0)) {
209        FatalError("GEExtensionInit: register client callback failed.\n");
210    }
211
212    if ((extEntry = AddExtension(GE_NAME,
213                                 0, GENumberErrors,
214                                 ProcGEDispatch, SProcGEDispatch,
215                                 GEResetProc, StandardMinorOpcode)) != 0) {
216        memset(GEExtensions, 0, sizeof(GEExtensions));
217
218        EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent;
219    }
220    else {
221        FatalError("GEInit: AddExtensions failed.\n");
222    }
223
224}
225
226/************************************************************/
227/*                interface for extensions                  */
228/************************************************************/
229
230/* Register an extension with GE. The given swap function will be called each
231 * time an event is sent to a client with different byte order.
232 * @param extension The extensions major opcode
233 * @param ev_swap The event swap function.
234 * @param ev_fill Called for an event before delivery. The extension now has
235 * the chance to fill in necessary fields for the event.
236 */
237void
238GERegisterExtension(int extension,
239                    void (*ev_swap) (xGenericEvent *from, xGenericEvent *to))
240{
241    if (EXT_MASK(extension) >= MAXEXTENSIONS)
242        FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n");
243
244    /* extension opcodes are > 128, might as well save some space here */
245    GEExtensions[EXT_MASK(extension)].evswap = ev_swap;
246}
247
248/* Sets type and extension field for a generic event. This is just an
249 * auxiliary function, extensions could do it manually too.
250 */
251void
252GEInitEvent(xGenericEvent *ev, int extension)
253{
254    ev->type = GenericEvent;
255    ev->extension = extension;
256    ev->length = 0;
257}
258