X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=sdl.c;h=20e45d93f049ec78357dbdb0fb4eff16286128e3;hb=7a962d3087d24fa0ea377cbde39ab97f81457ff6;hp=7b3c3b5eab38cda3851240d577ed2ee928e1eccb;hpb=b71e95fc2c030428c768de20332f9d857b9aed41;p=qemu diff --git a/sdl.c b/sdl.c index 7b3c3b5..20e45d9 100644 --- a/sdl.c +++ b/sdl.c @@ -36,6 +36,9 @@ static int gui_saved_grab; static int gui_fullscreen; static int gui_key_modifier_pressed; static int gui_keysym; +static int gui_fullscreen_initial_grab; +static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; +static uint8_t modifiers_state[256]; static void sdl_update(DisplayState *ds, int x, int y, int w, int h) { @@ -61,27 +64,57 @@ static void sdl_resize(DisplayState *ds, int w, int h) ds->data = screen->pixels; ds->linesize = screen->pitch; ds->depth = screen->format->BitsPerPixel; + ds->width = w; + ds->height = h; } -static const uint32_t x_keycode_to_pc_keycode[61] = { - 0x47e0, /* 97 Home */ - 0x48e0, /* 98 Up */ - 0x49e0, /* 99 PgUp */ - 0x4be0, /* 100 Left */ +/* generic keyboard conversion */ + +#include "sdl_keysym.h" +#include "keymaps.c" + +static kbd_layout_t *kbd_layout = NULL; + +static uint8_t sdl_keyevent_to_keycode_generic(const SDL_KeyboardEvent *ev) +{ + int keysym; + /* workaround for X11+SDL bug with AltGR */ + keysym = ev->keysym.sym; + if (keysym == 0 && ev->keysym.scancode == 113) + keysym = SDLK_MODE; + return keysym2scancode(kbd_layout, keysym); +} + +/* specific keyboard conversions from scan codes */ + +#if defined(_WIN32) + +static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) +{ + return ev->keysym.scancode; +} + +#else + +static const uint8_t x_keycode_to_pc_keycode[61] = { + 0xc7, /* 97 Home */ + 0xc8, /* 98 Up */ + 0xc9, /* 99 PgUp */ + 0xcb, /* 100 Left */ 0x4c, /* 101 KP-5 */ - 0x4de0, /* 102 Right */ - 0x4fe0, /* 103 End */ - 0x50e0, /* 104 Down */ - 0x51e0, /* 105 PgDn */ - 0x52e0, /* 106 Ins */ - 0x53e0, /* 107 Del */ - 0x1ce0, /* 108 Enter */ - 0x1de0, /* 109 Ctrl-R */ - 0x451de1, /* 110 Pause */ - 0x37e0, /* 111 Print */ - 0x35e0, /* 112 Divide */ - 0x38e0, /* 113 Alt-R */ - 0x46e0, /* 114 Break */ + 0xcd, /* 102 Right */ + 0xcf, /* 103 End */ + 0xd0, /* 104 Down */ + 0xd1, /* 105 PgDn */ + 0xd2, /* 106 Ins */ + 0xd3, /* 107 Del */ + 0x9c, /* 108 Enter */ + 0x9d, /* 109 Ctrl-R */ + 0x0, /* 110 Pause */ + 0xb7, /* 111 Print */ + 0xb5, /* 112 Divide */ + 0xb8, /* 113 Alt-R */ + 0xc6, /* 114 Break */ 0x0, /* 115 */ 0x0, /* 116 */ 0x0, /* 117 */ @@ -127,14 +160,12 @@ static const uint32_t x_keycode_to_pc_keycode[61] = { 0x53, /* 157 KP_Del */ }; -static void sdl_process_key(SDL_KeyboardEvent *ev) +static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev) { - int keycode, v; - - /* XXX: not portable, but avoids complicated mappings */ + int keycode; + keycode = ev->keysym.scancode; -#ifndef _WIN32 if (keycode < 9) { keycode = 0; } else if (keycode < 97) { @@ -145,16 +176,76 @@ static void sdl_process_key(SDL_KeyboardEvent *ev) } else { keycode = 0; } + return keycode; +} + #endif - - /* now send the key code */ - while (keycode != 0) { - v = keycode & 0xff; + +static void reset_keys(void) +{ + int i; + for(i = 0; i < 256; i++) { + if (modifiers_state[i]) { + if (i & 0x80) + kbd_put_keycode(0xe0); + kbd_put_keycode(i | 0x80); + modifiers_state[i] = 0; + } + } +} + +static void sdl_process_key(SDL_KeyboardEvent *ev) +{ + int keycode, v; + + if (ev->keysym.sym == SDLK_PAUSE) { + /* specific case */ + v = 0; if (ev->type == SDL_KEYUP) v |= 0x80; - kbd_put_keycode(v); - keycode >>= 8; + kbd_put_keycode(0xe1); + kbd_put_keycode(0x1d | v); + kbd_put_keycode(0x45 | v); + return; } + + if (kbd_layout) { + keycode = sdl_keyevent_to_keycode_generic(ev); + } else { + keycode = sdl_keyevent_to_keycode(ev); + } + + switch(keycode) { + case 0x00: + /* sent when leaving window: reset the modifiers state */ + reset_keys(); + return; + case 0x2a: /* Left Shift */ + case 0x36: /* Right Shift */ + case 0x1d: /* Left CTRL */ + case 0x9d: /* Right CTRL */ + case 0x38: /* Left ALT */ + case 0xb8: /* Right ALT */ + if (ev->type == SDL_KEYUP) + modifiers_state[keycode] = 0; + else + modifiers_state[keycode] = 1; + break; + case 0x45: /* num lock */ + case 0x3a: /* caps lock */ + /* SDL does not send the key up event, so we generate it */ + kbd_put_keycode(keycode); + kbd_put_keycode(keycode | 0x80); + return; + } + + /* now send the key code */ + if (keycode & 0x80) + kbd_put_keycode(0xe0); + if (ev->type == SDL_KEYUP) + kbd_put_keycode(keycode | 0x80); + else + kbd_put_keycode(keycode & 0x7f); } static void sdl_update_caption(void) @@ -165,7 +256,7 @@ static void sdl_update_caption(void) strcat(buf, " [Stopped]"); } if (gui_grab) { - strcat(buf, " - Press Ctrl-Shift to exit grab"); + strcat(buf, " - Press Ctrl-Alt to exit grab"); } SDL_WM_SetCaption(buf, "QEMU"); } @@ -188,9 +279,9 @@ static void sdl_grab_end(void) sdl_update_caption(); } -static void sdl_send_mouse_event(void) +static void sdl_send_mouse_event(int dz) { - int dx, dy, dz, state, buttons; + int dx, dy, state, buttons; state = SDL_GetRelativeMouseState(&dx, &dy); buttons = 0; if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) @@ -199,14 +290,6 @@ static void sdl_send_mouse_event(void) buttons |= MOUSE_EVENT_RBUTTON; if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) buttons |= MOUSE_EVENT_MBUTTON; - /* XXX: test wheel */ - dz = 0; -#ifdef SDL_BUTTON_WHEELUP - if (state & SDL_BUTTON(SDL_BUTTON_WHEELUP)) - dz--; - if (state & SDL_BUTTON(SDL_BUTTON_WHEELDOWN)) - dz++; -#endif kbd_mouse_event(dx, dy, dz, buttons); } @@ -221,8 +304,8 @@ static void toggle_full_screen(DisplayState *ds) if (!gui_saved_grab) sdl_grab_end(); } + vga_invalidate_display(); vga_update_display(); - sdl_update(ds, 0, 0, screen->w, screen->h); } static void sdl_refresh(DisplayState *ds) @@ -235,7 +318,9 @@ static void sdl_refresh(DisplayState *ds) sdl_update_caption(); } - vga_update_display(); + if (is_active_console(vga_console)) + vga_update_display(); + while (SDL_PollEvent(ev)) { switch (ev->type) { case SDL_VIDEOEXPOSE: @@ -244,27 +329,80 @@ static void sdl_refresh(DisplayState *ds) case SDL_KEYDOWN: case SDL_KEYUP: if (ev->type == SDL_KEYDOWN) { - mod_state = (SDL_GetModState() & (KMOD_LSHIFT | KMOD_LCTRL)) == - (KMOD_LSHIFT | KMOD_LCTRL); + mod_state = (SDL_GetModState() & gui_grab_code) == + gui_grab_code; gui_key_modifier_pressed = mod_state; - if (gui_key_modifier_pressed && - ev->key.keysym.sym == SDLK_f) { - gui_keysym = ev->key.keysym.sym; + if (gui_key_modifier_pressed) { + int keycode; + keycode = sdl_keyevent_to_keycode(&ev->key); + switch(keycode) { + case 0x21: /* 'f' key on US keyboard */ + toggle_full_screen(ds); + gui_keysym = 1; + break; + case 0x02 ... 0x0a: /* '1' to '9' keys */ + console_select(keycode - 0x02); + if (is_active_console(vga_console)) { + /* tell the vga console to redisplay itself */ + vga_invalidate_display(); + } else { + /* display grab if going to a text console */ + if (gui_grab) + sdl_grab_end(); + } + gui_keysym = 1; + break; + default: + break; + } + } else if (!is_active_console(vga_console)) { + int keysym; + keysym = 0; + if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) { + switch(ev->key.keysym.sym) { + case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break; + case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break; + case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break; + case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break; + case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break; + case SDLK_END: keysym = QEMU_KEY_CTRL_END; break; + case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break; + case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break; + default: break; + } + } else { + switch(ev->key.keysym.sym) { + case SDLK_UP: keysym = QEMU_KEY_UP; break; + case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break; + case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break; + case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break; + case SDLK_HOME: keysym = QEMU_KEY_HOME; break; + case SDLK_END: keysym = QEMU_KEY_END; break; + case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break; + case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break; + case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break; case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break; + default: break; + } + } + if (keysym) { + kbd_put_keysym(keysym); + } else if (ev->key.keysym.unicode != 0) { + kbd_put_keysym(ev->key.keysym.unicode); + } } } else if (ev->type == SDL_KEYUP) { - mod_state = (SDL_GetModState() & (KMOD_LSHIFT | KMOD_LCTRL)); + mod_state = (ev->key.keysym.mod & gui_grab_code); if (!mod_state) { if (gui_key_modifier_pressed) { - switch(gui_keysym) { - case SDLK_f: - toggle_full_screen(ds); - break; - case 0: - /* exit/enter grab if pressing Ctrl-Shift */ + if (gui_keysym == 0) { + /* exit/enter grab if pressing Ctrl-Alt */ if (!gui_grab) sdl_grab_start(); else sdl_grab_end(); + /* SDL does not send back all the + modifiers key, so we must correct it */ + reset_keys(); break; } gui_key_modifier_pressed = 0; @@ -272,14 +410,15 @@ static void sdl_refresh(DisplayState *ds) } } } - sdl_process_key(&ev->key); + if (is_active_console(vga_console)) + sdl_process_key(&ev->key); break; case SDL_QUIT: - reset_requested = 1; + qemu_system_shutdown_request(); break; case SDL_MOUSEMOTION: if (gui_grab) { - sdl_send_mouse_event(); + sdl_send_mouse_event(0); } break; case SDL_MOUSEBUTTONDOWN: @@ -293,12 +432,22 @@ static void sdl_refresh(DisplayState *ds) sdl_grab_start(); } } else { - sdl_send_mouse_event(); + int dz; + dz = 0; +#ifdef SDL_BUTTON_WHEELUP + if (bev->button == SDL_BUTTON_WHEELUP) { + dz = -1; + } else if (bev->button == SDL_BUTTON_WHEELDOWN) { + dz = 1; + } +#endif + sdl_send_mouse_event(dz); } } break; case SDL_ACTIVEEVENT: - if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0) { + if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0 && + !gui_fullscreen_initial_grab) { sdl_grab_end(); } break; @@ -313,16 +462,26 @@ static void sdl_cleanup(void) SDL_Quit(); } -void sdl_display_init(DisplayState *ds) +void sdl_display_init(DisplayState *ds, int full_screen) { int flags; +#if defined(__APPLE__) + /* always use generic keymaps */ + if (!keyboard_layout) + keyboard_layout = "en-us"; +#endif + if(keyboard_layout) { + kbd_layout = init_keyboard_layout(keyboard_layout); + if (!kbd_layout) + exit(1); + } + flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE; if (SDL_Init (flags)) { fprintf(stderr, "Could not initialize SDL - exiting\n"); exit(1); } - #ifndef _WIN32 /* NOTE: we still want Ctrl-C to work, so we undo the SDL redirections */ signal(SIGINT, SIG_DFL); @@ -336,7 +495,13 @@ void sdl_display_init(DisplayState *ds) sdl_resize(ds, 640, 400); sdl_update_caption(); SDL_EnableKeyRepeat(250, 50); + SDL_EnableUNICODE(1); gui_grab = 0; atexit(sdl_cleanup); + if (full_screen) { + gui_fullscreen = 1; + gui_fullscreen_initial_grab = 1; + sdl_grab_start(); + } }