From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1JJSey-00068T-Ll for qemu-devel@nongnu.org; Mon, 28 Jan 2008 07:00:20 -0500 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1JJSev-000658-4l for qemu-devel@nongnu.org; Mon, 28 Jan 2008 07:00:19 -0500 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1JJSev-000650-0w for qemu-devel@nongnu.org; Mon, 28 Jan 2008 07:00:17 -0500 Received: from smtp02.citrix.com ([66.165.176.63]) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1JJSeu-0000ua-IT for qemu-devel@nongnu.org; Mon, 28 Jan 2008 07:00:16 -0500 Received: from [172.31.33.111] (host217-46-209-99.in-addr.btopenworld.com [217.46.209.99]) (authenticated bits=0) by smtp01.ad.xensource.com (8.13.1/8.13.1) with ESMTP id m0SBxWKO018407 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 28 Jan 2008 03:59:34 -0800 Message-ID: <479DC394.6020008@citrix.com> Date: Mon, 28 Jan 2008 11:59:16 +0000 From: Stefano Stabellini MIME-Version: 1.0 Subject: Re: [Qemu-devel] [PATCH] mouse click simple queue References: <479DC0F0.5050205@citrix.com> In-Reply-To: <479DC0F0.5050205@citrix.com> Content-Type: multipart/mixed; boundary="------------060609060900020007000905" 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 This is a multi-part message in MIME format. --------------060609060900020007000905 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Sorry for the format of the patch, this time I have generated it using diff -uNp. Stefano Stabellini wrote: > Hi all, > > qemu doesn't enqueue mouse events, just records the latest mouse state. > This can cause some lost mouse double clicks if the events are not > processed fast enought. > I am attaching a patch that implements a simple queue for left mouse > click events. > > Best Regards, > > Stefano Stabellini > --------------060609060900020007000905 Content-Type: text/x-patch; name="mouseclick-queue.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="mouseclick-queue.patch" Index: sdl.c =================================================================== RCS file: /sources/qemu/qemu/sdl.c,v retrieving revision 1.45 diff -u -p -r1.45 sdl.c --- sdl.c 17 Nov 2007 17:14:38 -0000 1.45 +++ sdl.c 28 Jan 2008 11:57:05 -0000 @@ -290,11 +290,10 @@ static void sdl_grab_end(void) sdl_update_caption(); } -static void sdl_send_mouse_event(int dz) +static void sdl_send_mouse_event(int dx, int dy, int dz, int state) { - int dx, dy, state, buttons; - state = SDL_GetRelativeMouseState(&dx, &dy); - buttons = 0; + int buttons = 0; + if (state & SDL_BUTTON(SDL_BUTTON_LEFT)) buttons |= MOUSE_EVENT_LBUTTON; if (state & SDL_BUTTON(SDL_BUTTON_RIGHT)) @@ -311,7 +310,7 @@ static void sdl_send_mouse_event(int dz) absolute_enabled = 1; } - SDL_GetMouseState(&dx, &dy); + SDL_GetMouseState(&dx, &dy); dx = dx * 0x7FFF / width; dy = dy * 0x7FFF / height; } else if (absolute_enabled) { @@ -474,11 +473,19 @@ static void sdl_refresh(DisplayState *ds case SDL_MOUSEMOTION: if (gui_grab || kbd_mouse_is_absolute() || absolute_enabled) { - sdl_send_mouse_event(0); + int dx, dy, state; + state = SDL_GetRelativeMouseState(&dx, &dy); + sdl_send_mouse_event(dx, dy, 0, state); } break; - case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: + if (gui_grab || kbd_mouse_is_absolute()) { + int dx, dy, state; + state = SDL_GetRelativeMouseState(&dx, &dy); + sdl_send_mouse_event(dx, dy, 0, state); + } + break; + case SDL_MOUSEBUTTONDOWN: { SDL_MouseButtonEvent *bev = &ev->button; if (!gui_grab && !kbd_mouse_is_absolute()) { @@ -488,16 +495,21 @@ static void sdl_refresh(DisplayState *ds sdl_grab_start(); } } else { - int dz; + int dx, dy, dz, state; dz = 0; + state = SDL_GetRelativeMouseState(&dx, &dy); #ifdef SDL_BUTTON_WHEELUP - if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) { + if (bev->button == SDL_BUTTON_WHEELUP) { dz = -1; - } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) { + } + else if (bev->button == SDL_BUTTON_WHEELDOWN) { dz = 1; } + else { + state = bev->button | state; + } #endif - sdl_send_mouse_event(dz); + sdl_send_mouse_event(dx, dy, dz, state); } } break; Index: hw/usb-hid.c =================================================================== RCS file: /sources/qemu/qemu/hw/usb-hid.c,v retrieving revision 1.16 diff -u -p -r1.16 usb-hid.c --- hw/usb-hid.c 14 Jan 2008 02:25:44 -0000 1.16 +++ hw/usb-hid.c 28 Jan 2008 11:57:06 -0000 @@ -384,17 +384,39 @@ static const uint8_t usb_hid_usage_keys[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +static int currentbutton = 0; +typedef struct _mouseclick { + int button_state; + struct _mouseclick *next; +} mouseclick; +static mouseclick mousequeue[20]; +static mouseclick *head = mousequeue; +static mouseclick *tail = mousequeue; + static void usb_mouse_event(void *opaque, int dx1, int dy1, int dz1, int buttons_state) { USBHIDState *hs = opaque; USBMouseState *s = &hs->ptr; + if (hs->changed == 1){ + //A mouse event is lost + if (buttons_state != currentbutton && tail->next != head) { + //A left click event is lost: let's add it to the queue + //counter++; + tail->button_state = buttons_state; + tail = tail->next; + } + } + else { + s->buttons_state = buttons_state; + } + s->dx += dx1; s->dy += dy1; s->dz += dz1; - s->buttons_state = buttons_state; hs->changed = 1; + currentbutton = buttons_state; } static void usb_tablet_event(void *opaque, @@ -403,11 +425,24 @@ static void usb_tablet_event(void *opaqu USBHIDState *hs = opaque; USBMouseState *s = &hs->ptr; + if (hs->changed == 1){ + //A mouse event is lost + if (buttons_state != currentbutton && tail->next != head) { + //A left click event is lost: let's add it to the queue + //counter++; + tail->button_state = buttons_state; + tail = tail->next; + } + } + else { + s->buttons_state = buttons_state; + } + s->x = x; s->y = y; s->dz += dz; - s->buttons_state = buttons_state; hs->changed = 1; + currentbutton = buttons_state; } static void usb_keyboard_event(void *opaque, int keycode) @@ -776,13 +811,26 @@ static int usb_hid_handle_data(USBDevice /* TODO: Implement finite idle delays. */ if (!(s->changed || s->idle)) return USB_RET_NAK; - s->changed = 0; + if (s->kind == USB_MOUSE) ret = usb_mouse_poll(s, p->data, p->len); else if (s->kind == USB_TABLET) ret = usb_tablet_poll(s, p->data, p->len); else if (s->kind == USB_KEYBOARD) ret = usb_keyboard_poll(&s->kbd, p->data, p->len); + + if ((s->kind == USB_MOUSE || s->kind == USB_TABLET) && s->changed) { + USBMouseState *ms = &s->ptr; + if (head != tail) { + ms->buttons_state = head->button_state; + head = head->next; + } + else { + s->changed = 0; + } + } else { + s->changed = 0; + } } else { goto fail; } @@ -808,8 +856,16 @@ static void usb_hid_handle_destroy(USBDe USBDevice *usb_tablet_init(void) { + int i; USBHIDState *s; + for (i = 0; i < 19; i++) { + mousequeue[i].button_state = 0; + mousequeue[i].next = &(mousequeue[i + 1]); + } + mousequeue[i].button_state = 0; + mousequeue[i].next = mousequeue; + s = qemu_mallocz(sizeof(USBHIDState)); if (!s) return NULL; @@ -831,8 +887,16 @@ USBDevice *usb_tablet_init(void) USBDevice *usb_mouse_init(void) { + int i; USBHIDState *s; + for (i = 0; i < 19; i++) { + mousequeue[i].button_state = 0; + mousequeue[i].next = &(mousequeue[i + 1]); + } + mousequeue[i].button_state = 0; + mousequeue[i].next = mousequeue; + s = qemu_mallocz(sizeof(USBHIDState)); if (!s) return NULL; --------------060609060900020007000905--