diff options
Diffstat (limited to 'unix/vncconfig/vncExt.c')
-rw-r--r-- | unix/vncconfig/vncExt.c | 384 |
1 files changed, 384 insertions, 0 deletions
diff --git a/unix/vncconfig/vncExt.c b/unix/vncconfig/vncExt.c new file mode 100644 index 00000000..ff5532bf --- /dev/null +++ b/unix/vncconfig/vncExt.c @@ -0,0 +1,384 @@ +/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ +#include <stdio.h> + +#define NEED_REPLIES +#include <X11/Xlib.h> +#include <X11/Xlibint.h> +#define _VNCEXT_PROTO_ +#include "vncExt.h" + +static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w); +static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w); +static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w); + +static Bool extensionInited = False; +static XExtCodes* codes = 0; + +static Bool checkExtension(Display* dpy) +{ + if (!extensionInited) { + extensionInited = True; + codes = XInitExtension(dpy, VNCEXTNAME); + if (!codes) return False; + XESetWireToEvent(dpy, codes->first_event + VncExtClientCutTextNotify, + XVncExtClientCutTextNotifyWireToEvent); + XESetWireToEvent(dpy, codes->first_event + VncExtSelectionChangeNotify, + XVncExtSelectionChangeNotifyWireToEvent); + XESetWireToEvent(dpy, codes->first_event + VncExtQueryConnectNotify, + XVncExtQueryConnectNotifyWireToEvent); + } + return codes != 0; +} + +Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep) +{ + if (!checkExtension(dpy)) return False; + *event_basep = codes->first_event; + *error_basep = codes->first_error; + return True; +} + +Bool XVncExtSetParam(Display* dpy, const char* param) +{ + xVncExtSetParamReq* req; + xVncExtSetParamReply rep; + + int paramLen = strlen(param); + if (paramLen > 255) return False; + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtSetParam, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtSetParam; + req->length += (paramLen + 3) >> 2; + req->paramLen = paramLen; + Data(dpy, param, paramLen); + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.success; +} + +Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len) +{ + xVncExtGetParamReq* req; + xVncExtGetParamReply rep; + + int paramLen = strlen(param); + *value = 0; + *len = 0; + if (paramLen > 255) return False; + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtGetParam, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtGetParam; + req->length += (paramLen + 3) >> 2; + req->paramLen = paramLen; + Data(dpy, param, paramLen); + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + if (rep.success) { + *len = rep.valueLen; + *value = (char*) Xmalloc (*len+1); + _XReadPad(dpy, *value, *len); + (*value)[*len] = 0; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.success; +} + +char* XVncExtGetParamDesc(Display* dpy, const char* param) +{ + xVncExtGetParamDescReq* req; + xVncExtGetParamDescReply rep; + char* desc = 0; + + int paramLen = strlen(param); + if (paramLen > 255) return False; + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtGetParamDesc, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtGetParamDesc; + req->length += (paramLen + 3) >> 2; + req->paramLen = paramLen; + Data(dpy, param, paramLen); + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + if (rep.success) { + desc = (char*)Xmalloc(rep.descLen+1); + _XReadPad(dpy, desc, rep.descLen); + desc[rep.descLen] = 0; + } + UnlockDisplay(dpy); + SyncHandle(); + return desc; +} + +char** XVncExtListParams(Display* dpy, int* nParams) +{ + xVncExtListParamsReq* req; + xVncExtListParamsReply rep; + char** list = 0; + char* ch; + int rlen, paramLen, i; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtListParams, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtListParams; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + if (rep.nParams) { + list = (char**)Xmalloc(rep.nParams * sizeof(char*)); + rlen = rep.length << 2; + ch = (char*)Xmalloc(rlen + 1); + if (!list || !ch) { + if (list) Xfree((char*)list); + if (ch) Xfree(ch); + _XEatData(dpy, rlen); + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + _XReadPad(dpy, ch, rlen); + paramLen = *ch++; + for (i = 0; i < rep.nParams; i++) { + list[i] = ch; + ch += paramLen; + paramLen = *ch; + *ch++ = 0; + } + } + *nParams = rep.nParams; + UnlockDisplay(dpy); + SyncHandle(); + return list; +} + +void XVncExtFreeParamList(char** list) +{ + if (list) { + Xfree(list[0]-1); + Xfree((char*)list); + } +} + +Bool XVncExtSetServerCutText(Display* dpy, const char* str, int len) +{ + xVncExtSetServerCutTextReq* req; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtSetServerCutText, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtSetServerCutText; + req->length += (len + 3) >> 2; + req->textLen = len; + Data(dpy, str, len); + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool XVncExtGetClientCutText(Display* dpy, char** str, int* len) +{ + xVncExtGetClientCutTextReq* req; + xVncExtGetClientCutTextReply rep; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtGetClientCutText, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtGetClientCutText; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + *len = rep.textLen; + *str = (char*) Xmalloc (*len+1); + _XReadPad(dpy, *str, *len); + (*str)[*len] = 0; + return True; +} + +Bool XVncExtSelectInput(Display* dpy, Window w, int mask) +{ + xVncExtSelectInputReq* req; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtSelectInput, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtSelectInput; + req->window = w; + req->mask = mask; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + +Bool XVncExtConnect(Display* dpy, char* hostAndPort) +{ + xVncExtConnectReq* req; + xVncExtConnectReply rep; + + int strLen = strlen(hostAndPort); + if (strLen > 255) return False; + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtConnect, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtConnect; + req->length += (strLen + 3) >> 2; + req->strLen = strLen; + Data(dpy, hostAndPort, strLen); + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + return rep.success; +} + +Bool XVncExtGetQueryConnect(Display* dpy, char** addr, char** user, + int* timeout, void** opaqueId) +{ + xVncExtGetQueryConnectReq* req; + xVncExtGetQueryConnectReply rep; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtGetQueryConnect, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtGetQueryConnect; + if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { + UnlockDisplay(dpy); + SyncHandle(); + return False; + } + UnlockDisplay(dpy); + SyncHandle(); + + *addr = Xmalloc(rep.addrLen+1); + _XReadPad(dpy, *addr, rep.addrLen); + (*addr)[rep.addrLen] = 0; + *user = Xmalloc(rep.userLen+1); + _XReadPad(dpy, *user, rep.userLen); + (*user)[rep.userLen] = 0; + *timeout = rep.timeout; + *opaqueId = (void*)rep.opaqueId; + return True; +} + +Bool XVncExtApproveConnect(Display* dpy, void* opaqueId, int approve) +{ + xVncExtApproveConnectReq* req; + + if (!checkExtension(dpy)) return False; + + LockDisplay(dpy); + GetReq(VncExtApproveConnect, req); + req->reqType = codes->major_opcode; + req->vncExtReqType = X_VncExtApproveConnect; + req->approve = approve; + req->opaqueId = (CARD32)opaqueId; + UnlockDisplay(dpy); + SyncHandle(); + return True; +} + + +static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w) +{ + XVncExtClientCutTextEvent* ev = (XVncExtClientCutTextEvent*)e; + xVncExtClientCutTextNotifyEvent* wire = (xVncExtClientCutTextNotifyEvent*)w; + ev->type = wire->type & 0x7f; + ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire); + ev->send_event = (wire->type & 0x80) != 0; + ev->display = dpy; + ev->window = wire->window; + ev->time = wire->time; + return True; +} + +static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w) +{ + XVncExtSelectionChangeEvent* ev = (XVncExtSelectionChangeEvent*)e; + xVncExtSelectionChangeNotifyEvent* wire + = (xVncExtSelectionChangeNotifyEvent*)w; + ev->type = wire->type & 0x7f; + ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire); + ev->send_event = (wire->type & 0x80) != 0; + ev->display = dpy; + ev->window = wire->window; + ev->selection = wire->selection; + return True; +} + +static Bool XVncExtQueryConnectNotifyWireToEvent(Display* dpy, XEvent* e, + xEvent* w) +{ + XVncExtQueryConnectEvent* ev = (XVncExtQueryConnectEvent*)e; + xVncExtQueryConnectNotifyEvent* wire + = (xVncExtQueryConnectNotifyEvent*)w; + ev->type = wire->type & 0x7f; + ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire); + ev->send_event = (wire->type & 0x80) != 0; + ev->display = dpy; + ev->window = wire->window; + return True; +} |