/*
*
* This is an example of how to use libvncserver.
*
* libvncserver example
* Copyright (C) 2005 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>,
* Karl Runge <runge@karlrunge.com>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
* USA.
*/
#include <rfb/rfb.h>
static const int bpp=4;
static int maxx=800, maxy=600;
/* This initializes a nice (?) background */
static void initBuffer(unsigned char* buffer)
{
int i,j;
for(j=0;j<maxy;++j) {
for(i=0;i<maxx;++i) {
buffer[(j*maxx+i)*bpp+0]=(i+j)*128/(maxx+maxy); /* red */
buffer[(j*maxx+i)*bpp+1]=i*128/maxx; /* green */
buffer[(j*maxx+i)*bpp+2]=j*256/maxy; /* blue */
}
}
}
/* Example for an XCursor (foreground/background only) */
static void SetXCursor(rfbScreenInfoPtr rfbScreen)
{
int width=13,height=11;
char cursor[]=
" "
" xx xx "
" xx xx "
" xx xx "
" xx xx "
" xxx "
" xx xx "
" xx xx "
" xx xx "
" xx xx "
" ",
mask[]=
"xxxx xxxx"
"xxxx xxxx"
" xxxx xxxx "
" xxxx xxxx "
" xxxxxxx "
" xxxxx "
" xxxxxxx "
" xxxx xxxx "
" xxxx xxxx "
"xxxx xxxx"
"xxxx xxxx";
rfbCursorPtr c;
c=rfbMakeXCursor(width,height,cursor,mask);
c->xhot=width/2;c->yhot=height/2;
rfbSetCursor(rfbScreen, c);
}
static void SetXCursor2(rfbScreenInfoPtr rfbScreen)
{
int width=13,height=22;
char cursor[]=
" xx "
" x x "
" x x "
" x x "
" x x "
" x x "
" x x "
" x x "
" x xx x "
" x x x xxx "
" x xx x x "
" xx x x "
" xx x x "
" x x x "
" x x x "
" x x "
" x x "
" x x "
" xx "
" "
" ",
mask[]=
"xxx "
"xxxx "
"xxxxx "
"xxxxxx "
"xxxxxxx "
"xxxxxxxx "
"xxxxxxxxx "
"xxxxxxxxxx "
"xxxxxxxxxxx "
"xxxxxxxxxxxx "
"xxxxxxxxxxxxx"
"xxxxxxxxxxxxx"
"xxxxxxxxxx x"
"xxxxxxxxxx "
"xxx xxxxxx "
"xxx xxxxxx "
"xx xxxxxx "
" xxxxx "
" xxxxxx"
" xxxxx"
" xxx "
" ";
rfbCursorPtr c;
c=rfbMakeXCursor(width,height,cursor,mask);
c->xhot=0;c->yhot=0;
rfbSetCursor(rfbScreen, c);
}
/* Example for a rich cursor (full-colour) */
static void SetRichCursor(rfbScreenInfoPtr rfbScreen)
{
int i,j,w=32,h=32;
/* runge */
/* rfbCursorPtr c = rfbScreen->cursor; */
rfbCursorPtr c;
char bitmap[]=
" "
" xxxxxx "
" xxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxxxxxxxxx "
" xxxxx xxxxxxxx xxxxxxxx "
" xxxxxxxxxxxxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
" xxxxx xxxxxxxxxxx xxxxxxx "
" xxxx xxxxxxxxx xxxxxx "
" xxxxx xxxxxxxxxxx xxxxxxx "
" xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxx xxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxxxxxxxxxxxxxxx "
" xxxxxxxxxxx xxxxxxxxxxxxxx "
" xxxxxxxxxx xxxxxxxxxxxx "
" xxxxxxxxx xxxxxxxxx "
" xxxxxxxxxx xxxxxxxxx "
" xxxxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxx "
" xxxx xxxxxxxxxxxxx "
" xx x xxxxxxxxxxx "
" xxx xxxxxxxxxxx "
" xxxx xxxxxxxxxxx "
" xxxxxx xxxxxxxxxxxx "
" xxxxxxxxxxxxxxxxxxxxxx "
" xxxxxxxxxxxxxxxx "
" ";
c=rfbMakeXCursor(w,h,bitmap,bitmap);
c->xhot = 16; c->yhot = 24;
c->richSource = (char*)malloc(w*h*bpp);
for(j=0;j<h;j++) {
for(i=0;i<w;i++) {
c->richSource[j*w*bpp+i*bpp+0]=i*0xff/w;
c->richSource[j*w*bpp+i*bpp+1]=(i+j)*0xff/(w+h);
c->richSource[j*w*bpp+i*bpp+2]=j*0xff/h;
c->richSource[j*w*bpp+i*bpp+3]=0;
}
}
rfbSetCursor(rfbScreen, c);
}
/* runge */
static void SetRichCursor2(rfbScreenInfoPtr rfbScreen)
{
int i,j,w=17,h=16;
/* rfbCursorPtr c = rfbScreen->cursor; */
rfbCursorPtr c;
char bitmap[]=
" "
"xxxx "
"xxxxxxxx "
"xxxxxxxxxxxx x"
"xxx xxxxxxxx x"
"xxxxxxxxxxxxxx x"
"xxxxxxxxxxxxxxx x"
"xxxxx xxxxxxx x"
"xxxx xxxxxx x"
"xxxxx xxxxxxx x"
"xxxxxxxxxxxxxxx x"
"xxxxxxxxxxxxxxx x"
"xxxxxxxxxxxxxx x"
"xxxxxxxxxxxxx x"
"xxxxxxxxxxxxx x"
"xxxxxxxxxxxxx x";
/* c=rfbScreen->cursor = rfbMakeXCursor(w,h,bitmap,bitmap); */
c=rfbMakeXCursor(w,h,bitmap,bitmap);
c->xhot = 5; c->yhot = 7;
c->richSource = (char*)malloc(w*h*bpp);
for(j=0;j<h;j++) {
for(i=0;i<w;i++) {
c->richSource[j*w*bpp+i*bpp+0]=0xff;
c->richSource[j*w*bpp+i*bpp+1]=0x00;
c->richSource[j*w*bpp+i*bpp+2]=0x7f;
c->richSource[j*w*bpp+i*bpp+3]=0;
}
}
rfbSetCursor(rfbScreen, c);
}
/* alpha channel */
static void SetAlphaCursor(rfbScreenInfoPtr screen,int mode)
{
int i,j;
rfbCursorPtr c = screen->cursor;
int maskStride=(c->width+7)/8;
if(!c)
return;
if(c->alphaSource) {
free(c->alphaSource);
c->alphaSource=NULL;
}
if(mode==0)
return;
c->alphaSource = (unsigned char*)malloc(c->width*c->height);
for(j=0;j<c->height;j++)
for(i=0;i<c->width;i++) {
unsigned char value=0x100*i/c->width;
rfbBool masked=(c->mask[(i/8)+maskStride*j]<<(i&7))&0x80;
c->alphaSource[i+c->width*j]=(masked?(mode==1?value:0xff-value):0);
}
if(c->cleanupMask)
free(c->mask);
c->mask=rfbMakeMaskFromAlphaSource(c->width,c->height,c->alphaSource);
c->cleanupMask=TRUE;
}
/* Here the pointer events are handled */
static void doptr(int buttonMask,int x,int y,rfbClientPtr cl)
{
static int oldButtonMask=0;
static int counter=0;
if((oldButtonMask&1)==0 && (buttonMask&1)==1) {
switch(++counter) {
case 7:
SetRichCursor(cl->screen);
SetAlphaCursor(cl->screen,2);
break;
case 6:
SetRichCursor(cl->screen);
SetAlphaCursor(cl->screen,1);
break;
case 5:
SetRichCursor2(cl->screen);
SetAlphaCursor(cl->screen,0);
break;
case 4:
SetXCursor(cl->screen);
break;
case 3:
SetRichCursor2(cl->screen);
SetAlphaCursor(cl->screen,2);
break;
case 2:
SetXCursor(cl->screen);
SetAlphaCursor(cl->screen,2);
break;
case 1:
SetXCursor2(cl->screen);
SetAlphaCursor(cl->screen,0);
break;
default:
SetRichCursor(cl->screen);
counter=0;
}
}
if(buttonMask&2) {
rfbScreenCleanup(cl->screen);
exit(0);
}
if(buttonMask&4)
rfbCloseClient(cl);
oldButtonMask=buttonMask;
rfbDefaultPtrAddEvent(buttonMask,x,y,cl);
}
/* Initialization */
int main(int argc,char** argv)
{
rfbScreenInfoPtr rfbScreen = rfbGetScreen(&argc,argv,maxx,maxy,8,3,bpp);
if(!rfbScreen)
return 0;
rfbScreen->desktopName = "Cursor Test";
rfbScreen->frameBuffer = (char*)malloc(maxx*maxy*bpp);
rfbScreen->ptrAddEvent = doptr;
initBuffer((unsigned char*)rfbScreen->frameBuffer);
SetRichCursor(rfbScreen);
/* initialize the server */
rfbInitServer(rfbScreen);
rfbLog("Change cursor shape with left mouse button,\n\t"
"quit with right one (middle button quits server).\n");
/* this is the blocking event loop, i.e. it never returns */
/* 40000 are the microseconds to wait on select(), i.e. 0.04 seconds */
rfbRunEventLoop(rfbScreen,40000,FALSE);
free(rfbScreen->frameBuffer);
rfbScreenCleanup(rfbScreen);
return(0);
}