debuggers.hg

view tools/ioemu/sdl.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children 5c0bf00e371d
line source
1 /*
2 * QEMU SDL display driver
3 *
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24 #include "vl.h"
26 #include <SDL.h>
28 #ifndef _WIN32
29 #include <signal.h>
30 #endif
32 #ifdef CONFIG_OPENGL
33 #include <SDL_opengl.h>
34 #endif
36 static SDL_Surface *screen;
37 static SDL_Surface *shared = NULL;
38 static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
39 static int last_vm_running;
40 static int gui_saved_grab;
41 static int gui_fullscreen;
42 static int gui_key_modifier_pressed;
43 static int gui_keysym;
44 static int gui_fullscreen_initial_grab;
45 static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
46 static uint8_t modifiers_state[256];
47 static int width, height;
48 static SDL_Cursor *sdl_cursor_normal;
49 static SDL_Cursor *sdl_cursor_hidden;
50 static int absolute_enabled = 0;
51 static int opengl_enabled;
53 #ifdef CONFIG_OPENGL
54 static GLint tex_format;
55 static GLint tex_type;
56 static GLuint texture_ref = 0;
57 static GLint gl_format;
59 static void opengl_setdata(DisplayState *ds, void *pixels)
60 {
61 glEnable(GL_TEXTURE_RECTANGLE_ARB);
62 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
63 glClearColor(0, 0, 0, 0);
64 glDisable(GL_BLEND);
65 glDisable(GL_LIGHTING);
66 glDisable(GL_DEPTH_TEST);
67 glDepthMask(GL_FALSE);
68 glDisable(GL_CULL_FACE);
69 glViewport( 0, 0, screen->w, screen->h);
70 glMatrixMode(GL_PROJECTION);
71 glLoadIdentity();
72 glOrtho(0, screen->w, screen->h, 0, -1,1);
73 glMatrixMode(GL_MODELVIEW);
74 glLoadIdentity();
75 glClear(GL_COLOR_BUFFER_BIT);
76 ds->data = pixels;
78 if (texture_ref) {
79 glDeleteTextures(1, &texture_ref);
80 texture_ref = 0;
81 }
83 glGenTextures(1, &texture_ref);
84 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref);
85 glPixelStorei(GL_UNPACK_LSB_FIRST, 1);
86 switch (ds->depth) {
87 case 8:
88 if (ds->palette == NULL) {
89 tex_format = GL_RGB;
90 tex_type = GL_UNSIGNED_BYTE_3_3_2;
91 } else {
92 int i;
93 GLushort paletter[256], paletteg[256], paletteb[256];
94 for (i = 0; i < 256; i++) {
95 uint8_t rgb = ds->palette[i] >> 16;
96 paletter[i] = ((rgb & 0xe0) >> 5) * 65535 / 7;
97 paletteg[i] = ((rgb & 0x1c) >> 2) * 65535 / 7;
98 paletteb[i] = (rgb & 0x3) * 65535 / 3;
99 }
100 glPixelMapusv(GL_PIXEL_MAP_I_TO_R, 256, paletter);
101 glPixelMapusv(GL_PIXEL_MAP_I_TO_G, 256, paletteg);
102 glPixelMapusv(GL_PIXEL_MAP_I_TO_B, 256, paletteb);
104 tex_format = GL_COLOR_INDEX;
105 tex_type = GL_UNSIGNED_BYTE;
106 }
107 break;
108 case 16:
109 tex_format = GL_RGB;
110 tex_type = GL_UNSIGNED_SHORT_5_6_5;
111 break;
112 case 24:
113 tex_format = GL_BGR;
114 tex_type = GL_UNSIGNED_BYTE;
115 break;
116 case 32:
117 if (!ds->bgr) {
118 tex_format = GL_BGRA;
119 tex_type = GL_UNSIGNED_BYTE;
120 } else {
121 tex_format = GL_RGBA;
122 tex_type = GL_UNSIGNED_BYTE;
123 }
124 break;
125 }
126 glPixelStorei(GL_UNPACK_ROW_LENGTH, (ds->linesize * 8) / ds->depth);
127 glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_format, ds->width, ds->height, 0, tex_format, tex_type, pixels);
128 glTexParameterf(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_PRIORITY, 1.0);
129 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
130 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
131 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
132 glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
133 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
134 }
136 static void opengl_update(DisplayState *ds, int x, int y, int w, int h)
137 {
138 int bpp = ds->depth / 8;
139 GLvoid *pixels = ds->data + y * ds->linesize + x * bpp;
140 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_ref);
141 glPixelStorei(GL_UNPACK_ROW_LENGTH, ds->linesize / bpp);
142 glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, x, y, w, h, tex_format, tex_type, pixels);
143 glBegin(GL_QUADS);
144 glTexCoord2d(0, 0);
145 glVertex2d(0, 0);
146 glTexCoord2d(ds->width, 0);
147 glVertex2d(screen->w, 0);
148 glTexCoord2d(ds->width, ds->height);
149 glVertex2d(screen->w, screen->h);
150 glTexCoord2d(0, ds->height);
151 glVertex2d(0, screen->h);
152 glEnd();
153 glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
154 SDL_GL_SwapBuffers();
155 }
156 #endif
158 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
159 {
160 // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
161 if (shared) {
162 SDL_Rect rec;
163 rec.x = x;
164 rec.y = y;
165 rec.w = w;
166 rec.h = h;
167 SDL_BlitSurface(shared, &rec, screen, &rec);
168 }
169 SDL_Flip(screen);
170 }
172 static void sdl_setdata(DisplayState *ds, void *pixels)
173 {
174 uint32_t rmask, gmask, bmask, amask = 0;
175 switch (ds->depth) {
176 case 8:
177 rmask = 0x000000E0;
178 gmask = 0x0000001C;
179 bmask = 0x00000003;
180 break;
181 case 16:
182 rmask = 0x0000F800;
183 gmask = 0x000007E0;
184 bmask = 0x0000001F;
185 break;
186 case 24:
187 rmask = 0x00FF0000;
188 gmask = 0x0000FF00;
189 bmask = 0x000000FF;
190 break;
191 case 32:
192 rmask = 0x00FF0000;
193 gmask = 0x0000FF00;
194 bmask = 0x000000FF;
195 break;
196 default:
197 return;
198 }
199 shared = SDL_CreateRGBSurfaceFrom(pixels, width, height, ds->depth, ds->linesize, rmask , gmask, bmask, amask);
200 if (ds->depth == 8 && ds->palette != NULL) {
201 SDL_Color palette[256];
202 int i;
203 for (i = 0; i < 256; i++) {
204 uint8_t rgb = ds->palette[i] >> 16;
205 palette[i].r = ((rgb & 0xe0) >> 5) * 255 / 7;
206 palette[i].g = ((rgb & 0x1c) >> 2) * 255 / 7;
207 palette[i].b = (rgb & 0x3) * 255 / 3;
208 }
209 SDL_SetColors(shared, palette, 0, 256);
210 }
211 ds->data = pixels;
212 }
214 static void sdl_resize(DisplayState *ds, int w, int h, int linesize)
215 {
216 int flags;
218 // printf("resizing to %d %d\n", w, h);
220 #ifdef CONFIG_OPENGL
221 if (ds->shared_buf && opengl_enabled)
222 flags = SDL_OPENGL|SDL_RESIZABLE;
223 else
224 #endif
225 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL|SDL_DOUBLEBUF|SDL_HWPALETTE;
227 if (gui_fullscreen) {
228 flags |= SDL_FULLSCREEN;
229 flags &= ~SDL_RESIZABLE;
230 }
232 width = w;
233 height = h;
235 again:
236 screen = SDL_SetVideoMode(w, h, 0, flags);
238 /* Process any WM-generated resize event */
239 SDL_PumpEvents();
241 if (!screen) {
242 fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError());
243 if (opengl_enabled) {
244 /* Fallback to SDL */
245 opengl_enabled = 0;
246 ds->dpy_update = sdl_update;
247 ds->dpy_setdata = sdl_setdata;
248 sdl_resize(ds, w, h, linesize);
249 return;
250 }
251 exit(1);
252 }
254 if (!opengl_enabled) {
255 if (!screen->pixels && (flags & SDL_HWSURFACE) && (flags & SDL_FULLSCREEN)) {
256 flags &= ~SDL_HWSURFACE;
257 goto again;
258 }
260 if (!screen->pixels) {
261 fprintf(stderr, "Could not open SDL display: %s\n", SDL_GetError());
262 exit(1);
263 }
264 }
266 ds->width = w;
267 ds->height = h;
268 if (!ds->shared_buf) {
269 ds->depth = screen->format->BitsPerPixel;
270 if (ds->depth == 32 && screen->format->Rshift == 0) {
271 ds->bgr = 1;
272 } else {
273 ds->bgr = 0;
274 }
275 ds->data = screen->pixels;
276 ds->linesize = screen->pitch;
277 } else {
278 ds->linesize = linesize;
279 #ifdef CONFIG_OPENGL
280 switch(screen->format->BitsPerPixel) {
281 case 8:
282 gl_format = GL_RGB;
283 break;
284 case 16:
285 gl_format = GL_RGB;
286 break;
287 case 24:
288 gl_format = GL_RGB;
289 break;
290 case 32:
291 if (!screen->format->Rshift)
292 gl_format = GL_BGRA;
293 else
294 gl_format = GL_RGBA;
295 break;
296 };
297 #endif
298 }
299 }
301 static void sdl_colourdepth(DisplayState *ds, int depth)
302 {
303 if (!depth || !ds->depth) {
304 ds->shared_buf = 0;
305 return;
306 }
307 ds->shared_buf = 1;
308 ds->depth = depth;
309 ds->linesize = width * depth / 8;
310 #ifdef CONFIG_OPENGL
311 if (opengl_enabled) {
312 ds->dpy_update = opengl_update;
313 ds->dpy_setdata = opengl_setdata;
314 }
315 #endif
316 }
318 /* generic keyboard conversion */
320 #include "sdl_keysym.h"
321 #include "keymaps.c"
323 static kbd_layout_t *kbd_layout = NULL;
325 static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev)
326 {
327 int keysym;
328 /* workaround for X11+SDL bug with AltGR */
329 keysym = ev->keysym.sym;
330 if (keysym == 0 && ev->keysym.scancode == 113)
331 keysym = SDLK_MODE;
332 /* For Japanese key '\' and '|' */
333 if (keysym == 92 && ev->keysym.scancode == 133) {
334 keysym = 0xa5;
335 }
336 return keysym2scancode(kbd_layout, keysym);
337 }
339 /* specific keyboard conversions from scan codes */
341 #if defined(_WIN32)
343 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
344 {
345 return ev->keysym.scancode;
346 }
348 #else
350 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
351 {
352 int keycode;
354 keycode = ev->keysym.scancode;
356 if (keycode < 9) {
357 keycode = 0;
358 } else if (keycode < 97) {
359 keycode -= 8; /* just an offset */
360 } else if (keycode < 212) {
361 /* use conversion table */
362 keycode = _translate_keycode(keycode - 97);
363 } else {
364 keycode = 0;
365 }
366 return keycode;
367 }
369 #endif
371 static void reset_keys(void)
372 {
373 int i;
374 for(i = 0; i < 256; i++) {
375 if (modifiers_state[i]) {
376 if (i & 0x80)
377 kbd_put_keycode(0xe0);
378 kbd_put_keycode(i | 0x80);
379 modifiers_state[i] = 0;
380 }
381 }
382 }
384 static void sdl_process_key(SDL_KeyboardEvent *ev)
385 {
386 int keycode, v;
388 if (ev->keysym.sym == SDLK_PAUSE) {
389 /* specific case */
390 v = 0;
391 if (ev->type == SDL_KEYUP)
392 v |= 0x80;
393 kbd_put_keycode(0xe1);
394 kbd_put_keycode(0x1d | v);
395 kbd_put_keycode(0x45 | v);
396 return;
397 }
399 if (kbd_layout) {
400 keycode = sdl_keyevent_to_keycode_generic(ev);
401 } else {
402 keycode = sdl_keyevent_to_keycode(ev);
403 }
405 switch(keycode) {
406 case 0x00:
407 /* sent when leaving window: reset the modifiers state */
408 reset_keys();
409 return;
410 case 0x2a: /* Left Shift */
411 case 0x36: /* Right Shift */
412 case 0x1d: /* Left CTRL */
413 case 0x9d: /* Right CTRL */
414 case 0x38: /* Left ALT */
415 case 0xb8: /* Right ALT */
416 if (ev->type == SDL_KEYUP)
417 modifiers_state[keycode] = 0;
418 else
419 modifiers_state[keycode] = 1;
420 break;
421 case 0x45: /* num lock */
422 case 0x3a: /* caps lock */
423 /* SDL does not send the key up event, so we generate it */
424 kbd_put_keycode(keycode);
425 kbd_put_keycode(keycode | 0x80);
426 return;
427 }
429 /* now send the key code */
430 if (keycode & 0x80)
431 kbd_put_keycode(0xe0);
432 if (ev->type == SDL_KEYUP)
433 kbd_put_keycode(keycode | 0x80);
434 else
435 kbd_put_keycode(keycode & 0x7f);
436 }
438 static void sdl_update_caption(void)
439 {
440 char buf[1024];
441 strcpy(buf, domain_name);
442 if (!vm_running) {
443 strcat(buf, " [Stopped]");
444 }
445 if (gui_grab) {
446 strcat(buf, " - Press Ctrl-Alt to exit grab");
447 }
448 SDL_WM_SetCaption(buf, domain_name);
449 }
451 static void sdl_hide_cursor(void)
452 {
453 if (kbd_mouse_is_absolute()) {
454 SDL_ShowCursor(1);
455 SDL_SetCursor(sdl_cursor_hidden);
456 } else {
457 SDL_ShowCursor(0);
458 }
459 }
461 static void sdl_show_cursor(void)
462 {
463 if (!kbd_mouse_is_absolute()) {
464 SDL_ShowCursor(1);
465 SDL_SetCursor(sdl_cursor_normal);
466 }
467 }
469 static void sdl_grab_start(void)
470 {
471 sdl_hide_cursor();
472 SDL_WM_GrabInput(SDL_GRAB_ON);
473 /* dummy read to avoid moving the mouse */
474 SDL_GetRelativeMouseState(NULL, NULL);
475 gui_grab = 1;
476 sdl_update_caption();
477 }
479 static void sdl_grab_end(void)
480 {
481 SDL_WM_GrabInput(SDL_GRAB_OFF);
482 sdl_show_cursor();
483 gui_grab = 0;
484 sdl_update_caption();
485 }
487 static void sdl_send_mouse_event(int dx, int dy, int dz, int state)
488 {
489 int buttons = 0;
490 if (state & SDL_BUTTON(SDL_BUTTON_LEFT))
491 buttons |= MOUSE_EVENT_LBUTTON;
492 if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))
493 buttons |= MOUSE_EVENT_RBUTTON;
494 if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
495 buttons |= MOUSE_EVENT_MBUTTON;
497 if (kbd_mouse_is_absolute()) {
498 if (!absolute_enabled) {
499 sdl_hide_cursor();
500 if (gui_grab) {
501 sdl_grab_end();
502 }
503 absolute_enabled = 1;
504 }
506 SDL_GetMouseState(&dx, &dy);
507 dx = dx * 0x7FFF / (screen->w - 1);
508 dy = dy * 0x7FFF / (screen->h - 1);
509 } else if (absolute_enabled) {
510 sdl_show_cursor();
511 absolute_enabled = 0;
512 }
514 kbd_mouse_event(dx, dy, dz, buttons);
515 }
517 static void toggle_full_screen(DisplayState *ds)
518 {
519 gui_fullscreen = !gui_fullscreen;
520 sdl_resize(ds, ds->width, ds->height, ds->linesize);
521 ds->dpy_setdata(ds, ds->data);
522 if (gui_fullscreen) {
523 gui_saved_grab = gui_grab;
524 sdl_grab_start();
525 } else {
526 if (!gui_saved_grab)
527 sdl_grab_end();
528 }
529 vga_hw_invalidate();
530 vga_hw_update();
531 }
533 static void sdl_refresh(DisplayState *ds)
534 {
535 SDL_Event ev1, *ev = &ev1;
536 int mod_state;
538 if (last_vm_running != vm_running) {
539 last_vm_running = vm_running;
540 sdl_update_caption();
541 }
543 vga_hw_update();
545 while (SDL_PollEvent(ev)) {
546 switch (ev->type) {
547 case SDL_VIDEOEXPOSE:
548 ds->dpy_update(ds, 0, 0, ds->width, ds->height);
549 break;
550 case SDL_KEYDOWN:
551 case SDL_KEYUP:
552 if (ev->type == SDL_KEYDOWN) {
553 mod_state = (SDL_GetModState() & gui_grab_code) ==
554 gui_grab_code;
555 gui_key_modifier_pressed = mod_state;
556 if (gui_key_modifier_pressed) {
557 int keycode;
558 keycode = sdl_keyevent_to_keycode(&ev->key);
559 switch(keycode) {
560 case 0x21: /* 'f' key on US keyboard */
561 toggle_full_screen(ds);
562 gui_keysym = 1;
563 break;
564 case 0x02 ... 0x0a: /* '1' to '9' keys */
565 /* Reset the modifiers sent to the current console */
566 reset_keys();
567 console_select(keycode - 0x02);
568 if (!is_graphic_console()) {
569 /* display grab if going to a text console */
570 if (gui_grab)
571 sdl_grab_end();
572 }
573 gui_keysym = 1;
574 break;
575 default:
576 break;
577 }
578 } else if (!is_graphic_console()) {
579 int keysym;
580 keysym = 0;
581 if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
582 switch(ev->key.keysym.sym) {
583 case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break;
584 case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break;
585 case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break;
586 case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break;
587 case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break;
588 case SDLK_END: keysym = QEMU_KEY_CTRL_END; break;
589 case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break;
590 case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break;
591 default: break;
592 }
593 } else {
594 switch(ev->key.keysym.sym) {
595 case SDLK_UP: keysym = QEMU_KEY_UP; break;
596 case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break;
597 case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break;
598 case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break;
599 case SDLK_HOME: keysym = QEMU_KEY_HOME; break;
600 case SDLK_END: keysym = QEMU_KEY_END; break;
601 case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break;
602 case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break;
603 case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break; case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break;
604 default: break;
605 }
606 }
607 if (keysym) {
608 kbd_put_keysym(keysym);
609 } else if (ev->key.keysym.unicode != 0) {
610 kbd_put_keysym(ev->key.keysym.unicode);
611 }
612 }
613 } else if (ev->type == SDL_KEYUP) {
614 mod_state = (ev->key.keysym.mod & gui_grab_code);
615 if (!mod_state) {
616 if (gui_key_modifier_pressed) {
617 gui_key_modifier_pressed = 0;
618 if (gui_keysym == 0) {
619 /* exit/enter grab if pressing Ctrl-Alt */
620 if (!gui_grab) {
621 /* if the application is not active,
622 do not try to enter grab state. It
623 prevents
624 'SDL_WM_GrabInput(SDL_GRAB_ON)'
625 from blocking all the application
626 (SDL bug). */
627 if (SDL_GetAppState() & SDL_APPACTIVE)
628 sdl_grab_start();
629 } else {
630 sdl_grab_end();
631 }
632 /* SDL does not send back all the
633 modifiers key, so we must correct it */
634 reset_keys();
635 break;
636 }
637 gui_keysym = 0;
638 }
639 }
640 }
641 if (is_graphic_console() && !gui_keysym)
642 sdl_process_key(&ev->key);
643 break;
644 case SDL_QUIT:
645 if (!no_quit) {
646 qemu_system_shutdown_request();
647 }
648 break;
649 case SDL_MOUSEMOTION:
650 if (gui_grab || kbd_mouse_is_absolute() ||
651 absolute_enabled) {
652 int dx, dy, state;
653 state = SDL_GetRelativeMouseState(&dx, &dy);
654 sdl_send_mouse_event(dx, dy, 0, state);
655 }
656 break;
657 case SDL_MOUSEBUTTONUP:
658 if (gui_grab || kbd_mouse_is_absolute()) {
659 int dx, dy, state;
660 state = SDL_GetRelativeMouseState(&dx, &dy);
661 sdl_send_mouse_event(dx, dy, 0, state);
662 }
663 break;
664 case SDL_MOUSEBUTTONDOWN:
665 {
666 SDL_MouseButtonEvent *bev = &ev->button;
667 if (!gui_grab && !kbd_mouse_is_absolute()) {
668 if (ev->type == SDL_MOUSEBUTTONDOWN &&
669 (bev->state & SDL_BUTTON_LMASK)) {
670 /* start grabbing all events */
671 sdl_grab_start();
672 }
673 } else {
674 int dx, dy, dz, state;
675 dz = 0;
676 state = SDL_GetRelativeMouseState(&dx, &dy);
677 #ifdef SDL_BUTTON_WHEELUP
678 if (bev->button == SDL_BUTTON_WHEELUP) {
679 dz = -1;
680 } else if (bev->button == SDL_BUTTON_WHEELDOWN) {
681 dz = 1;
682 } else {
683 state = bev->button | state;
684 }
685 #endif
686 sdl_send_mouse_event(dx, dy, dz, state);
687 }
688 }
689 break;
690 case SDL_ACTIVEEVENT:
691 if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
692 !ev->active.gain && !gui_fullscreen_initial_grab) {
693 sdl_grab_end();
694 }
695 if (ev->active.state & SDL_APPACTIVE) {
696 if (ev->active.gain) {
697 /* Back to default interval */
698 ds->gui_timer_interval = 0;
699 ds->idle = 0;
700 } else {
701 /* Sleeping interval */
702 ds->gui_timer_interval = 500;
703 ds->idle = 1;
704 }
705 }
706 break;
707 #ifdef CONFIG_OPENGL
708 case SDL_VIDEORESIZE:
709 {
710 if (ds->shared_buf && opengl_enabled) {
711 SDL_ResizeEvent *rev = &ev->resize;
712 screen = SDL_SetVideoMode(rev->w, rev->h, 0, SDL_OPENGL|SDL_RESIZABLE);
713 opengl_setdata(ds, ds->data);
714 opengl_update(ds, 0, 0, ds->width, ds->height);
715 }
716 break;
717 }
718 #endif
719 default:
720 break;
721 }
722 }
723 }
725 static void sdl_cleanup(void)
726 {
727 #ifdef CONFIG_OPENGL
728 if (texture_ref) glDeleteTextures(1, &texture_ref);
729 #endif
730 SDL_Quit();
731 }
733 void sdl_display_init(DisplayState *ds, int full_screen, int opengl)
734 {
735 int flags;
736 uint8_t data = 0;
737 opengl_enabled = opengl;
739 #if defined(__APPLE__)
740 /* always use generic keymaps */
741 if (!keyboard_layout)
742 keyboard_layout = "en-us";
743 #endif
744 if(keyboard_layout) {
745 kbd_layout = init_keyboard_layout(keyboard_layout);
746 if (!kbd_layout)
747 exit(1);
748 }
750 flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
751 if (SDL_Init (flags)) {
752 fprintf(stderr, "Could not initialize SDL - exiting\n");
753 exit(1);
754 }
755 #ifndef _WIN32
756 /* NOTE: we still want Ctrl-C to work, so we undo the SDL redirections */
757 signal(SIGINT, SIG_DFL);
758 signal(SIGQUIT, SIG_DFL);
759 #endif
761 ds->dpy_update = sdl_update;
762 ds->dpy_resize = sdl_resize;
763 ds->dpy_refresh = sdl_refresh;
764 ds->dpy_colourdepth = sdl_colourdepth;
765 ds->dpy_setdata = sdl_setdata;
767 sdl_resize(ds, 640, 400, 640 * 4);
768 sdl_update_caption();
769 SDL_EnableKeyRepeat(250, 50);
770 SDL_EnableUNICODE(1);
771 gui_grab = 0;
773 sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
774 sdl_cursor_normal = SDL_GetCursor();
776 atexit(sdl_cleanup);
777 if (full_screen) {
778 gui_fullscreen = 1;
779 gui_fullscreen_initial_grab = 1;
780 sdl_grab_start();
781 }
782 }