blob: ff5532bf20fe80b248f84146b42dde1b65e9f295 [file] [log] [blame]
Constantin Kaplinskyb30ae7f2006-05-25 05:04:46 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18#include <stdio.h>
19
20#define NEED_REPLIES
21#include <X11/Xlib.h>
22#include <X11/Xlibint.h>
23#define _VNCEXT_PROTO_
24#include "vncExt.h"
25
26static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e,
27 xEvent* w);
28static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e,
29 xEvent* w);
30static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
31 xEvent* w);
32
33static Bool extensionInited = False;
34static XExtCodes* codes = 0;
35
36static Bool checkExtension(Display* dpy)
37{
38 if (!extensionInited) {
39 extensionInited = True;
40 codes = XInitExtension(dpy, VNCEXTNAME);
41 if (!codes) return False;
42 XESetWireToEvent(dpy, codes->first_event + VncExtClientCutTextNotify,
43 XVncExtClientCutTextNotifyWireToEvent);
44 XESetWireToEvent(dpy, codes->first_event + VncExtSelectionChangeNotify,
45 XVncExtSelectionChangeNotifyWireToEvent);
46 XESetWireToEvent(dpy, codes->first_event + VncExtQueryConnectNotify,
47 XVncExtQueryConnectNotifyWireToEvent);
48 }
49 return codes != 0;
50}
51
52Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep)
53{
54 if (!checkExtension(dpy)) return False;
55 *event_basep = codes->first_event;
56 *error_basep = codes->first_error;
57 return True;
58}
59
60Bool XVncExtSetParam(Display* dpy, const char* param)
61{
62 xVncExtSetParamReq* req;
63 xVncExtSetParamReply rep;
64
65 int paramLen = strlen(param);
66 if (paramLen > 255) return False;
67 if (!checkExtension(dpy)) return False;
68
69 LockDisplay(dpy);
70 GetReq(VncExtSetParam, req);
71 req->reqType = codes->major_opcode;
72 req->vncExtReqType = X_VncExtSetParam;
73 req->length += (paramLen + 3) >> 2;
74 req->paramLen = paramLen;
75 Data(dpy, param, paramLen);
76 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
77 UnlockDisplay(dpy);
78 SyncHandle();
79 return False;
80 }
81 UnlockDisplay(dpy);
82 SyncHandle();
83 return rep.success;
84}
85
86Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len)
87{
88 xVncExtGetParamReq* req;
89 xVncExtGetParamReply rep;
90
91 int paramLen = strlen(param);
92 *value = 0;
93 *len = 0;
94 if (paramLen > 255) return False;
95 if (!checkExtension(dpy)) return False;
96
97 LockDisplay(dpy);
98 GetReq(VncExtGetParam, req);
99 req->reqType = codes->major_opcode;
100 req->vncExtReqType = X_VncExtGetParam;
101 req->length += (paramLen + 3) >> 2;
102 req->paramLen = paramLen;
103 Data(dpy, param, paramLen);
104 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
105 UnlockDisplay(dpy);
106 SyncHandle();
107 return False;
108 }
109 if (rep.success) {
110 *len = rep.valueLen;
111 *value = (char*) Xmalloc (*len+1);
112 _XReadPad(dpy, *value, *len);
113 (*value)[*len] = 0;
114 }
115 UnlockDisplay(dpy);
116 SyncHandle();
117 return rep.success;
118}
119
120char* XVncExtGetParamDesc(Display* dpy, const char* param)
121{
122 xVncExtGetParamDescReq* req;
123 xVncExtGetParamDescReply rep;
124 char* desc = 0;
125
126 int paramLen = strlen(param);
127 if (paramLen > 255) return False;
128 if (!checkExtension(dpy)) return False;
129
130 LockDisplay(dpy);
131 GetReq(VncExtGetParamDesc, req);
132 req->reqType = codes->major_opcode;
133 req->vncExtReqType = X_VncExtGetParamDesc;
134 req->length += (paramLen + 3) >> 2;
135 req->paramLen = paramLen;
136 Data(dpy, param, paramLen);
137 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
138 UnlockDisplay(dpy);
139 SyncHandle();
140 return False;
141 }
142 if (rep.success) {
143 desc = (char*)Xmalloc(rep.descLen+1);
144 _XReadPad(dpy, desc, rep.descLen);
145 desc[rep.descLen] = 0;
146 }
147 UnlockDisplay(dpy);
148 SyncHandle();
149 return desc;
150}
151
152char** XVncExtListParams(Display* dpy, int* nParams)
153{
154 xVncExtListParamsReq* req;
155 xVncExtListParamsReply rep;
156 char** list = 0;
157 char* ch;
158 int rlen, paramLen, i;
159
160 if (!checkExtension(dpy)) return False;
161
162 LockDisplay(dpy);
163 GetReq(VncExtListParams, req);
164 req->reqType = codes->major_opcode;
165 req->vncExtReqType = X_VncExtListParams;
166 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
167 UnlockDisplay(dpy);
168 SyncHandle();
169 return False;
170 }
171 UnlockDisplay(dpy);
172 SyncHandle();
173 if (rep.nParams) {
174 list = (char**)Xmalloc(rep.nParams * sizeof(char*));
175 rlen = rep.length << 2;
176 ch = (char*)Xmalloc(rlen + 1);
177 if (!list || !ch) {
178 if (list) Xfree((char*)list);
179 if (ch) Xfree(ch);
180 _XEatData(dpy, rlen);
181 UnlockDisplay(dpy);
182 SyncHandle();
183 return 0;
184 }
185 _XReadPad(dpy, ch, rlen);
186 paramLen = *ch++;
187 for (i = 0; i < rep.nParams; i++) {
188 list[i] = ch;
189 ch += paramLen;
190 paramLen = *ch;
191 *ch++ = 0;
192 }
193 }
194 *nParams = rep.nParams;
195 UnlockDisplay(dpy);
196 SyncHandle();
197 return list;
198}
199
200void XVncExtFreeParamList(char** list)
201{
202 if (list) {
203 Xfree(list[0]-1);
204 Xfree((char*)list);
205 }
206}
207
208Bool XVncExtSetServerCutText(Display* dpy, const char* str, int len)
209{
210 xVncExtSetServerCutTextReq* req;
211
212 if (!checkExtension(dpy)) return False;
213
214 LockDisplay(dpy);
215 GetReq(VncExtSetServerCutText, req);
216 req->reqType = codes->major_opcode;
217 req->vncExtReqType = X_VncExtSetServerCutText;
218 req->length += (len + 3) >> 2;
219 req->textLen = len;
220 Data(dpy, str, len);
221 UnlockDisplay(dpy);
222 SyncHandle();
223 return True;
224}
225
226Bool XVncExtGetClientCutText(Display* dpy, char** str, int* len)
227{
228 xVncExtGetClientCutTextReq* req;
229 xVncExtGetClientCutTextReply rep;
230
231 if (!checkExtension(dpy)) return False;
232
233 LockDisplay(dpy);
234 GetReq(VncExtGetClientCutText, req);
235 req->reqType = codes->major_opcode;
236 req->vncExtReqType = X_VncExtGetClientCutText;
237 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
238 UnlockDisplay(dpy);
239 SyncHandle();
240 return False;
241 }
242 UnlockDisplay(dpy);
243 SyncHandle();
244 *len = rep.textLen;
245 *str = (char*) Xmalloc (*len+1);
246 _XReadPad(dpy, *str, *len);
247 (*str)[*len] = 0;
248 return True;
249}
250
251Bool XVncExtSelectInput(Display* dpy, Window w, int mask)
252{
253 xVncExtSelectInputReq* req;
254
255 if (!checkExtension(dpy)) return False;
256
257 LockDisplay(dpy);
258 GetReq(VncExtSelectInput, req);
259 req->reqType = codes->major_opcode;
260 req->vncExtReqType = X_VncExtSelectInput;
261 req->window = w;
262 req->mask = mask;
263 UnlockDisplay(dpy);
264 SyncHandle();
265 return True;
266}
267
268Bool XVncExtConnect(Display* dpy, char* hostAndPort)
269{
270 xVncExtConnectReq* req;
271 xVncExtConnectReply rep;
272
273 int strLen = strlen(hostAndPort);
274 if (strLen > 255) return False;
275 if (!checkExtension(dpy)) return False;
276
277 LockDisplay(dpy);
278 GetReq(VncExtConnect, req);
279 req->reqType = codes->major_opcode;
280 req->vncExtReqType = X_VncExtConnect;
281 req->length += (strLen + 3) >> 2;
282 req->strLen = strLen;
283 Data(dpy, hostAndPort, strLen);
284 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
285 UnlockDisplay(dpy);
286 SyncHandle();
287 return False;
288 }
289 UnlockDisplay(dpy);
290 SyncHandle();
291 return rep.success;
292}
293
294Bool XVncExtGetQueryConnect(Display* dpy, char** addr, char** user,
295 int* timeout, void** opaqueId)
296{
297 xVncExtGetQueryConnectReq* req;
298 xVncExtGetQueryConnectReply rep;
299
300 if (!checkExtension(dpy)) return False;
301
302 LockDisplay(dpy);
303 GetReq(VncExtGetQueryConnect, req);
304 req->reqType = codes->major_opcode;
305 req->vncExtReqType = X_VncExtGetQueryConnect;
306 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
307 UnlockDisplay(dpy);
308 SyncHandle();
309 return False;
310 }
311 UnlockDisplay(dpy);
312 SyncHandle();
313
314 *addr = Xmalloc(rep.addrLen+1);
315 _XReadPad(dpy, *addr, rep.addrLen);
316 (*addr)[rep.addrLen] = 0;
317 *user = Xmalloc(rep.userLen+1);
318 _XReadPad(dpy, *user, rep.userLen);
319 (*user)[rep.userLen] = 0;
320 *timeout = rep.timeout;
321 *opaqueId = (void*)rep.opaqueId;
322 return True;
323}
324
325Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve)
326{
327 xVncExtApproveConnectReq* req;
328
329 if (!checkExtension(dpy)) return False;
330
331 LockDisplay(dpy);
332 GetReq(VncExtApproveConnect, req);
333 req->reqType = codes->major_opcode;
334 req->vncExtReqType = X_VncExtApproveConnect;
335 req->approve = approve;
336 req->opaqueId = (CARD32)opaqueId;
337 UnlockDisplay(dpy);
338 SyncHandle();
339 return True;
340}
341
342
343static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e,
344 xEvent* w)
345{
346 XVncExtClientCutTextEvent* ev = (XVncExtClientCutTextEvent*)e;
347 xVncExtClientCutTextNotifyEvent* wire = (xVncExtClientCutTextNotifyEvent*)w;
348 ev->type = wire->type & 0x7f;
349 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
350 ev->send_event = (wire->type & 0x80) != 0;
351 ev->display = dpy;
352 ev->window = wire->window;
353 ev->time = wire->time;
354 return True;
355}
356
357static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e,
358 xEvent* w)
359{
360 XVncExtSelectionChangeEvent* ev = (XVncExtSelectionChangeEvent*)e;
361 xVncExtSelectionChangeNotifyEvent* wire
362 = (xVncExtSelectionChangeNotifyEvent*)w;
363 ev->type = wire->type & 0x7f;
364 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
365 ev->send_event = (wire->type & 0x80) != 0;
366 ev->display = dpy;
367 ev->window = wire->window;
368 ev->selection = wire->selection;
369 return True;
370}
371
372static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e,
373 xEvent* w)
374{
375 XVncExtQueryConnectEvent* ev = (XVncExtQueryConnectEvent*)e;
376 xVncExtQueryConnectNotifyEvent* wire
377 = (xVncExtQueryConnectNotifyEvent*)w;
378 ev->type = wire->type & 0x7f;
379 ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
380 ev->send_event = (wire->type & 0x80) != 0;
381 ev->display = dpy;
382 ev->window = wire->window;
383 return True;
384}