--- 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 address@hidden 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}. address@hidden mouse_move dx dy [dz] +Move the active mouse to the specified coordinates @var{dx} @var{dy} +with optional scroll axis @var{dz}. + address@hidden mouse_button val +Change the active mouse button state @var{val} (1=L, 2=M, 4=R). + address@hidden mouse_set index +Set which mouse device receives events at given @var{index}, index +can be obtained with address@hidden +info mice address@hidden 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)