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"
30 #define MAX_ENCODINGS 20
36 * Per-screen (framebuffer) structure. There is only one of these, since we
37 * don't allow the X server to have multiple screens.
43 int paddedWidthInBytes;
52 /* The following two members are used to minimise the amount of unnecessary
53 drawing caused by cursor movement. Whenever any drawing affects the
54 part of the screen where the cursor is, the cursor is removed first and
55 then the drawing is done (this is what the sprite routines test for).
56 Afterwards, however, we do not replace the cursor, even when the cursor
57 is logically being moved across the screen. We only draw the cursor
58 again just as we are about to send the client a framebuffer update.
60 We need to be careful when removing and drawing the cursor because of
61 their relationship with the normal drawing routines. The drawing
62 routines can invoke the cursor routines, but also the cursor routines
63 themselves end up invoking drawing routines.
65 Removing the cursor (rfbSpriteRemoveCursor) is eventually achieved by
66 doing a CopyArea from a pixmap to the screen, where the pixmap contains
67 the saved contents of the screen under the cursor. Before doing this,
68 however, we set cursorIsDrawn to FALSE. Then, when CopyArea is called,
69 it sees that cursorIsDrawn is FALSE and so doesn't feel the need to
70 (recursively!) remove the cursor before doing it.
72 Putting up the cursor (rfbSpriteRestoreCursor) involves a call to
73 PushPixels. While this is happening, cursorIsDrawn must be FALSE so
74 that PushPixels doesn't think it has to remove the cursor first.
75 Obviously cursorIsDrawn is set to TRUE afterwards.
77 Another problem we face is that drawing routines sometimes cause a
78 framebuffer update to be sent to the RFB client. When the RFB client is
79 already waiting for a framebuffer update and some drawing to the
80 framebuffer then happens, the drawing routine sees that the client is
81 ready, so it calls rfbSendFramebufferUpdate. If the cursor is not drawn
82 at this stage, it must be put up, and so rfbSpriteRestoreCursor is
83 called. However, if the original drawing routine was actually called
84 from within rfbSpriteRestoreCursor or rfbSpriteRemoveCursor we don't
85 want this to happen. So both the cursor routines set
86 dontSendFramebufferUpdate to TRUE, and all the drawing routines check
87 this before calling rfbSendFramebufferUpdate. */
89 Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */
90 Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the
93 /* wrapped screen functions */
95 CloseScreenProcPtr CloseScreen;
96 CreateGCProcPtr CreateGC;
97 PaintWindowBackgroundProcPtr PaintWindowBackground;
98 PaintWindowBorderProcPtr PaintWindowBorder;
99 CopyWindowProcPtr CopyWindow;
100 ClearToBackgroundProcPtr ClearToBackground;
101 RestoreAreasProcPtr RestoreAreas;
103 } rfbScreenInfo, *rfbScreenInfoPtr;
108 * Per-client structure.
111 typedef struct rfbClientRec {
115 /* Possible client states: */
117 RFB_PROTOCOL_VERSION, /* establishing protocol version */
118 RFB_AUTHENTICATION, /* authenticating */
119 RFB_INITIALISATION, /* sending initialisation messages */
120 RFB_NORMAL /* normal protocol messages */
123 Bool reverseConnection;
125 Bool readyForSetColourMapEntries;
128 int preferredEncoding;
129 int correMaxWidth, correMaxHeight;
132 /* The following members represent the update needed to get the client's
133 framebuffer from its present state to the current state of our
136 If the client does not accept CopyRect encoding then the update is
137 simply represented as the region of the screen which has been modified
140 If the client does accept CopyRect encoding, then the update consists of
141 two parts. First we have a single copy from one region of the screen to
142 another (the destination of the copy is copyRegion), and second we have
143 the region of the screen which has been modified in some other way
146 Although the copy is of a single region, this region may have many
147 rectangles. When sending an update, the copyRegion is always sent
148 before the modifiedRegion. This is because the modifiedRegion may
149 overlap parts of the screen which are in the source of the copy.
151 In fact during normal processing, the modifiedRegion may even overlap
152 the destination copyRegion. Just before an update is sent we remove
153 from the copyRegion anything in the modifiedRegion. */
155 RegionRec copyRegion; /* the destination region of the copy */
156 int copyDX, copyDY; /* the translation by which the copy happens */
158 RegionRec modifiedRegion; /* the region of the screen modified in any
161 /* As part of the FramebufferUpdateRequest, a client can express interest
162 in a subrectangle of the whole framebuffer. This is stored in the
163 requestedRegion member. In the normal case this is the whole
164 framebuffer if the client is ready, empty if it's not. */
166 RegionRec requestedRegion;
168 /* The following members represent the state of the "deferred update" timer
169 - when the framebuffer is modified and the client is ready, in most
170 cases it is more efficient to defer sending the update by a few
171 milliseconds so that several changes to the framebuffer can be combined
172 into a single update. */
174 Bool deferredUpdateScheduled;
175 OsTimerPtr deferredUpdateTimer;
177 char *translateLookupTable;
181 int rfbBytesSent[MAX_ENCODINGS];
182 int rfbRectanglesSent[MAX_ENCODINGS];
183 int rfbFramebufferUpdateMessagesSent;
184 int rfbRawBytesEquivalent;
185 int rfbKeyEventsRcvd;
186 int rfbPointerEventsRcvd;
188 struct rfbClientRec *next;
190 } rfbClientRec, *rfbClientPtr;
194 * This macro is used to test whether there is a framebuffer update needing to
195 * be sent to the client.
198 #define FB_UPDATE_PENDING(cl) \
199 (!rfbScreen.cursorIsDrawn || \
200 REGION_NOTEMPTY((pScreen),&(cl)->copyRegion) || \
201 REGION_NOTEMPTY((pScreen),&(cl)->modifiedRegion))
204 * This macro creates an empty region (ie. a region with no areas) if it is
205 * given a rectangle with a width or height of zero. It appears that
206 * REGION_INTERSECT does not quite do the right thing with zero-width
207 * rectangles, but it should with completely empty regions.
210 #define SAFE_REGION_INIT(pscreen, preg, rect, size) \
213 ( ( (rect)->x2 == (rect)->x1 ) || \
214 ( (rect)->y2 == (rect)->y1 ) ) ) { \
215 REGION_INIT( (pscreen), (preg), NullBox, 0 ); \
217 REGION_INIT( (pscreen), (preg), (rect), (size) ); \
222 * An rfbGCRec is where we store the pointers to the original GC funcs and ops
223 * which we wrap (NULL means not wrapped).
229 } rfbGCRec, *rfbGCPtr;
234 * Macros for endian swapping.
237 #define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
239 #define Swap32(l) (((l) >> 24) | \
240 (((l) & 0x00ff0000) >> 8) | \
241 (((l) & 0x0000ff00) << 8) | \
247 static const int rfbEndianTest = 1;
249 #define Swap16IfLE(s) (*(const char *)&rfbEndianTest ? Swap16(s) : (s))
251 #define Swap32IfLE(l) (*(const char *)&rfbEndianTest ? Swap32(l) : (l))
253 extern char *desktopName;
254 extern Bool rfbTrace;
255 extern char rfbThisHost[];
256 extern Atom VNC_LAST_CLIENT_ID;
258 extern rfbScreenInfo rfbScreen;
259 extern int rfbGCIndex;
261 extern int inetdSock;
263 extern int rfbBitsPerPixel(int depth);
264 extern void rfbLog(char *format, ...);
265 extern void rfbLogPerror(char *str);
270 extern int rfbMaxClientWait;
273 extern int rfbListenSock;
274 extern Bool rfbLocalhostOnly;
276 extern void rfbInitSockets();
277 extern void rfbCloseSock();
278 extern void rfbCheckFds();
279 extern void rfbWaitForClient(int sock);
280 extern int rfbConnect(char *host, int port);
282 extern int ReadExact(int sock, char *buf, int len);
283 extern int WriteExact(int sock, char *buf, int len);
284 extern int ListenOnTCPPort(int port);
285 extern int ConnectToTcpAddr(char *host, int port);
290 extern ColormapPtr rfbInstalledColormap;
292 extern int rfbListInstalledColormaps(ScreenPtr pScreen, Colormap *pmaps);
293 extern void rfbInstallColormap(ColormapPtr pmap);
294 extern void rfbUninstallColormap(ColormapPtr pmap);
295 extern void rfbStoreColors(ColormapPtr pmap, int ndef, xColorItem *pdefs);
300 extern int rfbDeferUpdateTime;
302 extern Bool rfbCloseScreen(int,ScreenPtr);
303 extern Bool rfbCreateGC(GCPtr);
304 extern void rfbPaintWindowBackground(WindowPtr, RegionPtr, int what);
305 extern void rfbPaintWindowBorder(WindowPtr, RegionPtr, int what);
306 extern void rfbCopyWindow(WindowPtr, DDXPointRec, RegionPtr);
307 extern void rfbClearToBackground(WindowPtr, int x, int y, int w,
308 int h, Bool generateExposures);
309 extern RegionPtr rfbRestoreAreas(WindowPtr, RegionPtr);
310 extern void rfbScheduleDeferredUpdate(rfbClientPtr cl);
315 extern void rfbSetXCutText(char *str, int len);
316 extern void rfbGotXCutText(char *str, int len);
321 extern void PtrDeviceInit();
322 extern void PtrDeviceOn();
323 extern void PtrDeviceOff();
324 extern void PtrDeviceControl();
325 extern void PtrAddEvent(int buttonMask, int x, int y, rfbClientPtr cl);
327 extern void KbdDeviceInit();
328 extern void KbdDeviceOn();
329 extern void KbdDeviceOff();
330 extern void KbdAddEvent(Bool down, KeySym keySym, rfbClientPtr cl);
331 extern void KbdReleaseAllKeys();
337 * UPDATE_BUF_SIZE must be big enough to send at least one whole line of the
338 * framebuffer. So for a max screen width of say 2K with 32-bit pixels this
342 #define UPDATE_BUF_SIZE 30000
343 extern char updateBuf[UPDATE_BUF_SIZE];
346 extern rfbClientPtr rfbClientHead;
347 extern rfbClientPtr pointerClient;
349 extern Bool rfbAlwaysShared;
350 extern Bool rfbNeverShared;
351 extern Bool rfbDontDisconnect;
352 extern int rfbMaxRects;
354 extern void rfbNewClientConnection(int sock);
355 extern rfbClientPtr rfbReverseConnection(char *host, int port);
356 extern void rfbClientConnectionGone(int sock);
357 extern void rfbProcessClientMessage(int sock);
358 extern void rfbClientConnFailed(rfbClientPtr cl, char *reason);
359 extern Bool rfbSendFramebufferUpdate(rfbClientPtr cl);
360 extern Bool rfbSendRectEncodingRaw(rfbClientPtr cl, int x,int y,int w,int h);
361 extern Bool rfbSendUpdateBuf(rfbClientPtr cl);
362 extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour,
364 extern void rfbSendBell();
365 extern void rfbSendServerCutText(char *str, int len);
370 extern Bool rfbEconomicTranslate;
372 extern Bool rfbSetTranslateFunction(rfbClientPtr cl);
373 extern void rfbSetClientColourMaps(int firstColour, int nColours);
374 extern Bool rfbSetClientColourMap(rfbClientPtr cl, int firstColour,
381 extern char *httpDir;
383 extern void httpInitSockets();
384 extern void httpCheckFds();
390 extern char *rfbAuthPasswdFile;
391 extern Bool rfbAuthenticating;
393 extern void rfbAuthNewClient(rfbClientPtr cl);
394 extern void rfbAuthProcessClientMessage(rfbClientPtr cl);
399 extern Bool rfbSendRectEncodingRRE(rfbClientPtr cl, int x,int y,int w,int h);
404 extern Bool rfbSendRectEncodingCoRRE(rfbClientPtr cl, int x,int y,int w,int h);
409 extern Bool rfbSendRectEncodingHextile(rfbClientPtr cl, int x, int y, int w,
414 extern Bool rfbSendRectEncodingZRLE(rfbClientPtr cl, int x, int y, int w,
416 extern void FreeZrleData(rfbClientPtr cl);
420 extern void rfbResetStats(rfbClientPtr cl);
421 extern void rfbPrintStats(rfbClientPtr cl);