2 * Copyright 2007-2008 Peter Hutterer
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:
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
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.
23 * Author: Peter Hutterer, University of South Australia, NICTA
26 #ifdef HAVE_DIX_CONFIG_H
27 #include <dix-config.h>
29 #include "windowstr.h"
30 #include <X11/extensions/ge.h>
34 #include "protocol-versions.h"
37 DevPrivateKeyRec GEClientPrivateKeyRec
;
39 GEExtension GEExtensions
[MAXEXTENSIONS
];
41 /* Major available requests */
42 static const int version_requests
[] = {
43 X_GEQueryVersion
, /* before client sends QueryVersion */
44 X_GEQueryVersion
, /* must be set to last request in version 1 */
47 /* Forward declarations */
48 static void SGEGenericEvent(xEvent
*from
, xEvent
*to
);
50 #define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
51 #define EXT_MASK(ext) ((ext) & 0x7F)
53 /************************************************************/
54 /* request handlers */
55 /************************************************************/
58 ProcGEQueryVersion(ClientPtr client
)
60 GEClientInfoPtr pGEClient
= GEGetClient(client
);
61 xGEQueryVersionReply rep
;
63 REQUEST(xGEQueryVersionReq
);
65 REQUEST_SIZE_MATCH(xGEQueryVersionReq
);
67 rep
= (xGEQueryVersionReply
) {
69 .RepType
= X_GEQueryVersion
,
70 .sequenceNumber
= client
->sequence
,
73 /* return the supported version by the server */
74 .majorVersion
= SERVER_GE_MAJOR_VERSION
,
75 .minorVersion
= SERVER_GE_MINOR_VERSION
78 /* Remember version the client requested */
79 pGEClient
->major_version
= stuff
->majorVersion
;
80 pGEClient
->minor_version
= stuff
->minorVersion
;
82 if (client
->swapped
) {
83 swaps(&rep
.sequenceNumber
);
85 swaps(&rep
.majorVersion
);
86 swaps(&rep
.minorVersion
);
89 WriteToClient(client
, sizeof(xGEQueryVersionReply
), &rep
);
93 int (*ProcGEVector
[GENumberRequests
]) (ClientPtr
) = {
97 /************************************************************/
98 /* swapped request handlers */
99 /************************************************************/
101 SProcGEQueryVersion(ClientPtr client
)
103 REQUEST(xGEQueryVersionReq
);
105 swaps(&stuff
->length
);
106 REQUEST_SIZE_MATCH(xGEQueryVersionReq
);
107 swaps(&stuff
->majorVersion
);
108 swaps(&stuff
->minorVersion
);
109 return (*ProcGEVector
[stuff
->ReqType
]) (client
);
112 int (*SProcGEVector
[GENumberRequests
]) (ClientPtr
) = {
114 SProcGEQueryVersion
};
116 /************************************************************/
118 /************************************************************/
120 /* dispatch requests */
122 ProcGEDispatch(ClientPtr client
)
124 GEClientInfoPtr pGEClient
= GEGetClient(client
);
128 if (pGEClient
->major_version
>= NUM_VERSION_REQUESTS
)
130 if (stuff
->ReqType
> version_requests
[pGEClient
->major_version
])
133 return (ProcGEVector
[stuff
->ReqType
]) (client
);
136 /* dispatch swapped requests */
138 SProcGEDispatch(ClientPtr client
)
141 if (stuff
->ReqType
>= GENumberRequests
)
143 return (*SProcGEVector
[stuff
->ReqType
]) (client
);
147 * Called when a new client inits a connection to the X server.
149 * We alloc a simple struct to store the client's major/minor version. Can be
150 * used in the furture for versioning support.
153 GEClientCallback(CallbackListPtr
*list
, pointer closure
, pointer data
)
155 NewClientInfoRec
*clientinfo
= (NewClientInfoRec
*) data
;
156 ClientPtr pClient
= clientinfo
->client
;
157 GEClientInfoPtr pGEClient
= GEGetClient(pClient
);
159 pGEClient
->major_version
= 0;
160 pGEClient
->minor_version
= 0;
163 /* Reset extension. Called on server shutdown. */
165 GEResetProc(ExtensionEntry
* extEntry
)
167 DeleteCallback(&ClientStateCallback
, GEClientCallback
, 0);
168 EventSwapVector
[GenericEvent
] = NotImplemented
;
171 /* Calls the registered event swap function for the extension.
173 * Each extension can register a swap function to handle GenericEvents being
174 * swapped properly. The server calls SGEGenericEvent() before the event is
175 * written on the wire, this one calls the registered swap function to do the
179 SGEGenericEvent(xEvent
*from
, xEvent
*to
)
181 xGenericEvent
*gefrom
= (xGenericEvent
*) from
;
182 xGenericEvent
*geto
= (xGenericEvent
*) to
;
184 if ((gefrom
->extension
& 0x7f) > MAXEXTENSIONS
) {
185 ErrorF("GE: Invalid extension offset for event.\n");
189 if (GEExtensions
[EXT_MASK(gefrom
->extension
)].evswap
)
190 GEExtensions
[EXT_MASK(gefrom
->extension
)].evswap(gefrom
, geto
);
193 /* Init extension, register at server.
194 * Since other extensions may rely on XGE (XInput does already), it is a good
195 * idea to init XGE first, before any other extension.
198 GEExtensionInit(void)
200 ExtensionEntry
*extEntry
;
202 if (!dixRegisterPrivateKey
203 (&GEClientPrivateKeyRec
, PRIVATE_CLIENT
, sizeof(GEClientInfoRec
)))
204 FatalError("GEExtensionInit: GE private request failed.\n");
206 if (!AddCallback(&ClientStateCallback
, GEClientCallback
, 0)) {
207 FatalError("GEExtensionInit: register client callback failed.\n");
210 if ((extEntry
= AddExtension(GE_NAME
,
212 ProcGEDispatch
, SProcGEDispatch
,
213 GEResetProc
, StandardMinorOpcode
)) != 0) {
214 memset(GEExtensions
, 0, sizeof(GEExtensions
));
216 EventSwapVector
[GenericEvent
] = (EventSwapPtr
) SGEGenericEvent
;
219 FatalError("GEInit: AddExtensions failed.\n");
224 /************************************************************/
225 /* interface for extensions */
226 /************************************************************/
228 /* Register an extension with GE. The given swap function will be called each
229 * time an event is sent to a client with different byte order.
230 * @param extension The extensions major opcode
231 * @param ev_swap The event swap function.
232 * @param ev_fill Called for an event before delivery. The extension now has
233 * the chance to fill in necessary fields for the event.
236 GERegisterExtension(int extension
,
237 void (*ev_swap
) (xGenericEvent
*from
, xGenericEvent
*to
))
239 if (EXT_MASK(extension
) >= MAXEXTENSIONS
)
240 FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n");
242 /* extension opcodes are > 128, might as well save some space here */
243 GEExtensions
[EXT_MASK(extension
)].evswap
= ev_swap
;
246 /* Sets type and extension field for a generic event. This is just an
247 * auxiliary function, extensions could do it manually too.
250 GEInitEvent(xGenericEvent
*ev
, int extension
)
252 ev
->type
= GenericEvent
;
253 ev
->extension
= extension
;