ia64/xen-unstable

changeset 17017:96b418cf047e

qemu: Queue mouse clicks.

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. This patch implements a simple queue for
left mouse click events.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Feb 11 09:57:38 2008 +0000 (2008-02-11)
parents c68ce89542c7
children df9e3ec0490a
files tools/ioemu/hw/usb-hid.c tools/ioemu/sdl.c
line diff
     1.1 --- a/tools/ioemu/hw/usb-hid.c	Mon Feb 11 09:47:19 2008 +0000
     1.2 +++ b/tools/ioemu/hw/usb-hid.c	Mon Feb 11 09:57:38 2008 +0000
     1.3 @@ -224,15 +224,37 @@ static const uint8_t qemu_tablet_hid_rep
     1.4          0xC0,       /* End Collection */
     1.5  };
     1.6  
     1.7 +static int currentbutton = 0;
     1.8 +typedef struct _mouseclick {
     1.9 +    int button_state;
    1.10 +    struct _mouseclick *next;
    1.11 +} mouseclick; 
    1.12 +static mouseclick mousequeue[20];
    1.13 +static mouseclick *head = mousequeue;
    1.14 +static mouseclick *tail = mousequeue;
    1.15 +
    1.16  static void usb_mouse_event(void *opaque,
    1.17                              int dx1, int dy1, int dz1, int buttons_state)
    1.18  {
    1.19      USBMouseState *s = opaque;
    1.20  
    1.21 +    if (s->status_changed == 1){
    1.22 +        //A mouse event is lost
    1.23 +        if (buttons_state != currentbutton && tail->next != head) {
    1.24 +            //A left click event is lost: let's add it to the queue
    1.25 +            //counter++;
    1.26 +            tail->button_state = buttons_state;
    1.27 +            tail = tail->next;
    1.28 +        }
    1.29 +    }
    1.30 +    else {
    1.31 +        s->buttons_state = buttons_state;
    1.32 +    }
    1.33 +
    1.34      s->dx += dx1;
    1.35      s->dy += dy1;
    1.36      s->dz += dz1;
    1.37 -    s->buttons_state = buttons_state;
    1.38 +    currentbutton = buttons_state;
    1.39      s->status_changed = 1;
    1.40  }
    1.41  
    1.42 @@ -240,11 +262,24 @@ static void usb_tablet_event(void *opaqu
    1.43  			     int x, int y, int dz, int buttons_state)
    1.44  {
    1.45      USBMouseState *s = opaque;
    1.46 +    
    1.47 +    if (s->status_changed == 1){
    1.48 +        //A mouse event is lost
    1.49 +        if (buttons_state != currentbutton && tail->next != head) {
    1.50 +            //A left click event is lost: let's add it to the queue
    1.51 +            //counter++;
    1.52 +            tail->button_state = buttons_state;
    1.53 +            tail = tail->next;
    1.54 +        }
    1.55 +    }
    1.56 +    else {
    1.57 +        s->buttons_state = buttons_state;
    1.58 +    }
    1.59  
    1.60      s->x = x;
    1.61      s->y = y;
    1.62      s->dz += dz;
    1.63 -    s->buttons_state = buttons_state;
    1.64 +    currentbutton = buttons_state;
    1.65      s->status_changed = 1;
    1.66  }
    1.67  
    1.68 @@ -493,10 +528,17 @@ static int usb_mouse_handle_data(USBDevi
    1.69              else if (s->kind == USB_TABLET)
    1.70                  ret = usb_tablet_poll(s, p->data, p->len);
    1.71  
    1.72 -            if (!s->status_changed)
    1.73 +            if (!s->status_changed) {
    1.74                  ret = USB_RET_NAK;
    1.75 -            else
    1.76 -                s->status_changed = 0;
    1.77 +            } else {
    1.78 +                if (head != tail) {
    1.79 +                    s->buttons_state = head->button_state;
    1.80 +                    head = head->next;
    1.81 +                }
    1.82 +                else {
    1.83 +                    s->status_changed = 0;
    1.84 +                }
    1.85 +            }
    1.86  
    1.87          } else {
    1.88              goto fail;
    1.89 @@ -567,6 +609,14 @@ int usb_mouse_load(QEMUFile *f, void *op
    1.90  USBDevice *usb_tablet_init(void)
    1.91  {
    1.92      USBMouseState *s;
    1.93 +    int i;
    1.94 +    
    1.95 +    for (i = 0; i < 19; i++) {
    1.96 +        mousequeue[i].button_state = 0;
    1.97 +        mousequeue[i].next = &(mousequeue[i + 1]);
    1.98 +    }
    1.99 +    mousequeue[i].button_state = 0;
   1.100 +    mousequeue[i].next = mousequeue;
   1.101  
   1.102      s = qemu_mallocz(sizeof(USBMouseState));
   1.103      if (!s)
   1.104 @@ -591,6 +641,14 @@ USBDevice *usb_tablet_init(void)
   1.105  USBDevice *usb_mouse_init(void)
   1.106  {
   1.107      USBMouseState *s;
   1.108 +    int i;
   1.109 +    
   1.110 +    for (i = 0; i < 19; i++) {
   1.111 +        mousequeue[i].button_state = 0;
   1.112 +        mousequeue[i].next = &(mousequeue[i + 1]);
   1.113 +    }
   1.114 +    mousequeue[i].button_state = 0;
   1.115 +    mousequeue[i].next = mousequeue;
   1.116  
   1.117      s = qemu_mallocz(sizeof(USBMouseState));
   1.118      if (!s)
     2.1 --- a/tools/ioemu/sdl.c	Mon Feb 11 09:47:19 2008 +0000
     2.2 +++ b/tools/ioemu/sdl.c	Mon Feb 11 09:57:38 2008 +0000
     2.3 @@ -259,11 +259,9 @@ static void sdl_grab_end(void)
     2.4      sdl_update_caption();
     2.5  }
     2.6  
     2.7 -static void sdl_send_mouse_event(int dz)
     2.8 +static void sdl_send_mouse_event(int dx, int dy, int dz, int state)
     2.9  {
    2.10 -    int dx, dy, state, buttons;
    2.11 -    state = SDL_GetRelativeMouseState(&dx, &dy);
    2.12 -    buttons = 0;
    2.13 +    int buttons = 0;
    2.14      if (state & SDL_BUTTON(SDL_BUTTON_LEFT))
    2.15          buttons |= MOUSE_EVENT_LBUTTON;
    2.16      if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))
    2.17 @@ -425,11 +423,19 @@ static void sdl_refresh(DisplayState *ds
    2.18          case SDL_MOUSEMOTION:
    2.19              if (gui_grab || kbd_mouse_is_absolute() ||
    2.20                  absolute_enabled) {
    2.21 -                sdl_send_mouse_event(0);
    2.22 +                int dx, dy, state;
    2.23 +                state = SDL_GetRelativeMouseState(&dx, &dy);
    2.24 +                sdl_send_mouse_event(dx, dy, 0, state);
    2.25 +            }
    2.26 +            break;
    2.27 +        case SDL_MOUSEBUTTONUP:
    2.28 +            if (gui_grab || kbd_mouse_is_absolute()) {
    2.29 +                int dx, dy, state;
    2.30 +                state = SDL_GetRelativeMouseState(&dx, &dy);
    2.31 +                sdl_send_mouse_event(dx, dy, 0, state);
    2.32              }
    2.33              break;
    2.34          case SDL_MOUSEBUTTONDOWN:
    2.35 -        case SDL_MOUSEBUTTONUP:
    2.36              {
    2.37                  SDL_MouseButtonEvent *bev = &ev->button;
    2.38                  if (!gui_grab && !kbd_mouse_is_absolute()) {
    2.39 @@ -439,16 +445,19 @@ static void sdl_refresh(DisplayState *ds
    2.40                          sdl_grab_start();
    2.41                      }
    2.42                  } else {
    2.43 -                    int dz;
    2.44 +                    int dx, dy, dz, state;
    2.45                      dz = 0;
    2.46 +                    state = SDL_GetRelativeMouseState(&dx, &dy);
    2.47  #ifdef SDL_BUTTON_WHEELUP
    2.48 -                    if (bev->button == SDL_BUTTON_WHEELUP && ev->type == SDL_MOUSEBUTTONDOWN) {
    2.49 +                    if (bev->button == SDL_BUTTON_WHEELUP) {
    2.50                          dz = -1;
    2.51 -                    } else if (bev->button == SDL_BUTTON_WHEELDOWN && ev->type == SDL_MOUSEBUTTONDOWN) {
    2.52 +                    } else if (bev->button == SDL_BUTTON_WHEELDOWN) {
    2.53                          dz = 1;
    2.54 +                    } else {
    2.55 +                        state = bev->button | state;
    2.56                      }
    2.57  #endif               
    2.58 -                    sdl_send_mouse_event(dz);
    2.59 +                    sdl_send_mouse_event(dx, dy, dz, state);
    2.60                  }
    2.61              }
    2.62              break;