3 * This is an example of how to use libvncserver.
6 * Copyright (C) 2001 Johannes E. Schindelin <Johannes.Schindelin@gmx.de>
8 * This is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This software is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this software; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
37 const int maxx
=640, maxy
=480, bpp
=4;
38 /* TODO: odd maxx doesn't work (vncviewer bug) */
40 /* This initializes a nice (?) background */
42 void initBuffer(unsigned char* buffer
)
47 buffer
[(j
*maxx
+i
)*bpp
+0]=(i
+j
)*128/(maxx
+maxy
); /* red */
48 buffer
[(j
*maxx
+i
)*bpp
+1]=i
*128/maxx
; /* green */
49 buffer
[(j
*maxx
+i
)*bpp
+2]=j
*256/maxy
; /* blue */
51 buffer
[j
*maxx
*bpp
+0]=0xff;
52 buffer
[j
*maxx
*bpp
+1]=0xff;
53 buffer
[j
*maxx
*bpp
+2]=0xff;
54 buffer
[j
*maxx
*bpp
+3]=0xff;
58 /* Here we create a structure so that every client has it's own pointer */
60 typedef struct ClientData
{
65 void clientgone(rfbClientPtr cl
)
70 enum rfbNewClientAction
newclient(rfbClientPtr cl
)
72 cl
->clientData
= (void*)calloc(sizeof(ClientData
),1);
73 cl
->clientGoneHook
= clientgone
;
74 return RFB_CLIENT_ACCEPT
;
77 /* aux function to draw a line */
79 void drawline(unsigned char* buffer
,int rowstride
,int bpp
,int x1
,int y1
,int x2
,int y2
)
85 buffer
[y1
*rowstride
+x1
*bpp
+i
]=0xff;
91 if(y1
>y2
) { i
=y2
; y2
=y1
; y1
=i
; i
=x2
; x2
=x1
; x1
=i
; }
92 if(y2
==y1
) { if(y2
>0) y1
--; else y2
++; }
95 buffer
[j
*rowstride
+(x1
+(j
-y1
)*(x2
-x1
)/(y2
-y1
))*bpp
+i
]=0xff;
97 if(x1
>x2
) { i
=y2
; y2
=y1
; y1
=i
; i
=x2
; x2
=x1
; x1
=i
; }
100 buffer
[(y1
+(i
-x1
)*(y2
-y1
)/(x2
-x1
))*rowstride
+i
*bpp
+j
]=0xff;
104 /* Here the pointer events are handled */
106 void doptr(int buttonMask
,int x
,int y
,rfbClientPtr cl
)
108 ClientData
* cd
=cl
->clientData
;
110 if(cl
->screen
->cursorIsDrawn
)
111 rfbUndrawCursor(cl
->screen
);
113 if(x
>=0 && y
>=0 && x
<maxx
&& y
<maxy
) {
117 if(cd
->oldButton
==buttonMask
) { /* draw a line */
118 drawline(cl
->screen
->frameBuffer
,cl
->screen
->paddedWidthInBytes
,bpp
,
119 x
,y
,cd
->oldx
,cd
->oldy
);
120 rfbMarkRectAsModified(cl
->screen
,x
,y
,cd
->oldx
,cd
->oldy
);
121 } else { /* draw a point (diameter depends on button) */
122 int w
=cl
->screen
->paddedWidthInBytes
;
123 x1
=x
-buttonMask
; if(x1
<0) x1
=0;
124 x2
=x
+buttonMask
; if(x2
>maxx
) x2
=maxx
;
125 y1
=y
-buttonMask
; if(y1
<0) y1
=0;
126 y2
=y
+buttonMask
; if(y2
>maxy
) y2
=maxy
;
128 for(i
=x1
*bpp
;i
<x2
*bpp
;i
++)
130 cl
->screen
->frameBuffer
[j
*w
+i
]=(char)0xff;
131 rfbMarkRectAsModified(cl
->screen
,x1
,y1
,x2
-1,y2
-1);
134 /* we could get a selection like that:
135 rfbGotXCutText(cl->screen,"Hallo",5);
140 cd
->oldx
=x
; cd
->oldy
=y
; cd
->oldButton
=buttonMask
;
142 defaultPtrAddEvent(buttonMask
,x
,y
,cl
);
145 /* aux function to draw a character to x, y */
149 /* Here the key events are handled */
151 void dokey(Bool down
,KeySym key
,rfbClientPtr cl
)
156 else if(key
==XK_Page_Up
) {
157 if(cl
->screen
->cursorIsDrawn
)
158 rfbUndrawCursor(cl
->screen
);
159 initBuffer(cl
->screen
->frameBuffer
);
160 rfbMarkRectAsModified(cl
->screen
,0,0,maxx
,maxy
);
161 } else if(key
>=' ' && key
<0x100) {
162 ClientData
* cd
=cl
->clientData
;
163 int x1
=cd
->oldx
,y1
=cd
->oldy
,x2
,y2
;
164 if(cl
->screen
->cursorIsDrawn
)
165 rfbUndrawCursor(cl
->screen
);
166 cd
->oldx
+=rfbDrawChar(cl
->screen
,&radonFont
,cd
->oldx
,cd
->oldy
,(char)key
,0x00ffffff);
167 rfbFontBBox(&radonFont
,(char)key
,&x1
,&y1
,&x2
,&y2
);
168 rfbMarkRectAsModified(cl
->screen
,x1
,y1
,x2
-1,y2
-1);
173 /* Example for an XCursor (foreground/background only) */
175 int exampleXCursorWidth
=9,exampleXCursorHeight
=7;
176 char exampleXCursor
[]=
185 /* Example for a rich cursor (full-colour) */
187 void MakeRichCursor(rfbScreenInfoPtr rfbScreen
)
190 rfbCursorPtr c
= rfbScreen
->cursor
;
194 " xxxxxxxxxxxxxxxxx "
195 " xxxxxxxxxxxxxxxxxxxxxx "
196 " xxxxx xxxxxxxx xxxxxxxx "
197 " xxxxxxxxxxxxxxxxxxxxxxxxxxx "
198 " xxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
199 " xxxxx xxxxxxxxxxx xxxxxxx "
200 " xxxx xxxxxxxxx xxxxxx "
201 " xxxxx xxxxxxxxxxx xxxxxxx "
202 " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
203 " xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx "
204 " xxxxxxxxxxxx xxxxxxxxxxxxxxx "
205 " xxxxxxxxxxxxxxxxxxxxxxxxxxxx "
206 " xxxxxxxxxxxxxxxxxxxxxxxxxxxx "
207 " xxxxxxxxxxx xxxxxxxxxxxxxx "
208 " xxxxxxxxxx xxxxxxxxxxxx "
209 " xxxxxxxxx xxxxxxxxx "
210 " xxxxxxxxxx xxxxxxxxx "
211 " xxxxxxxxxxxxxxxxxxx "
212 " xxxxxxxxxxxxxxxxxxx "
213 " xxxxxxxxxxxxxxxxxxx "
214 " xxxxxxxxxxxxxxxxx "
216 " xxxx xxxxxxxxxxxxx "
220 " xxxxxx xxxxxxxxxxxx "
221 " xxxxxxxxxxxxxxxxxxxxxx "
224 c
=rfbScreen
->cursor
= rfbMakeXCursor(w
,h
,bitmap
,bitmap
);
225 c
->xhot
= 16; c
->yhot
= 24;
227 c
->richSource
= malloc(w
*h
*bpp
);
230 c
->richSource
[j
*w
*bpp
+i
*bpp
+0]=i
*0xff/w
;
231 c
->richSource
[j
*w
*bpp
+i
*bpp
+1]=(i
+j
)*0xff/(w
+h
);
232 c
->richSource
[j
*w
*bpp
+i
*bpp
+2]=j
*0xff/h
;
233 c
->richSource
[j
*w
*bpp
+i
*bpp
+3]=0;
240 int main(int argc
,char** argv
)
242 rfbScreenInfoPtr rfbScreen
=
243 rfbGetScreen(&argc
,argv
,maxx
,maxy
,8,3,bpp
);
244 rfbScreen
->desktopName
= "LibVNCServer Example";
245 rfbScreen
->frameBuffer
= (char*)malloc(maxx
*maxy
*bpp
);
246 rfbScreen
->rfbAlwaysShared
= TRUE
;
247 rfbScreen
->ptrAddEvent
= doptr
;
248 rfbScreen
->kbdAddEvent
= dokey
;
249 rfbScreen
->newClientHook
= newclient
;
250 rfbScreen
->httpDir
= "./classes";
252 initBuffer(rfbScreen
->frameBuffer
);
253 rfbDrawString(rfbScreen
,&radonFont
,20,100,"Hello, World!",0xffffff);
255 /* This call creates a mask and then a cursor: */
256 /* rfbScreen->defaultCursor =
257 rfbMakeXCursor(exampleCursorWidth,exampleCursorHeight,exampleCursor,0);
260 MakeRichCursor(rfbScreen
);
262 /* initialize the server */
263 rfbInitServer(rfbScreen
);
265 #ifndef BACKGROUND_LOOP_TEST
266 /* this is the blocking event loop, i.e. it never returns */
267 /* 40000 are the microseconds, i.e. 0.04 seconds */
268 rfbRunEventLoop(rfbScreen
,40000,FALSE
);
269 #elif !defined(HAVE_PTHREADS)
270 #error "I need pthreads for that."
273 /* this is the non-blocking event loop; a background thread is started */
274 rfbRunEventLoop(rfbScreen
,-1,TRUE
);
275 /* now we could do some cool things like rendering */
276 while(1) sleep(5); /* render(); */