Commit 455204eb1a0880a5e4474acf07d4641f51123a1d
1 parent
6f30fa85
Dynamic handling of guest mice, by Lonnie Mendez.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2290 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
9 changed files
with
176 additions
and
19 deletions
hw/adb.c
... | ... | @@ -406,5 +406,5 @@ void adb_mouse_init(ADBBusState *bus) |
406 | 406 | d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, |
407 | 407 | adb_mouse_reset, s); |
408 | 408 | adb_mouse_reset(d); |
409 | - qemu_add_mouse_event_handler(adb_mouse_event, d, 0); | |
409 | + qemu_add_mouse_event_handler(adb_mouse_event, d, 0, "QEMU ADB Mouse"); | |
410 | 410 | } | ... | ... |
hw/ps2.c
... | ... | @@ -560,7 +560,7 @@ void *ps2_mouse_init(void (*update_irq)(void *, int), void *update_arg) |
560 | 560 | s->common.update_arg = update_arg; |
561 | 561 | ps2_reset(&s->common); |
562 | 562 | register_savevm("ps2mouse", 0, 2, ps2_mouse_save, ps2_mouse_load, s); |
563 | - qemu_add_mouse_event_handler(ps2_mouse_event, s, 0); | |
563 | + qemu_add_mouse_event_handler(ps2_mouse_event, s, 0, "QEMU PS/2 Mouse"); | |
564 | 564 | qemu_register_reset(ps2_reset, &s->common); |
565 | 565 | return s; |
566 | 566 | } | ... | ... |
hw/slavio_serial.c
... | ... | @@ -682,7 +682,7 @@ void slavio_serial_ms_kbd_init(int base, int irq) |
682 | 682 | slavio_serial_io_memory = cpu_register_io_memory(0, slavio_serial_mem_read, slavio_serial_mem_write, s); |
683 | 683 | cpu_register_physical_memory(base, SERIAL_MAXADDR, slavio_serial_io_memory); |
684 | 684 | |
685 | - qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0); | |
685 | + qemu_add_mouse_event_handler(sunmouse_event, &s->chn[0], 0, "QEMU Sun Mouse"); | |
686 | 686 | qemu_add_kbd_event_handler(sunkbd_event, &s->chn[1]); |
687 | 687 | qemu_register_reset(slavio_serial_reset, s); |
688 | 688 | slavio_serial_reset(s); | ... | ... |
hw/usb-hid.c
... | ... | @@ -39,6 +39,7 @@ typedef struct USBMouseState { |
39 | 39 | int x, y; |
40 | 40 | int kind; |
41 | 41 | int mouse_grabbed; |
42 | + QEMUPutMouseEntry *eh_entry; | |
42 | 43 | } USBMouseState; |
43 | 44 | |
44 | 45 | /* mostly the same values as the Bochs USB Mouse device */ |
... | ... | @@ -259,7 +260,8 @@ static int usb_mouse_poll(USBMouseState *s, uint8_t *buf, int len) |
259 | 260 | int dx, dy, dz, b, l; |
260 | 261 | |
261 | 262 | if (!s->mouse_grabbed) { |
262 | - qemu_add_mouse_event_handler(usb_mouse_event, s, 0); | |
263 | + s->eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s, | |
264 | + 0, "QEMU USB Mouse"); | |
263 | 265 | s->mouse_grabbed = 1; |
264 | 266 | } |
265 | 267 | |
... | ... | @@ -295,7 +297,8 @@ static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len) |
295 | 297 | int dz, b, l; |
296 | 298 | |
297 | 299 | if (!s->mouse_grabbed) { |
298 | - qemu_add_mouse_event_handler(usb_tablet_event, s, 1); | |
300 | + s->eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s, | |
301 | + 1, "QEMU USB Tablet"); | |
299 | 302 | s->mouse_grabbed = 1; |
300 | 303 | } |
301 | 304 | |
... | ... | @@ -503,7 +506,7 @@ static void usb_mouse_handle_destroy(USBDevice *dev) |
503 | 506 | { |
504 | 507 | USBMouseState *s = (USBMouseState *)dev; |
505 | 508 | |
506 | - qemu_add_mouse_event_handler(NULL, NULL, 0); | |
509 | + qemu_remove_mouse_event_handler(s->eh_entry); | |
507 | 510 | qemu_free(s); |
508 | 511 | } |
509 | 512 | ... | ... |
monitor.c
... | ... | @@ -1241,6 +1241,8 @@ static term_cmd_t term_cmds[] = { |
1241 | 1241 | "dx dy [dz]", "send mouse move events" }, |
1242 | 1242 | { "mouse_button", "i", do_mouse_button, |
1243 | 1243 | "state", "change mouse button state (1=L, 2=M, 4=R)" }, |
1244 | + { "mouse_set", "i", do_mouse_set, | |
1245 | + "index", "set which mouse device receives events" }, | |
1244 | 1246 | #ifdef HAS_AUDIO |
1245 | 1247 | { "wavcapture", "si?i?i?", do_wav_capture, |
1246 | 1248 | "path [frequency bits channels]", |
... | ... | @@ -1292,6 +1294,8 @@ static term_cmd_t info_cmds[] = { |
1292 | 1294 | "", "show capture information" }, |
1293 | 1295 | { "snapshots", "", do_info_snapshots, |
1294 | 1296 | "", "show the currently saved VM snapshots" }, |
1297 | + { "mice", "", do_info_mice, | |
1298 | + "", "show which guest mouse is receiving events" }, | |
1295 | 1299 | { NULL, NULL, }, |
1296 | 1300 | }; |
1297 | 1301 | ... | ... |
qemu-doc.texi
... | ... | @@ -781,6 +781,8 @@ show all USB host devices |
781 | 781 | show information about active capturing |
782 | 782 | @item info snapshots |
783 | 783 | show list of VM snapshots |
784 | +@item info mice | |
785 | +show which guest mouse is receiving events | |
784 | 786 | @end table |
785 | 787 | |
786 | 788 | @item q or quit |
... | ... | @@ -795,6 +797,20 @@ Change a removable media. |
795 | 797 | @item screendump filename |
796 | 798 | Save screen into PPM image @var{filename}. |
797 | 799 | |
800 | +@item mouse_move dx dy [dz] | |
801 | +Move the active mouse to the specified coordinates @var{dx} @var{dy} | |
802 | +with optional scroll axis @var{dz}. | |
803 | + | |
804 | +@item mouse_button val | |
805 | +Change the active mouse button state @var{val} (1=L, 2=M, 4=R). | |
806 | + | |
807 | +@item mouse_set index | |
808 | +Set which mouse device receives events at given @var{index}, index | |
809 | +can be obtained with | |
810 | +@example | |
811 | +info mice | |
812 | +@end example | |
813 | + | |
798 | 814 | @item wavcapture filename [frequency [bits [channels]]] |
799 | 815 | Capture audio into @var{filename}. Using sample rate @var{frequency} |
800 | 816 | bits per sample @var{bits} and number of channels @var{channels}. | ... | ... |
sdl.c
... | ... | @@ -319,6 +319,7 @@ static void sdl_show_cursor(void) |
319 | 319 | { |
320 | 320 | if (!kbd_mouse_is_absolute()) { |
321 | 321 | SDL_ShowCursor(1); |
322 | + SDL_SetCursor(sdl_cursor_normal); | |
322 | 323 | } |
323 | 324 | } |
324 | 325 | |
... | ... | @@ -364,6 +365,9 @@ static void sdl_send_mouse_event(int dz) |
364 | 365 | SDL_GetMouseState(&dx, &dy); |
365 | 366 | dx = dx * 0x7FFF / width; |
366 | 367 | dy = dy * 0x7FFF / height; |
368 | + } else if (absolute_enabled) { | |
369 | + sdl_show_cursor(); | |
370 | + absolute_enabled = 0; | |
367 | 371 | } |
368 | 372 | |
369 | 373 | kbd_mouse_event(dx, dy, dz, buttons); |
... | ... | @@ -501,7 +505,8 @@ static void sdl_refresh(DisplayState *ds) |
501 | 505 | } |
502 | 506 | break; |
503 | 507 | case SDL_MOUSEMOTION: |
504 | - if (gui_grab || kbd_mouse_is_absolute()) { | |
508 | + if (gui_grab || kbd_mouse_is_absolute() || | |
509 | + absolute_enabled) { | |
505 | 510 | sdl_send_mouse_event(0); |
506 | 511 | } |
507 | 512 | break; | ... | ... |
vl.c
... | ... | @@ -463,9 +463,8 @@ void hw_error(const char *fmt, ...) |
463 | 463 | |
464 | 464 | static QEMUPutKBDEvent *qemu_put_kbd_event; |
465 | 465 | static void *qemu_put_kbd_event_opaque; |
466 | -static QEMUPutMouseEvent *qemu_put_mouse_event; | |
467 | -static void *qemu_put_mouse_event_opaque; | |
468 | -static int qemu_put_mouse_event_absolute; | |
466 | +static QEMUPutMouseEntry *qemu_put_mouse_event_head; | |
467 | +static QEMUPutMouseEntry *qemu_put_mouse_event_current; | |
469 | 468 | |
470 | 469 | void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) |
471 | 470 | { |
... | ... | @@ -473,11 +472,68 @@ void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) |
473 | 472 | qemu_put_kbd_event = func; |
474 | 473 | } |
475 | 474 | |
476 | -void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute) | |
475 | +QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, | |
476 | + void *opaque, int absolute, | |
477 | + const char *name) | |
477 | 478 | { |
478 | - qemu_put_mouse_event_opaque = opaque; | |
479 | - qemu_put_mouse_event = func; | |
480 | - qemu_put_mouse_event_absolute = absolute; | |
479 | + QEMUPutMouseEntry *s, *cursor; | |
480 | + | |
481 | + s = qemu_mallocz(sizeof(QEMUPutMouseEntry)); | |
482 | + if (!s) | |
483 | + return NULL; | |
484 | + | |
485 | + s->qemu_put_mouse_event = func; | |
486 | + s->qemu_put_mouse_event_opaque = opaque; | |
487 | + s->qemu_put_mouse_event_absolute = absolute; | |
488 | + s->qemu_put_mouse_event_name = qemu_strdup(name); | |
489 | + s->next = NULL; | |
490 | + | |
491 | + if (!qemu_put_mouse_event_head) { | |
492 | + qemu_put_mouse_event_head = qemu_put_mouse_event_current = s; | |
493 | + return s; | |
494 | + } | |
495 | + | |
496 | + cursor = qemu_put_mouse_event_head; | |
497 | + while (cursor->next != NULL) | |
498 | + cursor = cursor->next; | |
499 | + | |
500 | + cursor->next = s; | |
501 | + qemu_put_mouse_event_current = s; | |
502 | + | |
503 | + return s; | |
504 | +} | |
505 | + | |
506 | +void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry) | |
507 | +{ | |
508 | + QEMUPutMouseEntry *prev = NULL, *cursor; | |
509 | + | |
510 | + if (!qemu_put_mouse_event_head || entry == NULL) | |
511 | + return; | |
512 | + | |
513 | + cursor = qemu_put_mouse_event_head; | |
514 | + while (cursor != NULL && cursor != entry) { | |
515 | + prev = cursor; | |
516 | + cursor = cursor->next; | |
517 | + } | |
518 | + | |
519 | + if (cursor == NULL) // does not exist or list empty | |
520 | + return; | |
521 | + else if (prev == NULL) { // entry is head | |
522 | + qemu_put_mouse_event_head = cursor->next; | |
523 | + if (qemu_put_mouse_event_current == entry) | |
524 | + qemu_put_mouse_event_current = cursor->next; | |
525 | + qemu_free(entry->qemu_put_mouse_event_name); | |
526 | + qemu_free(entry); | |
527 | + return; | |
528 | + } | |
529 | + | |
530 | + prev->next = entry->next; | |
531 | + | |
532 | + if (qemu_put_mouse_event_current == entry) | |
533 | + qemu_put_mouse_event_current = prev; | |
534 | + | |
535 | + qemu_free(entry->qemu_put_mouse_event_name); | |
536 | + qemu_free(entry); | |
481 | 537 | } |
482 | 538 | |
483 | 539 | void kbd_put_keycode(int keycode) |
... | ... | @@ -489,15 +545,72 @@ void kbd_put_keycode(int keycode) |
489 | 545 | |
490 | 546 | void kbd_mouse_event(int dx, int dy, int dz, int buttons_state) |
491 | 547 | { |
492 | - if (qemu_put_mouse_event) { | |
493 | - qemu_put_mouse_event(qemu_put_mouse_event_opaque, | |
494 | - dx, dy, dz, buttons_state); | |
548 | + QEMUPutMouseEvent *mouse_event; | |
549 | + void *mouse_event_opaque; | |
550 | + | |
551 | + if (!qemu_put_mouse_event_current) { | |
552 | + return; | |
553 | + } | |
554 | + | |
555 | + mouse_event = | |
556 | + qemu_put_mouse_event_current->qemu_put_mouse_event; | |
557 | + mouse_event_opaque = | |
558 | + qemu_put_mouse_event_current->qemu_put_mouse_event_opaque; | |
559 | + | |
560 | + if (mouse_event) { | |
561 | + mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state); | |
495 | 562 | } |
496 | 563 | } |
497 | 564 | |
498 | 565 | int kbd_mouse_is_absolute(void) |
499 | 566 | { |
500 | - return qemu_put_mouse_event_absolute; | |
567 | + if (!qemu_put_mouse_event_current) | |
568 | + return 0; | |
569 | + | |
570 | + return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute; | |
571 | +} | |
572 | + | |
573 | +void do_info_mice(void) | |
574 | +{ | |
575 | + QEMUPutMouseEntry *cursor; | |
576 | + int index = 0; | |
577 | + | |
578 | + if (!qemu_put_mouse_event_head) { | |
579 | + term_printf("No mouse devices connected\n"); | |
580 | + return; | |
581 | + } | |
582 | + | |
583 | + term_printf("Mouse devices available:\n"); | |
584 | + cursor = qemu_put_mouse_event_head; | |
585 | + while (cursor != NULL) { | |
586 | + term_printf("%c Mouse #%d: %s\n", | |
587 | + (cursor == qemu_put_mouse_event_current ? '*' : ' '), | |
588 | + index, cursor->qemu_put_mouse_event_name); | |
589 | + index++; | |
590 | + cursor = cursor->next; | |
591 | + } | |
592 | +} | |
593 | + | |
594 | +void do_mouse_set(int index) | |
595 | +{ | |
596 | + QEMUPutMouseEntry *cursor; | |
597 | + int i = 0; | |
598 | + | |
599 | + if (!qemu_put_mouse_event_head) { | |
600 | + term_printf("No mouse devices connected\n"); | |
601 | + return; | |
602 | + } | |
603 | + | |
604 | + cursor = qemu_put_mouse_event_head; | |
605 | + while (cursor != NULL && index != i) { | |
606 | + i++; | |
607 | + cursor = cursor->next; | |
608 | + } | |
609 | + | |
610 | + if (cursor != NULL) | |
611 | + qemu_put_mouse_event_current = cursor; | |
612 | + else | |
613 | + term_printf("Mouse at given index not found\n"); | |
501 | 614 | } |
502 | 615 | |
503 | 616 | /* compute with 96 bit intermediate result: (a*b)/c */ | ... | ... |
vl.h
... | ... | @@ -172,13 +172,29 @@ extern int no_quit; |
172 | 172 | typedef void QEMUPutKBDEvent(void *opaque, int keycode); |
173 | 173 | typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state); |
174 | 174 | |
175 | +typedef struct QEMUPutMouseEntry { | |
176 | + QEMUPutMouseEvent *qemu_put_mouse_event; | |
177 | + void *qemu_put_mouse_event_opaque; | |
178 | + int qemu_put_mouse_event_absolute; | |
179 | + char *qemu_put_mouse_event_name; | |
180 | + | |
181 | + /* used internally by qemu for handling mice */ | |
182 | + struct QEMUPutMouseEntry *next; | |
183 | +} QEMUPutMouseEntry; | |
184 | + | |
175 | 185 | void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); |
176 | -void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque, int absolute); | |
186 | +QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, | |
187 | + void *opaque, int absolute, | |
188 | + const char *name); | |
189 | +void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry); | |
177 | 190 | |
178 | 191 | void kbd_put_keycode(int keycode); |
179 | 192 | void kbd_mouse_event(int dx, int dy, int dz, int buttons_state); |
180 | 193 | int kbd_mouse_is_absolute(void); |
181 | 194 | |
195 | +void do_info_mice(void); | |
196 | +void do_mouse_set(int index); | |
197 | + | |
182 | 198 | /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx |
183 | 199 | constants) */ |
184 | 200 | #define QEMU_KEY_ESC1(c) ((c) | 0xe100) | ... | ... |