Commit 1e83d9a5 authored by dscho's avatar dscho

cleaned up warnings, cursor changes

parent febced55
......@@ -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
......
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
-------
......
.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
This diff is collapsed.
......@@ -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,32 +94,34 @@ 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) {
int i,j,x1,x2,y1,y2;
if(cd->oldButton==buttonMask) { /* draw a line */
drawline(cl->screen->frameBuffer,cl->screen->paddedWidthInBytes,bpp,
x,y,cd->oldx,cd->oldy);
rfbMarkRectAsModified(cl->screen,x,y,cd->oldx,cd->oldy);
} else { /* draw a point (diameter depends on button) */
x1=x-buttonMask; if(x1<0) x1=0;
x2=x+buttonMask; if(x2>maxx) x2=maxx;
y1=y-buttonMask; if(y1<0) y1=0;
y2=y+buttonMask; if(y2>maxy) y2=maxy;
for(i=x1*bpp;i<x2*bpp;i++)
for(j=y1;j<y2;j++)
cl->screen->frameBuffer[j*cl->screen->paddedWidthInBytes+i]=0xff;
rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1);
}
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 */
drawline(cl->screen->frameBuffer,cl->screen->paddedWidthInBytes,bpp,
x,y,cd->oldx,cd->oldy);
rfbMarkRectAsModified(cl->screen,x,y,cd->oldx,cd->oldy);
} else { /* draw a point (diameter depends on button) */
x1=x-buttonMask; if(x1<0) x1=0;
x2=x+buttonMask; if(x2>maxx) x2=maxx;
y1=y-buttonMask; if(y1<0) y1=0;
y2=y+buttonMask; if(y2>maxy) y2=maxy;
/* we could get a selection like that:
rfbGotXCutText(cl->screen,"Hallo",5);
*/
} else
cd->oldButton=0;
for(i=x1*bpp;i<x2*bpp;i++)
for(j=y1;j<y2;j++)
cl->screen->frameBuffer[j*cl->screen->paddedWidthInBytes+i]=0xff;
rfbMarkRectAsModified(cl->screen,x1,y1,x2-1,y2-1);
}
cd->oldx=x; cd->oldy=y; cd->oldButton=buttonMask;
/* we could get a selection like that:
rfbGotXCutText(cl->screen,"Hallo",5);
*/
} else
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,15 +389,12 @@ 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
avoid hacking up regionstr.h, or changing every call to REGION_*
......@@ -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);
......
......@@ -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);
/*
......@@ -125,7 +129,11 @@ typedef struct
Bool cursorIsDrawn; /* TRUE if the cursor is currently drawn */
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,14 +175,16 @@ 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;
KbdAddEventProcPtr kbdAddEvent;
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 */
/* newClientHook is called just after a new client is created */
......@@ -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,18 +631,15 @@ 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;
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) {
rfbLog("Enabling LastRect protocol extension for client "
......@@ -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);
if (!cl->screen->cursorIsDrawn && cl->cursorWasChanged)
sendCursorShape = TRUE;
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);
if (!cl->screen->cursorIsDrawn)
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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment