On Sun, Jul 7, 2013 at 12:22 PM, Henri Kemppainen <ducl...@guu.fi> wrote:
> So I needed to see my thoughts on paper but my desk was so full of stuff
> I couldn't make room for pen and paper.  Instead I fired up Gimp, and
> drawing with the mouse worked fine until I realized it's next to impossible
> to draw diagonal lines that look like lines.
>
> Instead of straight lines, I got waves.  The faster I draw the mouse, the
> deeper the waves.

That is a very cool effect (referring to your image). Having not seen
this issue, I tried drawing a few diagonal lines; this was using the
synaptics touchpad. The lines were pretty smooth looking. Then I
connected a USB mouse and reattempted drawing the diagonal lines.
That's when I see the stair-step effect; still not as wave-like as
yours are.

Just adding a data-point.

--patrick


> It looked like diagonal mouse motion generated a pair
> of pointer motion events, one for the X axis and another for Y.  And Gimp
> smoothed that stairstep motion, resulting in waves.  Xev(1) confirmed my
> hypothesis.
>
> It turns out wsmouse(4) is breaking the mouse input into multiple events.
> This isn't necessarily a bug, since it allows for a very small and simple
> event structure which works without modification as new properties (such
> as button states, axes, etc.) are added.
>
> Now wsmouse generates all the events it can in a loop before waking up
> the process that waits for these events.  So on the receiving side (i.e.
> in the xenocara ws(4) driver) we can sum all the consecutive X and Y
> deltas from a single read() before issuing a pointer motion event.  This
> eliminates the stairsteps as long as the events generated by wsmouse fit
> in the buffers involved.
>
> Other approaches would be either extending the event structure, or perhaps
> adding a new event type that somehow communicates the intended grouping
> for events that follow/precede (but ugh...).  I felt the ws(4) fix was
> the least intrusive, and it appears to work just fine here.  What do you
> think?
>
> This image (drawn in Gimp) illustrates the problem.  The last two lines
> were drawn with my diff applied.
>
>         http://guu.fi/mousebug.png
>
> Index: xenocara/driver/xf86-input-ws/src/ws.c
> ===================================================================
> RCS file: /cvs/xenocara/driver/xf86-input-ws/src/ws.c,v
> retrieving revision 1.57
> diff -u -p -r1.57 ws.c
> --- xenocara/driver/xf86-input-ws/src/ws.c      8 Jul 2012 14:22:03 -0000     
>   1.57
> +++ xenocara/driver/xf86-input-ws/src/ws.c      7 Jul 2013 18:33:57 -0000
> @@ -474,7 +474,7 @@ wsReadInput(InputInfoPtr pInfo)
>  {
>         WSDevicePtr priv = (WSDevicePtr)pInfo->private;
>         static struct wscons_event eventList[NUMEVENTS];
> -       int n, c;
> +       int n, c, dx, dy;
>         struct wscons_event *event = eventList;
>         unsigned char *pBuf;
>
> @@ -488,10 +488,11 @@ wsReadInput(InputInfoPtr pInfo)
>         if (n == 0)
>                 return;
>
> +       dx = dy = 0;
>         n /= sizeof(struct wscons_event);
>         while (n--) {
>                 int buttons = priv->lastButtons;
> -               int dx = 0, dy = 0, dz = 0, dw = 0, ax = 0, ay = 0;
> +               int dz = 0, dw = 0, ax = 0, ay = 0;
>                 int zbutton = 0, wbutton = 0;
>
>                 switch (event->type) {
> @@ -506,11 +507,11 @@ wsReadInput(InputInfoPtr pInfo)
>                             buttons));
>                         break;
>                 case WSCONS_EVENT_MOUSE_DELTA_X:
> -                       dx = event->value;
> +                       dx += event->value;
>                         DBG(4, ErrorF("Relative X %d\n", event->value));
>                         break;
>                 case WSCONS_EVENT_MOUSE_DELTA_Y:
> -                       dy = -event->value;
> +                       dy -= event->value;
>                         DBG(4, ErrorF("Relative Y %d\n", event->value));
>                         break;
>                 case WSCONS_EVENT_MOUSE_ABSOLUTE_X:
> @@ -548,14 +549,18 @@ wsReadInput(InputInfoPtr pInfo)
>                 }
>                 ++event;
>
> -               if (dx || dy) {
> -                       if (wsWheelEmuFilterMotion(pInfo, dx, dy))
> +               if ((dx || dy) && event->type != WSCONS_EVENT_MOUSE_DELTA_X &&
> +                   event->type != WSCONS_EVENT_MOUSE_DELTA_Y) {
> +                       int tmpx = dx, tmpy = dy;
> +                       dx = dy = 0;
> +
> +                       if (wsWheelEmuFilterMotion(pInfo, tmpx, tmpy))
>                                 continue;
>
>                         /* relative motion event */
>                         DBG(3, ErrorF("postMotionEvent dX %d dY %d\n",
> -                           dx, dy));
> -                       xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
> +                           tmpx, tmpy));
> +                       xf86PostMotionEvent(pInfo->dev, 0, 0, 2, tmpx, tmpy);
>                 }
>                 if (dz && priv->Z.negative != WS_NOMAP
>                     && priv->Z.positive != WS_NOMAP) {
> @@ -583,9 +588,9 @@ wsReadInput(InputInfoPtr pInfo)
>                         ay = tmp;
>                 }
>                 if (ax) {
> -                       dx = ax - priv->old_ax;
> +                       int xdelta = ax - priv->old_ax;
>                         priv->old_ax = ax;
> -                       if (wsWheelEmuFilterMotion(pInfo, dx, 0))
> +                       if (wsWheelEmuFilterMotion(pInfo, xdelta, 0))
>                                 continue;
>
>                         /* absolute position event */
> @@ -593,15 +598,24 @@ wsReadInput(InputInfoPtr pInfo)
>                         xf86PostMotionEvent(pInfo->dev, 1, 0, 1, ax);
>                 }
>                 if (ay) {
> -                       dy = ay - priv->old_ay;
> +                       int ydelta = ay - priv->old_ay;
>                         priv->old_ay = ay;
> -                       if (wsWheelEmuFilterMotion(pInfo, 0, dy))
> +                       if (wsWheelEmuFilterMotion(pInfo, 0, ydelta))
>                                 continue;
>
>                         /* absolute position event */
>                         DBG(3, ErrorF("postMotionEvent y %d\n", ay));
>                         xf86PostMotionEvent(pInfo->dev, 1, 1, 1, ay);
>                 }
> +       }
> +       if (dx || dy) {
> +               if (wsWheelEmuFilterMotion(pInfo, dx, dy))
> +                       return;
> +
> +               /* relative motion event */
> +               DBG(3, ErrorF("postMotionEvent dX %d dY %d\n",
> +                   dx, dy));
> +               xf86PostMotionEvent(pInfo->dev, 0, 0, 2, dx, dy);
>         }
>         return;
>  }
>
>
>

Reply via email to