File:  [Qemu by Fabrice Bellard] / qemu / sdl.c
Revision 1.1.1.7 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:50:43 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0100, HEAD
qemu 0.10.0

    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: }

unix.superglobalmegacorp.com