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@gmx.de>,
7 * Karl Runge <runge@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
initBuffer(unsigned char * buffer)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
SetXCursor(rfbScreenInfoPtr rfbScreen)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
SetXCursor2(rfbScreenInfoPtr rfbScreen)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
SetRichCursor(rfbScreenInfoPtr rfbScreen)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 */
SetRichCursor2(rfbScreenInfoPtr rfbScreen)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
SetAlphaCursor(rfbScreenInfoPtr screen,int mode)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
doptr(int buttonMask,int x,int y,rfbClientPtr cl)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
main(int argc,char ** argv)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