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; > } > > >