aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/dix')
-rw-r--r--xorg-server/dix/devices.c12
-rw-r--r--xorg-server/dix/dixfonts.c30
-rw-r--r--xorg-server/dix/eventconvert.c22
-rw-r--r--xorg-server/dix/events.c92
-rw-r--r--xorg-server/dix/getevents.c618
-rw-r--r--xorg-server/dix/inpututils.c32
-rw-r--r--xorg-server/dix/ptrveloc.c259
7 files changed, 624 insertions, 441 deletions
diff --git a/xorg-server/dix/devices.c b/xorg-server/dix/devices.c
index b6f7ea697..73c4d1460 100644
--- a/xorg-server/dix/devices.c
+++ b/xorg-server/dix/devices.c
@@ -264,6 +264,8 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
offsetof(DeviceIntRec, devPrivates), PRIVATE_DEVICE);
if (!dev)
return (DeviceIntPtr)NULL;
+
+ dev->last.scroll = NULL;
dev->id = devid;
dev->public.processInputProc = ProcessOtherEvent;
dev->public.realInputProc = ProcessOtherEvent;
@@ -943,6 +945,7 @@ CloseDevice(DeviceIntPtr dev)
free(dev->deviceGrab.sync.event);
free(dev->config_info); /* Allocated in xf86ActivateDevice. */
+ free(dev->last.scroll);
dev->config_info = NULL;
dixFreeObjectWithPrivates(dev, PRIVATE_DEVICE);
}
@@ -1285,10 +1288,19 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
if (!valc)
return FALSE;
+ dev->last.scroll = valuator_mask_new(numAxes);
+ if (!dev->last.scroll)
+ {
+ free(valc);
+ return FALSE;
+ }
+
valc->sourceid = dev->id;
valc->motion = NULL;
valc->first_motion = 0;
valc->last_motion = 0;
+ valc->h_scroll_axis = -1;
+ valc->v_scroll_axis = -1;
valc->numMotionEvents = numMotionEvents;
valc->motionHintWindow = NullWindow;
diff --git a/xorg-server/dix/dixfonts.c b/xorg-server/dix/dixfonts.c
index 45655de78..efc3c09ce 100644
--- a/xorg-server/dix/dixfonts.c
+++ b/xorg-server/dix/dixfonts.c
@@ -1332,31 +1332,30 @@ doPolyText(ClientPtr client, PTclosurePtr c)
goto bail;
}
*new_closure = *c;
- c = new_closure;
- len = c->endReq - c->pElt;
- c->data = malloc(len);
- if (!c->data)
+ len = new_closure->endReq - new_closure->pElt;
+ new_closure->data = malloc(len);
+ if (!new_closure->data)
{
- free(c);
+ free(new_closure);
err = BadAlloc;
goto bail;
}
- memmove(c->data, c->pElt, len);
- c->pElt = c->data;
- c->endReq = c->pElt + len;
+ memmove(new_closure->data, new_closure->pElt, len);
+ new_closure->pElt = new_closure->data;
+ new_closure->endReq = new_closure->pElt + len;
/* Step 2 */
- pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
+ pGC = GetScratchGC(new_closure->pGC->depth, new_closure->pGC->pScreen);
if (!pGC)
{
- free(c->data);
- free(c);
+ free(new_closure->data);
+ free(new_closure);
err = BadAlloc;
goto bail;
}
- if ((err = CopyGC(c->pGC, pGC, GCFunction |
+ if ((err = CopyGC(new_closure->pGC, pGC, GCFunction |
GCPlaneMask | GCForeground |
GCBackground | GCFillStyle |
GCTile | GCStipple |
@@ -1367,15 +1366,16 @@ doPolyText(ClientPtr client, PTclosurePtr c)
Success)
{
FreeScratchGC(pGC);
- free(c->data);
- free(c);
+ free(new_closure->data);
+ free(new_closure);
err = BadAlloc;
goto bail;
}
+ c = new_closure;
origGC = c->pGC;
c->pGC = pGC;
ValidateGC(c->pDraw, c->pGC);
-
+
ClientSleep(client, (ClientSleepProcPtr)doPolyText, c);
/* Set up to perform steps 3 and 4 */
diff --git a/xorg-server/dix/eventconvert.c b/xorg-server/dix/eventconvert.c
index dafe94207..47108fd70 100644
--- a/xorg-server/dix/eventconvert.c
+++ b/xorg-server/dix/eventconvert.c
@@ -605,6 +605,7 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi)
xde->root_x = FP1616(ev->root_x, ev->root_x_frac);
xde->root_y = FP1616(ev->root_y, ev->root_y_frac);
+ xde->flags = ev->flags;
if (ev->key_repeat)
xde->flags |= XIKeyRepeat;
@@ -632,8 +633,9 @@ eventToDeviceEvent(DeviceEvent *ev, xEvent **xi)
if (BitIsOn(ev->valuators.mask, i))
{
SetBit(ptr, i);
- axisval->integral = ev->valuators.data[i];
- axisval->frac = ev->valuators.data_frac[i];
+ axisval->integral = trunc(ev->valuators.data[i]);
+ axisval->frac = (ev->valuators.data[i] - axisval->integral) *
+ (1 << 16) * (1 << 16);
axisval++;
}
}
@@ -648,7 +650,7 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi)
int vallen, nvals;
int i, len = sizeof(xXIRawEvent);
char *ptr;
- FP3232 *axisval;
+ FP3232 *axisval, *axisval_raw;
nvals = count_bits(ev->valuators.mask, sizeof(ev->valuators.mask));
len += nvals * sizeof(FP3232) * 2; /* 8 byte per valuator, once
@@ -666,19 +668,25 @@ eventToRawEvent(RawDeviceEvent *ev, xEvent **xi)
raw->detail = ev->detail.button;
raw->deviceid = ev->deviceid;
raw->valuators_len = vallen;
+ raw->flags = ev->flags;
ptr = (char*)&raw[1];
axisval = (FP3232*)(ptr + raw->valuators_len * 4);
+ axisval_raw = axisval + nvals;
for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
{
if (BitIsOn(ev->valuators.mask, i))
{
SetBit(ptr, i);
- axisval->integral = ev->valuators.data[i];
- axisval->frac = ev->valuators.data_frac[i];
- (axisval + nvals)->integral = ev->valuators.data_raw[i];
- (axisval + nvals)->frac = ev->valuators.data_raw_frac[i];
+ axisval->integral = trunc(ev->valuators.data[i]);
+ axisval->frac = (ev->valuators.data[i] - axisval->integral) *
+ (1 << 16) * (1 << 16);
+ axisval_raw->integral = trunc(ev->valuators.data_raw[i]);
+ axisval_raw->frac =
+ (ev->valuators.data_raw[i] - axisval_raw->integral) *
+ (1 << 16) * (1 << 16);
axisval++;
+ axisval_raw++;
}
}
diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c
index 97fae6923..c5f435c11 100644
--- a/xorg-server/dix/events.c
+++ b/xorg-server/dix/events.c
@@ -2271,33 +2271,93 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
return nondeliveries;
}
+/**
+ * Filter out raw events for XI 2.0 and XI 2.1 clients.
+ *
+ * If there is a grab on the device, 2.0 clients only get raw events if they
+ * have the grab. 2.1+ clients get raw events in all cases.
+ *
+ * @return TRUE if the event should be discarded, FALSE otherwise.
+ */
+static BOOL
+FilterRawEvents(const ClientPtr client, const GrabPtr grab)
+{
+ XIClientPtr client_xi_version;
+ int cmp;
+
+ /* device not grabbed -> don't filter */
+ if (!grab)
+ return FALSE;
+
+ client_xi_version = dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
+
+ cmp = version_compare(client_xi_version->major_version,
+ client_xi_version->minor_version, 2, 0);
+ /* XI 2.0: if device is grabbed, skip
+ XI 2.1: if device is grabbed by us, skip, we've already delivered */
+ return (cmp == 0) ? TRUE : SameClient(grab, client);
+}
+
+/**
+ * Deliver a raw event to the grab owner (if any) and to all root windows.
+ *
+ * Raw event delivery differs between XI 2.0 and XI 2.1.
+ * XI 2.0: events delivered to the grabbing client (if any) OR to all root
+ * windows
+ * XI 2.1: events delivered to all root windows, regardless of grabbing
+ * state.
+ */
void
DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
{
GrabPtr grab = device->deviceGrab.grab;
+ xEvent *xi;
+ int i, rc;
+ int filter;
+
+ rc = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
+ if (rc != Success)
+ {
+ ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
+ __FUNCTION__, device->name, rc);
+ return;
+ }
if (grab)
DeliverGrabbedEvent((InternalEvent*)ev, device, FALSE);
- else { /* deliver to all root windows */
- xEvent *xi;
- int i;
- int filter;
- i = EventToXI2((InternalEvent*)ev, (xEvent**)&xi);
- if (i != Success)
- {
- ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
- __FUNCTION__, device->name, i);
- return;
- }
+ filter = GetEventFilter(device, xi);
+
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ WindowPtr root;
+ InputClients *inputclients;
- filter = GetEventFilter(device, xi);
+ root = screenInfo.screens[i]->root;
+ if (!GetClientsForDelivery(device, root, xi, filter, &inputclients))
+ continue;
- for (i = 0; i < screenInfo.numScreens; i++)
- DeliverEventsToWindow(device, screenInfo.screens[i]->root, xi, 1,
- filter, NullGrab);
- free(xi);
+ for (; inputclients; inputclients = inputclients->next)
+ {
+ ClientPtr c; /* unused */
+ Mask m; /* unused */
+ InputClients ic = *inputclients;
+
+ /* Because we run through the list manually, copy the actual
+ * list, shorten the copy to only have one client and then pass
+ * that down to DeliverEventToInputClients. This way we avoid
+ * double events on XI 2.1 clients that have a grab on the
+ * device.
+ */
+ ic.next = NULL;
+
+ if (!FilterRawEvents(rClient(&ic), grab))
+ DeliverEventToInputClients(device, &ic, root, xi, 1,
+ filter, NULL, &c, &m);
+ }
}
+
+ free(xi);
}
/* If the event goes to dontClient, don't send it and return 0. if
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index 6208a63af..374843f68 100644
--- a/xorg-server/dix/getevents.c
+++ b/xorg-server/dix/getevents.c
@@ -2,6 +2,7 @@
* Copyright © 2006 Nokia Corporation
* Copyright © 2006-2007 Daniel Stone
* Copyright © 2008 Red Hat, Inc.
+ * Copyright © 2011 The Chromium Authors
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -58,6 +59,7 @@
#endif
#include <X11/extensions/XI.h>
+#include <X11/extensions/XI2.h>
#include <X11/extensions/XIproto.h>
#include <pixman.h>
#include "exglobals.h"
@@ -182,7 +184,7 @@ init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
}
static void
-set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data)
+set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, double* data)
{
int i;
@@ -191,7 +193,7 @@ set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int32_t* data)
if (valuator_mask_isset(mask, i))
{
SetBit(event->valuators.mask, i);
- data[i] = valuator_mask_get(mask, i);
+ data[i] = valuator_mask_get_double(mask, i);
}
}
}
@@ -211,9 +213,7 @@ set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask)
SetBit(event->valuators.mask, i);
if (valuator_get_mode(dev, i) == Absolute)
SetBit(event->valuators.mode, i);
- event->valuators.data[i] = valuator_mask_get(mask, i);
- event->valuators.data_frac[i] =
- dev->last.remainder[i] * (1 << 16) * (1 << 16);
+ event->valuators.data[i] = valuator_mask_get_double(mask, i);
}
else if (valuator_get_mode(dev, i) == Absolute)
event->valuators.data[i] = dev->valuator->axisVal[i];
@@ -270,39 +270,29 @@ CreateClassesChangedEvent(InternalEvent* event,
/**
* Rescale the coord between the two axis ranges.
*/
-static int
-rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to,
- int defmax)
+static double
+rescaleValuatorAxis(double coord, AxisInfoPtr from, AxisInfoPtr to,
+ double defmax)
{
- int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return;
- float value;
+ double fmin = 0.0, fmax = defmax;
+ double tmin = 0.0, tmax = defmax;
- if(from && from->min_value < from->max_value) {
+ if (from && from->min_value < from->max_value) {
fmin = from->min_value;
fmax = from->max_value;
}
- if(to && to->min_value < to->max_value) {
+ if (to && to->min_value < to->max_value) {
tmin = to->min_value;
tmax = to->max_value;
}
- if(fmin == tmin && fmax == tmax) {
- if (remainder_return)
- *remainder_return = remainder;
+ if (fmin == tmin && fmax == tmax)
return coord;
- }
- if(fmax == fmin) { /* avoid division by 0 */
- if (remainder_return)
- *remainder_return = 0.0;
- return 0;
- }
+ if (fmax == fmin) /* avoid division by 0 */
+ return 0.0;
- value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
- coord_return = lroundf(value);
- if (remainder_return)
- *remainder_return = value - coord_return;
- return coord_return;
+ return (coord - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
}
/**
@@ -324,19 +314,25 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
* position of the pointer */
pDev->last.valuators[0] = master->last.valuators[0];
pDev->last.valuators[1] = master->last.valuators[1];
- pDev->last.remainder[0] = master->last.remainder[0];
- pDev->last.remainder[1] = master->last.remainder[1];
if (!pDev->valuator)
return;
/* scale back to device coordinates */
if(pDev->valuator->numAxes > 0)
- pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0],
- &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width);
+ {
+ pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0],
+ NULL,
+ pDev->valuator->axes + 0,
+ scr->width);
+ }
if(pDev->valuator->numAxes > 1)
- pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1],
- &pDev->last.remainder[1], NULL, pDev->valuator->axes + 1, scr->height);
+ {
+ pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1],
+ NULL,
+ pDev->valuator->axes + 1,
+ scr->height);
+ }
/* calculate the other axis as well based on info from the old
* slave-device. If the old slave had less axes than this one,
@@ -347,16 +343,13 @@ updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
if (i >= lastSlave->valuator->numAxes)
{
pDev->last.valuators[i] = 0;
- pDev->last.remainder[i] = 0;
}
else
{
- pDev->last.valuators[i] =
- rescaleValuatorAxis(pDev->last.valuators[i],
- pDev->last.remainder[i],
- &pDev->last.remainder[i],
- lastSlave->valuator->axes + i,
- pDev->valuator->axes + i, 0);
+ double val = pDev->last.valuators[i];
+ val = rescaleValuatorAxis(val, lastSlave->valuator->axes + i,
+ pDev->valuator->axes + i, 0);
+ pDev->last.valuators[i] = val;
}
}
}
@@ -467,7 +460,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
/* scale to screen coords */
to = &core_axis;
to->max_value = pScreen->width;
- coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width);
+ coord = rescaleValuatorAxis(coord, &from, to, pScreen->width);
memcpy(corebuf, &coord, sizeof(INT16));
corebuf++;
@@ -478,7 +471,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
memcpy(&coord, icbuf++, sizeof(INT32));
to->max_value = pScreen->height;
- coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height);
+ coord = rescaleValuatorAxis(coord, &from, to, pScreen->height);
memcpy(corebuf, &coord, sizeof(INT16));
} else if (IsMaster(pDev))
@@ -506,7 +499,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
from.max_value = pScreen->height;
/* scale from stored range into current range */
- coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
+ coord = rescaleValuatorAxis(coord, &from, to, 0);
memcpy(ocbuf, &coord, sizeof(INT32));
ocbuf++;
}
@@ -540,7 +533,7 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
*/
static void
updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
- int *valuators)
+ double *valuators)
{
char *buff = (char *) pDev->valuator->motion;
ValuatorClassPtr v;
@@ -562,6 +555,7 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
for (i = 0; i < v->numAxes; i++)
{
+ int val;
/* XI1 doesn't support mixed mode devices */
if (valuator_get_mode(pDev, i) != valuator_get_mode(pDev, 0))
break;
@@ -574,7 +568,8 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
buff += sizeof(INT32);
memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
buff += sizeof(INT32);
- memcpy(buff, &valuators[i], sizeof(INT32));
+ val = valuators[i];
+ memcpy(buff, &val, sizeof(INT32));
buff += sizeof(INT32);
}
} else
@@ -590,12 +585,14 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
for (i = 0; i < MAX_VALUATORS; i++)
{
+ int val;
if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
{
buff += sizeof(INT32);
continue;
}
- memcpy(buff, &valuators[i], sizeof(INT32));
+ val = valuators[i];
+ memcpy(buff, &val, sizeof(INT32));
buff += sizeof(INT32);
}
}
@@ -622,8 +619,10 @@ GetMaximumEventsNum(void) {
/* One raw event
* One device event
* One possible device changed event
+ * Lots of possible separate button scroll events (horiz + vert)
+ * Lots of possible separate raw button scroll events (horiz + vert)
*/
- return 3;
+ return 100;
}
@@ -632,7 +631,7 @@ GetMaximumEventsNum(void) {
* InitValuatorAxisClassStruct.
*/
static void
-clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
+clipAxis(DeviceIntPtr pDev, int axisNum, double *val)
{
AxisInfoPtr axis;
@@ -662,9 +661,9 @@ clipValuators(DeviceIntPtr pDev, ValuatorMask *mask)
for (i = 0; i < valuator_mask_size(mask); i++)
if (valuator_mask_isset(mask, i))
{
- int val = valuator_mask_get(mask, i);
+ double val = valuator_mask_get_double(mask, i);
clipAxis(pDev, i, &val);
- valuator_mask_set(mask, i, val);
+ valuator_mask_set_double(mask, i, val);
}
}
@@ -705,85 +704,52 @@ UpdateFromMaster(InternalEvent* events, DeviceIntPtr dev, int type, int *num_eve
/**
* Move the device's pointer to the position given in the valuators.
*
- * @param dev The device which's pointer is to be moved.
- * @param x Returns the x position of the pointer after the move.
- * @param y Returns the y position of the pointer after the move.
- * @param mask Bit mask of valid valuators.
- * @param valuators Valuator data for each axis between @first and
- * @first+@num.
+ * @param dev The device whose pointer is to be moved.
+ * @param mask Valuator data for this event.
*/
static void
-moveAbsolute(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
+moveAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
{
int i;
- if (valuator_mask_isset(mask, 0))
- *x = valuator_mask_get(mask, 0);
- else
- *x = dev->last.valuators[0];
-
- if (valuator_mask_isset(mask, 1))
- *y = valuator_mask_get(mask, 1);
- else
- *y = dev->last.valuators[1];
-
- clipAxis(dev, 0, x);
- clipAxis(dev, 1, y);
-
- for (i = 2; i < valuator_mask_size(mask); i++)
+ for (i = 0; i < valuator_mask_size(mask); i++)
{
- if (valuator_mask_isset(mask, i))
- {
- dev->last.valuators[i] = valuator_mask_get(mask, i);
- clipAxis(dev, i, &dev->last.valuators[i]);
- }
+ double val;
+
+ if (!valuator_mask_isset(mask, i))
+ continue;
+ val = valuator_mask_get_double(mask, i);
+ clipAxis(dev, i, &val);
+ valuator_mask_set_double(mask, i, val);
}
}
/**
* Move the device's pointer by the values given in @valuators.
*
- * @param dev The device which's pointer is to be moved.
- * @param x Returns the x position of the pointer after the move.
- * @param y Returns the y position of the pointer after the move.
- * @param mask Bit mask of valid valuators.
- * @param valuators Valuator data for each axis between @first and
- * @first+@num.
+ * @param dev The device whose pointer is to be moved.
+ * @param mask Valuator data for this event.
*/
static void
-moveRelative(DeviceIntPtr dev, int *x, int *y, ValuatorMask *mask)
+moveRelative(DeviceIntPtr dev, ValuatorMask *mask)
{
int i;
-
- *x = dev->last.valuators[0];
- *y = dev->last.valuators[1];
-
- if (valuator_mask_isset(mask, 0))
- *x += valuator_mask_get(mask, 0);
-
- if (valuator_mask_isset(mask, 1))
- *y += valuator_mask_get(mask, 1);
-
- /* if attached, clip both x and y to the defined limits (usually
- * co-ord space limit). If it is attached, we need x/y to go over the
- * limits to be able to change screens. */
- if (dev->valuator && (IsMaster(dev) || !IsFloating(dev))) {
- if (valuator_get_mode(dev, 0) == Absolute)
- clipAxis(dev, 0, x);
- if (valuator_get_mode(dev, 1) == Absolute)
- clipAxis(dev, 1, y);
- }
+ Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
/* calc other axes, clip, drop back into valuators */
- for (i = 2; i < valuator_mask_size(mask); i++)
+ for (i = 0; i < valuator_mask_size(mask); i++)
{
- if (valuator_mask_isset(mask, i))
- {
- dev->last.valuators[i] += valuator_mask_get(mask, i);
- if (valuator_get_mode(dev, i) == Absolute)
- clipAxis(dev, i, &dev->last.valuators[i]);
- valuator_mask_set(mask, i, dev->last.valuators[i]);
- }
+ double val = dev->last.valuators[i];
+
+ if (!valuator_mask_isset(mask, i))
+ continue;
+ val += valuator_mask_get_double(mask, i);
+ /* x & y need to go over the limits to cross screens if the SD
+ * isn't currently attached; otherwise, clip to screen bounds. */
+ if (valuator_get_mode(dev, i) == Absolute &&
+ ((i != 0 && i != 1) || clip_xy))
+ clipAxis(dev, i, &val);
+ valuator_mask_set_double(mask, i, val);
}
}
@@ -814,89 +780,68 @@ accelPointer(DeviceIntPtr dev, ValuatorMask* valuators, CARD32 ms)
*
* @param dev The device to be moved.
* @param mode Movement mode (Absolute or Relative)
- * @param x Pointer to current x-axis value, may be modified.
- * @param y Pointer to current y-axis value, may be modified.
- * @param x_frac Fractional part of current x-axis value, may be modified.
- * @param y_frac Fractional part of current y-axis value, may be modified.
* @param scr Screen the device's sprite is currently on.
+ * @param mask Mask of axis values for this event
* @param screenx Screen x coordinate the sprite is on after the update.
* @param screeny Screen y coordinate the sprite is on after the update.
- * @param screenx_frac Fractional part of screen x coordinate, as above.
- * @param screeny_frac Fractional part of screen y coordinate, as above.
*/
static void
-positionSprite(DeviceIntPtr dev, int mode,
- int *x, int *y, float x_frac, float y_frac,
- ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
+positionSprite(DeviceIntPtr dev, int mode, ScreenPtr scr, ValuatorMask *mask,
+ double *screenx, double *screeny)
{
- int old_screenx, old_screeny;
+ int isx, isy; /* screen {x, y}, in int */
+ double x, y;
- /* scale x&y to screen */
- if (dev->valuator && dev->valuator->numAxes > 0) {
- *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
- dev->valuator->axes + 0, NULL, scr->width);
- } else {
- *screenx = dev->last.valuators[0];
- *screenx_frac = dev->last.remainder[0];
- }
+ if (!dev->valuator || dev->valuator->numAxes < 2)
+ return;
- if (dev->valuator && dev->valuator->numAxes > 1) {
- *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
- dev->valuator->axes + 1, NULL, scr->height);
- } else {
- *screeny = dev->last.valuators[1];
- *screeny_frac = dev->last.remainder[1];
- }
+ if (valuator_mask_isset(mask, 0))
+ x = valuator_mask_get_double(mask, 0);
+ else
+ x = dev->last.valuators[0];
+ if (valuator_mask_isset(mask, 1))
+ y = valuator_mask_get_double(mask, 1);
+ else
+ y = dev->last.valuators[1];
- /* Hit the left screen edge? */
- if (*screenx <= 0 && *screenx_frac < 0.0f)
+ /* scale x&y to screen */
+ *screenx = rescaleValuatorAxis(x, dev->valuator->axes + 0, NULL,
+ scr->width);
+ *screeny = rescaleValuatorAxis(y, dev->valuator->axes + 1, NULL,
+ scr->height);
+
+ /* miPointerSetPosition takes care of crossing screens for us, as well as
+ * clipping to the current screen. In the event we actually change screen,
+ * we just drop the float component on the floor, then convert from
+ * screenx back into device co-ordinates. */
+ isx = trunc(*screenx);
+ isy = trunc(*screeny);
+ miPointerSetPosition(dev, mode, &isx, &isy);
+ scr = miPointerGetScreen(dev);
+ if (isx != trunc(*screenx))
{
- *screenx_frac = 0.0f;
- x_frac = 0.0f;
+ *screenx -= trunc(*screenx) - isx;
+ x = rescaleValuatorAxis(*screenx, NULL, dev->valuator->axes + 0,
+ scr->width);
}
- if (*screeny <= 0 && *screeny_frac < 0.0f)
+ if (isy != trunc(*screeny))
{
- *screeny_frac = 0.0f;
- y_frac = 0.0f;
+ *screeny -= trunc(*screeny) - isy;
+ y = rescaleValuatorAxis(*screeny, NULL, dev->valuator->axes + 1,
+ scr->height);
}
-
- old_screenx = *screenx;
- old_screeny = *screeny;
- /* This takes care of crossing screens for us, as well as clipping
- * to the current screen. */
- miPointerSetPosition(dev, mode, screenx, screeny);
-
- if(!IsMaster(dev) && !IsFloating(dev)) {
+ /* Update the MD's co-ordinates, which are always in screen space. */
+ if (!IsMaster(dev) || !IsFloating(dev)) {
DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
master->last.valuators[0] = *screenx;
master->last.valuators[1] = *screeny;
- master->last.remainder[0] = *screenx_frac;
- master->last.remainder[1] = *screeny_frac;
- }
-
- if (dev->valuator)
- {
- /* Crossed screen? Scale back to device coordiantes */
- if(*screenx != old_screenx)
- {
- scr = miPointerGetScreen(dev);
- *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL,
- dev->valuator->axes + 0, scr->width);
- }
- if(*screeny != old_screeny)
- {
- scr = miPointerGetScreen(dev);
- *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL,
- dev->valuator->axes + 1, scr->height);
- }
}
- /* dropy x/y (device coordinates) back into valuators for next event */
- dev->last.valuators[0] = *x;
- dev->last.valuators[1] = *y;
- dev->last.remainder[0] = x_frac;
- dev->last.remainder[1] = y_frac;
+ if (valuator_mask_isset(mask, 0))
+ valuator_mask_set_double(mask, 0, x);
+ if (valuator_mask_isset(mask, 1))
+ valuator_mask_set_double(mask, 1, y);
}
/**
@@ -1060,7 +1005,7 @@ FreeEventList(InternalEvent *list, int num_events)
* back into x/y.
*/
static void
-transform(struct pixman_f_transform *m, int *x, int *y)
+transform(struct pixman_f_transform *m, double *x, double *y)
{
struct pixman_f_vector p;
@@ -1071,27 +1016,32 @@ transform(struct pixman_f_transform *m, int *x, int *y)
pixman_f_transform_point(m, &p);
- *x = lround(p.v[0]);
- *y = lround(p.v[1]);
+ *x = p.v[0];
+ *y = p.v[1];
}
static void
transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
{
- int x, y, ox, oy;
+ double x, y, ox, oy;
+
+ if (valuator_mask_isset(mask, 0))
+ ox = x = valuator_mask_get_double(mask, 0);
+ else
+ ox = x = dev->last.valuators[0];
- ox = x = valuator_mask_isset(mask, 0) ? valuator_mask_get(mask, 0) :
- dev->last.valuators[0];
- oy = y = valuator_mask_isset(mask, 1) ? valuator_mask_get(mask, 1) :
- dev->last.valuators[1];
+ if (valuator_mask_isset(mask, 1))
+ oy = y = valuator_mask_get_double(mask, 1);
+ else
+ oy = y = dev->last.valuators[1];
transform(&dev->transform, &x, &y);
if (valuator_mask_isset(mask, 0) || ox != x)
- valuator_mask_set(mask, 0, x);
+ valuator_mask_set_double(mask, 0, x);
if (valuator_mask_isset(mask, 1) || oy != y)
- valuator_mask_set(mask, 1, y);
+ valuator_mask_set_double(mask, 1, y);
}
/**
@@ -1118,42 +1068,25 @@ QueuePointerEvents(DeviceIntPtr device, int type,
}
/**
- * Generate a series of InternalEvents representing pointer motion, or
- * button presses.
- *
- * The DDX is responsible for allocating the events in the first
- * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
- *
- * In the generated events rootX/Y will be in absolute screen coords and
- * the valuator information in the absolute or relative device coords.
- *
- * last.valuators[x] of the device is always in absolute device coords.
- * last.valuators[x] of the master device is in absolute screen coords.
+ * Helper function for GetPointerEvents, which only generates motion and
+ * raw motion events for the slave device: does not update the master device.
*
- * master->last.valuators[x] for x > 2 is undefined.
+ * Should not be called by anyone other than GetPointerEvents.
*
* @return the number of events written into events.
*/
-int
-GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons,
- int flags, const ValuatorMask *mask_in) {
- int num_events = 1;
- CARD32 ms;
+static int
+fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
+ int buttons, CARD32 ms, int flags,
+ const ValuatorMask *mask_in)
+{
+ int num_events = 1, i;
DeviceEvent *event;
- RawDeviceEvent *raw;
- int x = 0, y = 0, /* device coords */
- cx, cy; /* only screen coordinates */
- float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
+ RawDeviceEvent *raw;
+ double screenx = 0.0, screeny = 0.0;
ScreenPtr scr = miPointerGetScreen(pDev);
ValuatorMask mask;
- /* refuse events from disabled devices */
- if (!pDev->enabled)
- return 0;
-
- if (!scr)
- return 0;
-
switch (type)
{
case MotionNotify:
@@ -1169,10 +1102,6 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
return 0;
}
- ms = GetTimeInMillis(); /* before pointer update to help precision */
-
- events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
-
valuator_mask_copy(&mask, mask_in);
if ((flags & POINTER_NORAW) == 0)
@@ -1182,61 +1111,54 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
num_events++;
init_raw(pDev, raw, ms, type, buttons);
- set_raw_valuators(raw, &mask, raw->valuators.data_raw);
+ set_raw_valuators(raw, &mask, raw->valuators.data_raw);
}
if (flags & POINTER_ABSOLUTE)
{
if (flags & POINTER_SCREEN) /* valuators are in screen coords */
{
- int scaled;
+ double scaled;
if (valuator_mask_isset(&mask, 0))
{
- scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 0),
- 0.0, &x_frac, NULL,
- pDev->valuator->axes + 0,
+ scaled = rescaleValuatorAxis(valuator_mask_get_double(&mask, 0),
+ NULL, pDev->valuator->axes + 0,
scr->width);
- valuator_mask_set(&mask, 0, scaled);
+ valuator_mask_set_double(&mask, 0, scaled);
}
if (valuator_mask_isset(&mask, 1))
{
- scaled = rescaleValuatorAxis(valuator_mask_get(&mask, 1),
- 0.0, &y_frac, NULL,
- pDev->valuator->axes + 1,
+ scaled = rescaleValuatorAxis(valuator_mask_get_double(&mask, 1),
+ NULL, pDev->valuator->axes + 1,
scr->height);
- valuator_mask_set(&mask, 1, scaled);
+ valuator_mask_set_double(&mask, 1, scaled);
}
}
transformAbsolute(pDev, &mask);
- moveAbsolute(pDev, &x, &y, &mask);
+ moveAbsolute(pDev, &mask);
} else {
- if (flags & POINTER_ACCELERATE) {
+ if (flags & POINTER_ACCELERATE)
accelPointer(pDev, &mask, ms);
- /* The pointer acceleration code modifies the fractional part
- * in-place, so we need to extract this information first */
- x_frac = pDev->last.remainder[0];
- y_frac = pDev->last.remainder[1];
- }
- moveRelative(pDev, &x, &y, &mask);
+ moveRelative(pDev, &mask);
}
if ((flags & POINTER_NORAW) == 0)
- set_raw_valuators(raw, &mask, raw->valuators.data);
+ set_raw_valuators(raw, &mask, raw->valuators.data);
- positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
- &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
+ positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative, scr,
+ &mask, &screenx, &screeny);
updateHistory(pDev, &mask, ms);
- /* Update the valuators with the true value sent to the client*/
- if (valuator_mask_isset(&mask, 0))
- valuator_mask_set(&mask, 0, x);
- if (valuator_mask_isset(&mask, 1))
- valuator_mask_set(&mask, 1, y);
-
clipValuators(pDev, &mask);
+ for (i = 0; i < valuator_mask_size(&mask); i++)
+ {
+ if (valuator_mask_isset(&mask, i))
+ pDev->last.valuators[i] = valuator_mask_get_double(&mask, i);
+ }
+
event = &events->device_event;
init_device_event(event, pDev, ms);
@@ -1256,10 +1178,16 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
event->detail.button = buttons;
}
- event->root_x = cx; /* root_x/y always in screen coords */
- event->root_y = cy;
- event->root_x_frac = cx_frac;
- event->root_y_frac = cy_frac;
+ /* root_x and root_y must be in screen co-ordinates */
+ event->root_x = trunc(screenx);
+ event->root_y = trunc(screeny);
+ event->root_x_frac = screenx - trunc(screenx);
+ event->root_y_frac = screeny - trunc(screeny);
+
+ if (flags & POINTER_EMULATED) {
+ raw->flags = XIPointerEmulated;
+ event->flags = XIPointerEmulated;
+ }
set_valuators(pDev, event, &mask);
@@ -1267,6 +1195,204 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons
}
/**
+ * Generate events for each scroll axis that changed between before/after
+ * for the device.
+ *
+ * @param events The pointer to the event list to fill the events
+ * @param dev The device to generate the events for
+ * @param axis The axis number to generate events for
+ * @param mask State before this event in absolute coords
+ * @param[in,out] last Last scroll state posted in absolute coords (modified
+ * in-place)
+ * @param ms Current time in ms
+ * @param max_events Max number of events to be generated
+ * @return The number of events generated
+ */
+static int
+emulate_scroll_button_events(InternalEvent *events,
+ DeviceIntPtr dev,
+ int axis,
+ const ValuatorMask *mask,
+ ValuatorMask *last,
+ CARD32 ms,
+ int max_events)
+{
+ AxisInfoPtr ax;
+ double delta;
+ double incr;
+ int num_events = 0;
+ double total;
+ int b;
+
+ if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE)
+ return 0;
+
+ if (!valuator_mask_isset(mask, axis))
+ return 0;
+
+ ax = &dev->valuator->axes[axis];
+ incr = ax->scroll.increment;
+
+ if (!valuator_mask_isset(last, axis))
+ valuator_mask_set_double(last, axis, 0);
+
+ delta = valuator_mask_get_double(mask, axis) - valuator_mask_get_double(last, axis);
+ total = delta;
+ b = (ax->scroll.type == SCROLL_TYPE_VERTICAL) ? 5 : 7;
+
+ if ((incr > 0 && delta < 0) ||
+ (incr < 0 && delta > 0))
+ b--; /* we're scrolling up or left → button 4 or 6 */
+
+ while (fabs(delta) >= fabs(incr))
+ {
+ int nev_tmp;
+
+ if (delta > 0)
+ delta -= fabs(incr);
+ else if (delta < 0)
+ delta += fabs(incr);
+
+ /* fill_pointer_events() generates four events: one normal and one raw
+ * event for button press and button release.
+ * We may get a bigger scroll delta than we can generate events
+ * for. In that case, we keep decreasing delta, but skip events.
+ */
+ if (num_events + 4 < max_events)
+ {
+ nev_tmp = fill_pointer_events(events, dev, ButtonPress, b, ms,
+ POINTER_EMULATED, NULL);
+ events += nev_tmp;
+ num_events += nev_tmp;
+ nev_tmp = fill_pointer_events(events, dev, ButtonRelease, b, ms,
+ POINTER_EMULATED, NULL);
+ events += nev_tmp;
+ num_events += nev_tmp;
+ }
+ }
+
+ /* We emulated, update last.scroll */
+ if (total != delta)
+ {
+ total -= delta;
+ valuator_mask_set_double(last, axis,
+ valuator_mask_get_double(last, axis) + total);
+ }
+
+ return num_events;
+}
+
+
+/**
+ * Generate a complete series of InternalEvents (filled into the EventList)
+ * representing pointer motion, or button presses. If the device is a slave
+ * device, also potentially generate a DeviceClassesChangedEvent to update
+ * the master device.
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
+ *
+ * In the generated events rootX/Y will be in absolute screen coords and
+ * the valuator information in the absolute or relative device coords.
+ *
+ * last.valuators[x] of the device is always in absolute device coords.
+ * last.valuators[x] of the master device is in absolute screen coords.
+ *
+ * master->last.valuators[x] for x > 2 is undefined.
+ */
+int
+GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
+ int buttons, int flags, const ValuatorMask *mask_in)
+{
+ CARD32 ms = GetTimeInMillis();
+ int num_events = 0, nev_tmp;
+ int h_scroll_axis = pDev->valuator->h_scroll_axis;
+ int v_scroll_axis = pDev->valuator->v_scroll_axis;
+ ValuatorMask mask;
+ ValuatorMask scroll;
+ int i;
+
+ /* refuse events from disabled devices */
+ if (!pDev->enabled)
+ return 0;
+
+ if (!miPointerGetScreen(pDev))
+ return 0;
+
+ events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT,
+ &num_events);
+
+ valuator_mask_copy(&mask, mask_in);
+
+ /* Turn a scroll button press into a smooth-scrolling event if
+ * necessary. This only needs to cater for the XIScrollFlagPreferred
+ * axis (if more than one scrolling axis is present) */
+ if (type == ButtonPress)
+ {
+ double val, adj;
+ int axis;
+
+ switch (buttons) {
+ case 4:
+ adj = 1.0;
+ axis = v_scroll_axis;
+ break;
+ case 5:
+ adj = -1.0;
+ axis = v_scroll_axis;
+ break;
+ case 6:
+ adj = 1.0;
+ axis = h_scroll_axis;
+ break;
+ case 7:
+ adj = -1.0;
+ axis = h_scroll_axis;
+ break;
+ default:
+ adj = 0.0;
+ axis = -1;
+ break;
+ }
+
+ if (adj != 0.0 && axis != -1)
+ {
+ adj *= pDev->valuator->axes[axis].scroll.increment;
+ val = valuator_mask_get_double(&mask, axis) + adj;
+ valuator_mask_set_double(&mask, axis, val);
+ type = MotionNotify;
+ buttons = 0;
+ }
+ }
+
+ /* First fill out the original event set, with smooth-scrolling axes. */
+ nev_tmp = fill_pointer_events(events, pDev, type, buttons, ms, flags,
+ &mask);
+ events += nev_tmp;
+ num_events += nev_tmp;
+
+ valuator_mask_zero(&scroll);
+
+ /* Now turn the smooth-scrolling axes back into emulated button presses
+ * for legacy clients, based on the integer delta between before and now */
+ for (i = 0; i < valuator_mask_size(&mask); i++) {
+ if (!valuator_mask_isset(&mask, i))
+ continue;
+
+ valuator_mask_set_double(&scroll, i, pDev->last.valuators[i]);
+
+ nev_tmp = emulate_scroll_button_events(events, pDev, i, &scroll,
+ pDev->last.scroll, ms,
+ GetMaximumEventsNum() - num_events);
+ events += nev_tmp;
+ num_events += nev_tmp;
+ }
+
+ return num_events;
+}
+
+/**
* Generate internal events representing this proximity event and enqueue
* them on the event queue.
*
diff --git a/xorg-server/dix/inpututils.c b/xorg-server/dix/inpututils.c
index 7aeb1e516..0a3d3d8b4 100644
--- a/xorg-server/dix/inpututils.c
+++ b/xorg-server/dix/inpututils.c
@@ -497,10 +497,10 @@ valuator_mask_isset(const ValuatorMask *mask, int valuator)
}
/**
- * Set the valuator to the given data.
+ * Set the valuator to the given floating-point data.
*/
void
-valuator_mask_set(ValuatorMask *mask, int valuator, int data)
+valuator_mask_set_double(ValuatorMask *mask, int valuator, double data)
{
mask->last_bit = max(valuator, mask->last_bit);
SetBit(mask->mask, valuator);
@@ -508,13 +508,33 @@ valuator_mask_set(ValuatorMask *mask, int valuator, int data)
}
/**
- * Return the requested valuator value. If the mask bit is not set for the
- * given valuator, the returned value is undefined.
+ * Set the valuator to the given integer data.
+ */
+void
+valuator_mask_set(ValuatorMask *mask, int valuator, int data)
+{
+ valuator_mask_set_double(mask, valuator, data);
+}
+
+/**
+ * Return the requested valuator value as a double. If the mask bit is not
+ * set for the given valuator, the returned value is undefined.
+ */
+double
+valuator_mask_get_double(const ValuatorMask *mask, int valuator)
+{
+ return mask->valuators[valuator];
+}
+
+/**
+ * Return the requested valuator value as an integer, rounding towards zero.
+ * If the mask bit is not set for the given valuator, the returned value is
+ * undefined.
*/
int
valuator_mask_get(const ValuatorMask *mask, int valuator)
{
- return mask->valuators[valuator];
+ return trunc(valuator_mask_get_double(mask, valuator));
}
/**
@@ -527,7 +547,7 @@ valuator_mask_unset(ValuatorMask *mask, int valuator)
int i, lastbit = -1;
ClearBit(mask->mask, valuator);
- mask->valuators[valuator] = 0;
+ mask->valuators[valuator] = 0.0;
for (i = 0; i <= mask->last_bit; i++)
if (valuator_mask_isset(mask, i))
diff --git a/xorg-server/dix/ptrveloc.c b/xorg-server/dix/ptrveloc.c
index fe655d5f4..fc5cf49b8 100644
--- a/xorg-server/dix/ptrveloc.c
+++ b/xorg-server/dix/ptrveloc.c
@@ -72,9 +72,9 @@
/* fwds */
int
SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
-static float
-SimpleSmoothProfile(DeviceIntPtr dev, DeviceVelocityPtr vel, float velocity,
- float threshold, float acc);
+static double
+SimpleSmoothProfile(DeviceIntPtr dev, DeviceVelocityPtr vel, double velocity,
+ double threshold, double acc);
static PointerAccelerationProfileFunc
GetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
static BOOL
@@ -487,14 +487,10 @@ DoGetDirection(int dx, int dy){
else
dir = UNDEFINED; /* shouldn't happen */
} else { /* compute angle and set appropriate flags */
- float r;
+ double r;
int i1, i2;
-#ifdef _ISOC99_SOURCE
- r = atan2f(dy, dx);
-#else
r = atan2(dy, dx);
-#endif
/* find direction.
*
* Add 360° to avoid r become negative since C has no well-defined
@@ -533,8 +529,7 @@ static int
GetDirection(int dx, int dy){
static int cache[DIRECTION_CACHE_SIZE][DIRECTION_CACHE_SIZE];
int dir;
- if (abs(dx) <= DIRECTION_CACHE_RANGE &&
- abs(dy) <= DIRECTION_CACHE_RANGE) {
+ if (abs(dx) <= DIRECTION_CACHE_RANGE && abs(dy) <= DIRECTION_CACHE_RANGE) {
/* cacheable */
dir = cache[DIRECTION_CACHE_RANGE+dx][DIRECTION_CACHE_RANGE+dy];
if(dir == 0) {
@@ -562,7 +557,7 @@ GetDirection(int dx, int dy){
* 0/0 and set it as the current one.
*/
static inline void
-FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t)
+FeedTrackers(DeviceVelocityPtr vel, double dx, double dy, int cur_t)
{
int n;
for(n = 0; n < vel->num_tracker; n++){
@@ -570,8 +565,8 @@ FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t)
vel->tracker[n].dy += dy;
}
n = (vel->cur_tracker + 1) % vel->num_tracker;
- vel->tracker[n].dx = 0;
- vel->tracker[n].dy = 0;
+ vel->tracker[n].dx = 0.0;
+ vel->tracker[n].dy = 0.0;
vel->tracker[n].time = cur_t;
vel->tracker[n].dir = GetDirection(dx, dy);
DebugAccelF("(dix prtacc) motion [dx: %i dy: %i dir:%i diff: %i]\n",
@@ -585,9 +580,9 @@ FeedTrackers(DeviceVelocityPtr vel, int dx, int dy, int cur_t)
* velocity scaling.
* This assumes linear motion.
*/
-static float
+static double
CalcTracker(const MotionTracker *tracker, int cur_t){
- float dist = sqrt(tracker->dx * tracker->dx + tracker->dy * tracker->dy);
+ double dist = sqrt(tracker->dx * tracker->dx + tracker->dy * tracker->dy);
int dtime = cur_t - tracker->time;
if(dtime > 0)
return dist / dtime;
@@ -602,16 +597,16 @@ CalcTracker(const MotionTracker *tracker, int cur_t){
*
* @return The tracker's velocity or 0 if the above conditions are unmet
*/
-static float
+static double
QueryTrackers(DeviceVelocityPtr vel, int cur_t){
int offset, dir = UNDEFINED, used_offset = -1, age_ms;
/* initial velocity: a low-offset, valid velocity */
- float initial_velocity = 0, result = 0, velocity_diff;
- float velocity_factor = vel->corr_mul * vel->const_acceleration; /* premultiply */
+ double initial_velocity = 0, result = 0, velocity_diff;
+ double velocity_factor = vel->corr_mul * vel->const_acceleration; /* premultiply */
/* loop from current to older data */
for(offset = 1; offset < vel->num_tracker; offset++){
MotionTracker *tracker = TRACKER(vel, offset);
- float tracker_velocity;
+ double tracker_velocity;
age_ms = cur_t - tracker->time;
@@ -683,11 +678,11 @@ QueryTrackers(DeviceVelocityPtr vel, int cur_t){
BOOL
ProcessVelocityData2D(
DeviceVelocityPtr vel,
- int dx,
- int dy,
+ double dx,
+ double dy,
int time)
{
- float velocity;
+ double velocity;
vel->last_velocity = vel->velocity;
@@ -703,12 +698,12 @@ ProcessVelocityData2D(
* this flattens significant ( > 1) mickeys a little bit for more steady
* constant-velocity response
*/
-static inline float
-ApplySimpleSoftening(int prev_delta, int delta)
+static inline double
+ApplySimpleSoftening(double prev_delta, double delta)
{
- float result = delta;
+ double result = delta;
- if (delta < -1 || delta > 1) {
+ if (delta < -1.0 || delta > 1.0) {
if (delta > prev_delta)
result -= 0.5;
else if (delta < prev_delta)
@@ -727,8 +722,8 @@ ApplySimpleSoftening(int prev_delta, int delta)
static void
ApplySoftening(
DeviceVelocityPtr vel,
- float* fdx,
- float* fdy)
+ double* fdx,
+ double* fdy)
{
if (vel->use_softening) {
*fdx = ApplySimpleSoftening(vel->last_dx, *fdx);
@@ -737,7 +732,7 @@ ApplySoftening(
}
static void
-ApplyConstantDeceleration(DeviceVelocityPtr vel, float *fdx, float *fdy)
+ApplyConstantDeceleration(DeviceVelocityPtr vel, double *fdx, double *fdy)
{
*fdx *= vel->const_acceleration;
*fdy *= vel->const_acceleration;
@@ -746,15 +741,15 @@ ApplyConstantDeceleration(DeviceVelocityPtr vel, float *fdx, float *fdy)
/*
* compute the acceleration for given velocity and enforce min_acceleartion
*/
-float
+double
BasicComputeAcceleration(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc){
+ double velocity,
+ double threshold,
+ double acc){
- float result;
+ double result;
result = vel->Profile(dev, vel, velocity, threshold, acc);
/* enforce min_acceleration */
@@ -768,13 +763,13 @@ BasicComputeAcceleration(
* If the velocity has changed, an average is taken of 6 velocity factors:
* current velocity, last velocity and 4 times the average between the two.
*/
-static float
+static double
ComputeAcceleration(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float threshold,
- float acc){
- float result;
+ double threshold,
+ double acc){
+ double result;
if(vel->velocity <= 0){
DebugAccelF("(dix ptracc) profile skipped\n");
@@ -817,13 +812,13 @@ ComputeAcceleration(
/**
* Polynomial function similar previous one, but with f(1) = 1
*/
-static float
+static double
PolynomialAccelerationProfile(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float velocity,
- float ignored,
- float acc)
+ double velocity,
+ double ignored,
+ double acc)
{
return pow(velocity, (acc - 1.0) * 0.5);
}
@@ -833,13 +828,13 @@ PolynomialAccelerationProfile(
* returns acceleration for velocity.
* This profile selects the two functions like the old scheme did
*/
-static float
+static double
ClassicProfile(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
+ double velocity,
+ double threshold,
+ double acc)
{
if (threshold > 0) {
return SimpleSmoothProfile (dev,
@@ -865,15 +860,15 @@ ClassicProfile(
* This has the expense of overall response dependency on min-acceleration.
* In effect, min_acceleration mimics const_acceleration in this profile.
*/
-static float
+static double
PowerProfile(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
+ double velocity,
+ double threshold,
+ double acc)
{
- float vel_dist;
+ double vel_dist;
acc = (acc-1.0) * 0.1f + 1.0; /* without this, acc of 2 is unuseable */
@@ -891,11 +886,11 @@ PowerProfile(
* - starts faster than a sinoid
* - smoothness C1 (Cinf if you dare to ignore endpoints)
*/
-static inline float
-CalcPenumbralGradient(float x){
+static inline double
+CalcPenumbralGradient(double x){
x *= 2.0f;
x -= 1.0f;
- return 0.5f + (x * sqrt(1.0f - x*x) + asin(x))/M_PI;
+ return 0.5f + (x * sqrt(1.0 - x*x) + asin(x))/M_PI;
}
@@ -903,13 +898,13 @@ CalcPenumbralGradient(float x){
* acceleration function similar to classic accelerated/unaccelerated,
* but with smooth transition in between (and towards zero for adaptive dec.).
*/
-static float
+static double
SimpleSmoothProfile(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
+ double velocity,
+ double threshold,
+ double acc)
{
if(velocity < 1.0f)
return CalcPenumbralGradient(0.5 + velocity*0.5) * 2.0f - 1.0f;
@@ -929,15 +924,15 @@ SimpleSmoothProfile(
* This profile uses the first half of the penumbral gradient as a start
* and then scales linearly.
*/
-static float
+static double
SmoothLinearProfile(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
+ double velocity,
+ double threshold,
+ double acc)
{
- float res, nv;
+ double res, nv;
if(acc > 1.0f)
acc -= 1.0f; /*this is so acc = 1 is no acceleration */
@@ -964,15 +959,15 @@ SmoothLinearProfile(
* From 0 to threshold, the response graduates smoothly from min_accel to
* acceleration. Beyond threshold it is exactly the specified acceleration.
*/
-static float
+static double
SmoothLimitedProfile(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
+ double velocity,
+ double threshold,
+ double acc)
{
- float res;
+ double res;
if(velocity >= threshold || threshold == 0.0f)
return acc;
@@ -985,24 +980,24 @@ SmoothLimitedProfile(
}
-static float
+static double
LinearProfile(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
+ double velocity,
+ double threshold,
+ double acc)
{
return acc * velocity;
}
-static float
+static double
NoProfile(
DeviceIntPtr dev,
DeviceVelocityPtr vel,
- float velocity,
- float threshold,
- float acc)
+ double velocity,
+ double threshold,
+ double acc)
{
return 1.0f;
}
@@ -1128,11 +1123,11 @@ acceleratePointerPredictable(
ValuatorMask* val,
CARD32 evtime)
{
- int dx = 0, dy = 0, tmpi;
+ double dx = 0, dy = 0;
DeviceVelocityPtr velocitydata = GetDevicePredictableAccelData(dev);
Bool soften = TRUE;
- if (!velocitydata)
+ if (valuator_mask_num_valuators(val) == 0 || !velocitydata)
return;
if (velocitydata->statistics.profile_number == AccelProfileNone &&
@@ -1141,59 +1136,39 @@ acceleratePointerPredictable(
}
if (valuator_mask_isset(val, 0)) {
- dx = valuator_mask_get(val, 0);
+ dx = valuator_mask_get_double(val, 0);
}
if (valuator_mask_isset(val, 1)) {
- dy = valuator_mask_get(val, 1);
+ dy = valuator_mask_get_double(val, 1);
}
- if (dx || dy){
+ if (dx != 0.0 || dy != 0.0) {
/* reset non-visible state? */
if (ProcessVelocityData2D(velocitydata, dx , dy, evtime)) {
soften = FALSE;
}
if (dev->ptrfeed && dev->ptrfeed->ctrl.num) {
- float mult;
+ double mult;
/* invoke acceleration profile to determine acceleration */
mult = ComputeAcceleration (dev, velocitydata,
- dev->ptrfeed->ctrl.threshold,
- (float)dev->ptrfeed->ctrl.num /
- (float)dev->ptrfeed->ctrl.den);
+ dev->ptrfeed->ctrl.threshold,
+ (double)dev->ptrfeed->ctrl.num /
+ (double)dev->ptrfeed->ctrl.den);
if(mult != 1.0f || velocitydata->const_acceleration != 1.0f) {
- float fdx = dx,
- fdy = dy;
-
if (mult > 1.0f && soften)
- ApplySoftening(velocitydata, &fdx, &fdy);
- ApplyConstantDeceleration(velocitydata, &fdx, &fdy);
-
- /* Calculate the new delta (with accel) and drop it back
- * into the valuator masks */
- if (dx) {
- float tmp;
- tmp = mult * fdx + dev->last.remainder[0];
- /* Since it may not be apparent: lrintf() does not offer
- * strong statements about rounding; however because we
- * process each axis conditionally, there's no danger
- * of a toggling remainder. Its lack of guarantees likely
- * makes it faster on the average target. */
- tmpi = lrintf(tmp);
- valuator_mask_set(val, 0, tmpi);
- dev->last.remainder[0] = tmp - (float)tmpi;
- }
- if (dy) {
- float tmp;
- tmp = mult * fdy + dev->last.remainder[1];
- tmpi = lrintf(tmp);
- valuator_mask_set(val, 1, tmpi);
- dev->last.remainder[1] = tmp - (float)tmpi;
- }
- DebugAccelF("pos (%i | %i) remainders x: %.3f y: %.3f delta x:%.3f y:%.3f\n",
- *px, *py, dev->last.remainder[0], dev->last.remainder[1], fdx, fdy);
+ ApplySoftening(velocitydata, &dx, &dy);
+ ApplyConstantDeceleration(velocitydata, &dx, &dy);
+
+ if (dx != 0.0)
+ valuator_mask_set_double(val, 0, mult * dx);
+ if (dy != 0.0)
+ valuator_mask_set_double(val, 1, mult * dy);
+ DebugAccelF("pos (%i | %i) delta x:%.3f y:%.3f\n", mult * dx,
+ mult * dy);
}
}
}
@@ -1214,8 +1189,8 @@ acceleratePointerLightweight(
ValuatorMask* val,
CARD32 ignored)
{
- float mult = 0.0, tmpf;
- int dx = 0, dy = 0, tmpi;
+ double mult = 0.0, tmpf;
+ double dx = 0.0, dy = 0.0;
if (valuator_mask_isset(val, 0)) {
dx = valuator_mask_get(val, 0);
@@ -1225,53 +1200,35 @@ acceleratePointerLightweight(
dy = valuator_mask_get(val, 1);
}
- if (!dx && !dy)
+ if (valuator_mask_num_valuators(val) == 0)
return;
if (dev->ptrfeed && dev->ptrfeed->ctrl.num) {
/* modeled from xf86Events.c */
if (dev->ptrfeed->ctrl.threshold) {
- if ((abs(dx) + abs(dy)) >= dev->ptrfeed->ctrl.threshold) {
- tmpf = ((float)dx *
- (float)(dev->ptrfeed->ctrl.num)) /
- (float)(dev->ptrfeed->ctrl.den) +
- dev->last.remainder[0];
- if (dx) {
- tmpi = (int) tmpf;
- valuator_mask_set(val, 0, tmpi);
- dev->last.remainder[0] = tmpf - (float)tmpi;
+ if ((fabs(dx) + fabs(dy)) >= dev->ptrfeed->ctrl.threshold) {
+ if (dx != 0.0) {
+ tmpf = (dx * (double)(dev->ptrfeed->ctrl.num)) /
+ (double)(dev->ptrfeed->ctrl.den);
+ valuator_mask_set_double(val, 0, tmpf);
}
- tmpf = ((float)dy *
- (float)(dev->ptrfeed->ctrl.num)) /
- (float)(dev->ptrfeed->ctrl.den) +
- dev->last.remainder[1];
- if (dy) {
- tmpi = (int) tmpf;
- valuator_mask_set(val, 1, tmpi);
- dev->last.remainder[1] = tmpf - (float)tmpi;
+ if (dy != 0.0) {
+ tmpf = (dy * (double)(dev->ptrfeed->ctrl.num)) /
+ (double)(dev->ptrfeed->ctrl.den);
+ valuator_mask_set_double(val, 1, tmpf);
}
}
}
else {
- mult = pow((float)dx * (float)dx + (float)dy * (float)dy,
- ((float)(dev->ptrfeed->ctrl.num) /
- (float)(dev->ptrfeed->ctrl.den) - 1.0) /
+ mult = pow(dx * dx + dy * dy,
+ ((double)(dev->ptrfeed->ctrl.num) /
+ (double)(dev->ptrfeed->ctrl.den) - 1.0) /
2.0) / 2.0;
- if (dx) {
- tmpf = mult * (float)dx +
- dev->last.remainder[0];
- tmpi = (int) tmpf;
- valuator_mask_set(val, 0, tmpi);
- dev->last.remainder[0] = tmpf - (float)tmpi;
- }
- if (dy) {
- tmpf = mult * (float)dy +
- dev->last.remainder[1];
- tmpi = (int)tmpf;
- valuator_mask_set(val, 1, tmpi);
- dev->last.remainder[1] = tmpf - (float)tmpi;
- }
+ if (dx != 0.0)
+ valuator_mask_set_double(val, 0, mult * dx);
+ if (dy != 0.0)
+ valuator_mask_set_double(val, 1, mult * dy);
}
}
}