2 * rfb.h - header file for RFB DDX implementation.
6 * Copyright (C) 2002-2003 RealVNC Ltd.
7 * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
9 * This is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This software is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this software; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 #include "scrnintstr.h"
26 #include "colormapst.h"
29 #include <rfb/rfbproto.h>
30 #include <rfb/vncauth.h>
32 #define MAX_ENCODINGS 20
38 * Per-screen (framebuffer) structure. There is only one of these, since we
39 * don't allow the X server to have multiple screens.
45 int paddedWidthInBytes;
54 /* The following two members are used to minimise the amount of unnecessary
55 drawing caused by cursor movement. Whenever any drawing affects the
56 part of the screen where the cursor is, the cursor is removed first and
57 then the drawing is done (this is what the sprite routines test for).
58 Afterwards, however, we do not replace the cursor, even when the cursor
59 is logically being moved across the screen. We only draw the cursor
60 again just as we are about to send the client a framebuffer update.
62 We need to be careful when removing and drawing the cursor because of
63 their relationship with the normal drawing routines. The drawing
64 routines can invoke the cursor routines, but also the cursor routines
65 themselves end up invoking drawing routines.
67 Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by
68 doing a CopyArea from a pixmap to the screen, where the pixmap contains
69 the saved contents of the screen under the cursor. Before doing this,
70 however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called,
71 it sees that cursorIsDrawn is FALSE and so doesn't feel the need to
72 (recursively!) remove the cursor before doing it.
74 Putting up the cursor (rfbSpriteRestoreCursor) involves a call to
75 PushPixels. While this is happening, cursorIsDrawn must be FALSE so
76 that PushPixels doesn't think it has to remove the cursor first.
77 Obviously cursorIsDrawn is set to TRUE afterwards.
79 Another problem we face is that drawing routines sometimes cause a
80 framebuffer update to be sent to the RFB client. When the RFB client is
81 already waiting for a framebuffer update and some drawing to the
82 framebuffer then happens, the drawing routine sees that the client is
83 ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn
84 at this stage, it must be put up, and so rfbSpriteRestoreCursor is
85 called. However, if the original drawing routine was actually called
86 from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't
87 want this to happen. So both the cursor routines set
88 dontSendFramebufferUpdate to TRUE, and all the drawing routines check
89 this before calling rfbSendFramebufferUpdate. */
91 Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */
92 Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the
95 /* wrapped screen functions */
97 CloseScreenProcPtr CloseScreen;
98 CreateGCProcPtr CreateGC;
99 PaintWindowBackgroundProcPtr PaintWindowBackground;
100 PaintWindowBorderProcPtr PaintWindowBorder;
101 CopyWindowProcPtr CopyWindow;
102 ClearToBackgroundProcPtr ClearToBackground;
103 RestoreAreasProcPtr RestoreAreas;
105 } rfbScreenInfo, *rfbScreenInfoPtr;
109 * rfbTranslateFnType is the type of translation functions.
113 typedef void (*rfbTranslateFnType)(char *table, rfbPixelFormat *in,
115 char *iptr, char *optr,
116 int bytesBetweenInputLines,
117 int width, int height);
121 * Per-client structure.
124 typedef struct rfbClientRec {
128 /* Possible client states: */
130 RFB_PROTOCOL_VERSION, /* establishing protocol version */
131 RFB_AUTHENTICATION, /* authenticating */
132 RFB_INITIALISATION, /* sending initialisation messages */
133 RFB_NORMAL /* normal protocol messages */
136 Bool reverseConnection;
138 Bool readyForSetColourMapEntries;
141 int preferredEncoding;
142 int correMaxWidth, correMaxHeight;
145 /* The following member is only used during VNC authentication */
147 CARD8 authChallenge[CHALLENGESIZE];
149 /* The following members represent the update needed to get the client's
150 framebuffer from its present state to the current state of our
153 If the client does not accept CopyRect encoding then the update is
154 simply represented as the region of the screen which has been modified
157 If the client does accept CopyRect encoding, then the update consists of
158 two parts. First we have a single copy from one region of the screen to
159 another (the destination of the copy is copyRegion), and second we have
160 the region of the screen which has been modified in some other way
163 Although the copy is of a single region, this region may have many
164 rectangles. When sending an update, the copyRegion is always sent
165 before the modifiedRegion. This is because the modifiedRegion may
166 overlap parts of the screen which are in the source of the copy.
168 In fact during normal processing, the modifiedRegion may even overlap
169 the destination copyRegion. Just before an update is sent we remove
170 from the copyRegion anything in the modifiedRegion. */
172 RegionRec copyRegion; /* the destination region of the copy */
173 int copyDX, copyDY; /* the translation by which the copy happens */
175 RegionRec modifiedRegion; /* the region of the screen modified in any
178 /* As part of the FramebufferUpdateRequest, a client can express interest
179 in a subrectangle of the whole framebuffer. This is stored in the
180 requestedRegion member. In the normal case this is the whole
181 framebuffer if the client is ready, empty if it's not. */
183 RegionRec requestedRegion;
185 /* The following members represent the state of the "deferred update" timer
186 - when the framebuffer is modified and the client is ready, in most
187 cases it is more efficient to defer sending the update by a few
188 milliseconds so that several changes to the framebuffer can be combined
189 into a single update. */
191 Bool deferredUpdateScheduled;
192 OsTimerPtr deferredUpdateTimer;
194 /* translateFn points to the translation function which is used to copy
195 and translate a rectangle from the framebuffer to an output buffer. */
197 rfbTranslateFnType translateFn;
199 char *translateLookupTable;
201 rfbPixelFormat format;
205 int rfbBytesSent[MAX_ENCODINGS];
206 int rfbRectanglesSent[MAX_ENCODINGS];
207 int rfbFramebufferUpdateMessagesSent;
208 int rfbRawBytesEquivalent;
209 int rfbKeyEventsRcvd;
210 int rfbPointerEventsRcvd;
212 struct rfbClientRec *next;
214 } rfbClientRec, *rfbClientPtr;
218 * This macro is used to test whether there is a framebuffer update needing to
219 * be sent to the client.
222 #define FB_UPDATE_PENDING(cl) \
223 (!rfbScreen.cursorIsDrawn || \
224 REGION_NOTEMPTY((pScreen),&(cl)->copyRegion) || \
225 REGION_NOTEMPTY((pScreen),&(cl)->modifiedRegion))
228 * This macro creates an empty region (ie. a region with no areas) if it is
229 * given a rectangle with a width or height of zero. It appears that
230 * REGION_INTERSECT does not quite do the right thing with zero-width
231 * rectangles, but it should with completely empty regions.
234 #define SAFE_REGION_INIT(pscreen, preg, rect, size) \
237 ( ( (rect)->x2 == (rect)->x1 ) || \
238 ( (rect)->y2 == (rect)->y1 ) ) ) { \
239 REGION_INIT( (pscreen), (preg), NullBox, 0 ); \
241 REGION_INIT( (pscreen), (preg), (rect), (size) ); \
246 * An rfbGCRec is where we store the pointers to the original GC funcs and ops
247 * which we wrap (NULL means not wrapped).
253 } rfbGCRec, *rfbGCPtr;
258 * Macros for endian swapping.
261 #define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
263 #define Swap32(l) (((l) >> 24) | \
264 (((l) & 0x00ff0000) >> 8) | \
265 (((l) & 0x0000ff00) << 8) | \
271 static const int rfbEndianTest = 1;
273 #define Swap16IfLE(s) (*(const char *)&rfbEndianTest ? Swap16(s) : (s))
275 #define Swap32IfLE(l) (*(const char *)&rfbEndianTest ? Swap32(l) : (l))
277 extern char *desktopName;
278 extern Bool rfbTrace;
279 extern char rfbThisHost[];
280 extern Atom VNC_LAST_CLIENT_ID;
282 extern rfbScreenInfo rfbScreen;
283 extern int rfbGCIndex;
285 extern int inetdSock;
287 extern int rfbBitsPerPixel(int depth);
288 extern void rfbLog(char *format, ...);
289 extern void rfbLogPerror(char *str);
294 extern int rfbMaxClientWait;
297 extern int rfbListenSock;
298 extern Bool rfbLocalhostOnly;
300 extern void rfbInitSockets();
301 extern void rfbCloseSock();
302 extern void rfbCheckFds();
303 extern void rfbWaitForClient(int sock);
304 extern int rfbConnect(char *host, int port);
306 extern int ReadExact(int sock, char *buf, int len);
307 extern int WriteExact(int sock, char *buf, int len);
308 extern int ListenOnTCPPort(int port);
309 extern int ConnectToTcpAddr(char *host, int port);
314 extern ColormapPtr rfbInstalledColormap;
316 extern int rfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps);
317 extern void rfbInstallColormap(ColormapPtr pmap);
318 extern void rfbUninstallColormap(ColormapPtr pmap);
319 extern void rfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs);
324 extern int rfbDeferUpdateTime;
326 extern Bool rfbCloseScreen(int,ScreenPtr);
327 extern Bool rfbCreateGC(GCPtr);
328 extern void rfbPaintWindowBackground(WindowPtr, RegionPtr, int what);
329 extern void rfbPaintWindowBorder(WindowPtr, RegionPtr, int what);
330 extern void rfbCopyWindow(WindowPtr, DDXPointRec, RegionPtr);
331 extern void rfbClearToBackground(WindowPtr, int x, int y, int w,
332 int h, Bool generateExposures);
333 extern RegionPtr rfbRestoreAreas(WindowPtr, RegionPtr);
334 extern void rfbScheduleDeferredUpdate(rfbClientPtr cl);
339 extern void rfbSetXCutText(char *str, int len);
340 extern void rfbGotXCutText(char *str, int len);
345 extern void PtrDeviceInit();
346 extern void PtrDeviceOn();
347 extern void PtrDeviceOff();
348 extern void PtrDeviceControl();
349 extern void PtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl);
351 extern void KbdDeviceInit();
352 extern void KbdDeviceOn();
353 extern void KbdDeviceOff();
354 extern void KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl);
355 extern void KbdReleaseAllKeys();
361 * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the
362 * framebuffer. So for a max screen width of say 2K with 32-bit pixels this
366 #define UPDATE_BUF_SIZE 30000
367 extern char updateBuf[UPDATE_BUF_SIZE];
370 extern rfbClientPtr rfbClientHead;
371 extern rfbClientPtr pointerClient;
373 extern Bool rfbAlwaysShared;
374 extern Bool rfbNeverShared;
375 extern Bool rfbDontDisconnect;
376 extern int rfbMaxRects;
378 extern void rfbNewClientConnection(int sock);
379 extern rfbClientPtr rfbReverseConnection(char *host, int port);
380 extern void rfbClientConnectionGone(int sock);
381 extern void rfbProcessClientMessage(int sock);
382 extern void rfbClientConnFailed(rfbClientPtr cl, char *reason);
383 extern Bool rfbSendFramebufferUpdate(rfbClientPtr cl);
384 extern Bool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h);
385 extern Bool rfbSendUpdateBuf(rfbClientPtr cl);
386 extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour,
388 extern void rfbSendBell();
389 extern void rfbSendServerCutText(char *str, int len);
394 extern Bool rfbEconomicTranslate;
395 extern rfbPixelFormat rfbServerFormat;
397 extern void rfbTranslateNone(char *table, rfbPixelFormat *in,
399 char *iptr, char *optr,
400 int bytesBetweenInputLines,
401 int width, int height);
402 extern Bool rfbSetTranslateFunction(rfbClientPtr cl);
403 extern void rfbSetClientColourMaps(int firstColour, int nColours);
404 extern Bool rfbSetClientColourMap(rfbClientPtr cl, int firstColour,
411 extern char *httpDir;
413 extern void httpInitSockets();
414 extern void httpCheckFds();
420 extern char *rfbAuthPasswdFile;
421 extern Bool rfbAuthenticating;
423 extern void rfbAuthNewClient(rfbClientPtr cl);
424 extern void rfbAuthProcessClientMessage(rfbClientPtr cl);
429 extern Bool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h);
434 extern Bool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h);
439 extern Bool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w,
444 extern Bool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w,
446 extern void FreeZrleData(rfbClientPtr cl);
450 extern void rfbResetStats(rfbClientPtr cl);
451 extern void rfbPrintStats(rfbClientPtr cl);