cleaned up warnings, cursor changes

pull/1/head
dscho 24 years ago
parent febced5536
commit 1e83d9a599

@ -20,10 +20,10 @@ OSX_LIBS = -framework ApplicationServices -framework Carbon
SOURCES=main.c rfbserver.c miregion.c auth.c sockets.c xalloc.c \
stats.c corre.c hextile.c rre.c translate.c cutpaste.c \
zlib.c tight.c httpd.c
zlib.c tight.c httpd.c cursor.o
OBJS=main.o rfbserver.o miregion.o auth.o sockets.o xalloc.o \
stats.o corre.o hextile.o rre.o translate.o cutpaste.o \
zlib.o tight.o httpd.o
zlib.o tight.o httpd.o cursor.o
all: example pnmshow storepasswd

@ -1,6 +1,15 @@
LibVNCServer: a library for easy implementation of a RDP/VNC server.
Copyright (C) 2001 Johannes E. Schindelin
What is it?
-----------
VNC is set of programs using the RFB (Remote Frame Buffer) protocol. They
are designed to "export" a frame buffer via net. It is already in wide use
for administration, but it is not that easy to make a server yourself.
This has been changed by LibVNCServer.
There are two examples included:
- example, a shared scribble sheet
- pnmshow, a program to show PNMs (pictures) over the net.
@ -12,13 +21,56 @@ How to use
----------
To make a server, you just have to initialise a server structure using the
function rfbDefaultScreenInit.
function rfbDefaultScreenInit, like
rfbScreenInfoPtr rfbScreen =
rfbDefaultScreenInit(argc,argv,maxx,maxy,8,3,bpp);
You then can set hooks and io functions.
You then can set hooks and io functions (see below).
You can use a blocking event loop, a background (pthread based) event loop,
or implement your own using the processEvents function.
Also, there is functionality included to draw a cursor (see below).
To start also an HTTP server (running on port 5800+display_number), you have
to set rfbScreen->httpdDir to a directory containing vncviewer.jar and
index.vnc (like the included "classes" directory).
Hooks and IO functions
----------------------
TODO
Cursor handling
---------------
The rfbCursor structure consists mainly of a mask and a source. The mask
describes, which pixels are drawn for the cursor (a cursor needn't be
rectangular). The source describes, which colour those pixels should have.
The standard is an XCursor: a cursor with a foreground and a background
colour (stored in backRed and similar with a range from 0-0xffff). The
arrays "mask" and "source" consist of byte padded rows in MSB order (i.e. a
10x4 cursor's mask has 2x4 bytes, because 2 bytes are needed to hold 10 bits).
It is very easy to make a cursor like this:
char* cur=" "
" xx "
" x "
" ";
char* mask="xxxx"
"xxxx"
"xxxx"
"xxx ";
rfbCursorPtr c=rfbMakeXCursor(4,4,cur,mask);
You can even set "mask" to NULL in this call and LibVNCServer will calculate
a mask for you.
There is also an array named "richSource" for colourful cursors. They have
the same format as the frameBuffer.
History
-------

20
TODO

@ -1,17 +1,15 @@
.cutpaste
httpd
.other encodings
dont draw rich cursors as xcursors
test drawing of cursors when not using xcursor or rich cursor encoding
adapt rdp2vnc (rdesktop)
udp
rfbCloseClient, rfbConnect, ConnectToTcpAddr
CORBA
translate.c: warning about non 8-bit colourmaps
cursors
done:
.cursors
.cutpaste
.httpd
.other encodings

@ -24,11 +24,13 @@
#include <stdio.h>
#include "rfb.h"
#include "mipointer.h"
/*
#include "mipointer.h"
#include "sprite.h"
#include "cursorstr.h"
#include "servermd.h"
*/
/* Copied from Xvnc/lib/font/util/utilbitmap.c */
static unsigned char _reverse_byte[0x100] = {
@ -67,12 +69,12 @@ static unsigned char _reverse_byte[0x100] = {
};
static int EncodeRichCursorData8 (char *buf, rfbPixelFormat *fmt,
CursorPtr pCursor);
static int EncodeRichCursorData16 (char *buf, rfbPixelFormat *fmt,
CursorPtr pCursor);
static int EncodeRichCursorData32 (char *buf, rfbPixelFormat *fmt,
CursorPtr pCursor);
static int EncodeRichCursorData8 (rfbClientPtr cl, char *buf, rfbPixelFormat *fmt,
rfbCursorPtr pCursor);
static int EncodeRichCursorData16 (rfbClientPtr cl, char *buf, rfbPixelFormat *fmt,
rfbCursorPtr pCursor);
static int EncodeRichCursorData32 (rfbClientPtr cl, char *buf, rfbPixelFormat *fmt,
rfbCursorPtr pCursor);
/*
@ -80,45 +82,54 @@ static int EncodeRichCursorData32 (char *buf, rfbPixelFormat *fmt,
*/
Bool
rfbSendCursorShape(cl, pScreen)
rfbSendCursorShape(cl)
rfbClientPtr cl;
ScreenPtr pScreen;
{
CursorPtr pCursor;
rfbCursorPtr pCursor;
rfbFramebufferUpdateRectHeader rect;
rfbXCursorColors colors;
int saved_ublen;
int bitmapRowBytes, paddedRowBytes, maskBytes, dataBytes;
int bitmapRowBytes, maskBytes, dataBytes;
int i, j;
CARD8 *bitmapData;
CARD8 bitmapByte;
pCursor = cl->screen->getCursorPtr(cl);
if (cl->useRichCursorEncoding) {
if(!pCursor->richSource)
MakeRichCursorFromXCursor(cl->screen,pCursor);
rect.encoding = Swap32IfLE(rfbEncodingRichCursor);
} else {
if(!pCursor->source)
MakeXCursorFromRichCursor(cl->screen,pCursor);
rect.encoding = Swap32IfLE(rfbEncodingXCursor);
}
pCursor = rfbSpriteGetCursorPtr(pScreen);
/*{
rfbScreenInfoPtr s=cl->screen;
SetXCutTextProcPtr sx=cl->screen->setXCutText;
GetCursorProcPtr g=cl->screen->getCursorPtr;
}*/
/* If there is no cursor, send update with empty cursor data. */
if ( pCursor->bits->width == 1 &&
pCursor->bits->height == 1 &&
pCursor->bits->mask[0] == 0 ) {
if ( pCursor->width == 1 &&
pCursor->height == 1 &&
pCursor->mask[0] == 0 ) {
pCursor = NULL;
}
if (pCursor == NULL) {
if (ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE ) {
if (!rfbSendUpdateBuf(cl))
return FALSE;
}
rect.r.x = rect.r.y = 0;
rect.r.w = rect.r.h = 0;
memcpy(&updateBuf[ublen], (char *)&rect,
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
sz_rfbFramebufferUpdateRectHeader);
ublen += sz_rfbFramebufferUpdateRectHeader;
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
cl->rfbCursorBytesSent += sz_rfbFramebufferUpdateRectHeader;
cl->rfbCursorUpdatesSent++;
@ -131,37 +142,36 @@ rfbSendCursorShape(cl, pScreen)
/* Calculate data sizes. */
bitmapRowBytes = (pCursor->bits->width + 7) / 8;
paddedRowBytes = PixmapBytePad(pCursor->bits->width, 1);
maskBytes = bitmapRowBytes * pCursor->bits->height;
bitmapRowBytes = (pCursor->width + 7) / 8;
maskBytes = bitmapRowBytes * pCursor->height;
dataBytes = (cl->useRichCursorEncoding) ?
(pCursor->bits->width * pCursor->bits->height *
(pCursor->width * pCursor->height *
(cl->format.bitsPerPixel / 8)) : maskBytes;
/* Send buffer contents if needed. */
if ( ublen + sz_rfbFramebufferUpdateRectHeader +
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
if (!rfbSendUpdateBuf(cl))
return FALSE;
}
if ( ublen + sz_rfbFramebufferUpdateRectHeader +
if ( cl->ublen + sz_rfbFramebufferUpdateRectHeader +
sz_rfbXCursorColors + maskBytes + dataBytes > UPDATE_BUF_SIZE ) {
return FALSE; /* FIXME. */
}
saved_ublen = ublen;
saved_ublen = cl->ublen;
/* Prepare rectangle header. */
rect.r.x = Swap16IfLE(pCursor->bits->xhot);
rect.r.y = Swap16IfLE(pCursor->bits->yhot);
rect.r.w = Swap16IfLE(pCursor->bits->width);
rect.r.h = Swap16IfLE(pCursor->bits->height);
rect.r.x = Swap16IfLE(pCursor->xhot);
rect.r.y = Swap16IfLE(pCursor->yhot);
rect.r.w = Swap16IfLE(pCursor->width);
rect.r.h = Swap16IfLE(pCursor->height);
memcpy(&updateBuf[ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
ublen += sz_rfbFramebufferUpdateRectHeader;
memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,sz_rfbFramebufferUpdateRectHeader);
cl->ublen += sz_rfbFramebufferUpdateRectHeader;
/* Prepare actual cursor data (depends on encoding used). */
@ -174,57 +184,68 @@ rfbSendCursorShape(cl, pScreen)
colors.backGreen = (char)(pCursor->backGreen >> 8);
colors.backBlue = (char)(pCursor->backBlue >> 8);
memcpy(&updateBuf[ublen], (char *)&colors, sz_rfbXCursorColors);
ublen += sz_rfbXCursorColors;
memcpy(&cl->updateBuf[cl->ublen], (char *)&colors, sz_rfbXCursorColors);
cl->ublen += sz_rfbXCursorColors;
bitmapData = (CARD8 *)pCursor->bits->source;
bitmapData = (CARD8 *)pCursor->source;
for (i = 0; i < pCursor->bits->height; i++) {
for (i = 0; i < pCursor->height; i++) {
for (j = 0; j < bitmapRowBytes; j++) {
bitmapByte = bitmapData[i * paddedRowBytes + j];
if (screenInfo.bitmapBitOrder == LSBFirst) {
bitmapByte = bitmapData[i * bitmapRowBytes + j];
/*if (screenInfo.bitmapBitOrder == LSBFirst) {
bitmapByte = _reverse_byte[bitmapByte];
}
updateBuf[ublen++] = (char)bitmapByte;
}*/
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
}
}
} else {
/* RichCursor encoding. */
int bpp1=cl->screen->rfbServerFormat.bitsPerPixel/8,
bpp2=cl->format.bitsPerPixel/8;
(*cl->translateFn)(cl->translateLookupTable,
&(cl->screen->rfbServerFormat),
&cl->format, pCursor->richSource,
&cl->updateBuf[cl->ublen],
pCursor->width*bpp1, pCursor->width, pCursor->height);
cl->ublen += pCursor->width*bpp2*pCursor->height;
/*
switch (cl->format.bitsPerPixel) {
case 8:
ublen += EncodeRichCursorData8(&updateBuf[ublen],
cl->ublen += EncodeRichCursorData8(cl, &cl->updateBuf[cl->ublen],
&cl->format, pCursor);
break;
case 16:
ublen += EncodeRichCursorData16(&updateBuf[ublen],
cl->ublen += EncodeRichCursorData16(cl, &cl->updateBuf[cl->ublen],
&cl->format, pCursor);
break;
case 32:
ublen += EncodeRichCursorData32(&updateBuf[ublen],
cl->ublen += EncodeRichCursorData32(cl, &cl->updateBuf[cl->ublen],
&cl->format, pCursor);
break;
default:
return FALSE;
}
*/
}
/* Prepare transparency mask. */
bitmapData = (CARD8 *)pCursor->bits->mask;
bitmapData = (CARD8 *)pCursor->mask;
for (i = 0; i < pCursor->bits->height; i++) {
for (i = 0; i < pCursor->height; i++) {
for (j = 0; j < bitmapRowBytes; j++) {
bitmapByte = bitmapData[i * paddedRowBytes + j];
if (screenInfo.bitmapBitOrder == LSBFirst) {
bitmapByte = bitmapData[i * bitmapRowBytes + j];
/*if (screenInfo.bitmapBitOrder == LSBFirst) {
bitmapByte = _reverse_byte[bitmapByte];
}
updateBuf[ublen++] = (char)bitmapByte;
}*/
cl->updateBuf[cl->ublen++] = (char)bitmapByte;
}
}
/* Send everything we have prepared in the updateBuf[]. */
/* Send everything we have prepared in the cl->updateBuf[]. */
cl->rfbCursorBytesSent += (ublen - saved_ublen);
cl->rfbCursorBytesSent += (cl->ublen - saved_ublen);
cl->rfbCursorUpdatesSent++;
if (!rfbSendUpdateBuf(cl))
@ -244,10 +265,11 @@ rfbSendCursorShape(cl, pScreen)
((CARD32)(b) * ((fmt)->blueMax + 1) >> 16) << (fmt)->blueShift)
static int
EncodeRichCursorData8(buf, fmt, pCursor)
EncodeRichCursorData8(cl, buf, fmt, pCursor)
rfbClientPtr cl;
char *buf;
rfbPixelFormat *fmt;
CursorPtr pCursor;
rfbCursorPtr pCursor;
{
int widthPixels, widthBytes;
int x, y, b;
@ -260,41 +282,42 @@ EncodeRichCursorData8(buf, fmt, pCursor)
pix[1] = (char)RGB48_TO_PIXEL(fmt, pCursor->foreRed, pCursor->foreGreen,
pCursor->foreBlue);
src = (CARD8 *)pCursor->bits->source;
widthPixels = pCursor->bits->width;
widthBytes = PixmapBytePad(widthPixels, 1);
src = (CARD8 *)pCursor->richSource;
widthPixels = pCursor->width;
widthBytes = widthPixels;
for (y = 0; y < pCursor->bits->height; y++) {
for (y = 0; y < pCursor->height; y++) {
for (x = 0; x < widthPixels / 8; x++) {
bitmapByte = src[y * widthBytes + x];
if (screenInfo.bitmapBitOrder == LSBFirst) {
/*if (screenInfo.bitmapBitOrder == LSBFirst) {
bitmapByte = _reverse_byte[bitmapByte];
}
}*/
for (b = 7; b >= 0; b--) {
*buf++ = pix[bitmapByte >> b & 1];
}
}
if (widthPixels % 8) {
bitmapByte = src[y * widthBytes + x];
if (screenInfo.bitmapBitOrder == LSBFirst) {
/*if (screenInfo.bitmapBitOrder == LSBFirst) {
bitmapByte = _reverse_byte[bitmapByte];
}
}*/
for (b = 7; b > 7 - widthPixels % 8; b--) {
*buf++ = pix[bitmapByte >> b & 1];
}
}
}
return (widthPixels * pCursor->bits->height);
return (widthPixels * pCursor->height);
}
#define DEFINE_RICH_ENCODE(bpp) \
\
static int \
EncodeRichCursorData##bpp(buf, fmt, pCursor) \
EncodeRichCursorData##bpp(cl, buf, fmt, pCursor) \
rfbClientPtr cl; \
char *buf; \
rfbPixelFormat *fmt; \
CursorPtr pCursor; \
rfbCursorPtr pCursor; \
{ \
int widthPixels, widthBytes; \
int x, y, b; \
@ -308,21 +331,21 @@ EncodeRichCursorData##bpp(buf, fmt, pCursor) \
pix[1] = (CARD##bpp)RGB48_TO_PIXEL(fmt, pCursor->foreRed, \
pCursor->foreGreen, \
pCursor->foreBlue); \
if (!rfbServerFormat.bigEndian != !fmt->bigEndian) { \
if (!cl->screen->rfbServerFormat.bigEndian != !fmt->bigEndian) { \
pix[0] = Swap##bpp(pix[0]); \
pix[1] = Swap##bpp(pix[1]); \
} \
\
src = (CARD8 *)pCursor->bits->source; \
widthPixels = pCursor->bits->width; \
widthBytes = PixmapBytePad(widthPixels, 1); \
src = (CARD8 *)pCursor->richSource; \
widthPixels = pCursor->width; \
widthBytes = (pCursor->width*bpp)/8; \
\
for (y = 0; y < pCursor->bits->height; y++) { \
for (y = 0; y < pCursor->height; y++) { \
for (x = 0; x < widthPixels / 8; x++) { \
bitmapByte = src[y * widthBytes + x]; \
if (screenInfo.bitmapBitOrder == LSBFirst) { \
/*if (screenInfo.bitmapBitOrder == LSBFirst) { \
bitmapByte = _reverse_byte[bitmapByte]; \
} \
}*/ \
for (b = 7; b >= 0; b--) { \
memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \
sizeof(CARD##bpp)); \
@ -331,9 +354,9 @@ EncodeRichCursorData##bpp(buf, fmt, pCursor) \
} \
if (widthPixels % 8) { \
bitmapByte = src[y * widthBytes + x]; \
if (screenInfo.bitmapBitOrder == LSBFirst) { \
/*if (cl->screen.bitmapBitOrder == LSBFirst) { \
bitmapByte = _reverse_byte[bitmapByte]; \
} \
}*/ \
for (b = 7; b > 7 - widthPixels % 8; b--) { \
memcpy (buf, (char *)&pix[bitmapByte >> b & 1], \
sizeof(CARD##bpp)); \
@ -342,9 +365,208 @@ EncodeRichCursorData##bpp(buf, fmt, pCursor) \
} \
} \
\
return (widthPixels * pCursor->bits->height * (bpp / 8)); \
return (widthPixels * pCursor->height * (bpp / 8)); \
}
DEFINE_RICH_ENCODE(16)
DEFINE_RICH_ENCODE(32)
void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap)
{
int i,t=(width+7)/8*height;
for(i=0;i<t;i++)
bitmap[i]=_reverse_byte[(int)bitmap[i]];
}
rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString)
{
int i,j,w=(width+7)/8;
rfbCursorPtr cursor = (rfbCursorPtr)calloc(1,sizeof(rfbCursor));
char* cp;
unsigned char bit;
cursor->width=width;
cursor->height=height;
//cursor->backRed=cursor->backGreen=cursor->backBlue=0xffff;
cursor->foreRed=cursor->foreGreen=cursor->foreBlue=0xffff;
cursor->source = (char*)calloc(w,height);
for(j=0,cp=cursorString;j<height;j++)
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
if(*cp!=' ') cursor->source[j*w+i/8]|=bit;
if(maskString) {
cursor->mask = (char*)calloc(w,height);
for(j=0,cp=maskString;j<height;j++)
for(i=0,bit=0x80;i<width;i++,bit=(bit&1)?0x80:bit>>1,cp++)
if(*cp!=' ') cursor->mask[j*w+i/8]|=bit;
} else
cursor->mask = rfbMakeMaskForXCursor(width,height,cursor->source);
return(cursor);
}
char* rfbMakeMaskForXCursor(int width,int height,char* source)
{
int i,j,w=(width+7)/8;
char* mask=(char*)calloc(w,height);
unsigned char c;
for(j=0;j<height;j++)
for(i=w-1;i>=0;i--) {
c=source[j*w+i];
if(j>0) c|=source[(j-1)*w+i];
if(j<height-1) c|=source[(j+1)*w+i];
if(i>0 && (c&0x80))
mask[j*w+i-1]|=0x01;
if(i<w-1 && (c&0x01))
mask[j*w+i+1]|=0x80;
mask[j*w+i]|=(c<<1)|c|(c>>1);
}
return(mask);
}
void rfbFreeCursor(rfbCursorPtr cursor)
{
if(cursor) {
free(cursor->source);
free(cursor->mask);
free(cursor);
}
}
/* background and foregroud colour have to be set beforehand */
void MakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
{
rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8,
width=cursor->width*bpp;
CARD32 background;
char *back=(char*)&background;
unsigned char bit;
cursor->source=(char*)calloc(w,cursor->height);
if(format->bigEndian)
back+=4-bpp;
background=cursor->backRed<<format->redShift|
cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
for(j=0;j<cursor->height;j++)
for(i=0,bit=0x80;i<cursor->width;i++,bit=(bit&1)?0x80:bit>>1)
if(memcmp(cursor->richSource+j*width+i*bpp,back,bpp))
cursor->source[j*w+i/8]|=bit;
}
void MakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor)
{
rfbPixelFormat* format=&rfbScreen->rfbServerFormat;
int i,j,w=(cursor->width+7)/8,bpp=format->bitsPerPixel/8;
CARD32 background,foreground;
char *cp,*back=(char*)&background,*fore=(char*)&foreground;
unsigned char bit;
cp=cursor->richSource=(char*)calloc(cursor->width*bpp,cursor->height);
if(format->bigEndian) {
back+=4-bpp;
fore+=4-bpp;
}
background=cursor->backRed<<format->redShift|
cursor->backGreen<<format->greenShift|cursor->backBlue<<format->blueShift;
foreground=cursor->foreRed<<format->redShift|
cursor->foreGreen<<format->greenShift|cursor->foreBlue<<format->blueShift;
for(j=0;j<cursor->height;j++)
for(i=0,bit=0x80;i<cursor->height;i++,bit=(bit&1)?0x80:bit>>1,cp+=bpp)
if(cursor->source[j*w+i/8]&bit) memcpy(cp,fore,bpp);
else memcpy(cp,back,bpp);
}
void rfbUndrawCursor(rfbClientPtr cl)
{
rfbScreenInfoPtr s=cl->screen;
rfbCursorPtr c=s->cursor;
int j,x1,x2,y1,y2,bpp=s->rfbServerFormat.bitsPerPixel/8,
rowstride=s->paddedWidthInBytes;
if(!s->cursorIsDrawn)
return;
/* restore what is under the cursor */
x1=s->cursorX-c->xhot;
x2=x1+c->width;
if(x1<0) x1=0;
if(x2>=s->width) x2=s->width-1;
x2-=x1;
y1=s->cursorY-c->yhot;
y2=y1+c->height;
if(y1<0) y1=0;
if(y2>=s->height) y2=s->height-1;
y2-=y1;
for(j=0;j<y2;j++)
memcpy(s->frameBuffer+(y1+j)*rowstride+x1*bpp,
s->underCursorBuffer+j*x2*bpp,
x2*bpp);
}
void rfbDrawCursor(rfbClientPtr cl)
{
rfbScreenInfoPtr s=cl->screen;
rfbCursorPtr c=s->cursor;
int i,j,x1,x2,y1,y2,i1,j1,bpp=s->rfbServerFormat.bitsPerPixel/8,
rowstride=s->paddedWidthInBytes,
bufSize=c->width*c->height*bpp,w=(c->width+7)/8;
if(s->cursorIsDrawn)
rfbUndrawCursor(cl);
if(s->underCursorBufferLen<bufSize) {
if(s->underCursorBuffer!=NULL)
free(s->underCursorBuffer);
s->underCursorBuffer=malloc(bufSize);
s->underCursorBufferLen=bufSize;
}
/* save what is under the cursor */
i1=j1=0; /* offset in cursor */
x1=s->cursorX-c->xhot;
x2=x1+c->width;
if(x1<0) { i1=-x1; x1=0; }
if(x2>=s->width) x2=s->width-1;
x2-=x1;
y1=s->cursorY-c->yhot;
y2=y1+c->height;
if(y1<0) { j1=-y1; y1=0; }
if(y2>=s->height) y2=s->height-1;
y2-=y1;
for(j=0;j<y2;j++)
memcpy(s->underCursorBuffer+j*x2*bpp,
s->frameBuffer+(y1+j)*rowstride+x1*bpp,
x2*bpp);
if(!c->richSource)
MakeRichCursorFromXCursor(s,c);
/* now the cursor has to be drawn */
for(j=0;j<y2;j++)
for(i=0;i<x2;i++)
if((c->mask[(j+j1)*w+(i+i1)/8]<<((i+i1)&7))&0x80)
memcpy(s->frameBuffer+(j+y1)*rowstride+(i+x1)*bpp,
c->richSource+(j+j1)*c->width*bpp+(i+i1)*bpp,bpp);
}
void rfbPrintXCursor(rfbCursorPtr cursor)
{
int i,i1,j,w=(cursor->width+7)/8;
unsigned char bit;
for(j=0;j<cursor->height;j++) {
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
if(cursor->source[j*w+i]&bit) putchar('#'); else putchar(' ');
putchar(':');
for(i=0,i1=0,bit=0x80;i1<cursor->width;i1++,i+=(bit&1)?1:0,bit=(bit&1)?0x80:bit>>1)
if(cursor->mask[j*w+i]&bit) putchar('#'); else putchar(' ');
putchar('\n');
}
}

@ -68,6 +68,11 @@ void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,i
{
int i,j;
i=x1-x2; j=y1-y2;
if(i==0 && j==0) {
for(i=0;i<bpp;i++)
buffer[y1*rowstride+x1*bpp+i]=0xff;
return;
}
if(i<0) i=-i;
if(j<0) j=-j;
if(i<j) {
@ -89,7 +94,8 @@ void drawline(unsigned char* buffer,int rowstride,int bpp,int x1,int y1,int x2,i
void doptr(int buttonMask,int x,int y,rfbClientPtr cl)
{
ClientData* cd=cl->clientData;
if(buttonMask && x>=0 && y>=0 && x<maxx && y<maxy) {
if(x>=0 && y>=0 && x<maxx && y<maxy) {
if(buttonMask) {
int i,j,x1,x2,y1,y2;
if(cd->oldButton==buttonMask) { /* draw a line */
@ -115,6 +121,7 @@ void doptr(int buttonMask,int x,int y,rfbClientPtr cl)
cd->oldButton=0;
cd->oldx=x; cd->oldy=y; cd->oldButton=buttonMask;
}
}
/* aux function to draw a character to x, y */
@ -196,6 +203,24 @@ void dokey(Bool down,KeySym key,rfbClientPtr cl)
}
}
/*
extern void rfbPrintXCursor(rfbCursorPtr cursor);
int exampleCursorWidth=9,exampleCursorHeight=7;
char exampleCursor[]=
" "
" xx xx "
" xx xx "
" xxx "
" xx xx "
" xx xx "
" ";
rfbCursorPtr exampleCurse;
rfbCursorPtr exampleGetCursor(rfbClientPtr cl)
{
return(exampleCurse);
}
*/
/* Initialization */
int main(int argc,char** argv)
@ -211,8 +236,31 @@ int main(int argc,char** argv)
rfbScreen->httpDir = "./classes";
initBuffer(rfbScreen->frameBuffer);
drawstring(rfbScreen->frameBuffer,maxx*bpp,bpp,20,100,"Hello, World!");
drawstring(rfbScreen->frameBuffer,maxx*bpp,bpp,20,100,"Hallo, Welt!");
//exampleCurse = rfbMakeXCursor(exampleCursorWidth,exampleCursorHeight,exampleCursor,0);
{
int i,j,w=32,h=32;
rfbCursorPtr c = rfbScreen->cursor;
char x[32*32],mask[32*32/8];
c=rfbScreen->cursor = rfbMakeXCursor(w,h,x,mask);
c->mask[0]=0xff; c->mask[1]=0x0;
memset(c->mask,255,h*w/8);
c->richSource = malloc(w*h*bpp);
for(j=0;j<h;j++) {
for(i=0;i<w;i++) {
c->richSource[j*w*bpp+i*bpp+0]=0;
c->richSource[j*w*bpp+i*bpp+1]=0;
c->richSource[j*w*bpp+i*bpp+2]=j*0xff/h;
c->richSource[j*w*bpp+i*bpp+3]=0;
}
c->richSource[j*w*bpp+(w-1)*bpp+0]=0xff;
c->richSource[j*w*bpp+(w-1)*bpp+1]=0xff;
c->richSource[j*w*bpp+(w-1)*bpp+2]=0xff;
c->richSource[j*w*bpp+(w-1)*bpp+3]=0xff;
}
//memset(c->richSource,0xff,w*h*bpp);
}
/* this is the blocking event loop, i.e. it never returns */
/* 40000 are the microseconds, i.e. 0.04 seconds */

@ -31,6 +31,8 @@
#include <fcntl.h>
#include <errno.h>
#include <pwd.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "rfb.h"
@ -99,7 +101,7 @@ httpInitSockets(rfbScreenInfoPtr rfbScreen)
void
httpCheckFds(rfbScreenInfoPtr rfbScreen)
{
int nfds, n;
int nfds;
fd_set fds;
struct timeval tv;
struct sockaddr_in addr;

@ -37,6 +37,7 @@
#endif
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include "rfb.h"
@ -93,8 +94,16 @@ void rfbMarkRectAsModified(rfbScreenInfoPtr rfbScreen,int x1,int y1,int x2,int y
RegionRec region;
int i;
if(x1>x2) { i=x1; x1=x2; x2=i; }
x2++;
if(x1<0) { x1=0; if(x2==x1) x2++; }
if(x2>=rfbScreen->width) { x2=rfbScreen->width-1; if(x1==x2) x1--; }
if(y1>y2) { i=y1; y1=y2; y2=i; }
box.x1=x1; box.y1=y1; box.x2=x2+1; box.y2=y2+1;
y2++;
if(y1<0) { y1=0; if(y2==y1) y2++; }
if(y2>=rfbScreen->height) { y2=rfbScreen->height-1; if(y1==y2) y1--; }
box.x1=x1; box.y1=y1; box.x2=x2; box.y2=y2;
REGION_INIT(cl->screen,&region,&box,0);
rfbMarkRegionAsModified(rfbScreen,&region);
}
@ -295,6 +304,38 @@ void defaultSetXCutText(char* text, int len, rfbClientPtr cl)
{
}
static rfbCursor myCursor =
{
//width: 8, height: 7, xhot: 3, yhot: 3,
width: 8, height: 7, xhot: 0, yhot: 0,
//source: "\000\102\044\030\044\102\000",
//mask: "\347\347\176\074\176\347\347",
source: "\000\074\176\146\176\074\000",
mask: "\176\377\377\377\377\377\176",
foreRed: 0, foreGreen: 0, foreBlue: 0,
backRed: 0xffff, backGreen: 0xffff, backBlue: 0xffff,
#define D "\000\000\000\000"
#define R "\377\000\000\000"
#define G "\000\377\000\000"
#define B "\000\000\377\000"
#define S "\377\377\000\000"
#define H "\000\377\377\000"
#define C "\377\000\377\000"
richSource: 0
/*D D D D D D D D
D D R R R R D D
D S S S S S S D
D G G D D G G D
D H H H H H H D
D D B B B B D D
D D D D D D D D*/
};
rfbCursorPtr defaultGetCursorPtr(rfbClientPtr cl)
{
return(cl->screen->cursor);
}
void doNothingWithClient(rfbClientPtr cl)
{
}
@ -348,14 +389,11 @@ rfbScreenInfoPtr rfbDefaultScreenInit(int argc,char** argv,int width,int height,
rfbScreen->rfbServerFormat.redShift = bitsPerSample * 2;
rfbScreen->rfbServerFormat.greenShift = bitsPerSample;
rfbScreen->rfbServerFormat.blueShift = 0;
fprintf(stderr,"format: %d %d %d %d %d %d\n",
rfbScreen->rfbServerFormat.redMax,
rfbScreen->rfbServerFormat.greenMax,
rfbScreen->rfbServerFormat.blueMax,
rfbScreen->rfbServerFormat.redShift,
rfbScreen->rfbServerFormat.greenShift,
rfbScreen->rfbServerFormat.blueShift);
rfbScreen->cursorIsDrawn = FALSE;
rfbScreen->dontSendFramebufferUpdate = FALSE;
rfbScreen->cursorX=rfbScreen->cursorY=rfbScreen->underCursorBufferLen=0;
rfbScreen->underCursorBuffer=NULL;
/* We want to use the X11 REGION_* macros without having an actual
X11 ScreenPtr, so we do this. Pretty ugly, but at least it lets us
@ -384,6 +422,8 @@ fprintf(stderr,"format: %d %d %d %d %d %d\n",
rfbScreen->kbdReleaseAllKeys = doNothingWithClient;
rfbScreen->ptrAddEvent = defaultPtrAddEvent;
rfbScreen->setXCutText = defaultSetXCutText;
rfbScreen->getCursorPtr = defaultGetCursorPtr;
rfbScreen->cursor = &myCursor;
rfbScreen->newClientHook = doNothingWithClient;
return(rfbScreen);

32
rfb.h

@ -23,6 +23,8 @@
* USA.
*/
#include <stdlib.h>
#include <string.h>
#include "scrnintstr.h"
/* trying to replace the above with some more minimal set of includes */
@ -60,12 +62,14 @@
#endif
struct rfbClientRec;
//typedef struct rfbClientInfo* rfbClientPtr;
struct rfbScreenInfo;
struct rfbCursor;
typedef void (*KbdAddEventProcPtr) (Bool down, KeySym keySym, struct rfbClientRec* cl);
typedef void (*KbdReleaseAllKeysProcPtr) (struct rfbClientRec* cl);
typedef void (*PtrAddEventProcPtr) (int buttonMask, int x, int y, struct rfbClientRec* cl);
typedef void (*SetXCutTextProcPtr) (char* str,int len, struct rfbClientRec* cl);
typedef struct rfbCursor* (*GetCursorProcPtr) (struct rfbClientRec* pScreen);
typedef void (*NewClientHookPtr)(struct rfbClientRec* cl);
/*
@ -126,6 +130,10 @@ typedef struct
Bool dontSendFramebufferUpdate; /* TRUE while removing or drawing the
cursor */
/* these variables are needed to save the area under the cursor */
int cursorX, cursorY,underCursorBufferLen;
char* underCursorBuffer;
/* wrapped screen functions */
CloseScreenProcPtr CloseScreen;
@ -167,6 +175,7 @@ typedef struct
Bool rfbNeverShared;
Bool rfbDontDisconnect;
struct rfbClientRec* rfbClientHead;
struct rfbCursor* cursor;
/* the following members have to be supplied by the serving process */
char* frameBuffer;
@ -174,6 +183,7 @@ typedef struct
KbdReleaseAllKeysProcPtr kbdReleaseAllKeys;
PtrAddEventProcPtr ptrAddEvent;
SetXCutTextProcPtr setXCutText;
GetCursorProcPtr getCursorPtr;
/* the following members are hooks, i.e. they are called if set,
but not overriding original functionality */
@ -513,8 +523,22 @@ extern Bool rfbSendRectEncodingTight(rfbClientPtr cl, int x,int y,int w,int h);
/* cursor.c */
extern Bool rfbSendCursorShape(rfbClientPtr cl, ScreenPtr pScreen);
typedef struct rfbCursor {
unsigned char *source; /* points to bits */
unsigned char *mask; /* points to bits */
unsigned short width, height, xhot, yhot; /* metrics */
unsigned short foreRed, foreGreen, foreBlue; /* device-independent color */
unsigned short backRed, backGreen, backBlue; /* device-independent color */
unsigned char *richSource; /* source bytes for a rich cursor */
} rfbCursor, *rfbCursorPtr;
extern Bool rfbSendCursorShape(rfbClientPtr cl/*, rfbScreenInfoPtr pScreen*/);
extern void rfbConvertLSBCursorBitmapOrMask(int width,int height,unsigned char* bitmap);
extern rfbCursorPtr rfbMakeXCursor(int width,int height,char* cursorString,char* maskString);
extern char* rfbMakeMaskForXCursor(int width,int height,char* cursorString);
extern void MakeXCursorFromRichCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor);
extern void MakeRichCursorFromXCursor(rfbScreenInfoPtr rfbScreen,rfbCursorPtr cursor);
extern void rfbFreeCursor(rfbCursorPtr cursor);
/* stats.c */

@ -221,6 +221,7 @@ rfbNewClient(rfbScreen,sock)
cl->zsActive[i] = FALSE;
cl->enableCursorShapeUpdates = FALSE;
cl->useRichCursorEncoding = FALSE;
cl->enableLastRectEncoding = FALSE;
rfbResetStats(cl);
@ -630,17 +631,14 @@ rfbProcessClientNormalMessage(cl)
rfbLog("Enabling X-style cursor updates for client %s\n",
cl->host);
cl->enableCursorShapeUpdates = TRUE;
cl->useRichCursorEncoding = FALSE;
cl->cursorWasChanged = TRUE;
break;
case rfbEncodingRichCursor:
if (!cl->enableCursorShapeUpdates) {
rfbLog("Enabling full-color cursor updates for client "
"%s\n", cl->host);
cl->enableCursorShapeUpdates = TRUE;
cl->useRichCursorEncoding = TRUE;
cl->cursorWasChanged = TRUE;
}
break;
case rfbEncodingLastRect:
if (!cl->enableLastRectEncoding) {
@ -829,23 +827,24 @@ rfbSendFramebufferUpdate(cl, updateRegion)
RegionRec updateCopyRegion;
int dx, dy;
Bool sendCursorShape = FALSE;
Bool cursorWasDrawn = FALSE;
/*
* If this client understands cursor shape updates, cursor should be
* removed from the framebuffer. Otherwise, make sure it's put up.
*/
#ifdef NOT_YET
if (cl->enableCursorShapeUpdates) {
if (cl->screen->cursorIsDrawn)
rfbSpriteRemoveCursor(pScreen);
cursorWasDrawn = cl->screen->cursorIsDrawn;
if (cl->screen->cursorIsDrawn) {
fprintf(stderr,"rfbSpriteRemoveCursor(pScreen); not yet!\n");
}
if (!cl->screen->cursorIsDrawn && cl->cursorWasChanged)
sendCursorShape = TRUE;
} else {
if (!cl->screen->cursorIsDrawn)
rfbSpriteRestoreCursor(pScreen);
fprintf(stderr,"rfbSpriteRestoreCursor(pScreen); not yet!\n");
}
#endif
/*
* The modifiedRegion may overlap the destination copyRegion. We remove
@ -976,13 +975,11 @@ rfbSendFramebufferUpdate(cl, updateRegion)
}
cl->ublen = sz_rfbFramebufferUpdateMsg;
#ifdef NOT_YET
if (sendCursorShape) {
cl->cursorWasChanged = FALSE;
if (!rfbSendCursorShape(cl, pScreen))
if (!rfbSendCursorShape(cl))
return FALSE;
}
#endif
if (REGION_NOTEMPTY(pScreen,&updateCopyRegion)) {
if (!rfbSendCopyRegion(cl,&updateCopyRegion,dx,dy)) {
@ -1047,6 +1044,13 @@ rfbSendFramebufferUpdate(cl, updateRegion)
if (!rfbSendUpdateBuf(cl))
return FALSE;
if(cursorWasDrawn != cl->screen->cursorIsDrawn) {
if(cursorWasDrawn)
fprintf(stderr,"rfbSpriteRestoreCursor(pScreen); not yet!!\n");
else
fprintf(stderr,"rfbSpriteRemoveCursor(pScreen); not yet!!\n");
}
return TRUE;
}

@ -57,6 +57,7 @@ struct timeval
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <arpa/inet.h>
#include "rfb.h"

@ -235,8 +235,6 @@ rfbSendRectEncodingZlib(cl, x, y, w, h)
rfbClientPtr cl;
int x, y, w, h;
{
int totalSize = 0;
int partialSize = 0;
int maxLines;
int linesRemaining;
rfbRectangle partialRect;

Loading…
Cancel
Save