File:  [Qemu by Fabrice Bellard] / qemu / sdl.c
Revision 1.1.1.12 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:57:43 2018 UTC (23 months, 1 week ago) by root
Branches: qemu, MAIN
CVS tags: qemu0125, qemu0124, qemu0123, HEAD
qemu 0.12.3

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

unix.superglobalmegacorp.com