From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1FSyKF-0006Jo-IB for qemu-devel@nongnu.org; Mon, 10 Apr 2006 11:29:11 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1FSyKC-0006J9-1S for qemu-devel@nongnu.org; Mon, 10 Apr 2006 11:29:11 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1FSyKB-0006J6-TL for qemu-devel@nongnu.org; Mon, 10 Apr 2006 11:29:07 -0400 Received: from [32.97.182.146] (helo=e6.ny.us.ibm.com) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA:32) (Exim 4.52) id 1FSyOq-0003Kw-QS for qemu-devel@nongnu.org; Mon, 10 Apr 2006 11:33:57 -0400 Received: from d01relay02.pok.ibm.com (d01relay02.pok.ibm.com [9.56.227.234]) by e6.ny.us.ibm.com (8.12.11.20060308/8.12.11) with ESMTP id k3AFT0CX002331 for ; Mon, 10 Apr 2006 11:29:00 -0400 Received: from d01av04.pok.ibm.com (d01av04.pok.ibm.com [9.56.224.64]) by d01relay02.pok.ibm.com (8.12.10/NCO/VER6.8) with ESMTP id k3AFRdIm187642 for ; Mon, 10 Apr 2006 11:27:39 -0400 Received: from d01av04.pok.ibm.com (loopback [127.0.0.1]) by d01av04.pok.ibm.com (8.12.11/8.13.3) with ESMTP id k3AFRddN023193 for ; Mon, 10 Apr 2006 11:27:39 -0400 Received: from [9.76.22.184] (sig-9-76-22-184.mts.ibm.com [9.76.22.184]) by d01av04.pok.ibm.com (8.12.11/8.12.11) with ESMTP id k3AFRcUc022811 for ; Mon, 10 Apr 2006 11:27:38 -0400 Message-ID: <443A7964.7050704@us.ibm.com> Date: Mon, 10 Apr 2006 10:27:32 -0500 From: Anthony Liguori MIME-Version: 1.0 Subject: Re: [Qemu-devel] USB Tablet Emulation References: <443802FB.9060700@win4lin.com> <44381AE0.1020106@wasp.net.au> <443825D8.3080602@win4lin.com> <443953D7.3060109@wasp.net.au> <44395575.1040303@austin.rr.com> <44395EE9.3040403@wasp.net.au> <44396E20.6010103@wasp.net.au> <4439753C.8080405@us.ibm.com> <44397848.1070707@wasp.net.au> <44397EFA.5070104@us.ibm.com> <44398445.4010602@wasp.net.au> <443985C3.1000206@us.ibm.com> <4439954C.1050609@wasp.net.au> <4439D396.6010006@us.ibm.com> <443A72A4.4090608@win4lin.com> In-Reply-To: <443A72A4.4090608@win4lin.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Leonardo E. Reiter wrote: > Anthony, > > your patch works perfectly, even with Windows XP as well. Make sure to give credit where credit's due. Brad Campbell figured out the hard stuff :-) > The transition from the boot-time PS/2 mouse is perfect, and the way > the cursor grab logic is handled is seamless. I haven't been able to > test the scroll wheel because I have some hardware restrictions today > (laptop only for a while)... does that still work as well? I haven't tried it but Brad has. Perhaps he can comment here. Regards, Anthony Liguori > I also tested it as a normal X11 application on top of an Xvnc server, > and that works great, even with -full-screen set. > > Thank you, > > Leo Reiter > > Anthony Liguori wrote: >> I spent some time cleaning this all up. The following integrates >> Brad's patches and the patch from >> http://gnome.dnsalias.net/patches/qemu-hidmousexp.patch >> >> It adds a new emulated USB device that reports absolute coordinates. >> It also modifies SDL to operate in grabless mode when an absolute >> input device is enabled. I think it's pretty close to apply-able. >> To use, just specify: -usbdevice tablet >> >> With Xorg from CVS, the evdev driver segfaults. This is apparently >> expected behavior. Hopefully it will be fixed soon. It works quite >> nicely under Win2k. >> >> Regards, >> >> Anthony Liguori >> >> Brad Campbell wrote: >> >>> Anthony Liguori wrote: >>> >>>> >>>> Final one of the night. This patch disables relative mouse >>>> reporting and disables grab automatically the first time SDL >>>> detects that the absolute mouse was enabled. Needs a lot of >>>> cleanup but I'm very happy with the user experience on this one. >>>> >>> >>> Wish I'd just gone to bed now.. >>> Heres a patch against your last one to implement wheel support. >>> >>> Brad >>> ------------------------------------------------------------------------ >>> >>> >>> diff -ur qemu-clean/hw/usb-hid.c qemu/hw/usb-hid.c >>> --- qemu-clean/hw/usb-hid.c 2006-04-10 02:57:46.000000000 +0400 >>> +++ qemu/hw/usb-hid.c 2006-04-10 03:11:58.000000000 +0400 >>> @@ -101,7 +101,7 @@ >>> 0x00, /* u8 country_code */ >>> 0x01, /* u8 num_descriptors */ >>> 0x22, /* u8 type; Report */ >>> - 53, 0, /* u16 len */ >>> + 65, 0, /* u16 len */ >>> >>> /* one endpoint (status change endpoint) */ >>> 0x07, /* u8 ep_bLength; */ >>> @@ -145,14 +145,15 @@ >>> 0x09, 0x31, /* Usage Y */ >>> 0x15, 0x00, /* Logical Minimum 0 */ >>> 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum 0xffff */ >>> - 0x75, 0x10, /* Report Size 32 */ >>> + 0x75, 0x10, /* Report Size 16 */ >>> 0x95, 0x02, /* Report Count 2 */ >>> 0x81, 0x02, /* Input (Data, Var, Abs) */ >>> -// 0x09, 0x32, /* Usage Z */ >>> -// 0x15, 0x81, /* Logical Minimum -127 */ >>> -// 0x25, 0x7F, /* Logical Maximum 127 */ >>> -// 0x75, 0x08, /* Report Size 8 */ >>> -// 0x95, 0x01, /* Report Count 1 */ >>> + 0x09, 0x38, /* Usage Wheel */ >>> + 0x15, 0x81, /* Logical Minimum -127 */ >>> + 0x25, 0x7F, /* Logical Maximum 127 */ >>> + 0x75, 0x08, /* Report Size 8 */ >>> + 0x95, 0x01, /* Report Count 1 */ >>> + 0x81, 0x02, /* Input (Data, Var, Rel) */ >>> 0xC0, /* End Collection */ >>> 0xC0, /* End Collection */ >>> }; >>> @@ -224,14 +225,18 @@ >>> qemu_add_mouse_event_handler(NULL, NULL); >>> absolute_mouse = 1; >>> } >>> - >>> +/* >>> dx = int_clamp(s->dx, -128, 127); >>> dy = int_clamp(s->dy, -128, 127); >>> - dz = int_clamp(s->dz, -128, 127); >>> >>> s->dx -= dx; >>> s->dy -= dy; >>> +*/ >>> + >>> + dz = int_clamp(s->dz, -128, 127); >>> s->dz -= dz; >>> +/* Appears we have to invert the wheel direction */ >>> + dz = 0 - dz; >>> b = 0; >>> if (s->buttons_state & MOUSE_EVENT_LBUTTON) >>> b |= 0x01; >>> @@ -245,7 +250,8 @@ >>> buf[2] = s->X >> 8; >>> buf[3] = s->Y & 0xff; >>> buf[4] = s->Y >> 8; >>> - l = 5; >>> + buf[5] = dz; >>> + l = 6; >>> >>> return l; >>> } >>> >>> ------------------------------------------------------------------------ >>> >>> >>> _______________________________________________ >>> Qemu-devel mailing list >>> Qemu-devel@nongnu.org >>> http://lists.nongnu.org/mailman/listinfo/qemu-devel >>> >> >> >> >> ------------------------------------------------------------------------ >> >> diff -r 6a786a97b822 hw/ps2.c >> --- a/hw/ps2.c Mon Apr 10 01:47:35 2006 +0000 >> +++ b/hw/ps2.c Sun Apr 9 22:34:20 2006 -0500 >> @@ -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); >> + qemu_add_mouse_event_handler(ps2_mouse_event, s, 0); >> qemu_register_reset(ps2_reset, &s->common); >> return s; >> } >> diff -r 6a786a97b822 hw/usb-hid.c >> --- a/hw/usb-hid.c Mon Apr 10 01:47:35 2006 +0000 >> +++ b/hw/usb-hid.c Sun Apr 9 22:34:20 2006 -0500 >> @@ -30,9 +30,15 @@ >> #define SET_IDLE 0x210a >> #define SET_PROTOCOL 0x210b >> >> +#define USB_MOUSE 1 >> +#define USB_TABLET 2 >> + >> typedef struct USBMouseState { >> USBDevice dev; >> int dx, dy, dz, buttons_state; >> + int x, y; >> + int kind; >> + int mouse_grabbed; >> } USBMouseState; >> >> /* mostly the same values as the Bochs USB Mouse device */ >> @@ -93,14 +99,6 @@ >> 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ >> 0x05, /* u8 if_iInterface; */ >> - /* one endpoint (status change endpoint) */ >> - 0x07, /* u8 ep_bLength; */ >> - 0x05, /* u8 ep_bDescriptorType; Endpoint */ >> - 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ >> - 0x03, /* u8 ep_bmAttributes; Interrupt */ >> - 0x03, 0x00, /* u16 ep_wMaxPacketSize; */ >> - 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ >> - >> /* HID descriptor */ >> 0x09, /* u8 bLength; */ >> 0x21, /* u8 bDescriptorType; */ >> @@ -109,6 +107,69 @@ >> 0x01, /* u8 num_descriptors */ >> 0x22, /* u8 type; Report */ >> 50, 0, /* u16 len */ >> + >> + /* one endpoint (status change endpoint) */ >> + 0x07, /* u8 ep_bLength; */ >> + 0x05, /* u8 ep_bDescriptorType; Endpoint */ >> + 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ >> + 0x03, /* u8 ep_bmAttributes; Interrupt */ >> + 0x03, 0x00, /* u16 ep_wMaxPacketSize; */ >> + 0x0a, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ >> +}; >> + >> +static const uint8_t qemu_tablet_config_descriptor[] = { >> + /* one configuration */ >> + 0x09, /* u8 bLength; */ >> + 0x02, /* u8 bDescriptorType; Configuration */ >> + 0x22, 0x00, /* u16 wTotalLength; */ >> + 0x01, /* u8 bNumInterfaces; (1) */ >> + 0x01, /* u8 bConfigurationValue; */ >> + 0x04, /* u8 iConfiguration; */ >> + 0xa0, /* u8 bmAttributes; + Bit 7: must >> be set, >> + 6: Self-powered, >> + 5: Remote wakeup, >> + 4..0: resvd */ >> + 50, /* u8 MaxPower; */ >> + + /* USB 1.1: >> + * USB 2.0, single TT organization (mandatory): >> + * one interface, protocol 0 >> + * >> + * USB 2.0, multiple TT organization (optional): >> + * two interfaces, protocols 1 (like single TT) >> + * and 2 (multiple TT mode) ... config is >> + * sometimes settable >> + * NOT IMPLEMENTED >> + */ >> + >> + /* one interface */ >> + 0x09, /* u8 if_bLength; */ >> + 0x04, /* u8 if_bDescriptorType; Interface */ >> + 0x00, /* u8 if_bInterfaceNumber; */ >> + 0x00, /* u8 if_bAlternateSetting; */ >> + 0x01, /* u8 if_bNumEndpoints; */ >> + 0x03, /* u8 if_bInterfaceClass; */ >> + 0x01, /* u8 if_bInterfaceSubClass; */ >> + 0x02, /* u8 if_bInterfaceProtocol; [usb1.1 or single tt] */ >> + 0x05, /* u8 if_iInterface; */ >> + >> + /* HID descriptor */ >> + 0x09, /* u8 bLength; */ >> + 0x21, /* u8 bDescriptorType; */ >> + 0x01, 0x00, /* u16 HID_class */ >> + 0x00, /* u8 country_code */ >> + 0x01, /* u8 num_descriptors */ >> + 0x22, /* u8 type; Report */ >> + 65, 0, /* u16 len */ >> + >> + /* one endpoint (status change endpoint) */ >> + 0x07, /* u8 ep_bLength; */ >> + 0x05, /* u8 ep_bDescriptorType; Endpoint */ >> + 0x81, /* u8 ep_bEndpointAddress; IN Endpoint 1 */ >> + 0x03, /* u8 ep_bmAttributes; Interrupt */ >> + 0x08, 0x00, /* u16 ep_wMaxPacketSize; */ >> + 0x03, /* u8 ep_bInterval; (255ms -- usb 2.0 spec) */ >> }; >> >> static const uint8_t qemu_mouse_hid_report_descriptor[] = { >> @@ -121,6 +182,41 @@ >> 0xC0, 0xC0, >> }; >> >> +static const uint8_t qemu_tablet_hid_report_descriptor[] = { >> + 0x05, 0x01, /* Usage Page Generic Desktop */ >> + 0x09, 0x01, /* Usage Mouse */ >> + 0xA1, 0x01, /* Collection Application */ >> + 0x09, 0x01, /* Usage Pointer */ >> + 0xA1, 0x00, /* Collection Physical */ >> + 0x05, 0x09, /* Usage Page Button */ >> + 0x19, 0x01, /* Usage Minimum Button 1 */ >> + 0x29, 0x03, /* Usage Maximum Button 3 */ >> + 0x15, 0x00, /* Logical Minimum 0 */ >> + 0x25, 0x01, /* Logical Maximum 1 */ >> + 0x95, 0x03, /* Report Count 3 */ >> + 0x75, 0x01, /* Report Size 1 */ >> + 0x81, 0x02, /* Input (Data, Var, Abs) */ >> + 0x95, 0x01, /* Report Count 1 */ >> + 0x75, 0x05, /* Report Size 5 */ >> + 0x81, 0x01, /* Input (Cnst, Var, Abs) */ >> + 0x05, 0x01, /* Usage Page Generic Desktop */ >> + 0x09, 0x30, /* Usage X */ >> + 0x09, 0x31, /* Usage Y */ >> + 0x15, 0x00, /* Logical Minimum 0 */ >> + 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum 0xffff */ >> + 0x75, 0x10, /* Report Size 16 */ >> + 0x95, 0x02, /* Report Count 2 */ >> + 0x81, 0x02, /* Input (Data, Var, Abs) */ >> + 0x09, 0x38, /* Usage Wheel */ >> + 0x15, 0x81, /* Logical Minimum -127 */ >> + 0x25, 0x7F, /* Logical Maximum 127 */ >> + 0x75, 0x08, /* Report Size 8 */ >> + 0x95, 0x01, /* Report Count 1 */ >> + 0x81, 0x02, /* Input (Data, Var, Rel) */ >> + 0xC0, /* End Collection */ >> + 0xC0, /* End Collection */ >> +}; >> + >> static void usb_mouse_event(void *opaque, >> int dx1, int dy1, int dz1, int >> buttons_state) >> { >> @@ -129,6 +225,17 @@ >> s->dx += dx1; >> s->dy += dy1; >> s->dz += dz1; >> + s->buttons_state = buttons_state; >> +} >> + >> +static void usb_tablet_event(void *opaque, >> + int x, int y, int dz, int buttons_state) >> +{ >> + USBMouseState *s = opaque; >> + >> + s->x = x; >> + s->y = y; >> + s->dz += dz; >> s->buttons_state = buttons_state; >> } >> >> @@ -146,6 +253,11 @@ >> { >> int dx, dy, dz, b, l; >> >> + if (!s->mouse_grabbed) { >> + qemu_add_mouse_event_handler(usb_mouse_event, s, 0); >> + s->mouse_grabbed = 1; >> + } >> + dx = int_clamp(s->dx, -128, 127); >> dy = int_clamp(s->dy, -128, 127); >> dz = int_clamp(s->dz, -128, 127); >> @@ -173,6 +285,39 @@ >> return l; >> } >> >> +static int usb_tablet_poll(USBMouseState *s, uint8_t *buf, int len) >> +{ >> + int dz, b, l; >> + >> + if (!s->mouse_grabbed) { >> + qemu_add_mouse_event_handler(usb_tablet_event, s, 1); >> + s->mouse_grabbed = 1; >> + } >> + + dz = int_clamp(s->dz, -128, 127); >> + s->dz -= dz; >> + >> + /* Appears we have to invert the wheel direction */ >> + dz = 0 - dz; >> + b = 0; >> + if (s->buttons_state & MOUSE_EVENT_LBUTTON) >> + b |= 0x01; >> + if (s->buttons_state & MOUSE_EVENT_RBUTTON) >> + b |= 0x02; >> + if (s->buttons_state & MOUSE_EVENT_MBUTTON) >> + b |= 0x04; >> + >> + buf[0] = b; >> + buf[1] = s->x & 0xff; >> + buf[2] = s->x >> 8; >> + buf[3] = s->y & 0xff; >> + buf[4] = s->y >> 8; >> + buf[5] = dz; >> + l = 6; >> + >> + return l; >> +} >> + >> static void usb_mouse_handle_reset(USBDevice *dev) >> { >> USBMouseState *s = (USBMouseState *)dev; >> @@ -180,6 +325,8 @@ >> s->dx = 0; >> s->dy = 0; >> s->dz = 0; >> + s->x = 0; >> + s->y = 0; >> s->buttons_state = 0; >> } >> >> @@ -187,7 +334,7 @@ >> int index, int length, uint8_t *data) >> { >> USBMouseState *s = (USBMouseState *)dev; >> - int ret; >> + int ret = 0; >> >> switch(request) { >> case DeviceRequest | USB_REQ_GET_STATUS: >> @@ -224,9 +371,15 @@ >> ret = sizeof(qemu_mouse_dev_descriptor); >> break; >> case USB_DT_CONFIG: >> - memcpy(data, qemu_mouse_config_descriptor, >> - sizeof(qemu_mouse_config_descriptor)); >> - ret = sizeof(qemu_mouse_config_descriptor); >> + if (s->kind == USB_MOUSE) { >> + memcpy(data, qemu_mouse_config_descriptor, + >> sizeof(qemu_mouse_config_descriptor)); >> + ret = sizeof(qemu_mouse_config_descriptor); >> + } else if (s->kind == USB_TABLET) { >> + memcpy(data, qemu_tablet_config_descriptor, + >> sizeof(qemu_tablet_config_descriptor)); >> + ret = sizeof(qemu_tablet_config_descriptor); >> + } >> break; >> case USB_DT_STRING: >> switch(value & 0xff) { >> @@ -244,7 +397,10 @@ >> break; >> case 2: >> /* product description */ >> - ret = set_usb_string(data, "QEMU USB Mouse"); >> + if (s->kind == USB_MOUSE) >> + ret = set_usb_string(data, "QEMU USB Mouse"); >> + else if (s->kind == USB_TABLET) >> + ret = set_usb_string(data, "QEMU USB Tablet"); >> break; >> case 3: >> /* vendor description */ >> @@ -282,16 +438,25 @@ >> case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: >> switch(value >> 8) { >> case 0x22: >> - memcpy(data, qemu_mouse_hid_report_descriptor, >> - sizeof(qemu_mouse_hid_report_descriptor)); >> - ret = sizeof(qemu_mouse_hid_report_descriptor); >> - break; >> + if (s->kind == USB_MOUSE) { >> + memcpy(data, qemu_mouse_hid_report_descriptor, >> + sizeof(qemu_mouse_hid_report_descriptor)); >> + ret = sizeof(qemu_mouse_hid_report_descriptor); >> + } else if (s->kind == USB_TABLET) { >> + memcpy(data, qemu_tablet_hid_report_descriptor, >> + sizeof(qemu_tablet_hid_report_descriptor)); >> + ret = sizeof(qemu_tablet_hid_report_descriptor); >> + } >> + break; >> default: >> goto fail; >> } >> break; >> case GET_REPORT: >> - ret = usb_mouse_poll(s, data, length); >> + if (s->kind == USB_MOUSE) >> + ret = usb_mouse_poll(s, data, length); >> + else if (s->kind == USB_TABLET) >> + ret = usb_tablet_poll(s, data, length); >> break; >> case SET_IDLE: >> ret = 0; >> @@ -308,12 +473,15 @@ >> uint8_t devep, uint8_t *data, int len) >> { >> USBMouseState *s = (USBMouseState *)dev; >> - int ret; >> + int ret = 0; >> >> switch(pid) { >> case USB_TOKEN_IN: >> if (devep == 1) { >> - ret = usb_mouse_poll(s, data, len); >> + if (s->kind == USB_MOUSE) >> + ret = usb_mouse_poll(s, data, len); >> + else if (s->kind == USB_TABLET) >> + ret = usb_tablet_poll(s, data, len); >> } else { >> goto fail; >> } >> @@ -327,7 +495,7 @@ >> return ret; >> } >> >> -USBDevice *usb_mouse_init(void) >> +USBDevice *usb_tablet_init(void) >> { >> USBMouseState *s; >> >> @@ -340,8 +508,25 @@ >> s->dev.handle_reset = usb_mouse_handle_reset; >> s->dev.handle_control = usb_mouse_handle_control; >> s->dev.handle_data = usb_mouse_handle_data; >> - >> - qemu_add_mouse_event_handler(usb_mouse_event, s); >> - + s->kind = USB_TABLET; >> + >> return (USBDevice *)s; >> } >> + >> +USBDevice *usb_mouse_init(void) >> +{ >> + USBMouseState *s; >> + >> + s = qemu_mallocz(sizeof(USBMouseState)); >> + if (!s) >> + return NULL; >> + s->dev.speed = USB_SPEED_FULL; >> + s->dev.handle_packet = usb_generic_handle_packet; >> + >> + s->dev.handle_reset = usb_mouse_handle_reset; >> + s->dev.handle_control = usb_mouse_handle_control; >> + s->dev.handle_data = usb_mouse_handle_data; >> + s->kind = USB_MOUSE; >> + >> + return (USBDevice *)s; >> +} >> diff -r 6a786a97b822 hw/usb.h >> --- a/hw/usb.h Mon Apr 10 01:47:35 2006 +0000 >> +++ b/hw/usb.h Sun Apr 9 22:34:20 2006 -0500 >> @@ -163,3 +163,4 @@ >> >> /* usb-hid.c */ >> USBDevice *usb_mouse_init(void); >> +USBDevice *usb_tablet_init(void); >> diff -r 6a786a97b822 sdl.c >> --- a/sdl.c Mon Apr 10 01:47:35 2006 +0000 >> +++ b/sdl.c Sun Apr 9 22:34:20 2006 -0500 >> @@ -39,6 +39,10 @@ >> static int gui_fullscreen_initial_grab; >> static int gui_grab_code = KMOD_LALT | KMOD_LCTRL; >> static uint8_t modifiers_state[256]; >> +static int width, height; >> +static SDL_Cursor *sdl_cursor_normal; >> +static SDL_Cursor *sdl_cursor_hidden; >> +static int absolute_enabled = 0; >> >> static void sdl_update(DisplayState *ds, int x, int y, int w, int h) >> { >> @@ -55,6 +59,9 @@ >> flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL; >> if (gui_fullscreen) >> flags |= SDL_FULLSCREEN; >> + >> + width = w; >> + height = h; >> >> again: >> screen = SDL_SetVideoMode(w, h, 0, flags); >> @@ -271,9 +278,21 @@ >> SDL_WM_SetCaption(buf, "QEMU"); >> } >> >> +static void sdl_hide_cursor(void) >> +{ >> + SDL_SetCursor(sdl_cursor_hidden); >> +} >> + >> +static void sdl_show_cursor(void) >> +{ >> + if (!kbd_mouse_is_absolute()) { >> + SDL_SetCursor(sdl_cursor_normal); >> + } >> +} >> + >> static void sdl_grab_start(void) >> { >> - SDL_ShowCursor(0); >> + sdl_hide_cursor(); >> SDL_WM_GrabInput(SDL_GRAB_ON); >> /* dummy read to avoid moving the mouse */ >> SDL_GetRelativeMouseState(NULL, NULL); >> @@ -284,7 +303,7 @@ >> static void sdl_grab_end(void) >> { >> SDL_WM_GrabInput(SDL_GRAB_OFF); >> - SDL_ShowCursor(1); >> + sdl_show_cursor(); >> gui_grab = 0; >> sdl_update_caption(); >> } >> @@ -300,6 +319,21 @@ >> buttons |= MOUSE_EVENT_RBUTTON; >> if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE)) >> buttons |= MOUSE_EVENT_MBUTTON; >> + >> + if (kbd_mouse_is_absolute()) { >> + if (!absolute_enabled) { >> + sdl_hide_cursor(); >> + if (gui_grab) { >> + sdl_grab_end(); >> + } >> + absolute_enabled = 1; >> + } >> + >> + SDL_GetMouseState(&dx, &dy); >> + dx = dx * 0x7FFF / width; >> + dy = dy * 0x7FFF / height; >> + } >> + >> kbd_mouse_event(dx, dy, dz, buttons); >> } >> >> @@ -423,7 +457,7 @@ >> qemu_system_shutdown_request(); >> break; >> case SDL_MOUSEMOTION: >> - if (gui_grab) { >> + if (gui_grab || kbd_mouse_is_absolute()) { >> sdl_send_mouse_event(0); >> } >> break; >> @@ -431,7 +465,7 @@ >> case SDL_MOUSEBUTTONUP: >> { >> SDL_MouseButtonEvent *bev = &ev->button; >> - if (!gui_grab) { >> + if (!gui_grab && !kbd_mouse_is_absolute()) { >> if (ev->type == SDL_MOUSEBUTTONDOWN && >> (bev->state & SDL_BUTTON_LMASK)) { >> /* start grabbing all events */ >> @@ -471,6 +505,7 @@ >> void sdl_display_init(DisplayState *ds, int full_screen) >> { >> int flags; >> + uint8_t data = 0; >> >> #if defined(__APPLE__) >> /* always use generic keymaps */ >> @@ -504,6 +539,9 @@ >> SDL_EnableUNICODE(1); >> gui_grab = 0; >> >> + sdl_cursor_hidden = SDL_CreateCursor(&data, &data, 8, 1, 0, 0); >> + sdl_cursor_normal = SDL_GetCursor(); >> + >> atexit(sdl_cleanup); >> if (full_screen) { >> gui_fullscreen = 1; >> diff -r 6a786a97b822 vl.c >> --- a/vl.c Mon Apr 10 01:47:35 2006 +0000 >> +++ b/vl.c Sun Apr 9 22:34:20 2006 -0500 >> @@ -474,6 +474,7 @@ >> 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; >> >> void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque) >> { >> @@ -481,10 +482,11 @@ >> qemu_put_kbd_event = func; >> } >> >> -void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void >> *opaque) >> +void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void >> *opaque, int absolute) >> { >> qemu_put_mouse_event_opaque = opaque; >> qemu_put_mouse_event = func; >> + qemu_put_mouse_event_absolute = absolute; >> } >> >> void kbd_put_keycode(int keycode) >> @@ -500,6 +502,11 @@ >> qemu_put_mouse_event(qemu_put_mouse_event_opaque, >> dx, dy, dz, buttons_state); >> } >> +} >> + >> +int kbd_mouse_is_absolute(void) >> +{ >> + return qemu_put_mouse_event_absolute; >> } >> >> /***********************************************************/ >> @@ -2855,6 +2862,10 @@ >> dev = usb_mouse_init(); >> if (!dev) >> return -1; >> + } else if (!strcmp(devname, "tablet")) { >> + dev = usb_tablet_init(); >> + if (!dev) >> + return -1; >> } else { >> return -1; >> } >> diff -r 6a786a97b822 vl.h >> --- a/vl.h Mon Apr 10 01:47:35 2006 +0000 >> +++ b/vl.h Sun Apr 9 22:34:20 2006 -0500 >> @@ -158,10 +158,11 @@ >> typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, >> int buttons_state); >> >> void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque); >> -void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void >> *opaque); >> +void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void >> *opaque, int absolute); >> >> 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); >> >> /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx >> constants) */ >> >> >> ------------------------------------------------------------------------ >> >> _______________________________________________ >> Qemu-devel mailing list >> Qemu-devel@nongnu.org >> http://lists.nongnu.org/mailman/listinfo/qemu-devel >