diff options
Diffstat (limited to 'xorg-server/dix')
-rw-r--r-- | xorg-server/dix/devices.c | 12 | ||||
-rw-r--r-- | xorg-server/dix/dixfonts.c | 30 | ||||
-rw-r--r-- | xorg-server/dix/eventconvert.c | 22 | ||||
-rw-r--r-- | xorg-server/dix/events.c | 92 | ||||
-rw-r--r-- | xorg-server/dix/getevents.c | 618 | ||||
-rw-r--r-- | xorg-server/dix/inpututils.c | 32 | ||||
-rw-r--r-- | xorg-server/dix/ptrveloc.c | 259 |
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); } } } |