lo list.  The attached patch allows qemu to handle 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 will also allow the user to choose which guest mouse
will receive events from the mouse input source on the host.
--- qemu/vl.c	2006-10-31 19:44:16.000000000 -0600
+++ qemu/vl.c	2006-11-26 16:53:56.000000000 -0600
@@ -451,9 +451,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)
 {
@@ -461,11 +460,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)
+        return;
+    
+    cursor = qemu_put_mouse_event_head;
+    while (cursor != NULL && cursor != entry) {
+        prev = cursor;
+        cursor = cursor->next;
+    }
+    
+    if (!cursor) // does not exist or list empty
+        return;
+    else if (!prev) { // 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)
@@ -477,15 +533,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("(%d)  %c%s\n", index,
+                    (cursor == qemu_put_mouse_event_current ? '*' : ' '),
+                    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)
+        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-09-24 13:49:43.000000000 -0500
+++ qemu/vl.h	2006-11-26 04:38:53.000000000 -0600
@@ -171,13 +171,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;
+    char *qemu_put_mouse_event_name;
+    int qemu_put_mouse_event_absolute;
+    
+    /* 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/sdl.c	2006-08-19 09:27:30.000000000 -0500
+++ qemu/sdl.c	2006-11-26 17:02:10.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);
@@ -499,7 +503,8 @@
             qemu_system_shutdown_request();
             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/hw/usb-hid.c	2006-08-11 20:04:27.000000000 -0500
+++ qemu/hw/usb-hid.c	2006-11-26 17:04:29.000000000 -0600
@@ -39,6 +39,7 @@
     int x, y;
     int kind;
     int mouse_grabbed;
+    QEMUPutMouseEntry *eh;
 } USBMouseState;
 
 /* mostly the same values as the Bochs USB Mouse device */
@@ -259,7 +260,7 @@
     int dx, dy, dz, b, l;
 
     if (!s->mouse_grabbed) {
-	qemu_add_mouse_event_handler(usb_mouse_event, s, 0);
+	s->eh = qemu_add_mouse_event_handler(usb_mouse_event, s, 0, "QEMU USB Mouse");
 	s->mouse_grabbed = 1;
     }
     
@@ -295,7 +296,7 @@
     int dz, b, l;
 
     if (!s->mouse_grabbed) {
-	qemu_add_mouse_event_handler(usb_tablet_event, s, 1);
+	s->eh = qemu_add_mouse_event_handler(usb_tablet_event, s, 1, "QEMU USB Tablet");
 	s->mouse_grabbed = 1;
     }
     
@@ -503,7 +504,7 @@
 {
     USBMouseState *s = (USBMouseState *)dev;
 
-    qemu_add_mouse_event_handler(NULL, NULL, 0);
+    qemu_remove_mouse_event_handler(s->eh);
     qemu_free(s);
 }
 
--- qemu/hw/adb.c	2006-04-12 16:59:55.000000000 -0500
+++ qemu/hw/adb.c	2006-11-26 04:12:23.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-04-12 16:09:07.000000000 -0500
+++ qemu/hw/ps2.c	2006-11-26 04:03:41.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-09-09 07:17:15.000000000 -0500
+++ qemu/hw/slavio_serial.c	2006-11-26 04:14:24.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/monitor.c	2006-09-25 16:33:49.000000000 -0500
+++ qemu/monitor.c	2006-11-26 16:10:23.000000000 -0600
@@ -1184,6 +1184,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]",
@@ -1233,6 +1235,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-10-21 19:18:54.000000000 -0500
+++ qemu/qemu-doc.texi	2006-11-26 16:31:58.000000000 -0600
@@ -757,6 +757,8 @@
 show information about active capturing
 @item info snapshots
 show list of VM snapshots
[EMAIL PROTECTED] info mice
+show which guest mouse is receiving events
 @end table
 
 @item q or quit
@@ -771,6 +773,20 @@
 @item screendump filename
 Save screen into PPM image @var{filename}.
 
[EMAIL PROTECTED] mouse_move dx dy [dz]
+Move the active mouse to the specified coordinates @var{dx} @var{dy}
+with optional scroll axis @var{dz}.
+
[EMAIL PROTECTED] mouse_button val
+Change the active mouse button state @var{val} (1=L, 2=M, 4=R).
+
[EMAIL PROTECTED] mouse_set index
+Set which mouse device receives events at given @var{index}, index
+can be obtained with
[EMAIL PROTECTED]
+info mice
[EMAIL PROTECTED] 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-devel mailing list
Qemu-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/qemu-devel

Reply via email to