Add version information for 0.10.0 release.
[qemu] / sdl.c
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 "qemu-common.h"
25 #include "console.h"
26 #include "sysemu.h"
27 #include "x_keymap.h"
28
29 #include <SDL.h>
30 #include <SDL/SDL_syswm.h>
31
32 #ifndef _WIN32
33 #include <signal.h>
34 #endif
35
36 static DisplayChangeListener *dcl;
37 static SDL_Surface *real_screen;
38 static SDL_Surface *guest_screen = NULL;
39 static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
40 static int last_vm_running;
41 static int gui_saved_grab;
42 static int gui_fullscreen;
43 static int gui_noframe;
44 static int gui_key_modifier_pressed;
45 static int gui_keysym;
46 static int gui_fullscreen_initial_grab;
47 static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
48 static uint8_t modifiers_state[256];
49 static int width, height;
50 static SDL_Cursor *sdl_cursor_normal;
51 static SDL_Cursor *sdl_cursor_hidden;
52 static int absolute_enabled = 0;
53 static int guest_cursor = 0;
54 static int guest_x, guest_y;
55 static SDL_Cursor *guest_sprite = 0;
56
57 static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
58 {
59     SDL_Rect rec;
60     rec.x = x;
61     rec.y = y;
62     rec.w = w;
63     rec.h = h;
64     //    printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
65
66     SDL_BlitSurface(guest_screen, &rec, real_screen, &rec);
67     SDL_UpdateRect(real_screen, x, y, w, h);
68 }
69
70 static void sdl_setdata(DisplayState *ds)
71 {
72     SDL_Rect rec;
73     rec.x = 0;
74     rec.y = 0;
75     rec.w = real_screen->w;
76     rec.h = real_screen->h;
77
78     if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
79
80     guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds),
81                                             ds_get_bits_per_pixel(ds), ds_get_linesize(ds),
82                                             ds->surface->pf.rmask, ds->surface->pf.gmask,
83                                             ds->surface->pf.bmask, ds->surface->pf.amask);
84 }
85
86 static void sdl_resize(DisplayState *ds)
87 {
88     int flags;
89
90     //    printf("resizing to %d %d\n", w, h);
91
92     flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
93     if (gui_fullscreen)
94         flags |= SDL_FULLSCREEN;
95     if (gui_noframe)
96         flags |= SDL_NOFRAME;
97
98     width = ds_get_width(ds);
99     height = ds_get_height(ds);
100     real_screen = SDL_SetVideoMode(width, height, 0, flags);
101     if (!real_screen) {
102         fprintf(stderr, "Could not open SDL display\n");
103         exit(1);
104     }
105
106     sdl_setdata(ds);
107 }
108
109 /* generic keyboard conversion */
110
111 #include "sdl_keysym.h"
112 #include "keymaps.c"
113
114 static kbd_layout_t *kbd_layout = NULL;
115
116 static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev)
117 {
118     int keysym;
119     /* workaround for X11+SDL bug with AltGR */
120     keysym = ev->keysym.sym;
121     if (keysym == 0 && ev->keysym.scancode == 113)
122         keysym = SDLK_MODE;
123     /* For Japanese key '\' and '|' */
124     if (keysym == 92 && ev->keysym.scancode == 133) {
125         keysym = 0xa5;
126     }
127     return keysym2scancode(kbd_layout, keysym);
128 }
129
130 /* specific keyboard conversions from scan codes */
131
132 #if defined(_WIN32)
133
134 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
135 {
136     return ev->keysym.scancode;
137 }
138
139 #else
140
141 #if defined(SDL_VIDEO_DRIVER_X11)
142 #include <X11/XKBlib.h>
143
144 static int check_for_evdev(void)
145 {
146     SDL_SysWMinfo info;
147     XkbDescPtr desc;
148     int has_evdev = 0;
149     const char *keycodes;
150
151     SDL_VERSION(&info.version);
152     if (!SDL_GetWMInfo(&info))
153         return 0;
154
155     desc = XkbGetKeyboard(info.info.x11.display,
156                           XkbGBN_AllComponentsMask,
157                           XkbUseCoreKbd);
158     if (desc == NULL || desc->names == NULL)
159         return 0;
160
161     keycodes = XGetAtomName(info.info.x11.display, desc->names->keycodes);
162     if (keycodes == NULL)
163         fprintf(stderr, "could not lookup keycode name\n");
164     else if (strstart(keycodes, "evdev_", NULL))
165         has_evdev = 1;
166     else if (!strstart(keycodes, "xfree86_", NULL))
167         fprintf(stderr,
168                 "unknown keycodes `%s', please report to qemu-devel@nongnu.org\n",
169                 keycodes);
170
171     XkbFreeClientMap(desc, XkbGBN_AllComponentsMask, True);
172
173     return has_evdev;
174 }
175 #else
176 static int check_for_evdev(void)
177 {
178         return 0;
179 }
180 #endif
181
182 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
183 {
184     int keycode;
185     static int has_evdev = -1;
186
187     if (has_evdev == -1)
188         has_evdev = check_for_evdev();
189
190     keycode = ev->keysym.scancode;
191
192     if (keycode < 9) {
193         keycode = 0;
194     } else if (keycode < 97) {
195         keycode -= 8; /* just an offset */
196     } else if (keycode < 158) {
197         /* use conversion table */
198         if (has_evdev)
199             keycode = translate_evdev_keycode(keycode - 97);
200         else
201             keycode = translate_xfree86_keycode(keycode - 97);
202     } else if (keycode == 208) { /* Hiragana_Katakana */
203         keycode = 0x70;
204     } else if (keycode == 211) { /* backslash */
205         keycode = 0x73;
206     } else {
207         keycode = 0;
208     }
209     return keycode;
210 }
211
212 #endif
213
214 static void reset_keys(void)
215 {
216     int i;
217     for(i = 0; i < 256; i++) {
218         if (modifiers_state[i]) {
219             if (i & 0x80)
220                 kbd_put_keycode(0xe0);
221             kbd_put_keycode(i | 0x80);
222             modifiers_state[i] = 0;
223         }
224     }
225 }
226
227 static void sdl_process_key(SDL_KeyboardEvent *ev)
228 {
229     int keycode, v;
230
231     if (ev->keysym.sym == SDLK_PAUSE) {
232         /* specific case */
233         v = 0;
234         if (ev->type == SDL_KEYUP)
235             v |= 0x80;
236         kbd_put_keycode(0xe1);
237         kbd_put_keycode(0x1d | v);
238         kbd_put_keycode(0x45 | v);
239         return;
240     }
241
242     if (kbd_layout) {
243         keycode = sdl_keyevent_to_keycode_generic(ev);
244     } else {
245         keycode = sdl_keyevent_to_keycode(ev);
246     }
247
248     switch(keycode) {
249     case 0x00:
250         /* sent when leaving window: reset the modifiers state */
251         reset_keys();
252         return;
253     case 0x2a:                          /* Left Shift */
254     case 0x36:                          /* Right Shift */
255     case 0x1d:                          /* Left CTRL */
256     case 0x9d:                          /* Right CTRL */
257     case 0x38:                          /* Left ALT */
258     case 0xb8:                         /* Right ALT */
259         if (ev->type == SDL_KEYUP)
260             modifiers_state[keycode] = 0;
261         else
262             modifiers_state[keycode] = 1;
263         break;
264     case 0x45: /* num lock */
265     case 0x3a: /* caps lock */
266         /* SDL does not send the key up event, so we generate it */
267         kbd_put_keycode(keycode);
268         kbd_put_keycode(keycode | 0x80);
269         return;
270     }
271
272     /* now send the key code */
273     if (keycode & 0x80)
274         kbd_put_keycode(0xe0);
275     if (ev->type == SDL_KEYUP)
276         kbd_put_keycode(keycode | 0x80);
277     else
278         kbd_put_keycode(keycode & 0x7f);
279 }
280
281 static void sdl_update_caption(void)
282 {
283     char buf[1024];
284     const char *status = "";
285
286     if (!vm_running)
287         status = " [Stopped]";
288     else if (gui_grab) {
289         if (!alt_grab)
290             status = " - Press Ctrl-Alt to exit grab";
291         else
292             status = " - Press Ctrl-Alt-Shift to exit grab";
293     }
294
295     if (qemu_name)
296         snprintf(buf, sizeof(buf), "QEMU (%s)%s", qemu_name, status);
297     else
298         snprintf(buf, sizeof(buf), "QEMU%s", status);
299
300     SDL_WM_SetCaption(buf, "QEMU");
301 }
302
303 static void sdl_hide_cursor(void)
304 {
305     if (!cursor_hide)
306         return;
307
308     if (kbd_mouse_is_absolute()) {
309         SDL_ShowCursor(1);
310         SDL_SetCursor(sdl_cursor_hidden);
311     } else {
312         SDL_ShowCursor(0);
313     }
314 }
315
316 static void sdl_show_cursor(void)
317 {
318     if (!cursor_hide)
319         return;
320
321     if (!kbd_mouse_is_absolute()) {
322         SDL_ShowCursor(1);
323         if (guest_cursor &&
324                 (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
325             SDL_SetCursor(guest_sprite);
326         else
327             SDL_SetCursor(sdl_cursor_normal);
328     }
329 }
330
331 static void sdl_grab_start(void)
332 {
333     if (guest_cursor) {
334         SDL_SetCursor(guest_sprite);
335         if (!kbd_mouse_is_absolute() && !absolute_enabled)
336             SDL_WarpMouse(guest_x, guest_y);
337     } else
338         sdl_hide_cursor();
339
340     if (SDL_WM_GrabInput(SDL_GRAB_ON) == SDL_GRAB_ON) {
341         gui_grab = 1;
342         sdl_update_caption();
343     } else
344         sdl_show_cursor();
345 }
346
347 static void sdl_grab_end(void)
348 {
349     SDL_WM_GrabInput(SDL_GRAB_OFF);
350     gui_grab = 0;
351     sdl_show_cursor();
352     sdl_update_caption();
353 }
354
355 static void sdl_send_mouse_event(int dx, int dy, int dz, int x, int y, int state)
356 {
357     int buttons;
358     buttons = 0;
359     if (state & SDL_BUTTON(SDL_BUTTON_LEFT))
360         buttons |= MOUSE_EVENT_LBUTTON;
361     if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))
362         buttons |= MOUSE_EVENT_RBUTTON;
363     if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
364         buttons |= MOUSE_EVENT_MBUTTON;
365
366     if (kbd_mouse_is_absolute()) {
367         if (!absolute_enabled) {
368             sdl_hide_cursor();
369             if (gui_grab) {
370                 sdl_grab_end();
371             }
372             absolute_enabled = 1;
373         }
374
375        dx = x * 0x7FFF / (width - 1);
376        dy = y * 0x7FFF / (height - 1);
377     } else if (absolute_enabled) {
378         sdl_show_cursor();
379         absolute_enabled = 0;
380     } else if (guest_cursor) {
381         x -= guest_x;
382         y -= guest_y;
383         guest_x += x;
384         guest_y += y;
385         dx = x;
386         dy = y;
387     }
388
389     kbd_mouse_event(dx, dy, dz, buttons);
390 }
391
392 static void toggle_full_screen(DisplayState *ds)
393 {
394     gui_fullscreen = !gui_fullscreen;
395     sdl_resize(ds);
396     if (gui_fullscreen) {
397         gui_saved_grab = gui_grab;
398         sdl_grab_start();
399     } else {
400         if (!gui_saved_grab)
401             sdl_grab_end();
402     }
403     vga_hw_invalidate();
404     vga_hw_update();
405 }
406
407 static void sdl_refresh(DisplayState *ds)
408 {
409     SDL_Event ev1, *ev = &ev1;
410     int mod_state;
411     int buttonstate = SDL_GetMouseState(NULL, NULL);
412
413     if (last_vm_running != vm_running) {
414         last_vm_running = vm_running;
415         sdl_update_caption();
416     }
417
418     vga_hw_update();
419     SDL_EnableUNICODE(!is_graphic_console());
420
421     while (SDL_PollEvent(ev)) {
422         switch (ev->type) {
423         case SDL_VIDEOEXPOSE:
424             sdl_update(ds, 0, 0, real_screen->w, real_screen->h);
425             break;
426         case SDL_KEYDOWN:
427         case SDL_KEYUP:
428             if (ev->type == SDL_KEYDOWN) {
429                 if (!alt_grab) {
430                     mod_state = (SDL_GetModState() & gui_grab_code) ==
431                                 gui_grab_code;
432                 } else {
433                     mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) ==
434                                 (gui_grab_code | KMOD_LSHIFT);
435                 }
436                 gui_key_modifier_pressed = mod_state;
437                 if (gui_key_modifier_pressed) {
438                     int keycode;
439                     keycode = sdl_keyevent_to_keycode(&ev->key);
440                     switch(keycode) {
441                     case 0x21: /* 'f' key on US keyboard */
442                         toggle_full_screen(ds);
443                         gui_keysym = 1;
444                         break;
445                     case 0x02 ... 0x0a: /* '1' to '9' keys */
446                         /* Reset the modifiers sent to the current console */
447                         reset_keys();
448                         console_select(keycode - 0x02);
449                         if (!is_graphic_console()) {
450                             /* display grab if going to a text console */
451                             if (gui_grab)
452                                 sdl_grab_end();
453                         }
454                         gui_keysym = 1;
455                         break;
456                     default:
457                         break;
458                     }
459                 } else if (!is_graphic_console()) {
460                     int keysym;
461                     keysym = 0;
462                     if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
463                         switch(ev->key.keysym.sym) {
464                         case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break;
465                         case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break;
466                         case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break;
467                         case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break;
468                         case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break;
469                         case SDLK_END: keysym = QEMU_KEY_CTRL_END; break;
470                         case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break;
471                         case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break;
472                         default: break;
473                         }
474                     } else {
475                         switch(ev->key.keysym.sym) {
476                         case SDLK_UP: keysym = QEMU_KEY_UP; break;
477                         case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break;
478                         case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break;
479                         case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break;
480                         case SDLK_HOME: keysym = QEMU_KEY_HOME; break;
481                         case SDLK_END: keysym = QEMU_KEY_END; break;
482                         case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break;
483                         case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break;
484                         case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break;
485                         case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break;
486                         default: break;
487                         }
488                     }
489                     if (keysym) {
490                         kbd_put_keysym(keysym);
491                     } else if (ev->key.keysym.unicode != 0) {
492                         kbd_put_keysym(ev->key.keysym.unicode);
493                     }
494                 }
495             } else if (ev->type == SDL_KEYUP) {
496                 if (!alt_grab) {
497                     mod_state = (ev->key.keysym.mod & gui_grab_code);
498                 } else {
499                     mod_state = (ev->key.keysym.mod &
500                                  (gui_grab_code | KMOD_LSHIFT));
501                 }
502                 if (!mod_state) {
503                     if (gui_key_modifier_pressed) {
504                         gui_key_modifier_pressed = 0;
505                         if (gui_keysym == 0) {
506                             /* exit/enter grab if pressing Ctrl-Alt */
507                             if (!gui_grab) {
508                                 /* if the application is not active,
509                                    do not try to enter grab state. It
510                                    prevents
511                                    'SDL_WM_GrabInput(SDL_GRAB_ON)'
512                                    from blocking all the application
513                                    (SDL bug). */
514                                 if (SDL_GetAppState() & SDL_APPACTIVE)
515                                     sdl_grab_start();
516                             } else {
517                                 sdl_grab_end();
518                             }
519                             /* SDL does not send back all the
520                                modifiers key, so we must correct it */
521                             reset_keys();
522                             break;
523                         }
524                         gui_keysym = 0;
525                     }
526                 }
527             }
528             if (is_graphic_console() && !gui_keysym)
529                 sdl_process_key(&ev->key);
530             break;
531         case SDL_QUIT:
532             if (!no_quit)
533                 qemu_system_shutdown_request();
534             break;
535         case SDL_MOUSEMOTION:
536             if (gui_grab || kbd_mouse_is_absolute() ||
537                 absolute_enabled) {
538                 sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0,
539                        ev->motion.x, ev->motion.y, ev->motion.state);
540             }
541             break;
542         case SDL_MOUSEBUTTONDOWN:
543         case SDL_MOUSEBUTTONUP:
544             {
545                 SDL_MouseButtonEvent *bev = &ev->button;
546                 if (!gui_grab && !kbd_mouse_is_absolute()) {
547                     if (ev->type == SDL_MOUSEBUTTONDOWN &&
548                         (bev->button == SDL_BUTTON_LEFT)) {
549                         /* start grabbing all events */
550                         sdl_grab_start();
551                     }
552                 } else {
553                     int dz;
554                     dz = 0;
555                     if (ev->type == SDL_MOUSEBUTTONDOWN) {
556                         buttonstate |= SDL_BUTTON(bev->button);
557                     } else {
558                         buttonstate &= ~SDL_BUTTON(bev->button);
559                     }
560 #ifdef SDL_BUTTON_WHEELUP
561                     if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) {
562                         dz = -1;
563                     } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
564                         dz = 1;
565                     }
566 #endif
567                     sdl_send_mouse_event(0, 0, dz, bev->x, bev->y, buttonstate);
568                 }
569             }
570             break;
571         case SDL_ACTIVEEVENT:
572             if (gui_grab && ev->active.state == SDL_APPINPUTFOCUS &&
573                 !ev->active.gain && !gui_fullscreen_initial_grab) {
574                 sdl_grab_end();
575             }
576             if (ev->active.state & SDL_APPACTIVE) {
577                 if (ev->active.gain) {
578                     /* Back to default interval */
579                     dcl->gui_timer_interval = 0;
580                     dcl->idle = 0;
581                 } else {
582                     /* Sleeping interval */
583                     dcl->gui_timer_interval = 500;
584                     dcl->idle = 1;
585                 }
586             }
587             break;
588         default:
589             break;
590         }
591     }
592 }
593
594 static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c)
595 {
596     SDL_Rect dst = { x, y, w, h };
597     SDL_FillRect(real_screen, &dst, c);
598 }
599
600 static void sdl_mouse_warp(int x, int y, int on)
601 {
602     if (on) {
603         if (!guest_cursor)
604             sdl_show_cursor();
605         if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) {
606             SDL_SetCursor(guest_sprite);
607             if (!kbd_mouse_is_absolute() && !absolute_enabled)
608                 SDL_WarpMouse(x, y);
609         }
610     } else if (gui_grab)
611         sdl_hide_cursor();
612     guest_cursor = on;
613     guest_x = x, guest_y = y;
614 }
615
616 static void sdl_mouse_define(int width, int height, int bpp,
617                              int hot_x, int hot_y,
618                              uint8_t *image, uint8_t *mask)
619 {
620     uint8_t sprite[256], *line;
621     int x, y, dst, bypl, src = 0;
622     if (guest_sprite)
623         SDL_FreeCursor(guest_sprite);
624
625     memset(sprite, 0, 256);
626     bypl = ((width * bpp + 31) >> 5) << 2;
627     for (y = 0, dst = 0; y < height; y ++, image += bypl) {
628         line = image;
629         for (x = 0; x < width; x ++, dst ++) {
630             switch (bpp) {
631             case 24:
632                 src = *(line ++); src |= *(line ++); src |= *(line ++);
633                 break;
634             case 16:
635             case 15:
636                 src = *(line ++); src |= *(line ++);
637                 break;
638             case 8:
639                 src = *(line ++);
640                 break;
641             case 4:
642                 src = 0xf & (line[x >> 1] >> ((x & 1)) << 2);
643                 break;
644             case 2:
645                 src = 3 & (line[x >> 2] >> ((x & 3)) << 1);
646                 break;
647             case 1:
648                 src = 1 & (line[x >> 3] >> (x & 7));
649                 break;
650             }
651             if (!src)
652                 sprite[dst >> 3] |= (1 << (~dst & 7)) & mask[dst >> 3];
653         }
654     }
655     guest_sprite = SDL_CreateCursor(sprite, mask, width, height, hot_x, hot_y);
656
657     if (guest_cursor &&
658             (gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
659         SDL_SetCursor(guest_sprite);
660 }
661
662 static void sdl_cleanup(void)
663 {
664     if (guest_sprite)
665         SDL_FreeCursor(guest_sprite);
666     SDL_Quit();
667 }
668
669 void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
670 {
671     int flags;
672     uint8_t data = 0;
673
674 #if defined(__APPLE__)
675     /* always use generic keymaps */
676     if (!keyboard_layout)
677         keyboard_layout = "en-us";
678 #endif
679     if(keyboard_layout) {
680         kbd_layout = init_keyboard_layout(keyboard_layout);
681         if (!kbd_layout)
682             exit(1);
683     }
684
685     if (no_frame)
686         gui_noframe = 1;
687
688     flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
689     if (SDL_Init (flags)) {
690         fprintf(stderr, "Could not initialize SDL - exiting\n");
691         exit(1);
692     }
693
694     dcl = qemu_mallocz(sizeof(DisplayChangeListener));
695     dcl->dpy_update = sdl_update;
696     dcl->dpy_resize = sdl_resize;
697     dcl->dpy_refresh = sdl_refresh;
698     dcl->dpy_setdata = sdl_setdata;
699     dcl->dpy_fill = sdl_fill;
700     ds->mouse_set = sdl_mouse_warp;
701     ds->cursor_define = sdl_mouse_define;
702     register_displaychangelistener(ds, dcl);
703
704     sdl_update_caption();
705     SDL_EnableKeyRepeat(250, 50);
706     gui_grab = 0;
707
708     sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
709     sdl_cursor_normal = SDL_GetCursor();
710
711     atexit(sdl_cleanup);
712     if (full_screen) {
713         gui_fullscreen = 1;
714         gui_fullscreen_initial_grab = 1;
715         sdl_grab_start();
716     }
717 }