direct-io.hg

view tools/xenfb/sdlfb.c @ 15456:eb2b7ce05f97

hvm vlapic: Fix one_shot argument passed to create_periodic_time().
Signed-off-by: Yosuke Iwamatsu <y-iwamatsu@ab.jp.nec.com>
author kfraser@localhost.localdomain
date Tue Jul 03 11:47:08 2007 +0100 (2007-07-03)
parents 0536dbde1562
children
line source
1 #include <SDL.h>
2 #include <errno.h>
3 #include <sys/types.h>
4 #include <sys/select.h>
5 #include <stdlib.h>
6 #include <linux/input.h>
7 #include <getopt.h>
8 #include <string.h>
9 #include "xenfb.h"
11 struct SDLFBData
12 {
13 SDL_Surface *dst;
14 SDL_Surface *src;
15 };
17 /*
18 * Map from scancode to Linux input layer keycode. Scancodes are
19 * hardware-specific. This map assumes a standard AT or PS/2
20 * keyboard.
21 *
22 * Why use scancodes? We can't use key symbols, because they don't
23 * identify keys --- they're what keys are mapped to. The standard
24 * German keymap, for instance, maps both KEY_COMMA and KEY_102ND to
25 * SDLK_LESS.
26 */
27 static int keymap[256] = {
28 [9] = KEY_ESC,
29 [10] = KEY_1,
30 [11] = KEY_2,
31 [12] = KEY_3,
32 [13] = KEY_4,
33 [14] = KEY_5,
34 [15] = KEY_6,
35 [16] = KEY_7,
36 [17] = KEY_8,
37 [18] = KEY_9,
38 [19] = KEY_0,
39 [20] = KEY_MINUS,
40 [21] = KEY_EQUAL,
41 [22] = KEY_BACKSPACE,
42 [23] = KEY_TAB,
43 [24] = KEY_Q,
44 [25] = KEY_W,
45 [26] = KEY_E,
46 [27] = KEY_R,
47 [28] = KEY_T,
48 [29] = KEY_Y,
49 [30] = KEY_U,
50 [31] = KEY_I,
51 [32] = KEY_O,
52 [33] = KEY_P,
53 [34] = KEY_LEFTBRACE,
54 [35] = KEY_RIGHTBRACE,
55 [36] = KEY_ENTER,
56 [37] = KEY_LEFTCTRL,
57 [38] = KEY_A,
58 [39] = KEY_S,
59 [40] = KEY_D,
60 [41] = KEY_F,
61 [42] = KEY_G,
62 [43] = KEY_H,
63 [44] = KEY_J,
64 [45] = KEY_K,
65 [46] = KEY_L,
66 [47] = KEY_SEMICOLON,
67 [48] = KEY_APOSTROPHE,
68 [49] = KEY_GRAVE,
69 [50] = KEY_LEFTSHIFT,
70 [51] = KEY_BACKSLASH,
71 [52] = KEY_Z,
72 [53] = KEY_X,
73 [54] = KEY_C,
74 [55] = KEY_V,
75 [56] = KEY_B,
76 [57] = KEY_N,
77 [58] = KEY_M,
78 [59] = KEY_COMMA,
79 [60] = KEY_DOT,
80 [61] = KEY_SLASH,
81 [62] = KEY_RIGHTSHIFT,
82 [63] = KEY_KPASTERISK,
83 [64] = KEY_LEFTALT,
84 [65] = KEY_SPACE,
85 [66] = KEY_CAPSLOCK,
86 [67] = KEY_F1,
87 [68] = KEY_F2,
88 [69] = KEY_F3,
89 [70] = KEY_F4,
90 [71] = KEY_F5,
91 [72] = KEY_F6,
92 [73] = KEY_F7,
93 [74] = KEY_F8,
94 [75] = KEY_F9,
95 [76] = KEY_F10,
96 [77] = KEY_NUMLOCK,
97 [78] = KEY_SCROLLLOCK,
98 [79] = KEY_KP7,
99 [80] = KEY_KP8,
100 [81] = KEY_KP9,
101 [82] = KEY_KPMINUS,
102 [83] = KEY_KP4,
103 [84] = KEY_KP5,
104 [85] = KEY_KP6,
105 [86] = KEY_KPPLUS,
106 [87] = KEY_KP1,
107 [88] = KEY_KP2,
108 [89] = KEY_KP3,
109 [90] = KEY_KP0,
110 [91] = KEY_KPDOT,
111 [94] = KEY_102ND, /* FIXME is this correct? */
112 [95] = KEY_F11,
113 [96] = KEY_F12,
114 [108] = KEY_KPENTER,
115 [109] = KEY_RIGHTCTRL,
116 [112] = KEY_KPSLASH,
117 [111] = KEY_SYSRQ,
118 [113] = KEY_RIGHTALT,
119 [97] = KEY_HOME,
120 [98] = KEY_UP,
121 [99] = KEY_PAGEUP,
122 [100] = KEY_LEFT,
123 [102] = KEY_RIGHT,
124 [103] = KEY_END,
125 [104] = KEY_DOWN,
126 [105] = KEY_PAGEDOWN,
127 [106] = KEY_INSERT,
128 [107] = KEY_DELETE,
129 [110] = KEY_PAUSE,
130 [115] = KEY_LEFTMETA,
131 [116] = KEY_RIGHTMETA,
132 [117] = KEY_MENU,
133 };
135 static int btnmap[] = {
136 [SDL_BUTTON_LEFT] = BTN_LEFT,
137 [SDL_BUTTON_MIDDLE] = BTN_MIDDLE,
138 [SDL_BUTTON_RIGHT] = BTN_RIGHT,
139 /* FIXME not 100% sure about these: */
140 [SDL_BUTTON_WHEELUP] = BTN_FORWARD,
141 [SDL_BUTTON_WHEELDOWN] BTN_BACK
142 };
144 static void sdl_update(struct xenfb *xenfb, int x, int y, int width, int height)
145 {
146 struct SDLFBData *data = xenfb->user_data;
147 SDL_Rect r = { x, y, width, height };
148 SDL_BlitSurface(data->src, &r, data->dst, &r);
149 SDL_UpdateRect(data->dst, x, y, width, height);
150 }
152 static int sdl_on_event(struct xenfb *xenfb, SDL_Event *event)
153 {
154 int x, y, ret;
156 switch (event->type) {
157 case SDL_KEYDOWN:
158 case SDL_KEYUP:
159 if (keymap[event->key.keysym.scancode] == 0)
160 break;
161 ret = xenfb_send_key(xenfb,
162 event->type == SDL_KEYDOWN,
163 keymap[event->key.keysym.scancode]);
164 if (ret < 0)
165 fprintf(stderr, "Key %d %s lost (%s)\n",
166 keymap[event->key.keysym.scancode],
167 event->type == SDL_KEYDOWN ? "down" : "up",
168 strerror(errno));
169 break;
170 case SDL_MOUSEMOTION:
171 if (xenfb->abs_pointer_wanted) {
172 SDL_GetMouseState(&x, &y);
173 ret = xenfb_send_position(xenfb, x, y);
174 } else {
175 SDL_GetRelativeMouseState(&x, &y);
176 ret = xenfb_send_motion(xenfb, x, y);
177 }
178 if (ret < 0)
179 fprintf(stderr, "Pointer to %d,%d lost (%s)\n",
180 x, y, strerror(errno));
181 break;
182 case SDL_MOUSEBUTTONDOWN:
183 case SDL_MOUSEBUTTONUP:
184 if (event->button.button >= sizeof(btnmap) / sizeof(*btnmap))
185 break;
186 if (btnmap[event->button.button] == 0)
187 break;
188 ret = xenfb_send_key(xenfb,
189 event->type == SDL_MOUSEBUTTONDOWN,
190 btnmap[event->button.button]);
191 if (ret < 0)
192 fprintf(stderr, "Button %d %s lost (%s)\n",
193 btnmap[event->button.button] - BTN_MOUSE,
194 event->type == SDL_MOUSEBUTTONDOWN ? "down" : "up",
195 strerror(errno));
196 break;
197 case SDL_QUIT:
198 return 0;
199 }
201 return 1;
202 }
204 static struct option options[] = {
205 { "domid", 1, NULL, 'd' },
206 { "title", 1, NULL, 't' },
207 { NULL }
208 };
210 int main(int argc, char **argv)
211 {
212 struct xenfb *xenfb;
213 int domid = -1;
214 char * title = NULL;
215 fd_set readfds;
216 int nfds;
217 struct SDLFBData data;
218 SDL_Rect r;
219 struct timeval tv;
220 SDL_Event event;
221 int do_quit = 0;
222 int opt;
223 char *endp;
224 int retval;
226 while ((opt = getopt_long(argc, argv, "d:t:", options,
227 NULL)) != -1) {
228 switch (opt) {
229 case 'd':
230 domid = strtol(optarg, &endp, 10);
231 if (endp == optarg || *endp) {
232 fprintf(stderr, "Invalid domain id specified\n");
233 exit(1);
234 }
235 break;
236 case 't':
237 title = strdup(optarg);
238 break;
239 case '?':
240 exit(1);
241 }
242 }
243 if (optind != argc) {
244 fprintf(stderr, "Invalid options!\n");
245 exit(1);
246 }
247 if (domid <= 0) {
248 fprintf(stderr, "Domain ID must be specified!\n");
249 exit(1);
250 }
252 xenfb = xenfb_new();
253 if (xenfb == NULL) {
254 fprintf(stderr, "Could not create framebuffer (%s)\n",
255 strerror(errno));
256 exit(1);
257 }
259 if (xenfb_attach_dom(xenfb, domid) < 0) {
260 fprintf(stderr, "Could not connect to domain (%s)\n",
261 strerror(errno));
262 exit(1);
263 }
265 if (SDL_Init(SDL_INIT_VIDEO) < 0) {
266 fprintf(stderr, "Could not initialize SDL\n");
267 exit(1);
268 }
270 data.dst = SDL_SetVideoMode(xenfb->width, xenfb->height, xenfb->depth,
271 SDL_SWSURFACE);
272 if (!data.dst) {
273 fprintf(stderr, "SDL_SetVideoMode failed\n");
274 exit(1);
275 }
277 data.src = SDL_CreateRGBSurfaceFrom(xenfb->pixels,
278 xenfb->width, xenfb->height,
279 xenfb->depth, xenfb->row_stride,
280 0xFF0000, 0xFF00, 0xFF, 0);
282 if (!data.src) {
283 fprintf(stderr, "SDL_CreateRGBSurfaceFrom failed\n");
284 exit(1);
285 }
287 if (title == NULL)
288 title = strdup("xen-sdlfb");
289 SDL_WM_SetCaption(title, title);
291 r.x = r.y = 0;
292 r.w = xenfb->width;
293 r.h = xenfb->height;
294 SDL_BlitSurface(data.src, &r, data.dst, &r);
295 SDL_UpdateRect(data.dst, 0, 0, xenfb->width, xenfb->height);
297 xenfb->update = sdl_update;
298 xenfb->user_data = &data;
300 SDL_ShowCursor(0);
302 /*
303 * We need to wait for fds becoming ready or SDL events to
304 * arrive. We time out the select after 10ms to poll for SDL
305 * events. Clunky, but works. Could avoid the clunkiness
306 * with a separate thread.
307 */
308 for (;;) {
309 FD_ZERO(&readfds);
310 nfds = xenfb_select_fds(xenfb, &readfds);
311 tv = (struct timeval){0, 10000};
313 if (select(nfds, &readfds, NULL, NULL, &tv) < 0) {
314 if (errno == EINTR)
315 continue;
316 fprintf(stderr,
317 "Can't select() on event channel (%s)\n",
318 strerror(errno));
319 break;
320 }
322 while (SDL_PollEvent(&event)) {
323 if (!sdl_on_event(xenfb, &event))
324 do_quit = 1;
325 }
327 if (do_quit)
328 break;
330 retval = xenfb_poll(xenfb, &readfds);
331 if (retval == -2)
332 xenfb_teardown(xenfb);
333 if (retval < 0)
334 break;
335 }
337 xenfb_delete(xenfb);
339 SDL_Quit();
341 return 0;
342 }