| /* |
| * |
| * 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); |
| } |
| |