Source of x11vnc.c
void init_keycodes()
void clientGone(rfbClientPtr cl)
enum rfbNewClientAction newClient(rfbClientPtr cl)
void tweakModifiers(char mod, Bool down)
void keyboard(Bool down, KeySym keySym, rfbClientPtr cl)
int open_control_file(single_instance_struct* str)
void delete_control_file(single_instance_struct* str)
void close_control_file(single_instance_struct* str)
int get_next_message(char* buffer,int len,single_instance_struct* str,int usecs)
int dispatch_event(single_instance_struct* str,event_dispatcher dispatcher,int usecs)
int loop_if_server(single_instance_struct* str,event_dispatcher dispatcher)
void send_message(single_instance_struct* str,char* message)
void my_dispatcher(char* message)
int main(int argc,char** argv)
int main(int argc, char** argv)
/* x11vnc.c -- a small clone of x0rfbserver by HexoNet, demonstrating the capabilities of LibVNCServer. */
/* Modified by rj@elilabs.com 15-Oct-2002 to tidy up source formatting and add comments. */
#include <X11/Xlib.h>
#include <X11/keysym.h>
#include <X11/extensions/XTest.h>
#ifndef NO_SHM
#include <X11/extensions/XShm.h>
#include <sys/shm.h>
#endif
#define KEYSYM_H
#undef Bool
#define KeySym RFBKeySym
#include "rfb.h"
#define min(i, j) ((i) < (j) ? (i) : (j)) /* return the minimum of 2 numbers */
Display* dpy = 0;
int window;
int c = 0;
int blockLength = 32;
int tileX = 0;
int tileY = 0;
int tileWidth = 32;
int tileHeight = 32*2;
int dontTile = TRUE;
Bool gotInput = FALSE;
Bool viewOnly = FALSE;
Bool sharedMode = FALSE;
Bool disconnectAfterFirstClient = TRUE;
/* keyboard handling */
#define KBDDEBUG
char modifiers[0x100];
KeyCode keycodes[0x100];
KeyCode leftShiftCode;
KeyCode rightShiftCode;
KeyCode altGrCode;
void init_keycodes() { /* keyboard initialization stuff */
KeySym key;
KeySym *keymap;
int i;
int j;
int minkey;
int maxkey;
int syms_per_keycode;
memset(modifiers, -1, sizeof(modifiers));
XDisplayKeycodes(dpy, &minkey, &maxkey);
keymap = XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1), &syms_per_keycode);
#ifdef KBDDEBUG
fprintf(stderr, "minkey=%d, maxkey=%d, syms_per_keycode=%d\n", minkey, maxkey, syms_per_keycode);
#endif
for (i = minkey; i <= maxkey; i++) {
for (j = 0; j < syms_per_keycode; j++) {
key = keymap[(i - minkey)*syms_per_keycode + j];
#ifdef KBDDEBUG
fprintf(stderr, "keymap(i=0x%x, j=%d)==0x%lx\n", i, j, key);
#endif
if (key >= ' ' && key < 0x100 && i == XKeysymToKeycode(dpy, key)) {
keycodes[key] = i;
modifiers[key] = j;
#ifdef KBDDEBUG
fprintf(stderr, "key 0x%lx (%c): keycode=0x%x, modifier=%d\n", key, (char)key, i, j);
#endif
}
}
}
leftShiftCode = XKeysymToKeycode(dpy, XK_Shift_L);
rightShiftCode = XKeysymToKeycode(dpy, XK_Shift_R);
altGrCode = XKeysymToKeycode(dpy, XK_Mode_switch);
#ifdef KBDDEBUG
fprintf(stderr, "leftShift=0x%x, rightShift=0x%x, altGr=0x%x\n", leftShiftCode, rightShiftCode, altGrCode);
#endif
XFree ((char*) keymap);
}
static Bool shutDownServer = 0;
/* the hooks */
void clientGone(rfbClientPtr cl) {
shutDownServer = -1;
}
enum rfbNewClientAction newClient(rfbClientPtr cl) {
if (disconnectAfterFirstClient) {
cl->clientGoneHook = clientGone;
}
if (viewOnly) {
cl->clientData = (void*)-1;
} else {
cl->clientData = (void*)0;
}
return(RFB_CLIENT_ACCEPT);
}
#define LEFTSHIFT 1
#define RIGHTSHIFT 2
#define ALTGR 4
char ModifierState = 0;
/* This function adjusts the modifiers according to mod (as from modifiers) and ModifierState. */
void tweakModifiers(char mod, Bool down) {
Bool isShift = ModifierState & (LEFTSHIFT | RIGHTSHIFT);
#ifdef KBDDEBUG
fprintf(stderr, "tweakModifiers: 0x%x %s\n", mod, down?"down":"up");
#endif
if (mod < 0) {
return;
}
if (isShift && mod != 1) {
if (ModifierState & LEFTSHIFT) {
XTestFakeKeyEvent(dpy, leftShiftCode, !down, CurrentTime);
}
if (ModifierState & RIGHTSHIFT) {
XTestFakeKeyEvent(dpy, rightShiftCode, !down, CurrentTime);
}
}
if (!isShift && mod == 1) {
XTestFakeKeyEvent(dpy, leftShiftCode, down, CurrentTime);
}
if (ModifierState & ALTGR && mod != 2) {
XTestFakeKeyEvent(dpy, altGrCode, !down, CurrentTime);
}
if (!(ModifierState & ALTGR) && mod == 2) {
XTestFakeKeyEvent(dpy, altGrCode, down, CurrentTime);
}
}
void keyboard(Bool down, KeySym keySym, rfbClientPtr cl) {
if ((int)(cl->clientData) == -1) {
return; /* viewOnly */
}
#define ADJUSTMOD(sym, state) \
if (keySym == sym) { \
if (down) { \
ModifierState |= state; \
} else { \
ModifierState &= ~state; \
} \
}
ADJUSTMOD(XK_Shift_L, LEFTSHIFT)
ADJUSTMOD(XK_Shift_R, RIGHTSHIFT)
ADJUSTMOD(XK_Mode_switch, ALTGR)
#ifdef KBDDEBUG
fprintf(stderr, "keyboard: down=%s, keySym=0x%lx (%s), ModState=0x%x\n",
down ? "down" : "up", keySym, XKeysymToString(keySym), ModifierState);
#endif
if (keySym >= ' ' && keySym < 0x100) {
KeyCode k;
if (down) {
tweakModifiers(modifiers[keySym], True);
}
k = keycodes[keySym];
if (k != NoSymbol) {
XTestFakeKeyEvent(dpy, k, down, CurrentTime);
gotInput = TRUE;
}
if (down) {
tweakModifiers(modifiers[keySym], False);
}
gotInput = TRUE;
} else {
KeyCode k = XKeysymToKeycode(dpy, keySym);
if (k != NoSymbol) {
XTestFakeKeyEvent(dpy, k, down, CurrentTime);
gotInput = TRUE;
}
}
}
void mouse( /* update real X-server with vncviewer's mouse data */
int buttonMask, /* state of remote mouse buttons */
int x, /* remote mouse x position */
int y, /* remote mouse y position */
rfbClientPtr cl) { /* the client vncviewer's state vector */
static int oldButtonMask = 0; /* remember previous button status */
int m; /* mask for a single mouse button */
int i; /* loop index */
if ((int)cl->clientData == -1) { /* view only -- remote cannot control? */
return; /* yes, skip setting mouse data */
}
XTestFakeMotionEvent(dpy, /* stuff remote mouse data into real X-server */
0, /* should this be -1 for multi-headed displays? */
x,
y,
CurrentTime);
for (i = 0, /* for each button on the remote mouse */
m = 1;
i < 5;
i++,
m <<= 1) {
if ((oldButtonMask & m) != (buttonMask & m)) { /* has button changed since we last looked at it? */
XTestFakeButtonEvent(dpy, /* yes, stuff new button data into X-server */
i + 1,
(buttonMask & m) ? True : False,
CurrentTime);
}
}
oldButtonMask = buttonMask; /* remember button status for next time */
gotInput = TRUE; /* flag that we got some new input */
}
/* the X11 interaction */
#ifndef NO_SHM
Bool useSHM = TRUE;
XShmSegmentInfo shminfo;
#else
Bool useSHM = FALSE;
#endif
void getImage( /* get an X11 display image, shared or not */
int bpp, /* bits per pexel */
Display* dpy, /* the X display */
int xscreen, /* and screen */
XImage** i, /* the X11 image */
int x, /* its location */
int y,
int width, /* and size */
int height) {
if (width <= 0) { /* set display width and height if not already set */
width = DisplayWidth(dpy, xscreen);
}
if (height <= 0) {
height=DisplayHeight(dpy, xscreen);
}
if (useSHM && bpp > 0) { /* if using X11 MIT shared memory extension */
static Bool firstTime = TRUE; /* initialize first time thru */
if (firstTime) {
firstTime = FALSE;
*i = XShmCreateImage(dpy, /* try to create an X11 shared memory image */
DefaultVisual(dpy, xscreen),
bpp,
ZPixmap,
NULL,
&shminfo,
width, height);
if (*i == 0) { /* if could not create shared memory image */
useSHM = FALSE; /* say no shared memory */
getImage(bpp, /* and try again */
dpy,
xscreen,
i,
x,
y,
width,
height);
return;
}
shminfo.shmid = shmget(IPC_PRIVATE, /* now get the data that is there from the shared memory */
(*i)->bytes_per_line * (*i)->height,
IPC_CREAT | 0777);
shminfo.shmaddr = (*i)->data /* set the shared memory address */
= (char *) shmat(shminfo.shmid, 0, 0);
shminfo.readOnly = False; /* read-write mode */
XShmAttach(dpy, &shminfo); /* hook it up and make it live! */
}
if (x == 0 /* full screen request? */
&& y == 0
&& width == DisplayWidth(dpy, xscreen)
&& height == DisplayHeight(dpy, xscreen)) {
XShmGetImage(dpy, /* yes, get the whole shared image */
window,
*i,
0,
0,
AllPlanes);
} else {
XGetSubImage(dpy, /* no, just get a sub-image (FIXME Not shared?) */
window,
x,
y,
width,
height,
AllPlanes,
ZPixmap,
*i,
0,
0);
}
} else { /* not using X11 MIT shared memory extension at all */
*i = XGetImage(dpy, /* just get it the slow way (FIXME How about subimages?) */
window,
x,
y,
width,
height,
AllPlanes,
ZPixmap);
}
}
void checkForImageUpdates(
rfbScreenInfoPtr s, /* the live X-server's framebuffer, et al */
char* b, /* our saved framebuffer */
int rowstride, /* width of a row in bytes */
int x, /* position */
int y,
int width, /* and size */
int height) {
Bool changed; /* changed flag */
int i; /* horiz index */
int j; /* vert index */
int k; /* byte index for compare loop */
int l1; /* location 1 -- offset in our saved framebuffer */
int l2; /* location 2 -- offset in original X-server frame buffer */
int x1; /* horiz end of region of interest */
int y1; /* vert end of region of interest */
int bpp = s->bitsPerPixel/8;
for (j = 0; j < height; j += blockLength) { /* vertical scan loop by blocks */
for (i = 0; i < width; i += blockLength) { /* horiz scan loop by blocks */
y1 = min(j + blockLength, height); /* bottom of block */
x1 = min(i + blockLength, width); /* right edge of block (blocks are square, so height == width) */
y1 *= rowstride; /* width of an entire row in bytes */
x1 *= bpp; /* bytes per pixel */
changed = FALSE; /* TRUE if anything has changed since last scan */
for (l1 = j*rowstride, /* sweep vertically thru a block */
l2 = (j + y)*(s->paddedWidthInBytes) + x*bpp;
(l1 < y1) && !changed;
l1 += rowstride,
l2 += s->paddedWidthInBytes) {
for (k = i*bpp; (k < x1) && !changed; k++) { /* sweep horizontally thru a block */
if (s->frameBuffer[l2 + k] != b[l1 + k]) { /* different? */
changed=TRUE; /* yes, say so! */
}
}
}
if (changed) { /* was anything different? */
for (l1 += i*bpp - rowstride, /* yes */
l2 += i*bpp - s->paddedWidthInBytes;
l1 < y1;
l1 += rowstride,
l2 += s->paddedWidthInBytes) {
memcpy(s->frameBuffer+l2, b+l1, x1-i*bpp); /* copy new stuff to our private frameBuffer */
}
rfbMarkRectAsModified(s, /* mark it as changed so we can send it to the vncviewer */
x+i,
y+j,
x+i+blockLength,
y+j+blockLength);
}
}
}
}
int probeX;
int probeY;
void probeScreen( /* check X-server for changed and mark changed rectangles */
rfbScreenInfoPtr s, /* the live X-server et al */
int xscreen) { /* the X screen of that server */
int i; /* horizontal loop index */
int j; /* vertical loop index */
int j1; /* row index for buffer copy */
int bpp = s->rfbServerFormat.bitsPerPixel/8; /* bytes per pixel == sizeof(pixel) */
int rstride = s->paddedWidthInBytes; /* row stride -- how wide each full row is in bytes */
XImage* im; /* pointer to the X11 image */
#if 1
probeX++; /* sequential scan */
if(probeX>=tileWidth) {
probeX=0;
probeY++;
if(probeY>=tileHeight) {
probeY=0;
}
}
#else
probeX = rand() % tileWidth; /* random scan */
probeY= rand() % tileHeight;
#endif
for (j = probeY; j < s->height; j += tileHeight) { /* sweep vertically */
for (i = 0 /*probeX*/; i < s->width; i += tileWidth) { /* and horizontally within each vertical sweep */
im = XGetImage(dpy, /* get a live image of the X-server's screen */
window,
i,
j,
tileWidth /*1*/,
1,
AllPlanes,
ZPixmap);
if (memcmp(im->data, /* is the X11 framebuffer different from our old copy? */
s->frameBuffer + i*bpp + j*rstride,
tileWidth*bpp)) {
/* yes, do an update */
int x = i /* -probeX */;
int w = (x + tileWidth > s->width) ? s->width-x : tileWidth;
int y = j - probeY;
int h = (y + tileHeight > s->height) ? s->height-y : tileHeight;
XDestroyImage(im); /* kill the old image */
im = XGetImage(dpy, window, x, y, w, h, AllPlanes, ZPixmap); /* and get a new one */
for (j1 = 0; j1 < h; j1++) { /* save it in our copy of the framebuffer */
memcpy(s->frameBuffer + x*bpp + (y + j1)*rstride,
im->data + j1*im->bytes_per_line,
bpp*w);
}
XDestroyImage(im); /* get rid of live image -- we have our copy now */
rfbMarkRectAsModified(s, x, y, x+w, y+h);
} else {
XDestroyImage(im); /* no differences found, discard framebuffer image */
}
}
}
}
/* #include "1instance.c" */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
typedef struct {
char* filename; /* this file is the pipe (set by user) */
char is_server; /* this is set by open_control_file */
int fd; /* this is set by open_control_file */
} single_instance_struct;
/* returns fd, is_server is set to -1 if server, 0 if client */
int open_control_file(single_instance_struct* str)
{
struct stat buf;
if(stat(str->filename,&buf)) {
mkfifo(str->filename,128|256);
str->is_server=-1;
str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
} else {
str->fd=open(str->filename,O_NONBLOCK|O_WRONLY);
if(errno==ENXIO) {
str->is_server=-1;
str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
} else
str->is_server=0;
}
return(str->fd);
}
void delete_control_file(single_instance_struct* str)
{
remove(str->filename);
}
void close_control_file(single_instance_struct* str)
{
close(str->fd);
}
typedef void (*event_dispatcher)(char* message);
//#if defined(__linux__) && defined(NEED_TIMEVAL)
//struct timeval {
// long int tv_sec,tv_usec;
//};
//#endif
int get_next_message(char* buffer,int len,single_instance_struct* str,int usecs)
{
struct timeval tv;
fd_set fdset;
int num_fds;
FD_ZERO(&fdset);
FD_SET(str->fd,&fdset);
tv.tv_sec=0;
tv.tv_usec=usecs;
num_fds=select(str->fd+1,&fdset,NULL,NULL,&tv);
if(num_fds) {
int reallen;
reallen=read(str->fd,buffer,len);
if(reallen==0) {
close(str->fd);
str->fd=open(str->filename,O_NONBLOCK|O_RDONLY);
num_fds--;
}
buffer[reallen]=0;
#ifdef DEBUG_1INSTANCE
if(reallen!=0) fprintf(stderr,"message received: %s.\n",buffer);
#endif
}
return(num_fds);
}
int dispatch_event(single_instance_struct* str,event_dispatcher dispatcher,int usecs)
{
char buffer[1024];
int num_fds;
if((num_fds=get_next_message(buffer,1024,str,usecs)) && buffer[0])
dispatcher(buffer);
return(num_fds);
}
int loop_if_server(single_instance_struct* str,event_dispatcher dispatcher)
{
open_control_file(str);
if(str->is_server) {
while(1)
dispatch_event(str,dispatcher,50);
}
return(str->fd);
}
void send_message(single_instance_struct* str,char* message)
{
#ifdef DEBUG_1INSTANCE
int i=
#endif
write(str->fd,message,strlen(message));
#ifdef DEBUG_1INSTANCE
fprintf(stderr,"send: %s => %d(%d)\n",message,i,strlen(message));
#endif
}
#ifdef DEBUG_MAIN
#include <stdio.h>
#include <stdlib.h>
single_instance_struct str1 = { "/tmp/1instance" };
void my_dispatcher(char* message)
{
#ifdef DEBUG_1INSTANCE
fprintf(stderr,"Message arrived: %s.\n",message);
#endif
if(!strcmp(message,"quit")) {
delete_control_file(str1);
exit(0);
}
}
int main(int argc,char** argv)
{
int i;
loop_if_server(str1,my_dispatcher);
for(i=1;i<argc;i++)
send_event(str1,argv[i]);
return(0);
}
#endif
/* END OF #include "1instance.c" */
/* ---------------- The Main Program ---------------- */
int main(int argc, char** argv) {
XImage *framebufferImage;
char* backupImage;
int xscreen;
int i;
rfbScreenInfoPtr screen;
int maxMsecsToConnect = 5000; /* a maximum of 5 seconds to connect */
// FIXME maxMsecsToConnect is out of calibration. On linux intel PC, this is 20 sec, not 5 sec. What is wrong?
int updateCounter; /* about every 50 ms a screen update should be made. */
// FIXME Is this a scan of the X-server framebuffer to see if an update needs to be sent to the vncviewer?
char message[1024]; /* message buffer to send to "single_instance" below */
single_instance_struct single_instance = { "/tmp/x11vnc_control" }; /* FIXME what is this? some kind of message passing thing? */
open_control_file(&single_instance);
/* ---------------- Parse The Command Line Arguments In Reverse Order... ---------------- */
for (i = argc - 1; i > 0; i--) { /* for each argument on the command line... */
/* FIXME Each of these options needs to be documented!!! */
if (i < argc - 1 && !strcmp(argv[i], "-toggleviewonly")) { /* -toggleviewonly */
sprintf(message, "t%s", argv[i + 1]);
send_message(&single_instance, message);
exit(0);
} else if (!strcmp(argv[i], "-listclients")) { /* -listclients */
fprintf(stderr, "list clients\n");
send_message(&single_instance, "l");
exit(0);
} else
#ifdef BACKCHANNEL
if (i < argc - 1 && !strcmp(argv[i], "-backchannel")) { /* -backchannel */
sprintf(message, "b%s", argv[i+1]);
send_message(&single_instance, message);
exit(0);
} else
#endif
if (i < argc - 1 && strcmp(argv[i], "-display")==0) { /* -display */
fprintf(stderr, "Using display %s\n", argv[i + 1]);
dpy = XOpenDisplay(argv[i + 1]);
if (dpy == 0) {
fprintf(stderr, "Couldn't connect to display \"%s\".\n", argv[i + 1]);
exit(1);
}
} else if (i < argc - 1 && strcmp(argv[i], "-wait4client") == 0) { /* -wait4client */
maxMsecsToConnect = atoi(argv[i + 1]);
} else if (i < argc - 1 && strcmp(argv[i], "-update") == 0) { /* -update */
updateCounter = atoi(argv[i + 1]);
} else if (strcmp(argv[i], "-noshm") == 0) { /* -noshm */
useSHM = FALSE;
} else if (strcmp(argv[i], "-runforever") == 0) { /* -runforever */
disconnectAfterFirstClient = FALSE;
} else if (strcmp(argv[i], "-tile") == 0) { /* -tile */
dontTile = FALSE;
} else if (strcmp(argv[i], "-viewonly") == 0) { /* viewonly */
viewOnly = TRUE;
} else if (strcmp(argv[i], "-shared") == 0) { /* -shared */
sharedMode = TRUE;
}
}
/* ---------------- End Of Parsing Command Line Arguments ---------------- */
updateCounter = dontTile ? 20 : 1; /* FIXME This overrides the setting of -update */
if (dpy == 0) { /* open default DISPLAY if none already opened */
dpy = XOpenDisplay("");
}
if (dpy == 0) { /* could not open default either */
fprintf(stderr, "Couldn't open display!\n");
exit(2); /* DIE! */
}
xscreen = DefaultScreen(dpy); /* default screen of selected DISPLAY */
window = RootWindow(dpy, xscreen); /* root window of that screen */
init_keycodes(); /* initialize the keyboard */
getImage(0, dpy, xscreen, &framebufferImage, 0, 0, -1, -1); /* get the initial state of the live X-server's framebuffer */
screen = rfbGetScreen(&argc, argv,
framebufferImage->width,
framebufferImage->height,
framebufferImage->bits_per_pixel,
8,
framebufferImage->bits_per_pixel/8);
screen->paddedWidthInBytes = framebufferImage->bytes_per_line;
screen->rfbServerFormat.bitsPerPixel = framebufferImage->bits_per_pixel;
screen->rfbServerFormat.depth = framebufferImage->depth;
// rfbEndianTest = framebufferImage->bitmap_bit_order != MSBFirst;
screen->rfbServerFormat.trueColour = TRUE;
if (screen->rfbServerFormat.bitsPerPixel == 8) {
if (CellsOfScreen(ScreenOfDisplay(dpy, xscreen))) {
XColor color[256];
int i;
screen->colourMap.count = 256;
screen->rfbServerFormat.trueColour = FALSE;
screen->colourMap.is16 = TRUE;
for (i = 0; i < 256; i++) {
color[i].pixel=i;
}
XQueryColors(dpy, DefaultColormap(dpy, xscreen), color, 256);
screen->colourMap.data.shorts = (short*)malloc(3*sizeof(short)*screen->colourMap.count);
for (i = 0; i < screen->colourMap.count; i++) {
screen->colourMap.data.shorts[i*3 + 0] = color[i].red;
screen->colourMap.data.shorts[i*3 + 1] = color[i].green;
screen->colourMap.data.shorts[i*3 + 2] = color[i].blue;
}
} else {
screen->rfbServerFormat.redShift = 0;
screen->rfbServerFormat.greenShift = 2;
screen->rfbServerFormat.blueShift = 5;
screen->rfbServerFormat.redMax = 3;
screen->rfbServerFormat.greenMax = 7;
screen->rfbServerFormat.blueMax = 3;
}
} else {
screen->rfbServerFormat.redShift = 0;
if (framebufferImage->red_mask) {
while (!(framebufferImage->red_mask & (1 << screen->rfbServerFormat.redShift))) {
screen->rfbServerFormat.redShift++;
}
}
screen->rfbServerFormat.greenShift = 0;
if (framebufferImage->green_mask) {
while (!(framebufferImage->green_mask & (1 << screen->rfbServerFormat.greenShift))) {
screen->rfbServerFormat.greenShift++;
}
}
screen->rfbServerFormat.blueShift = 0;
if (framebufferImage->blue_mask) {
while (!(framebufferImage->blue_mask & (1 << screen->rfbServerFormat.blueShift))) {
screen->rfbServerFormat.blueShift++;
}
}
screen->rfbServerFormat.redMax = framebufferImage->red_mask >> screen->rfbServerFormat.redShift;
screen->rfbServerFormat.greenMax = framebufferImage->green_mask >> screen->rfbServerFormat.greenShift;
screen->rfbServerFormat.blueMax = framebufferImage->blue_mask >> screen->rfbServerFormat.blueShift;
}
backupImage = malloc(screen->height*screen->paddedWidthInBytes);
memcpy(backupImage, framebufferImage->data, screen->height*screen->paddedWidthInBytes);
screen->frameBuffer = backupImage;
screen->cursor = 0;
screen->newClientHook = newClient;
screen->kbdAddEvent = keyboard;
screen->ptrAddEvent = mouse;
if (sharedMode) {
screen->rfbAlwaysShared = TRUE;
}
screen->rfbDeferUpdateTime = 1;
updateCounter /= screen->rfbDeferUpdateTime;
rfbInitServer(screen);
c = 0;
for(;;) {
if (screen->rfbClientHead) {
maxMsecsToConnect = 1<<16;
} else {
maxMsecsToConnect -= screen->rfbDeferUpdateTime;
if (maxMsecsToConnect < 0) {
fprintf(stderr, "Maximum time to connect reached. Exiting.\n");
XTestDiscard(dpy);
exit(2);
}
}
if (get_next_message(message, 1024, &single_instance, 50)) {
if (message[0] == 'l' && message[1] == 0) {
rfbClientPtr cl;
int i;
for (i = 0,
cl = screen->rfbClientHead;
cl;
cl = cl->next,
i++) {
fprintf(stderr, "%02d: %s\n", i, cl->host);
}
} else if (message[0] == 't') {
rfbClientPtr cl;
for (cl = screen->rfbClientHead; cl; cl = cl->next) {
if (!strcmp(message+1, cl->host)) {
cl->clientData=(void*)((cl->clientData==0)?-1:0);
break;
}
}
}
#ifdef BACKCHANNEL
else if (message[0]=='b')
rfbSendBackChannel(screen, message+1, strlen(message+1));
#endif
}
rfbProcessEvents(screen, -1);
if (shutDownServer) {
free(backupImage);
rfbScreenCleanup(screen);
XFree(dpy);
exit(0);
}
if (dontTile) {
if (gotInput) {
gotInput = FALSE;
c = updateCounter;
} else if (screen->rfbClientHead && c++ > updateCounter) {
c=0;
if (!useSHM) {
framebufferImage->f.destroy_image(framebufferImage);
}
getImage(screen->rfbServerFormat.bitsPerPixel,
dpy,
xscreen,
&framebufferImage,
0,
0,
screen->width,
screen->height);
checkForImageUpdates(screen,
framebufferImage->data,
framebufferImage->bytes_per_line,
0,
0,
screen->width,
screen->height);
}
} else if (c++ > updateCounter) {
c = 0;
probeScreen(screen, xscreen);
}
#ifdef WRITE_SNAPS
{
int i;
int j;
int r;
int g;
int b;
FILE* f = fopen("test.pnm", "wb");
fprintf(f, "P6\n%d %d\n255\n", screen->width, screen->height);
for (j = 0; j < screen->height; j++) {
for (i = 0; i < screen->width; i++) {
r = framebufferImage->data[j*screen->paddedWidthInBytes + i*2];
fputc(((r >> screen->rfbServerFormat.redShift) & screen->rfbServerFormat.redMax) * 255/screen->rfbServerFormat.redMax, f);
fputc(((r >> screen->rfbServerFormat.greenShift) & screen->rfbServerFormat.greenMax) * 255/screen->rfbServerFormat.greenMax, f);
fputc(((r >> screen->rfbServerFormat.blueShift) & screen->rfbServerFormat.blueMax) * 255/screen->rfbServerFormat.blueMax, f);
}
}
fclose(f);
}
#endif
}
return(0);
}