[prev in list] [next in list] [prev in thread] [next in thread] 

List:       qemu-devel
Subject:    [Qemu-devel] Re: [PATCH] dynamic handling of guest mice
From:       Lonnie Mendez <lmendez19 () austin ! rr ! com>
Date:       2006-12-24 10:58:25
Message-ID: 1166957906.4715.15.camel () vaio
[Download RAW message or body]

Attached is a revised patch.  This code allows qemu to manage several
guest mice.  It solves the problem of removing a usb mouse/tablet
removable mouse device and losing all guest input from the ps/2 or other
emulated mouse device.  It also allows the user to choose which guest
mouse will receive events from the mouse input source on the host.

   I've made the user output seen from the qemu monitor more uniform.

["qemu-mouse-handling-rev.diff" (qemu-mouse-handling-rev.diff)]

--- qemu/hw/adb.c	2006-12-24 04:39:59.000000000 -0600
+++ qemu/hw/adb.c	2006-12-23 22:37:55.000000000 -0600
@@ -406,5 +406,5 @@
     d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request,
                             adb_mouse_reset, s);
     adb_mouse_reset(d);
-    qemu_add_mouse_event_handler(adb_mouse_event, d, 0);
+    qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse");
 }
--- qemu/hw/ps2.c	2006-12-24 04:39:59.000000000 -0600
+++ qemu/hw/ps2.c	2006-12-23 22:37:57.000000000 -0600
@@ -560,7 +560,7 @@
     s->common.update_arg = update_arg;
     ps2_reset(&s->common);
     register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s);
-    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0);
+    qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse");
     qemu_register_reset(ps2_reset, &s->common);
     return s;
 }
--- qemu/hw/slavio_serial.c	2006-12-24 04:39:59.000000000 -0600
+++ qemu/hw/slavio_serial.c	2006-12-23 22:38:01.000000000 -0600
@@ -682,7 +682,7 @@
     slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, \
                slavio_serial_mem_write, s);
     cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory);
 
-    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0);
+    qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, "QEMU Sun Mouse");
     qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]);
     qemu_register_reset(slavio_serial_reset, s);
     slavio_serial_reset(s);
--- qemu/hw/usb-hid.c	2006-12-24 04:39:59.000000000 -0600
+++ qemu/hw/usb-hid.c	2006-12-24 04:42:46.000000000 -0600
@@ -39,6 +39,7 @@
     int x, y;
     int kind;
     int mouse_grabbed;
+    QEMUPutMouseEntry *eh_entry;
 } USBMouseState;
 
 /* mostly the same values as the Bochs USB Mouse device */
@@ -259,7 +260,8 @@
     int dx, dy, dz, b, l;
 
     if (!s->mouse_grabbed) {
-	qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
+	s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
+                                                  0, "QEMU USB Mouse");
 	s->mouse_grabbed = 1;
     }
     
@@ -295,7 +297,8 @@
     int dz, b, l;
 
     if (!s->mouse_grabbed) {
-	qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
+	s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
+                                                  1, "QEMU USB Tablet");
 	s->mouse_grabbed = 1;
     }
     
@@ -503,7 +506,7 @@
 {
     USBMouseState *s = (USBMouseState *)dev;
 
-    qemu_add_mouse_event_handler(NULL, NULL, 0);
+    qemu_remove_mouse_event_handler(s->eh_entry);
     qemu_free(s);
 }
 
--- qemu/monitor.c	2006-12-24 04:39:59.000000000 -0600
+++ qemu/monitor.c	2006-12-24 04:09:45.000000000 -0600
@@ -1211,6 +1211,8 @@
       "dx dy [dz]", "send mouse move events" },
     { "mouse_button", "i", do_mouse_button, 
       "state", "change mouse button state (1=L, 2=M, 4=R)" },
+    { "mouse_set", "i", do_mouse_set,
+      "index", "set which mouse device receives events" },
 #ifdef HAS_AUDIO
     { "wavcapture", "si?i?i?", do_wav_capture,
       "path [frequency bits channels]",
@@ -1260,6 +1262,8 @@
       "", "show capture information" },
     { "snapshots", "", do_info_snapshots,
       "", "show the currently saved VM snapshots" },
+    { "mice", "", do_info_mice,
+      "", "show which guest mouse is receiving events" },
     { NULL, NULL, },
 };
 
--- qemu/qemu-doc.texi	2006-12-24 04:39:59.000000000 -0600
+++ qemu/qemu-doc.texi	2006-12-23 22:38:01.000000000 -0600
@@ -781,6 +781,8 @@
 show information about active capturing
 @item info snapshots
 show list of VM snapshots
+@item info mice
+show which guest mouse is receiving events
 @end table
 
 @item q or quit
@@ -795,6 +797,20 @@
 @item screendump filename
 Save screen into PPM image @var{filename}.
 
+@item mouse_move dx dy [dz]
+Move the active mouse to the specified coordinates @var{dx} @var{dy}
+with optional scroll axis @var{dz}.
+
+@item mouse_button val
+Change the active mouse button state @var{val} (1=L, 2=M, 4=R).
+
+@item mouse_set index
+Set which mouse device receives events at given @var{index}, index
+can be obtained with
+@example
+info mice
+@end example
+
 @item wavcapture filename [frequency [bits [channels]]]
 Capture audio into @var{filename}. Using sample rate @var{frequency}
 bits per sample @var{bits} and number of channels @var{channels}.
--- qemu/sdl.c	2006-12-24 04:39:59.000000000 -0600
+++ qemu/sdl.c	2006-12-23 22:37:36.000000000 -0600
@@ -319,6 +319,7 @@
 {
     if (!kbd_mouse_is_absolute()) {
         SDL_ShowCursor(1);
+        SDL_SetCursor(sdl_cursor_normal);
     }
 }
 
@@ -364,6 +365,9 @@
 	SDL_GetMouseState(&dx, &dy);
 	dx = dx * 0x7FFF / width;
 	dy = dy * 0x7FFF / height;
+    } else if (absolute_enabled) {
+	sdl_show_cursor();
+	absolute_enabled = 0;
     }
 
     kbd_mouse_event(dx, dy, dz, buttons);
@@ -501,7 +505,8 @@
             }
             break;
         case SDL_MOUSEMOTION:
-            if (gui_grab || kbd_mouse_is_absolute()) {
+            if (gui_grab || kbd_mouse_is_absolute() ||
+                absolute_enabled) {
                 sdl_send_mouse_event(0);
             }
             break;
--- qemu/vl.c	2006-12-24 04:39:59.000000000 -0600
+++ qemu/vl.c	2006-12-24 04:39:16.000000000 -0600
@@ -463,9 +463,8 @@
 
 static QEMUPutKBDEvent *qemu_put_kbd_event;
 static void *qemu_put_kbd_event_opaque;
-static QEMUPutMouseEvent *qemu_put_mouse_event;
-static void *qemu_put_mouse_event_opaque;
-static int qemu_put_mouse_event_absolute;
+static QEMUPutMouseEntry *qemu_put_mouse_event_head;
+static QEMUPutMouseEntry *qemu_put_mouse_event_current;
 
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
 {
@@ -473,11 +472,68 @@
     qemu_put_kbd_event = func;
 }
 
-void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int \
absolute) +QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
+                                                void *opaque, int absolute,
+                                                const char *name)
 {
-    qemu_put_mouse_event_opaque = opaque;
-    qemu_put_mouse_event = func;
-    qemu_put_mouse_event_absolute = absolute;
+    QEMUPutMouseEntry *s, *cursor;
+    
+    s = qemu_mallocz(sizeof(QEMUPutMouseEntry));
+    if (!s)
+        return NULL;
+    
+    s->qemu_put_mouse_event = func;
+    s->qemu_put_mouse_event_opaque = opaque;
+    s->qemu_put_mouse_event_absolute = absolute;
+    s->qemu_put_mouse_event_name = qemu_strdup(name);
+    s->next = NULL;
+    
+    if (!qemu_put_mouse_event_head) {
+        qemu_put_mouse_event_head = qemu_put_mouse_event_current = s;
+        return s;
+    }
+    
+    cursor = qemu_put_mouse_event_head;
+    while (cursor->next != NULL)
+        cursor = cursor->next;
+    
+    cursor->next = s;
+    qemu_put_mouse_event_current = s;
+    
+    return s;
+}
+
+void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
+{
+    QEMUPutMouseEntry *prev = NULL, *cursor;
+    
+    if (!qemu_put_mouse_event_head || entry == NULL)
+        return;
+    
+    cursor = qemu_put_mouse_event_head;
+    while (cursor != NULL && cursor != entry) {
+        prev = cursor;
+        cursor = cursor->next;
+    }
+    
+    if (cursor == NULL) // does not exist or list empty
+        return;
+    else if (prev == NULL) { // entry is head
+        qemu_put_mouse_event_head = cursor->next;
+        if (qemu_put_mouse_event_current == entry)
+            qemu_put_mouse_event_current = cursor->next;
+        qemu_free(entry->qemu_put_mouse_event_name);
+        qemu_free(entry);
+        return;
+    }
+    
+    prev->next = entry->next;
+    
+    if (qemu_put_mouse_event_current == entry)
+        qemu_put_mouse_event_current = prev;
+    
+    qemu_free(entry->qemu_put_mouse_event_name);
+    qemu_free(entry);
 }
 
 void kbd_put_keycode(int keycode)
@@ -489,15 +545,72 @@
 
 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
 {
-    if (qemu_put_mouse_event) {
-        qemu_put_mouse_event(qemu_put_mouse_event_opaque, 
-                             dx, dy, dz, buttons_state);
+    QEMUPutMouseEvent *mouse_event;
+    void *mouse_event_opaque;
+    
+    if (!qemu_put_mouse_event_current) {
+        return;
+    }
+    
+    mouse_event =
+        qemu_put_mouse_event_current->qemu_put_mouse_event;
+    mouse_event_opaque =
+        qemu_put_mouse_event_current->qemu_put_mouse_event_opaque;
+    
+    if (mouse_event) {
+        mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state);
     }
 }
 
 int kbd_mouse_is_absolute(void)
 {
-    return qemu_put_mouse_event_absolute;
+    if (!qemu_put_mouse_event_current)
+        return 0;
+    
+    return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
+}
+
+void do_info_mice(void)
+{
+    QEMUPutMouseEntry *cursor;
+    int index = 0;
+    
+    if (!qemu_put_mouse_event_head) {
+        term_printf("No mouse devices connected\n");
+        return;
+    }
+    
+    term_printf("Mouse devices available:\n");
+    cursor = qemu_put_mouse_event_head;
+    while (cursor != NULL) {
+        term_printf("%c Mouse #%d: %s\n",
+                    (cursor == qemu_put_mouse_event_current ? '*' : ' '),
+                    index, cursor->qemu_put_mouse_event_name);
+        index++;
+        cursor = cursor->next;
+    }
+}
+
+void do_mouse_set(int index)
+{
+    QEMUPutMouseEntry *cursor;
+    int i = 0;
+    
+    if (!qemu_put_mouse_event_head) {
+        term_printf("No mouse devices connected\n");
+        return;
+    }
+    
+    cursor = qemu_put_mouse_event_head;
+    while (cursor != NULL && index != i) {
+        i++;
+        cursor = cursor->next;
+    }
+    
+    if (cursor != NULL)
+        qemu_put_mouse_event_current = cursor;
+    else
+        term_printf("Mouse at given index not found\n");
 }
 
 /* compute with 96 bit intermediate result: (a*b)/c */
--- qemu/vl.h	2006-12-24 04:39:59.000000000 -0600
+++ qemu/vl.h	2006-12-23 22:39:51.000000000 -0600
@@ -172,13 +172,29 @@
 typedef void QEMUPutKBDEvent(void *opaque, int keycode);
 typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int \
buttons_state);  
+typedef struct QEMUPutMouseEntry {
+    QEMUPutMouseEvent *qemu_put_mouse_event;
+    void *qemu_put_mouse_event_opaque;
+    int qemu_put_mouse_event_absolute;
+    char *qemu_put_mouse_event_name;
+    
+    /* used internally by qemu for handling mice */
+    struct QEMUPutMouseEntry *next;
+} QEMUPutMouseEntry;
+
 void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
-void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int \
absolute); +QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
+                                                void *opaque, int absolute,
+                                                const char *name);
+void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry);
 
 void kbd_put_keycode(int keycode);
 void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
 int kbd_mouse_is_absolute(void);
 
+void do_info_mice(void);
+void do_mouse_set(int index);
+
 /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
    constants) */
 #define QEMU_KEY_ESC1(c) ((c) | 0xe100)



_______________________________________________
Qemu-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic