aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix/getevents.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/dix/getevents.c')
-rw-r--r--xorg-server/dix/getevents.c618
1 files changed, 372 insertions, 246 deletions
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index be2840c47..c42971592 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"
@@ -167,7 +169,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;
@@ -176,7 +178,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);
}
}
}
@@ -196,9 +198,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];
@@ -255,39 +255,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;
}
/**
@@ -309,19 +299,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,
@@ -332,16 +328,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;
}
}
}
@@ -452,7 +445,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++;
@@ -463,7 +456,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))
@@ -491,7 +484,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++;
}
@@ -525,7 +518,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;
@@ -547,6 +540,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;
@@ -559,7 +553,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
@@ -575,12 +570,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);
}
}
@@ -607,8 +604,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;
}
@@ -617,7 +616,7 @@ GetMaximumEventsNum(void) {
* InitValuatorAxisClassStruct.
*/
static void
-clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
+clipAxis(DeviceIntPtr pDev, int axisNum, double *val)
{
AxisInfoPtr axis;
@@ -647,9 +646,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);
}
}
@@ -690,85 +689,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);
}
}
@@ -799,89 +765,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);
}
/**
@@ -1045,32 +990,37 @@ 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 = {.v = {*x, *y, 1}};
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);
}
/**
@@ -1097,42 +1047,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:
@@ -1148,10 +1081,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)
@@ -1161,61 +1090,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);
@@ -1235,10 +1157,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);
@@ -1246,6 +1174,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.
*