summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES1
-rw-r--r--classes/VncViewer.jarbin36406 -> 37317 bytes
-rw-r--r--classes/index.vnc3
-rw-r--r--example.c42
-rw-r--r--httpd.c2
-rw-r--r--main.c161
-rw-r--r--rfb.h18
-rw-r--r--rfbproto.h1
-rw-r--r--rfbserver.c62
-rw-r--r--stats.c2
10 files changed, 246 insertions, 46 deletions
diff --git a/CHANGES b/CHANGES
index 8767a12..bba61b9 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,4 @@
+ support for NewFB from Const Kaplinsky
memory leaks squashed (localtime pseudo leak is still there :-)
small improvements for OSXvnc (still not working correctly)
synced with TightVNC 1.2.3
diff --git a/classes/VncViewer.jar b/classes/VncViewer.jar
index ac35865..cf4c124 100644
--- a/classes/VncViewer.jar
+++ b/classes/VncViewer.jar
Binary files differ
diff --git a/classes/index.vnc b/classes/index.vnc
index 5eae27e..6cab43e 100644
--- a/classes/index.vnc
+++ b/classes/index.vnc
@@ -8,9 +8,10 @@
<TITLE>
$USER's $DESKTOP desktop ($DISPLAY)
</TITLE>
-<APPLET CODE=vncviewer.class ARCHIVE=VncViewer.jar
+<APPLET CODE=VncViewer.class ARCHIVE=VncViewer.jar
WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT>
<param name=PORT value=$PORT>
+<param name="Open New Window" value=yes>
</APPLET>
<BR>
<A href="http://www.tightvnc.com/">www.TightVNC.com</A>
diff --git a/example.c b/example.c
index 01ec504..2100b41 100644
--- a/example.c
+++ b/example.c
@@ -34,7 +34,8 @@
#include "rfb.h"
#include "keysym.h"
-const int maxx=640, maxy=480, bpp=4;
+const int bpp=4;
+int maxx=800, maxy=600;
/* TODO: odd maxx doesn't work (vncviewer bug) */
/* This initializes a nice (?) background */
@@ -74,6 +75,23 @@ enum rfbNewClientAction newclient(rfbClientPtr cl)
return RFB_CLIENT_ACCEPT;
}
+/* switch to new framebuffer contents */
+
+void newframebuffer(rfbScreenInfoPtr screen, int width, int height)
+{
+ char *oldfb, *newfb;
+
+ maxx = width;
+ maxy = height;
+ oldfb = screen->frameBuffer;
+ newfb = (char*)malloc(maxx * maxy * bpp);
+ initBuffer(newfb);
+ rfbNewFramebuffer(screen, newfb, maxx, maxy, 8, 3, bpp);
+ free(oldfb);
+
+ /*** FIXME: Re-install cursor. ***/
+}
+
/* aux function to draw a line */
void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,int y2)
@@ -158,6 +176,22 @@ void dokey(Bool down,KeySym key,rfbClientPtr cl)
rfbUndrawCursor(cl->screen);
initBuffer(cl->screen->frameBuffer);
rfbMarkRectAsModified(cl->screen,0,0,maxx,maxy);
+ } else if (key == XK_Up) {
+ if (maxx < 1024) {
+ if (maxx < 800) {
+ newframebuffer(cl->screen, 800, 600);
+ } else {
+ newframebuffer(cl->screen, 1024, 768);
+ }
+ }
+ } else if(key==XK_Down) {
+ if (maxx > 640) {
+ if (maxx > 800) {
+ newframebuffer(cl->screen, 800, 600);
+ } else {
+ newframebuffer(cl->screen, 640, 480);
+ }
+ }
} else if(key>=' ' && key<0x100) {
ClientData* cd=cl->clientData;
int x1=cd->oldx,y1=cd->oldy,x2,y2;
@@ -266,7 +300,7 @@ int main(int argc,char** argv)
#ifdef USE_OWN_LOOP
{
int i;
- for(i=0;i<200;i++) {
+ for(i=0;;i++) {
fprintf(stderr,"%d\r",i);
rfbProcessEvents(rfbScreen,100000);
}
@@ -275,7 +309,7 @@ int main(int argc,char** argv)
#ifndef BACKGROUND_LOOP_TEST
/* this is the blocking event loop, i.e. it never returns */
- /* 40000 are the microseconds, i.e. 0.04 seconds */
+ /* 40000 are the microseconds to wait on select(), i.e. 0.04 seconds */
rfbRunEventLoop(rfbScreen,40000,FALSE);
#elif !defined(HAVE_PTHREADS)
#error "I need pthreads for that."
@@ -283,7 +317,7 @@ int main(int argc,char** argv)
/* this is the non-blocking event loop; a background thread is started */
rfbRunEventLoop(rfbScreen,-1,TRUE);
- /* now we could do some cool things like rendering */
+ /* now we could do some cool things like rendering in idle time */
while(1) sleep(5); /* render(); */
#endif
diff --git a/httpd.c b/httpd.c
index 8f6aa01..813b239 100644
--- a/httpd.c
+++ b/httpd.c
@@ -218,6 +218,8 @@ httpProcessInput(rfbScreenInfoPtr rfbScreen)
fname = &fullFname[strlen(fullFname)];
maxFnameLen = 255 - strlen(fullFname);
+ buf_filled=0;
+
/* Read data from the HTTP client until we get a complete request. */
while (1) {
ssize_t got = read (rfbScreen->httpSock, buf + buf_filled,
diff --git a/main.c b/main.c
index f1f800a..ea2eeb9 100644
--- a/main.c
+++ b/main.c
@@ -468,12 +468,57 @@ enum rfbNewClientAction defaultNewClientHook(rfbClientPtr cl)
return RFB_CLIENT_ACCEPT;
}
+/*
+ * Update server's pixel format in rfbScreenInfo structure. This
+ * function is called from rfbGetScreen() and rfbNewFramebuffer().
+ */
+
+static void rfbInitServerFormat(rfbScreenInfoPtr rfbScreen, int bitsPerSample)
+{
+ rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
+
+ format->bitsPerPixel = rfbScreen->bitsPerPixel;
+ format->depth = rfbScreen->depth;
+ format->bigEndian = rfbEndianTest?FALSE:TRUE;
+ format->trueColour = TRUE;
+ rfbScreen->colourMap.count = 0;
+ rfbScreen->colourMap.is16 = 0;
+ rfbScreen->colourMap.data.bytes = NULL;
+
+ if (format->bitsPerPixel == 8) {
+ format->redMax = 7;
+ format->greenMax = 7;
+ format->blueMax = 3;
+ format->redShift = 0;
+ format->greenShift = 3;
+ format->blueShift = 6;
+ } else {
+ format->redMax = (1 << bitsPerSample) - 1;
+ format->greenMax = (1 << bitsPerSample) - 1;
+ format->blueMax = (1 << bitsPerSample) - 1;
+ if(rfbEndianTest) {
+ format->redShift = 0;
+ format->greenShift = bitsPerSample;
+ format->blueShift = bitsPerSample * 2;
+ } else {
+ if(format->bitsPerPixel==8*3) {
+ format->redShift = bitsPerSample*2;
+ format->greenShift = bitsPerSample*1;
+ format->blueShift = 0;
+ } else {
+ format->redShift = bitsPerSample*3;
+ format->greenShift = bitsPerSample*2;
+ format->blueShift = bitsPerSample;
+ }
+ }
+ }
+}
+
rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
int width,int height,int bitsPerSample,int samplesPerPixel,
int bytesPerPixel)
{
rfbScreenInfoPtr rfbScreen=malloc(sizeof(rfbScreenInfo));
- rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
INIT_MUTEX(logMutex);
@@ -530,41 +575,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
/* format */
- format->bitsPerPixel = rfbScreen->bitsPerPixel;
- format->depth = rfbScreen->depth;
- format->bigEndian = rfbEndianTest?FALSE:TRUE;
- format->trueColour = TRUE;
- rfbScreen->colourMap.count = 0;
- rfbScreen->colourMap.is16 = 0;
- rfbScreen->colourMap.data.bytes = NULL;
-
- if(bytesPerPixel == 1) {
- format->redMax = 7;
- format->greenMax = 7;
- format->blueMax = 3;
- format->redShift = 0;
- format->greenShift = 3;
- format->blueShift = 6;
- } else {
- format->redMax = (1 << bitsPerSample) - 1;
- format->greenMax = (1 << bitsPerSample) - 1;
- format->blueMax = (1 << bitsPerSample) - 1;
- if(rfbEndianTest) {
- format->redShift = 0;
- format->greenShift = bitsPerSample;
- format->blueShift = bitsPerSample * 2;
- } else {
- if(bytesPerPixel==3) {
- format->redShift = bitsPerSample*2;
- format->greenShift = bitsPerSample*1;
- format->blueShift = 0;
- } else {
- format->redShift = bitsPerSample*3;
- format->greenShift = bitsPerSample*2;
- format->blueShift = bitsPerSample;
- }
- }
- }
+ rfbInitServerFormat(rfbScreen, bitsPerSample);
/* cursor */
@@ -597,6 +608,84 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
return(rfbScreen);
}
+/*
+ * Switch to another framebuffer (maybe of different size and color
+ * format). Clients supporting NewFBSize pseudo-encoding will change
+ * their local framebuffer dimensions if necessary.
+ * NOTE: Rich cursor data should be converted to new pixel format by
+ * the caller.
+ */
+
+void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen, char *framebuffer,
+ int width, int height,
+ int bitsPerSample, int samplesPerPixel,
+ int bytesPerPixel)
+{
+ rfbPixelFormat old_format;
+ Bool format_changed = FALSE;
+ rfbClientIteratorPtr iterator;
+ rfbClientPtr cl;
+
+ /* Remove the pointer */
+
+ rfbUndrawCursor(rfbScreen);
+
+ /* Update information in the rfbScreenInfo structure */
+
+ old_format = rfbScreen->rfbServerFormat;
+
+ if (width & 3)
+ rfbLog("WARNING: New width (%d) is not a multiple of 4.\n", width);
+
+ rfbScreen->width = width;
+ rfbScreen->height = height;
+ rfbScreen->bitsPerPixel = rfbScreen->depth = 8*bytesPerPixel;
+ rfbScreen->paddedWidthInBytes = width*bytesPerPixel;
+
+ rfbInitServerFormat(rfbScreen, bitsPerSample);
+
+ if (memcmp(&rfbScreen->rfbServerFormat, &old_format,
+ sizeof(rfbPixelFormat)) != 0) {
+ format_changed = TRUE;
+ }
+
+ rfbScreen->frameBuffer = framebuffer;
+
+ /* Adjust pointer position if necessary */
+
+ if (rfbScreen->cursorX >= width)
+ rfbScreen->cursorX = width - 1;
+ if (rfbScreen->cursorY >= height)
+ rfbScreen->cursorY = height - 1;
+
+ /* For each client: */
+ iterator = rfbGetClientIterator(rfbScreen);
+ while ((cl = rfbClientIteratorNext(iterator)) != NULL) {
+
+ /* Re-install color translation tables if necessary */
+
+ if (format_changed)
+ rfbScreen->setTranslateFunction(cl);
+
+ /* Mark the screen contents as changed, and schedule sending
+ NewFBSize message if supported by this client. */
+
+ LOCK(cl->updateMutex);
+ sraRgnDestroy(cl->modifiedRegion);
+ cl->modifiedRegion = sraRgnCreateRect(0, 0, width, height);
+ sraRgnMakeEmpty(cl->copyRegion);
+ cl->copyDX = 0;
+ cl->copyDY = 0;
+
+ if (cl->useNewFBSize)
+ cl->newFBSizePending = TRUE;
+
+ TSIGNAL(cl->updateCond);
+ UNLOCK(cl->updateMutex);
+ }
+ rfbReleaseClientIterator(iterator);
+}
+
void rfbScreenCleanup(rfbScreenInfoPtr rfbScreen)
{
rfbClientIteratorPtr i=rfbGetClientIterator(rfbScreen);
diff --git a/rfb.h b/rfb.h
index 7c7121c..98dc004 100644
--- a/rfb.h
+++ b/rfb.h
@@ -503,8 +503,12 @@ typedef struct _rfbClientRec {
Bool enableCursorShapeUpdates; /* client supports cursor shape updates */
Bool useRichCursorEncoding; /* rfbEncodingRichCursor is preferred */
Bool cursorWasChanged; /* cursor shape update should be sent */
+
+ Bool useNewFBSize; /* client supports NewFBSize encoding */
+ Bool newFBSizePending; /* framebuffer size was changed */
+
#ifdef BACKCHANNEL
- Bool enableBackChannel;
+ Bool enableBackChannel; /* custom channel for special clients */
#endif
struct _rfbClientRec *prev;
@@ -532,9 +536,10 @@ typedef struct _rfbClientRec {
* be sent to the client.
*/
-#define FB_UPDATE_PENDING(cl) \
- ((!(cl)->enableCursorShapeUpdates && !(cl)->screen->cursorIsDrawn) || \
- ((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \
+#define FB_UPDATE_PENDING(cl) \
+ ((!(cl)->enableCursorShapeUpdates && !(cl)->screen->cursorIsDrawn) || \
+ ((cl)->enableCursorShapeUpdates && (cl)->cursorWasChanged) || \
+ ((cl)->useNewFBSize && (cl)->newFBSizePending) || \
!sraRgnEmpty((cl)->copyRegion) || !sraRgnEmpty((cl)->modifiedRegion))
/*
@@ -603,6 +608,7 @@ extern Bool rfbSendUpdateBuf(rfbClientPtr cl);
extern void rfbSendServerCutText(rfbScreenInfoPtr rfbScreen,char *str, int len);
extern Bool rfbSendCopyRegion(rfbClientPtr cl,sraRegionPtr reg,int dx,int dy);
extern Bool rfbSendLastRectMarker(rfbClientPtr cl);
+extern Bool rfbSendNewFBSize(rfbClientPtr cl, int w, int h);
extern Bool rfbSendSetColourMapEntries(rfbClientPtr cl, int firstColour, int nColours);
extern void rfbSendBell(rfbScreenInfoPtr rfbScreen);
@@ -796,6 +802,10 @@ extern rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
int width,int height,int bitsPerSample,int samplesPerPixel,
int bytesPerPixel);
extern void rfbInitServer(rfbScreenInfoPtr rfbScreen);
+extern void rfbNewFramebuffer(rfbScreenInfoPtr rfbScreen,char *framebuffer,
+ int width,int height, int bitsPerSample,int samplesPerPixel,
+ int bytesPerPixel);
+
extern void rfbScreenCleanup(rfbScreenInfoPtr screenInfo);
/* functions to accept/refuse a client that has been put on hold
diff --git a/rfbproto.h b/rfbproto.h
index 6ea6a62..f839019 100644
--- a/rfbproto.h
+++ b/rfbproto.h
@@ -328,6 +328,7 @@ typedef struct {
#define rfbEncodingRichCursor 0xFFFFFF11
#define rfbEncodingLastRect 0xFFFFFF20
+#define rfbEncodingNewFBSize 0xFFFFFF21
#define rfbEncodingQualityLevel0 0xFFFFFFE0
#define rfbEncodingQualityLevel1 0xFFFFFFE1
diff --git a/rfbserver.c b/rfbserver.c
index 11aeff6..f2dfada 100644
--- a/rfbserver.c
+++ b/rfbserver.c
@@ -266,6 +266,7 @@ rfbNewTCPOrUDPClient(rfbScreen,sock,isUDP)
cl->enableCursorShapeUpdates = FALSE;
cl->useRichCursorEncoding = FALSE;
cl->enableLastRectEncoding = FALSE;
+ cl->useNewFBSize = FALSE;
cl->compStreamInited = FALSE;
cl->compStream.total_in = 0;
@@ -663,6 +664,7 @@ rfbProcessClientNormalMessage(cl)
cl->useCopyRect = FALSE;
cl->enableCursorShapeUpdates = FALSE;
cl->enableLastRectEncoding = FALSE;
+ cl->useNewFBSize = FALSE;
for (i = 0; i < msg.se.nEncodings; i++) {
if ((n = ReadExact(cl, (char *)&enc, 4)) <= 0) {
@@ -742,6 +744,13 @@ rfbProcessClientNormalMessage(cl)
cl->enableLastRectEncoding = TRUE;
}
break;
+ case rfbEncodingNewFBSize:
+ if (!cl->useNewFBSize) {
+ rfbLog("Enabling NewFBSize protocol extension for client "
+ "%s\n", cl->host);
+ cl->useNewFBSize = TRUE;
+ }
+ break;
#ifdef BACKCHANNEL
case rfbEncodingBackChannel:
if (!cl->enableBackChannel) {
@@ -924,6 +933,25 @@ rfbSendFramebufferUpdate(cl, givenUpdateRegion)
if(cl->screen->displayHook)
cl->screen->displayHook(cl);
+
+ /*
+ * If framebuffer size was changed and the client supports NewFBSize
+ * encoding, just send NewFBSize marker and return.
+ */
+
+ if (cl->useNewFBSize && cl->newFBSizePending) {
+ LOCK(cl->updateMutex);
+ cl->newFBSizePending = FALSE;
+ UNLOCK(cl->updateMutex);
+ cl->rfbFramebufferUpdateMessagesSent++;
+ fu->type = rfbFramebufferUpdate;
+ fu->nRects = Swap16IfLE(1);
+ cl->ublen = sz_rfbFramebufferUpdateMsg;
+ if (!rfbSendNewFBSize(cl, cl->screen->width, cl->screen->height)) {
+ return FALSE;
+ }
+ return rfbSendUpdateBuf(cl);
+ }
/*
* If this client understands cursor shape updates, cursor should be
@@ -1310,6 +1338,40 @@ rfbSendLastRectMarker(cl)
/*
+ * Send NewFBSize pseudo-rectangle. This tells the client to change
+ * its framebuffer size.
+ */
+
+Bool
+rfbSendNewFBSize(cl, w, h)
+ rfbClientPtr cl;
+ int w, h;
+{
+ rfbFramebufferUpdateRectHeader rect;
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.encoding = Swap32IfLE(rfbEncodingNewFBSize);
+ rect.r.x = 0;
+ rect.r.y = 0;
+ rect.r.w = Swap16IfLE(w);
+ rect.r.h = Swap16IfLE(h);
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->rfbLastRectMarkersSent++;
+ cl->rfbLastRectBytesSent += sz_rfbFramebufferUpdateRectHeader;
+
+ return TRUE;
+}
+
+
+/*
* Send the contents of cl->updateBuf. Returns 1 if successful, -1 if
* not (errno should be set).
*/
diff --git a/stats.c b/stats.c
index 7774d2f..a0b5ccc 100644
--- a/stats.c
+++ b/stats.c
@@ -78,7 +78,7 @@ rfbPrintStats(rfbClientPtr cl)
totalBytesSent);
if (cl->rfbLastRectMarkersSent != 0)
- rfbLog(" LastRect markers %d, bytes %d\n",
+ rfbLog(" LastRect and NewFBSize markers %d, bytes %d\n",
cl->rfbLastRectMarkersSent, cl->rfbLastRectBytesSent);
if (cl->rfbCursorUpdatesSent != 0)