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