|
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 "gui_host.h" |
|
28 |
|
29 #include <SDL.h> |
|
30 |
|
31 #ifndef _WIN32 |
|
32 #include <signal.h> |
|
33 #endif |
|
34 |
|
35 static SDL_Surface *screen; |
|
36 static int gui_noframe; |
|
37 static int gui_key_modifier_pressed; |
|
38 static int special_key_combination; |
|
39 static int kbd_in_terminal_mode; |
|
40 static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; |
|
41 static uint8_t modifiers_state[256]; |
|
42 static int width, height; |
|
43 static SDL_Cursor *sdl_cursor_normal; |
|
44 static SDL_Cursor *sdl_cursor_hidden; |
|
45 static SDL_Cursor *guest_sprite = 0; |
|
46 |
|
47 static void sdl_update(DisplayState *ds, int x, int y, int w, int h) |
|
48 { |
|
49 // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); |
|
50 SDL_UpdateRect(screen, ds->x0 + x, ds->y0 + y, w, h); |
|
51 } |
|
52 |
|
53 static void sdl_gui_set_screen_size(int w, int h, int fullscreen_on) |
|
54 { |
|
55 int flags; |
|
56 |
|
57 // printf("resizing to %d %d\n", w, h); |
|
58 |
|
59 flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL; |
|
60 if (fullscreen_on) |
|
61 flags |= SDL_FULLSCREEN; |
|
62 if (gui_noframe) |
|
63 flags |= SDL_NOFRAME; |
|
64 |
|
65 width = w; |
|
66 height = h; |
|
67 |
|
68 again: |
|
69 screen = SDL_SetVideoMode(width, height, 0, flags); |
|
70 if (!screen) { |
|
71 fprintf(stderr, "Could not open SDL display\n"); |
|
72 exit(1); |
|
73 } |
|
74 if (!screen->pixels && (flags & SDL_HWSURFACE) && (flags & SDL_FULLSCREEN)) { |
|
75 flags &= ~SDL_HWSURFACE; |
|
76 goto again; |
|
77 } |
|
78 |
|
79 if (!screen->pixels) { |
|
80 fprintf(stderr, "Could not open SDL display\n"); |
|
81 exit(1); |
|
82 } |
|
83 } |
|
84 |
|
85 static void sdl_gui_get_screen_data(screen_data_t *new_screen_data) |
|
86 { |
|
87 new_screen_data->data = screen->pixels; |
|
88 new_screen_data->linesize = screen->pitch; |
|
89 new_screen_data->width = screen->w; |
|
90 new_screen_data->height = screen->h; |
|
91 new_screen_data->depth = screen->format->BitsPerPixel; |
|
92 /* SDL BitsPerPixel never indicates any values other than |
|
93 multiples of 8, so we need to check for strange depths. */ |
|
94 if (new_screen_data->depth == 16) { |
|
95 uint32_t mask; |
|
96 |
|
97 mask = screen->format->Rmask; |
|
98 mask |= screen->format->Gmask; |
|
99 mask |= screen->format->Bmask; |
|
100 if ((mask & 0x8000) == 0) |
|
101 new_screen_data->depth = 15; |
|
102 } |
|
103 if (new_screen_data->depth == 32 && screen->format->Rshift == 0) { |
|
104 new_screen_data->bgr = 1; |
|
105 } else { |
|
106 new_screen_data->bgr = 0; |
|
107 } |
|
108 } |
|
109 |
|
110 |
|
111 /* generic keyboard conversion */ |
|
112 |
|
113 #include "sdl_keysym.h" |
|
114 #include "keymaps.c" |
|
115 |
|
116 static kbd_layout_t *kbd_layout = NULL; |
|
117 |
|
118 static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev) |
|
119 { |
|
120 int keysym; |
|
121 /* workaround for X11+SDL bug with AltGR */ |
|
122 keysym = ev->keysym.sym; |
|
123 if (keysym == 0 && ev->keysym.scancode == 113) |
|
124 keysym = SDLK_MODE; |
|
125 /* For Japanese key '\' and '|' */ |
|
126 if (keysym == 92 && ev->keysym.scancode == 133) { |
|
127 keysym = 0xa5; |
|
128 } |
|
129 return keysym2scancode(kbd_layout, keysym); |
|
130 } |
|
131 |
|
132 /* specific keyboard conversions from scan codes */ |
|
133 |
|
134 #if defined(_WIN32) |
|
135 |
|
136 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) |
|
137 { |
|
138 return ev->keysym.scancode; |
|
139 } |
|
140 |
|
141 #else |
|
142 |
|
143 static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) |
|
144 { |
|
145 int keycode; |
|
146 |
|
147 keycode = ev->keysym.scancode; |
|
148 |
|
149 if (keycode < 9) { |
|
150 keycode = 0; |
|
151 } else if (keycode < 97) { |
|
152 keycode -= 8; /* just an offset */ |
|
153 } else if (keycode < 212) { |
|
154 /* use conversion table */ |
|
155 keycode = _translate_keycode(keycode - 97); |
|
156 } else { |
|
157 keycode = 0; |
|
158 } |
|
159 return keycode; |
|
160 } |
|
161 |
|
162 #endif |
|
163 |
|
164 static void reset_keys(void) |
|
165 { |
|
166 int i; |
|
167 for(i = 0; i < 256; i++) { |
|
168 if (modifiers_state[i]) { |
|
169 if (i & 0x80) |
|
170 gui_notify_dev_key(0xe0); |
|
171 gui_notify_dev_key(i | 0x80); |
|
172 modifiers_state[i] = 0; |
|
173 } |
|
174 } |
|
175 } |
|
176 |
|
177 static void sdl_process_key(SDL_KeyboardEvent *ev) |
|
178 { |
|
179 int keycode, v; |
|
180 |
|
181 if (ev->keysym.sym == SDLK_PAUSE) { |
|
182 /* specific case */ |
|
183 v = 0; |
|
184 if (ev->type == SDL_KEYUP) |
|
185 v |= 0x80; |
|
186 gui_notify_dev_key(0xe1); |
|
187 gui_notify_dev_key(0x1d | v); |
|
188 gui_notify_dev_key(0x45 | v); |
|
189 return; |
|
190 } |
|
191 |
|
192 if (kbd_layout) { |
|
193 keycode = sdl_keyevent_to_keycode_generic(ev); |
|
194 } else { |
|
195 keycode = sdl_keyevent_to_keycode(ev); |
|
196 } |
|
197 |
|
198 switch(keycode) { |
|
199 case 0x00: |
|
200 /* sent when leaving window: reset the modifiers state */ |
|
201 reset_keys(); |
|
202 return; |
|
203 case 0x2a: /* Left Shift */ |
|
204 case 0x36: /* Right Shift */ |
|
205 case 0x1d: /* Left CTRL */ |
|
206 case 0x9d: /* Right CTRL */ |
|
207 case 0x38: /* Left ALT */ |
|
208 case 0xb8: /* Right ALT */ |
|
209 if (ev->type == SDL_KEYUP) |
|
210 modifiers_state[keycode] = 0; |
|
211 else |
|
212 modifiers_state[keycode] = 1; |
|
213 break; |
|
214 case 0x45: /* num lock */ |
|
215 case 0x3a: /* caps lock */ |
|
216 /* SDL does not send the key up event, so we generate it */ |
|
217 gui_notify_dev_key(keycode); |
|
218 gui_notify_dev_key(keycode | 0x80); |
|
219 return; |
|
220 } |
|
221 |
|
222 /* now send the key code */ |
|
223 if (keycode & 0x80) |
|
224 gui_notify_dev_key(0xe0); |
|
225 if (ev->type == SDL_KEYUP) |
|
226 gui_notify_dev_key(keycode | 0x80); |
|
227 else |
|
228 gui_notify_dev_key(keycode & 0x7f); |
|
229 } |
|
230 |
|
231 static int sdl_state_to_qemu(int sdl_state) |
|
232 { |
|
233 int buttons = 0; |
|
234 if (sdl_state & SDL_BUTTON(SDL_BUTTON_LEFT)) |
|
235 buttons |= MOUSE_EVENT_LBUTTON; |
|
236 if (sdl_state & SDL_BUTTON(SDL_BUTTON_RIGHT)) |
|
237 buttons |= MOUSE_EVENT_RBUTTON; |
|
238 if (sdl_state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) |
|
239 buttons |= MOUSE_EVENT_MBUTTON; |
|
240 |
|
241 return buttons; |
|
242 } |
|
243 |
|
244 static void sdl_gui_process_events(void) |
|
245 { |
|
246 SDL_Event ev1, *ev = &ev1; |
|
247 int mod_state; |
|
248 int buttonstate = SDL_GetMouseState(NULL, NULL); |
|
249 |
|
250 gui_refresh_caption(); |
|
251 |
|
252 /*vga_hw_update();*/ |
|
253 SDL_EnableUNICODE(kbd_in_terminal_mode); |
|
254 |
|
255 while (SDL_PollEvent(ev)) { |
|
256 switch (ev->type) { |
|
257 case SDL_VIDEOEXPOSE: |
|
258 gui_notify_repaint_screen(); |
|
259 break; |
|
260 case SDL_KEYDOWN: |
|
261 case SDL_KEYUP: |
|
262 if (ev->type == SDL_KEYDOWN) { |
|
263 if (!alt_grab) { |
|
264 mod_state = (SDL_GetModState() & gui_grab_code) == |
|
265 gui_grab_code; |
|
266 } else { |
|
267 mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) == |
|
268 (gui_grab_code | KMOD_LSHIFT); |
|
269 } |
|
270 gui_key_modifier_pressed = mod_state; |
|
271 if (gui_key_modifier_pressed) { |
|
272 int keycode; |
|
273 keycode = sdl_keyevent_to_keycode(&ev->key); |
|
274 switch(keycode) { |
|
275 case 0x21: /* 'f' key on US keyboard */ |
|
276 if (gui_allows_fullscreen()) { |
|
277 gui_notify_toggle_fullscreen(); |
|
278 special_key_combination = 1; |
|
279 } |
|
280 break; |
|
281 case 0x02 ... 0x0a: /* '1' to '9' keys */ |
|
282 /* Reset the modifiers sent to the current console */ |
|
283 reset_keys(); |
|
284 gui_notify_console_select(keycode - 0x02); |
|
285 special_key_combination = 1; |
|
286 break; |
|
287 default: |
|
288 break; |
|
289 } |
|
290 } else if (kbd_in_terminal_mode) { |
|
291 int keysym; |
|
292 keysym = 0; |
|
293 if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) { |
|
294 switch(ev->key.keysym.sym) { |
|
295 case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break; |
|
296 case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break; |
|
297 case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break; |
|
298 case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break; |
|
299 case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break; |
|
300 case SDLK_END: keysym = QEMU_KEY_CTRL_END; break; |
|
301 case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break; |
|
302 case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break; |
|
303 default: break; |
|
304 } |
|
305 } else { |
|
306 switch(ev->key.keysym.sym) { |
|
307 case SDLK_UP: keysym = QEMU_KEY_UP; break; |
|
308 case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break; |
|
309 case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break; |
|
310 case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break; |
|
311 case SDLK_HOME: keysym = QEMU_KEY_HOME; break; |
|
312 case SDLK_END: keysym = QEMU_KEY_END; break; |
|
313 case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break; |
|
314 case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break; |
|
315 case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break; |
|
316 case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break; |
|
317 default: break; |
|
318 } |
|
319 } |
|
320 if (keysym) { |
|
321 gui_notify_term_key(keysym); |
|
322 } else if (ev->key.keysym.unicode != 0) { |
|
323 gui_notify_term_key(ev->key.keysym.unicode); |
|
324 } |
|
325 } |
|
326 } else if (ev->type == SDL_KEYUP) { |
|
327 if (!alt_grab) { |
|
328 mod_state = (ev->key.keysym.mod & gui_grab_code); |
|
329 } else { |
|
330 mod_state = (ev->key.keysym.mod & |
|
331 (gui_grab_code | KMOD_LSHIFT)); |
|
332 } |
|
333 if (!mod_state) { |
|
334 if (gui_key_modifier_pressed) { |
|
335 gui_key_modifier_pressed = 0; |
|
336 if (!special_key_combination) { |
|
337 /* exit/enter grab if pressing Ctrl-Alt */ |
|
338 gui_notify_toggle_grabmode(); |
|
339 /* SDL does not send back all the |
|
340 modifiers key, so we must correct it */ |
|
341 reset_keys(); |
|
342 break; |
|
343 } |
|
344 special_key_combination = 0; |
|
345 } |
|
346 } |
|
347 } |
|
348 if (!kbd_in_terminal_mode && !special_key_combination) |
|
349 sdl_process_key(&ev->key); |
|
350 break; |
|
351 case SDL_QUIT: |
|
352 if (!no_quit) |
|
353 qemu_system_shutdown_request(); |
|
354 break; |
|
355 case SDL_MOUSEMOTION: |
|
356 gui_notify_mouse_motion(ev->motion.xrel, ev->motion.yrel, 0, |
|
357 ev->motion.x, ev->motion.y, |
|
358 sdl_state_to_qemu(ev->motion.state)); |
|
359 break; |
|
360 case SDL_MOUSEBUTTONDOWN: |
|
361 case SDL_MOUSEBUTTONUP: |
|
362 { |
|
363 SDL_MouseButtonEvent *bev = &ev->button; |
|
364 int dz = 0; |
|
365 |
|
366 if (ev->type == SDL_MOUSEBUTTONDOWN) { |
|
367 buttonstate |= SDL_BUTTON(bev->button); |
|
368 } else { |
|
369 buttonstate &= ~SDL_BUTTON(bev->button); |
|
370 } |
|
371 #ifdef SDL_BUTTON_WHEELUP |
|
372 if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) { |
|
373 dz = -1; |
|
374 } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) { |
|
375 dz = 1; |
|
376 } |
|
377 #endif |
|
378 gui_notify_mouse_button(dz, bev->x, bev->y, sdl_state_to_qemu(buttonstate)); |
|
379 } |
|
380 break; |
|
381 case SDL_ACTIVEEVENT: |
|
382 if (ev->active.state == SDL_APPINPUTFOCUS && !ev->active.gain) { |
|
383 gui_notify_input_focus_lost(); |
|
384 } else if (ev->active.state & SDL_APPACTIVE) { |
|
385 gui_notify_app_focus(ev->active.gain); |
|
386 } |
|
387 break; |
|
388 default: |
|
389 break; |
|
390 } |
|
391 } |
|
392 } |
|
393 |
|
394 static void sdl_gui_set_kbd_terminal_mode(int on) |
|
395 { |
|
396 kbd_in_terminal_mode = on; |
|
397 } |
|
398 |
|
399 static void sdl_fill(DisplayState *ds, int x, int y, int w, int h, uint32_t c) |
|
400 { |
|
401 SDL_Rect dst = { x, y, w, h }; |
|
402 SDL_FillRect(screen, &dst, c); |
|
403 } |
|
404 |
|
405 static void sdl_mouse_warp(int x, int y, int on) |
|
406 { |
|
407 gui_notify_mouse_warp(x, y, on); |
|
408 } |
|
409 |
|
410 static void sdl_mouse_define(int width, int height, int bpp, |
|
411 int hot_x, int hot_y, |
|
412 uint8_t *image, uint8_t *mask) |
|
413 { |
|
414 uint8_t sprite[256], *line; |
|
415 int x, y, dst, bypl, src = 0; |
|
416 if (guest_sprite) |
|
417 SDL_FreeCursor(guest_sprite); |
|
418 |
|
419 memset(sprite, 0, 256); |
|
420 bypl = ((width * bpp + 31) >> 5) << 2; |
|
421 for (y = 0, dst = 0; y < height; y ++, image += bypl) { |
|
422 line = image; |
|
423 for (x = 0; x < width; x ++, dst ++) { |
|
424 switch (bpp) { |
|
425 case 24: |
|
426 src = *(line ++); src |= *(line ++); src |= *(line ++); |
|
427 break; |
|
428 case 16: |
|
429 case 15: |
|
430 src = *(line ++); src |= *(line ++); |
|
431 break; |
|
432 case 8: |
|
433 src = *(line ++); |
|
434 break; |
|
435 case 4: |
|
436 src = 0xf & (line[x >> 1] >> ((x & 1)) << 2); |
|
437 break; |
|
438 case 2: |
|
439 src = 3 & (line[x >> 2] >> ((x & 3)) << 1); |
|
440 break; |
|
441 case 1: |
|
442 src = 1 & (line[x >> 3] >> (x & 7)); |
|
443 break; |
|
444 } |
|
445 if (!src) |
|
446 sprite[dst >> 3] |= (1 << (~dst & 7)) & mask[dst >> 3]; |
|
447 } |
|
448 } |
|
449 guest_sprite = SDL_CreateCursor(sprite, mask, width, height, hot_x, hot_y); |
|
450 |
|
451 gui_notify_new_guest_cursor(); |
|
452 } |
|
453 |
|
454 static void sdl_cleanup(void) |
|
455 { |
|
456 if (guest_sprite) |
|
457 SDL_FreeCursor(guest_sprite); |
|
458 SDL_Quit(); |
|
459 } |
|
460 |
|
461 /******** GUI CALLBACKS **********/ |
|
462 static void sdl_gui_turn_cursor_on(gui_cursor_type_t cursor_type) |
|
463 { |
|
464 SDL_ShowCursor(1); |
|
465 |
|
466 switch(cursor_type) { |
|
467 case GUI_CURSOR_NORMAL: |
|
468 SDL_SetCursor(sdl_cursor_normal); |
|
469 break; |
|
470 case GUI_CURSOR_GUEST_SPRITE: |
|
471 SDL_SetCursor(guest_sprite); |
|
472 break; |
|
473 case GUI_CURSOR_HIDDEN: |
|
474 SDL_SetCursor(sdl_cursor_hidden); |
|
475 break; |
|
476 case GUI_CURSOR_GRABBING: |
|
477 if (guest_sprite) |
|
478 SDL_SetCursor(guest_sprite); |
|
479 else |
|
480 SDL_SetCursor(sdl_cursor_normal); |
|
481 break; |
|
482 } |
|
483 } |
|
484 |
|
485 static void sdl_gui_turn_cursor_off(void) |
|
486 { |
|
487 SDL_ShowCursor(0); |
|
488 } |
|
489 |
|
490 static void sdl_gui_mouse_warp(int x, int y) |
|
491 { |
|
492 SDL_WarpMouse(x, y); |
|
493 } |
|
494 |
|
495 static void sdl_gui_grab_input_on(void) |
|
496 { |
|
497 SDL_WM_GrabInput(SDL_GRAB_ON); |
|
498 } |
|
499 |
|
500 static void sdl_gui_grab_input_off(void) |
|
501 { |
|
502 SDL_WM_GrabInput(SDL_GRAB_OFF); |
|
503 } |
|
504 |
|
505 static void sdl_gui_set_caption(const char* title, const char* icon) |
|
506 { |
|
507 SDL_WM_SetCaption(title, icon); |
|
508 } |
|
509 |
|
510 static int sdl_gui_is_app_active(void) |
|
511 { |
|
512 return (SDL_GetAppState() & SDL_APPACTIVE); |
|
513 } |
|
514 |
|
515 static void sdl_init_ds(DisplayState *ds) |
|
516 { |
|
517 ds->dpy_update = sdl_update; |
|
518 ds->dpy_fill = sdl_fill; |
|
519 ds->mouse_set = sdl_mouse_warp; |
|
520 ds->cursor_define = sdl_mouse_define; |
|
521 } |
|
522 |
|
523 /*********************************/ |
|
524 |
|
525 |
|
526 void sdl_display_init(int full_screen, int no_frame) |
|
527 { |
|
528 int flags; |
|
529 uint8_t data = 0; |
|
530 gui_host_callbacks_t gui_callbacks; |
|
531 |
|
532 #if defined(__APPLE__) |
|
533 /* always use generic keymaps */ |
|
534 if (!keyboard_layout) |
|
535 keyboard_layout = "en-us"; |
|
536 #endif |
|
537 if(keyboard_layout) { |
|
538 kbd_layout = init_keyboard_layout(keyboard_layout); |
|
539 if (!kbd_layout) |
|
540 exit(1); |
|
541 } |
|
542 |
|
543 if (no_frame) |
|
544 gui_noframe = 1; |
|
545 |
|
546 flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE; |
|
547 if (SDL_Init (flags)) { |
|
548 fprintf(stderr, "Could not initialize SDL - exiting\n"); |
|
549 exit(1); |
|
550 } |
|
551 |
|
552 memset(&gui_callbacks, 0, sizeof(gui_host_callbacks_t)); |
|
553 gui_callbacks.turn_cursor_on = &sdl_gui_turn_cursor_on; |
|
554 gui_callbacks.turn_cursor_off = &sdl_gui_turn_cursor_off; |
|
555 gui_callbacks.mouse_warp = &sdl_gui_mouse_warp; |
|
556 gui_callbacks.grab_input_on = &sdl_gui_grab_input_on; |
|
557 gui_callbacks.grab_input_off = &sdl_gui_grab_input_off; |
|
558 gui_callbacks.set_caption = &sdl_gui_set_caption; |
|
559 gui_callbacks.set_screen_size = &sdl_gui_set_screen_size; |
|
560 gui_callbacks.get_screen_data = &sdl_gui_get_screen_data; |
|
561 gui_callbacks.is_app_active = &sdl_gui_is_app_active; |
|
562 gui_callbacks.init_ds = &sdl_init_ds; |
|
563 gui_callbacks.process_events = &sdl_gui_process_events; |
|
564 gui_callbacks.set_kbd_terminal_mode = &sdl_gui_set_kbd_terminal_mode; |
|
565 gui_init(&gui_callbacks); |
|
566 |
|
567 if (full_screen && gui_allows_fullscreen()) { |
|
568 gui_notify_toggle_fullscreen(); |
|
569 } |
|
570 |
|
571 SDL_EnableKeyRepeat(250, 50); |
|
572 |
|
573 sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0); |
|
574 sdl_cursor_normal = SDL_GetCursor(); |
|
575 |
|
576 atexit(sdl_cleanup); |
|
577 |
|
578 } |
|
579 |