summaryrefslogtreecommitdiffstats
path: root/client_examples/SDLvncviewer.c
blob: 07d3869ce279025251aa097a98a567981a9ad341 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
#include <SDL.h>
#include <rfb/rfbclient.h>

static rfbBool resize(rfbClient* client) {
	static char first=TRUE;
#ifdef SDL_ASYNCBLIT
	int flags=SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
#else
	int flags=SDL_HWSURFACE|SDL_HWACCEL;
#endif
	int width=client->width,height=client->height,
		depth=client->format.bitsPerPixel;
	rfbBool okay=SDL_VideoModeOK(width,height,depth,flags);
	if(!okay)
		for(depth=24;!okay && depth>4;depth/=2)
			okay=SDL_VideoModeOK(width,height,depth,flags);
	if(okay) {
		SDL_Surface* sdl=SDL_SetVideoMode(width,height,depth,flags);
		client->clientData=sdl;
		client->frameBuffer=sdl->pixels;
		if(first || depth!=client->format.bitsPerPixel) {
			first=FALSE;
			client->format.bitsPerPixel=depth;
			client->format.redShift=sdl->format->Rshift;
			client->format.greenShift=sdl->format->Gshift;
			client->format.blueShift=sdl->format->Bshift;
			client->format.redMax=sdl->format->Rmask>>client->format.redShift;
			client->format.greenMax=sdl->format->Gmask>>client->format.greenShift;
			client->format.blueMax=sdl->format->Bmask>>client->format.blueShift;
			SetFormatAndEncodings(client);
		}
	} else {
		SDL_Surface* sdl=client->clientData;
		rfbClientLog("Could not set resolution %dx%d!\n",
				client->width,client->height);
		if(sdl) {
			client->width=sdl->w;
			client->height=sdl->h;
		} else {
			client->width=0;
			client->height=0;
		}
		return FALSE;
	}
	SDL_WM_SetCaption(client->desktopName, "SDL");
	return TRUE;
}

static rfbKeySym SDL_keysym2rfbKeySym(int keysym) {
	switch(keysym) {
	case SDLK_BACKSPACE: return XK_BackSpace;
	case SDLK_TAB: return XK_ISO_Left_Tab;
	case SDLK_CLEAR: return XK_Clear;
	case SDLK_RETURN: return XK_Return;
	case SDLK_PAUSE: return XK_Pause;
	case SDLK_ESCAPE: return XK_Escape;
	case SDLK_SPACE: return XK_space;
	case SDLK_EXCLAIM: return XK_exclam;
	case SDLK_QUOTEDBL: return XK_quotedbl;
	case SDLK_HASH: return XK_numbersign;
	case SDLK_DOLLAR: return XK_dollar;
	case SDLK_AMPERSAND: return XK_ampersand;
	case SDLK_QUOTE: return XK_apostrophe;
	case SDLK_LEFTPAREN: return XK_parenleft;
	case SDLK_RIGHTPAREN: return XK_parenright;
	case SDLK_ASTERISK: return XK_asterisk;
	case SDLK_PLUS: return XK_plus;
	case SDLK_COMMA: return XK_comma;
	case SDLK_MINUS: return XK_minus;
	case SDLK_PERIOD: return XK_period;
	case SDLK_SLASH: return XK_slash;
	case SDLK_0: return XK_0;
	case SDLK_1: return XK_1;
	case SDLK_2: return XK_2;
	case SDLK_3: return XK_3;
	case SDLK_4: return XK_4;
	case SDLK_5: return XK_5;
	case SDLK_6: return XK_6;
	case SDLK_7: return XK_7;
	case SDLK_8: return XK_8;
	case SDLK_9: return XK_9;
	case SDLK_COLON: return XK_colon;
	case SDLK_SEMICOLON: return XK_semicolon;
	case SDLK_LESS: return XK_less;
	case SDLK_EQUALS: return XK_equal;
	case SDLK_GREATER: return XK_greater;
	case SDLK_QUESTION: return XK_question;
	case SDLK_AT: return XK_at;
	case SDLK_LEFTBRACKET: return XK_bracketleft;
	case SDLK_BACKSLASH: return XK_backslash;
	case SDLK_RIGHTBRACKET: return XK_bracketright;
	case SDLK_CARET: return XK_asciicircum;
	case SDLK_UNDERSCORE: return XK_underscore;
	case SDLK_BACKQUOTE: return XK_grave;
	case SDLK_a: return XK_a;
	case SDLK_b: return XK_b;
	case SDLK_c: return XK_c;
	case SDLK_d: return XK_d;
	case SDLK_e: return XK_e;
	case SDLK_f: return XK_f;
	case SDLK_g: return XK_g;
	case SDLK_h: return XK_h;
	case SDLK_i: return XK_i;
	case SDLK_j: return XK_j;
	case SDLK_k: return XK_k;
	case SDLK_l: return XK_l;
	case SDLK_m: return XK_m;
	case SDLK_n: return XK_n;
	case SDLK_o: return XK_o;
	case SDLK_p: return XK_p;
	case SDLK_q: return XK_q;
	case SDLK_r: return XK_r;
	case SDLK_s: return XK_s;
	case SDLK_t: return XK_t;
	case SDLK_u: return XK_u;
	case SDLK_v: return XK_v;
	case SDLK_w: return XK_w;
	case SDLK_x: return XK_x;
	case SDLK_y: return XK_y;
	case SDLK_z: return XK_z;
	case SDLK_DELETE: return XK_Delete;
	case SDLK_KP0: return XK_KP_0;
	case SDLK_KP1: return XK_KP_1;
	case SDLK_KP2: return XK_KP_2;
	case SDLK_KP3: return XK_KP_3;
	case SDLK_KP4: return XK_KP_4;
	case SDLK_KP5: return XK_KP_5;
	case SDLK_KP6: return XK_KP_6;
	case SDLK_KP7: return XK_KP_7;
	case SDLK_KP8: return XK_KP_8;
	case SDLK_KP9: return XK_KP_9;
	case SDLK_KP_PERIOD: return XK_KP_Decimal;
	case SDLK_KP_DIVIDE: return XK_KP_Divide;
	case SDLK_KP_MULTIPLY: return XK_KP_Multiply;
	case SDLK_KP_MINUS: return XK_KP_Subtract;
	case SDLK_KP_PLUS: return XK_KP_Add;
	case SDLK_KP_ENTER: return XK_KP_Enter;
	case SDLK_KP_EQUALS: return XK_KP_Equal;
	case SDLK_UP: return XK_Up;
	case SDLK_DOWN: return XK_Down;
	case SDLK_RIGHT: return XK_Right;
	case SDLK_LEFT: return XK_Left;
	case SDLK_INSERT: return XK_Insert;
	case SDLK_HOME: return XK_Home;
	case SDLK_END: return XK_End;
	case SDLK_PAGEUP: return XK_Page_Up;
	case SDLK_PAGEDOWN: return XK_Page_Down;
	case SDLK_F1: return XK_F1;
	case SDLK_F2: return XK_F2;
	case SDLK_F3: return XK_F3;
	case SDLK_F4: return XK_F4;
	case SDLK_F5: return XK_F5;
	case SDLK_F6: return XK_F6;
	case SDLK_F7: return XK_F7;
	case SDLK_F8: return XK_F8;
	case SDLK_F9: return XK_F9;
	case SDLK_F10: return XK_F10;
	case SDLK_F11: return XK_F11;
	case SDLK_F12: return XK_F12;
	case SDLK_F13: return XK_F13;
	case SDLK_F14: return XK_F14;
	case SDLK_F15: return XK_F15;
	case SDLK_NUMLOCK: return XK_Num_Lock;
	case SDLK_CAPSLOCK: return XK_Caps_Lock;
	case SDLK_SCROLLOCK: return XK_Scroll_Lock;
	case SDLK_RSHIFT: return XK_Shift_R;
	case SDLK_LSHIFT: return XK_Shift_L;
	case SDLK_RCTRL: return XK_Control_R;
	case SDLK_LCTRL: return XK_Control_L;
	case SDLK_RALT: return XK_Alt_R;
	case SDLK_LALT: return XK_Alt_L;
	case SDLK_RMETA: return XK_Meta_R;
	case SDLK_LMETA: return XK_Meta_L;
#if 0
	/* TODO: find out keysyms */
	case SDLK_LSUPER: return XK_LSuper;		/* left "windows" key */
	case SDLK_RSUPER: return XK_RSuper;		/* right "windows" key */
	case SDLK_COMPOSE: return XK_Compose;
#endif
	case SDLK_MODE: return XK_Mode_switch;
	case SDLK_HELP: return XK_Help;
	case SDLK_PRINT: return XK_Print;
	case SDLK_SYSREQ: return XK_Sys_Req;
	case SDLK_BREAK: return XK_Break;
	default: rfbClientLog("Unknown keysym: %d\n",keysym);
	}
	return 0;
}

static void update(rfbClient* cl,int x,int y,int w,int h) {
	SDL_UpdateRect(cl->clientData, x, y, w, h);
}

#ifdef __MINGW32__
#define LOG_TO_FILE
#endif

#ifdef LOG_TO_FILE
#include <stdarg.h>
static void
log_to_file(const char *format, ...)
{
    FILE* logfile;
    static char* logfile_str=0;
    va_list args;
    char buf[256];
    time_t log_clock;

    if(!rfbEnableClientLogging)
      return;

    if(logfile_str==0) {
	logfile_str=getenv("VNCLOG");
	if(logfile_str==0)
	    logfile_str="vnc.log";
    }

    logfile=fopen(logfile_str,"a");

    va_start(args, format);

    time(&log_clock);
    strftime(buf, 255, "%d/%m/%Y %X ", localtime(&log_clock));
    fprintf(logfile,buf);

    vfprintf(logfile, format, args);
    fflush(logfile);

    va_end(args);
    fclose(logfile);
}
#endif

#ifdef mac
#define main SDLmain
#endif

int main(int argc,char** argv) {
	rfbClient* cl;
	int i,buttonMask=0;
	SDL_Event e;

#ifdef LOG_TO_FILE
	rfbClientLog=rfbClientErr=log_to_file;
#endif

	SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE);

	/* 16-bit: cl=rfbGetClient(5,3,2); */
	cl=rfbGetClient(8,3,4);
	cl->MallocFrameBuffer=resize;
	cl->GotFrameBufferUpdate=update;
	if(!rfbInitClient(cl,&argc,argv))
		return 1;

	while(1) {
		if(SDL_PollEvent(&e))
			switch(e.type) {
#if SDL_MAJOR_VERSION>1 || SDL_MINOR_VERSION>=2
				case SDL_VIDEOEXPOSE:
					SendFramebufferUpdateRequest(cl,0,0,cl->width,cl->height,FALSE);
					break;
#endif
				case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN:
				case SDL_MOUSEMOTION: {
						int x,y;
						int state=SDL_GetMouseState(&x,&y);
						struct { int sdl; int rfb; } buttonMapping[]={
							{1, rfbButton1Mask},
							{3, rfbButton2Mask},
							{2, rfbButton3Mask},
							{0,0}
						};
						int i;
						for(buttonMask=0,i=0;buttonMapping[i].sdl;i++)
							if(state&SDL_BUTTON(buttonMapping[i].sdl))
								buttonMask|=buttonMapping[i].rfb;
						SendPointerEvent(cl,x,y,buttonMask);
					}
					break;
				case SDL_KEYUP: case SDL_KEYDOWN:
					SendKeyEvent(cl,SDL_keysym2rfbKeySym(e.key.keysym.sym),(e.type==SDL_KEYDOWN)?TRUE:FALSE);
					break;
				case SDL_QUIT:
					rfbClientCleanup(cl);
					return 0;
				case SDL_ACTIVEEVENT:
					break;
				default:
					rfbClientLog("ignore SDL event: 0x%x\n",e.type);
			}
		else {
			i=WaitForMessage(cl,500);
			if(i<0)
				return 0;
			if(i)
		    		if(!HandleRFBServerMessage(cl))
					return 0;
		}
	}

	return 0;
}