Attached is a draft patch that fixes this in my configuration; I don't know whether it's good for everyone or not. One problem is that I don't know whether earlier versions of SDL included the Meta modifier or mapped it to Alt themselves, which I suspect may be the original reason that this is now semi-broken for people who have only Meta keysyms assigned.
---> Drake Wilson
--- sdl.c.orig 2008-01-06 13:38:42.000000000 -0600 +++ sdl.c 2008-08-06 08:53:32.000000000 -0500 @@ -40,7 +40,9 @@ 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 int gui_grab_mods = KMOD_LALT | KMOD_LCTRL | KMOD_LMETA; +static int gui_grab_req_all = KMOD_LCTRL; /* possibly modified on init */ +static int gui_grab_req_any = KMOD_LALT | KMOD_LMETA; static uint8_t modifiers_state[256]; static int width, height; static SDL_Cursor *sdl_cursor_normal; @@ -303,20 +305,20 @@ buttons |= MOUSE_EVENT_MBUTTON; if (kbd_mouse_is_absolute()) { - if (!absolute_enabled) { - sdl_hide_cursor(); - if (gui_grab) { - sdl_grab_end(); - } - absolute_enabled = 1; - } - - SDL_GetMouseState(&dx, &dy); - dx = dx * 0x7FFF / width; - dy = dy * 0x7FFF / height; + if (!absolute_enabled) { + sdl_hide_cursor(); + if (gui_grab) { + sdl_grab_end(); + } + absolute_enabled = 1; + } + + SDL_GetMouseState(&dx, &dy); + dx = dx * 0x7FFF / width; + dy = dy * 0x7FFF / height; } else if (absolute_enabled) { - sdl_show_cursor(); - absolute_enabled = 0; + sdl_show_cursor(); + absolute_enabled = 0; } else if (guest_cursor) { SDL_GetMouseState(&dx, &dy); dx -= guest_x; @@ -363,13 +365,10 @@ case SDL_KEYDOWN: case SDL_KEYUP: if (ev->type == SDL_KEYDOWN) { - if (!alt_grab) { - mod_state = (SDL_GetModState() & gui_grab_code) == - gui_grab_code; - } else { - mod_state = (SDL_GetModState() & (gui_grab_code | KMOD_LSHIFT)) == - (gui_grab_code | KMOD_LSHIFT); - } + SDLMod sdl_mod_state = SDL_GetModState(); + mod_state = (((sdl_mod_state & gui_grab_req_all) == + gui_grab_req_all) && + ((sdl_mod_state & gui_grab_req_any) != 0)); gui_key_modifier_pressed = mod_state; if (gui_key_modifier_pressed) { int keycode; @@ -430,12 +429,7 @@ } } } else if (ev->type == SDL_KEYUP) { - if (!alt_grab) { - mod_state = (ev->key.keysym.mod & gui_grab_code); - } else { - mod_state = (ev->key.keysym.mod & - (gui_grab_code | KMOD_LSHIFT)); - } + mod_state = (ev->key.keysym.mod & gui_grab_mods); if (!mod_state) { if (gui_key_modifier_pressed) { gui_key_modifier_pressed = 0; @@ -468,7 +462,7 @@ case SDL_QUIT: if (!no_quit) { qemu_system_shutdown_request(); - vm_start(); /* In case we're paused */ + vm_start(); /* In case we're paused */ } break; case SDL_MOUSEMOTION: @@ -630,6 +624,9 @@ SDL_EnableUNICODE(1); gui_grab = 0; + if (alt_grab) + gui_grab_req_all |= KMOD_LSHIFT; + sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0); sdl_cursor_normal = SDL_GetCursor();