1 /* 2 * 3 * This is an example of how to use libvncserver. 4 * 5 * libvncserver example 6 * Copyright (C) 2005 Johannes E. Schindelin <Johannes.Schindelin (at) gmx.de>, 7 * Karl Runge <runge (at) karlrunge.com> 8 * 9 * This is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This software is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this software; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 22 * USA. 23 */ 24 25 #include <rfb/rfb.h> 26 27 static const int bpp=4; 28 static int maxx=800, maxy=600; 29 30 /* This initializes a nice (?) background */ 31 32 static void initBuffer(unsigned char* buffer) 33 { 34 int i,j; 35 for(j=0;j<maxy;++j) { 36 for(i=0;i<maxx;++i) { 37 buffer[(j*maxx+i)*bpp+0]=(i+j)*128/(maxx+maxy); /* red */ 38 buffer[(j*maxx+i)*bpp+1]=i*128/maxx; /* green */ 39 buffer[(j*maxx+i)*bpp+2]=j*256/maxy; /* blue */ 40 } 41 } 42 } 43 44 /* Example for an XCursor (foreground/background only) */ 45 46 static void SetXCursor(rfbScreenInfoPtr rfbScreen) 47 { 48 int width=13,height=11; 49 char cursor[]= 50 " " 51 " xx xx " 52 " xx xx " 53 " xx xx " 54 " xx xx " 55 " xxx " 56 " xx xx " 57 " xx xx " 58 " xx xx " 59 " xx xx " 60 " ", 61 mask[]= 62 "xxxx xxxx" 63 "xxxx xxxx" 64 " xxxx xxxx " 65 " xxxx xxxx " 66 " xxxxxxx " 67 " xxxxx " 68 " xxxxxxx " 69 " xxxx xxxx " 70 " xxxx xxxx " 71 "xxxx xxxx" 72 "xxxx xxxx"; 73 rfbCursorPtr c; 74 75 c=rfbMakeXCursor(width,height,cursor,mask); 76 c->xhot=width/2;c->yhot=height/2; 77 78 rfbSetCursor(rfbScreen, c); 79 } 80 81 static void SetXCursor2(rfbScreenInfoPtr rfbScreen) 82 { 83 int width=13,height=22; 84 char cursor[]= 85 " xx " 86 " x x " 87 " x x " 88 " x x " 89 " x x " 90 " x x " 91 " x x " 92 " x x " 93 " x xx x " 94 " x x x xxx " 95 " x xx x x " 96 " xx x x " 97 " xx x x " 98 " x x x " 99 " x x x " 100 " x x " 101 " x x " 102 " x x " 103 " xx " 104 " " 105 " ", 106 mask[]= 107 "xxx " 108 "xxxx " 109 "xxxxx " 110 "xxxxxx " 111 "xxxxxxx " 112 "xxxxxxxx " 113 "xxxxxxxxx " 114 "xxxxxxxxxx " 115 "xxxxxxxxxxx " 116 "xxxxxxxxxxxx " 117 "xxxxxxxxxxxxx" 118 "xxxxxxxxxxxxx" 119 "xxxxxxxxxx x" 120 "xxxxxxxxxx " 121 "xxx xxxxxx " 122 "xxx xxxxxx " 123 "xx xxxxxx " 124 " xxxxx " 125 " xxxxxx" 126 " xxxxx" 127 " xxx " 128 " "; 129 rfbCursorPtr c; 130 131 c=rfbMakeXCursor(width,height,cursor,mask); 132 c->xhot=0;c->yhot=0; 133 134 rfbSetCursor(rfbScreen, c); 135 } 136 137 /* Example for a rich cursor (full-colour) */ 138 139 static void SetRichCursor(rfbScreenInfoPtr rfbScreen) 140 { 141 int i,j,w=32,h=32; 142 /* runge */ 143 /* rfbCursorPtr c = rfbScreen->cursor; */ 144 rfbCursorPtr c; 145 char bitmap[]= 146 " " 147 " xxxxxx " 148 " xxxxxxxxxxxxxxxxx " 149 " xxxxxxxxxxxxxxxxxxxxxx " 150 " xxxxx xxxxxxxx xxxxxxxx " 151 " xxxxxxxxxxxxxxxxxxxxxxxxxxx " 152 " xxxxxxxxxxxxxxxxxxxxxxxxxxxxx " 153 " xxxxx xxxxxxxxxxx xxxxxxx " 154 " xxxx xxxxxxxxx xxxxxx " 155 " xxxxx xxxxxxxxxxx xxxxxxx " 156 " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " 157 " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx " 158 " xxxxxxxxxxxx xxxxxxxxxxxxxxx " 159 " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " 160 " xxxxxxxxxxxxxxxxxxxxxxxxxxxx " 161 " xxxxxxxxxxx xxxxxxxxxxxxxx " 162 " xxxxxxxxxx xxxxxxxxxxxx " 163 " xxxxxxxxx xxxxxxxxx " 164 " xxxxxxxxxx xxxxxxxxx " 165 " xxxxxxxxxxxxxxxxxxx " 166 " xxxxxxxxxxxxxxxxxxx " 167 " xxxxxxxxxxxxxxxxxxx " 168 " xxxxxxxxxxxxxxxxx " 169 " xxxxxxxxxxxxxxx " 170 " xxxx xxxxxxxxxxxxx " 171 " xx x xxxxxxxxxxx " 172 " xxx xxxxxxxxxxx " 173 " xxxx xxxxxxxxxxx " 174 " xxxxxx xxxxxxxxxxxx " 175 " xxxxxxxxxxxxxxxxxxxxxx " 176 " xxxxxxxxxxxxxxxx " 177 " "; 178 179 c=rfbMakeXCursor(w,h,bitmap,bitmap); 180 c->xhot = 16; c->yhot = 24; 181 182 c->richSource = (char*)malloc(w*h*bpp); 183 for(j=0;j<h;j++) { 184 for(i=0;i<w;i++) { 185 c->richSource[j*w*bpp+i*bpp+0]=i*0xff/w; 186 c->richSource[j*w*bpp+i*bpp+1]=(i+j)*0xff/(w+h); 187 c->richSource[j*w*bpp+i*bpp+2]=j*0xff/h; 188 c->richSource[j*w*bpp+i*bpp+3]=0; 189 } 190 } 191 rfbSetCursor(rfbScreen, c); 192 } 193 194 /* runge */ 195 static void SetRichCursor2(rfbScreenInfoPtr rfbScreen) 196 { 197 int i,j,w=17,h=16; 198 /* rfbCursorPtr c = rfbScreen->cursor; */ 199 rfbCursorPtr c; 200 char bitmap[]= 201 " " 202 "xxxx " 203 "xxxxxxxx " 204 "xxxxxxxxxxxx x" 205 "xxx xxxxxxxx x" 206 "xxxxxxxxxxxxxx x" 207 "xxxxxxxxxxxxxxx x" 208 "xxxxx xxxxxxx x" 209 "xxxx xxxxxx x" 210 "xxxxx xxxxxxx x" 211 "xxxxxxxxxxxxxxx x" 212 "xxxxxxxxxxxxxxx x" 213 "xxxxxxxxxxxxxx x" 214 "xxxxxxxxxxxxx x" 215 "xxxxxxxxxxxxx x" 216 "xxxxxxxxxxxxx x"; 217 /* c=rfbScreen->cursor = rfbMakeXCursor(w,h,bitmap,bitmap); */ 218 c=rfbMakeXCursor(w,h,bitmap,bitmap); 219 c->xhot = 5; c->yhot = 7; 220 221 c->richSource = (char*)malloc(w*h*bpp); 222 for(j=0;j<h;j++) { 223 for(i=0;i<w;i++) { 224 c->richSource[j*w*bpp+i*bpp+0]=0xff; 225 c->richSource[j*w*bpp+i*bpp+1]=0x00; 226 c->richSource[j*w*bpp+i*bpp+2]=0x7f; 227 c->richSource[j*w*bpp+i*bpp+3]=0; 228 } 229 } 230 rfbSetCursor(rfbScreen, c); 231 } 232 233 /* alpha channel */ 234 235 static void SetAlphaCursor(rfbScreenInfoPtr screen,int mode) 236 { 237 int i,j; 238 rfbCursorPtr c = screen->cursor; 239 int maskStride=(c->width+7)/8; 240 241 if(!c) 242 return; 243 244 if(c->alphaSource) { 245 free(c->alphaSource); 246 c->alphaSource=NULL; 247 } 248 249 if(mode==0) 250 return; 251 252 c->alphaSource = (unsigned char*)malloc(c->width*c->height); 253 254 for(j=0;j<c->height;j++) 255 for(i=0;i<c->width;i++) { 256 unsigned char value=0x100*i/c->width; 257 rfbBool masked=(c->mask[(i/8)+maskStride*j]<<(i&7))&0x80; 258 c->alphaSource[i+c->width*j]=(masked?(mode==1?value:0xff-value):0); 259 } 260 if(c->cleanupMask) 261 free(c->mask); 262 c->mask=rfbMakeMaskFromAlphaSource(c->width,c->height,c->alphaSource); 263 c->cleanupMask=TRUE; 264 } 265 266 /* Here the pointer events are handled */ 267 268 static void doptr(int buttonMask,int x,int y,rfbClientPtr cl) 269 { 270 static int oldButtonMask=0; 271 static int counter=0; 272 273 if((oldButtonMask&1)==0 && (buttonMask&1)==1) { 274 switch(++counter) { 275 case 7: 276 SetRichCursor(cl->screen); 277 SetAlphaCursor(cl->screen,2); 278 break; 279 case 6: 280 SetRichCursor(cl->screen); 281 SetAlphaCursor(cl->screen,1); 282 break; 283 case 5: 284 SetRichCursor2(cl->screen); 285 SetAlphaCursor(cl->screen,0); 286 break; 287 case 4: 288 SetXCursor(cl->screen); 289 break; 290 case 3: 291 SetRichCursor2(cl->screen); 292 SetAlphaCursor(cl->screen,2); 293 break; 294 case 2: 295 SetXCursor(cl->screen); 296 SetAlphaCursor(cl->screen,2); 297 break; 298 case 1: 299 SetXCursor2(cl->screen); 300 SetAlphaCursor(cl->screen,0); 301 break; 302 default: 303 SetRichCursor(cl->screen); 304 counter=0; 305 } 306 } 307 if(buttonMask&2) { 308 rfbScreenCleanup(cl->screen); 309 exit(0); 310 } 311 312 if(buttonMask&4) 313 rfbCloseClient(cl); 314 315 316 oldButtonMask=buttonMask; 317 318 rfbDefaultPtrAddEvent(buttonMask,x,y,cl); 319 } 320 321 /* Initialization */ 322 323 int main(int argc,char** argv) 324 { 325 rfbScreenInfoPtr rfbScreen = rfbGetScreen(&argc,argv,maxx,maxy,8,3,bpp); 326 if(!rfbScreen) 327 return 0; 328 329 rfbScreen->desktopName = "Cursor Test"; 330 rfbScreen->frameBuffer = (char*)malloc(maxx*maxy*bpp); 331 rfbScreen->ptrAddEvent = doptr; 332 333 initBuffer((unsigned char*)rfbScreen->frameBuffer); 334 335 336 SetRichCursor(rfbScreen); 337 338 /* initialize the server */ 339 rfbInitServer(rfbScreen); 340 341 rfbLog("Change cursor shape with left mouse button,\n\t" 342 "quit with right one (middle button quits server).\n"); 343 344 /* this is the blocking event loop, i.e. it never returns */ 345 /* 40000 are the microseconds to wait on select(), i.e. 0.04 seconds */ 346 rfbRunEventLoop(rfbScreen,40000,FALSE); 347 348 free(rfbScreen->frameBuffer); 349 rfbScreenCleanup(rfbScreen); 350 351 return(0); 352 } 353 354