[12/15] sdl: Dynamically grab input in absolute mouse mode

Submitted by Jan Kiszka on July 30, 2011, 9:39 a.m.

Details

Message ID ceaadf7e4172bc980735abb6bcf51673fc97d002.1312018756.git.jan.kiszka@web.de
State New
Headers show

Commit Message

Jan Kiszka July 30, 2011, 9:39 a.m.
From: Jan Kiszka <jan.kiszka@siemens.com>

Not grabbing the input means that special keys like ALT+TAB are still
handled by the host. Improve the usability by grabbing input once the
mouse is inside the guest screen, provided the SDL window has the input
focus. Release it again when the mouse is moved to any border. Also grab
the input when we gain the input focus and the mouse is within the
screen limits.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---
 ui/sdl.c |   43 +++++++++++++++++++++++++++++++++++++------
 1 files changed, 37 insertions(+), 6 deletions(-)

Patch hide | download patch | download mbox

diff --git a/ui/sdl.c b/ui/sdl.c
index 5ad38d5..e8ac3bb 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -490,15 +490,12 @@  static void sdl_mouse_mode_change(Notifier *notify, void *data)
 {
     if (kbd_mouse_is_absolute()) {
         if (!absolute_enabled) {
-            sdl_hide_cursor();
-            if (gui_grab) {
-                sdl_grab_end();
-            }
+            sdl_grab_start();
             absolute_enabled = 1;
         }
     } else if (absolute_enabled) {
-	sdl_show_cursor();
-	absolute_enabled = 0;
+        sdl_grab_end();
+        absolute_enabled = 0;
     }
 }
 
@@ -572,6 +569,19 @@  static void toggle_full_screen(DisplayState *ds)
     vga_hw_update();
 }
 
+static void absolute_mouse_grab(void)
+{
+    int mouse_x, mouse_y;
+
+    if (SDL_GetAppState() & SDL_APPINPUTFOCUS) {
+        SDL_GetMouseState(&mouse_x, &mouse_y);
+        if (mouse_x > 0 && mouse_x < real_screen->w - 1 &&
+            mouse_y > 0 && mouse_y < real_screen->h - 1) {
+            sdl_grab_start();
+        }
+    }
+}
+
 static void sdl_refresh(DisplayState *ds)
 {
     SDL_Event ev1, *ev = &ev1;
@@ -638,6 +648,7 @@  static void sdl_refresh(DisplayState *ds)
                             }
                         } else if (absolute_enabled) {
                             sdl_hide_cursor();
+                            absolute_mouse_grab();
                         }
                         break;
                     default:
@@ -724,6 +735,22 @@  static void sdl_refresh(DisplayState *ds)
             }
             break;
         case SDL_MOUSEMOTION:
+            if (is_graphic_console() &&
+                (kbd_mouse_is_absolute() || absolute_enabled)) {
+                int max_x = real_screen->w - 1;
+                int max_y = real_screen->h - 1;
+
+                if (gui_grab &&
+                    (ev->motion.x == 0 || ev->motion.y == 0 ||
+                     ev->motion.x == max_x || ev->motion.y == max_y)) {
+                    sdl_grab_end();
+                }
+                if (!gui_grab && SDL_GetAppState() & SDL_APPINPUTFOCUS &&
+                    (ev->motion.x > 0 && ev->motion.x < max_x &&
+                     ev->motion.y > 0 && ev->motion.y < max_y)) {
+                    sdl_grab_start();
+                }
+            }
             if (gui_grab || kbd_mouse_is_absolute() ||
                 absolute_enabled) {
                 sdl_send_mouse_event(ev->motion.xrel, ev->motion.yrel, 0,
@@ -764,6 +791,10 @@  static void sdl_refresh(DisplayState *ds)
                 !ev->active.gain && !gui_fullscreen) {
                 sdl_grab_end();
             }
+            if (!gui_grab && ev->active.gain && is_graphic_console() &&
+                (kbd_mouse_is_absolute() || absolute_enabled)) {
+                absolute_mouse_grab();
+            }
             if (ev->active.state & SDL_APPACTIVE) {
                 if (ev->active.gain) {
                     /* Back to default interval */