[PATCH 3/5] input: support the new XIScrollClass to mark axes as scrolling axes
Peter Hutterer
peter.hutterer at who-t.net
Thu Sep 8 21:19:27 PDT 2011
Don't require specific axis labels for smooth scrolling. Instead, let the
driver mark axes as scrolling axes as required.
Currently missing: the XIDeviceChangeEvent being sent when a driver changes
a scroll axis at run-time. This can be added later.
Note: the SCROLL_TYPE enums are intentionally different values to the XI2
proto values to avoid copy/overlapping range bugs.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Xi/exevents.c | 48 +++++++++++++
Xi/xiquerydevice.c | 70 +++++++++++++++++++-
Xi/xiquerydevice.h | 1 +
dix/devices.c | 16 +++--
dix/getevents.c | 135 ++++++++++++++++++++++++++----------
include/exevents.h | 23 ++++++
include/inputstr.h | 18 +++++
test/input.c | 57 ++++++++++++++++
test/xi2/protocol-common.c | 63 +++++++++++++++++-
test/xi2/protocol-xiquerydevice.c | 49 ++++++++++++--
10 files changed, 429 insertions(+), 51 deletions(-)
diff --git a/Xi/exevents.c b/Xi/exevents.c
index a6455e6..6224e94 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1091,6 +1091,54 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int
if (mode & OutOfProximity)
dev->proximity->in_proximity = FALSE;
+ return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
+}
+
+/**
+ * Set the given axis number as a scrolling valuator.
+ */
+Bool
+SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, double increment, int flags)
+{
+ AxisInfoPtr ax;
+ int *current_ax;
+
+ if (!dev || !dev->valuator || axnum >= dev->valuator->numAxes)
+ return FALSE;
+
+ switch (type)
+ {
+ case SCROLL_TYPE_VERTICAL:
+ current_ax = &dev->valuator->v_scroll_axis;
+ break;
+ case SCROLL_TYPE_HORIZONTAL:
+ current_ax = &dev->valuator->h_scroll_axis;
+ break;
+ case SCROLL_TYPE_NONE:
+ ax = &dev->valuator->axes[axnum];
+ ax->scroll.type = type;
+ return TRUE;
+ default:
+ return FALSE;
+ }
+
+ if (increment == 0.0)
+ return FALSE;
+
+ if (*current_ax != -1 && axnum != *current_ax)
+ {
+ ax = &dev->valuator->axes[*current_ax];
+ if (ax->scroll.type == type && (flags & SCROLL_FLAG_PREFERRED) == (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
+ return FALSE;
+ }
+ *current_ax = axnum;
+
+ ax = &dev->valuator->axes[axnum];
+ ax->scroll.type = type;
+ ax->scroll.increment = increment;
+ ax->scroll.flags = flags;
+ /* FIXME: generate DeviceChanged Events */
+
return TRUE;
}
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
index a768d49..2ea6562 100644
--- a/Xi/xiquerydevice.c
+++ b/Xi/xiquerydevice.c
@@ -233,7 +233,16 @@ SizeDeviceClasses(DeviceIntPtr dev)
}
if (dev->valuator)
- len += sizeof(xXIValuatorInfo) * dev->valuator->numAxes;
+ {
+ int i;
+ len += (sizeof(xXIValuatorInfo)) * dev->valuator->numAxes;
+
+ for (i = 0; i < dev->valuator->numAxes; i++) {
+ if (dev->valuator->axes[i].scroll.type != SCROLL_TYPE_NONE)
+ len += sizeof(xXIScrollInfo);
+ }
+ }
+
return len;
}
@@ -376,6 +385,53 @@ SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info)
swaps(&info->sourceid, n);
}
+int
+ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo *info, int axisnumber)
+{
+ ValuatorClassPtr v = dev->valuator;
+ AxisInfoPtr axis = &v->axes[axisnumber];
+
+ if (axis->scroll.type == SCROLL_TYPE_NONE)
+ return 0;
+
+ info->type = XIScrollClass;
+ info->length = sizeof(xXIScrollInfo)/4;
+ info->number = axisnumber;
+ switch(axis->scroll.type)
+ {
+ case SCROLL_TYPE_VERTICAL: info->scroll_type = XIScrollTypeVertical; break;
+ case SCROLL_TYPE_HORIZONTAL: info->scroll_type = XIScrollTypeHorizontal; break;
+ default:
+ ErrorF("[Xi] Unknown scroll type %d. This is a bug.\n", axis->scroll.type);
+ break;
+ }
+ info->increment.integral = (int)axis->scroll.increment;
+ info->increment.frac = (unsigned int)(axis->scroll.increment * (1UL << 32));
+ info->sourceid = v->sourceid;
+
+ info->flags = 0;
+
+ if (axis->scroll.flags & SCROLL_FLAG_DONT_EMULATE)
+ info->flags |= XIScrollFlagNoEmulation;
+ if (axis->scroll.flags & SCROLL_FLAG_PREFERRED)
+ info->flags |= XIScrollFlagPreferred;
+
+ return info->length * 4;
+}
+
+static void
+SwapScrollInfo(DeviceIntPtr dev, xXIScrollInfo* info)
+{
+ char n;
+ swaps(&info->type, n);
+ swaps(&info->length, n);
+ swaps(&info->number, n);
+ swaps(&info->sourceid, n);
+ swaps(&info->scroll_type, n);
+ swapl(&info->increment.integral, n);
+ swapl(&info->increment.frac, n);
+}
+
int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment)
{
DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED);
@@ -465,6 +521,15 @@ ListDeviceClasses(ClientPtr client, DeviceIntPtr dev,
total_len += len;
}
+ for (i = 0; dev->valuator && i < dev->valuator->numAxes; i++)
+ {
+ len = ListScrollInfo(dev, (xXIScrollInfo*)any, i);
+ if (len)
+ (*nclasses)++;
+ any += len;
+ total_len += len;
+ }
+
return total_len;
}
@@ -492,6 +557,9 @@ SwapDeviceInfo(DeviceIntPtr dev, xXIDeviceInfo* info)
case XIValuatorClass:
SwapValuatorInfo(dev, (xXIValuatorInfo*)any);
break;
+ case XIScrollClass:
+ SwapScrollInfo(dev, (xXIScrollInfo*)any);
+ break;
}
any += len * 4;
diff --git a/Xi/xiquerydevice.h b/Xi/xiquerydevice.h
index 02f0659..9db6aa2 100644
--- a/Xi/xiquerydevice.h
+++ b/Xi/xiquerydevice.h
@@ -44,4 +44,5 @@ int ListButtonInfo(DeviceIntPtr dev, xXIButtonInfo* info, Bool reportState);
int ListKeyInfo(DeviceIntPtr dev, xXIKeyInfo* info);
int ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info,
int axisnumber, Bool reportState);
+int ListScrollInfo(DeviceIntPtr dev, xXIScrollInfo* info, int axisnumber);
#endif /* QUERYDEV_H */
diff --git a/dix/devices.c b/dix/devices.c
index 0310119..64557aa 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -260,6 +260,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;
@@ -939,6 +941,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);
}
@@ -1261,8 +1264,6 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
{
int i;
ValuatorClassPtr valc;
- Atom h_scroll_label = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
- Atom v_scroll_label = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
if (!dev)
return FALSE;
@@ -1279,6 +1280,13 @@ 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;
@@ -1299,10 +1307,6 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, Atom *labels,
for (i=0; i<numAxes; i++) {
InitValuatorAxisStruct(dev, i, labels[i], NO_AXIS_LIMITS, NO_AXIS_LIMITS,
0, 0, 0, mode);
- if (labels[i] == h_scroll_label)
- valc->h_scroll_axis = i;
- else if (labels[i] == v_scroll_label)
- valc->v_scroll_axis = i;
valc->axisVal[i]=0;
}
diff --git a/dix/getevents.c b/dix/getevents.c
index 2890b6f..4f0ad9f 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -1175,6 +1175,88 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
}
/**
+ * 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
+ * @param[in,out] last Last scroll state posted (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;
+
+ if (dev->valuator->axes[axis].scroll.type == SCROLL_TYPE_NONE)
+ return 0;
+
+ ax = &dev->valuator->axes[axis];
+ incr = ax->scroll.increment;
+
+ if (!valuator_mask_isset(last, axis))
+ {
+ valuator_mask_set_double(last, axis, valuator_mask_get_double(mask, axis));
+ return 0;
+ }
+
+ delta = valuator_mask_get_double(last, axis) - valuator_mask_get_double(mask, axis);
+ total = delta;
+
+ while (fabs(delta) >= fabs(incr))
+ {
+ int b = ax->scroll.type == SCROLL_TYPE_VERTICAL ? 4 : 6;
+ int nev_tmp;
+
+ /* fill_pointer_events() generates four events: one normal and one raw
+ * event each for the emulated button press and release both. */
+ if (num_events + 4 >= max_events)
+ break;
+
+ if (delta <= -incr)
+ delta += incr;
+ else if (delta >= incr) {
+ delta -= incr;
+ b++;
+ }
+
+ 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
@@ -1201,6 +1283,8 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
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)
@@ -1214,7 +1298,9 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
valuator_mask_copy(&mask, mask_in);
- /* Turn a scroll button press into a smooth-scrolling event if necessary. */
+ /* 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;
@@ -1245,6 +1331,7 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
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;
@@ -1259,49 +1346,21 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type,
num_events += nev_tmp;
/* Now turn the smooth-scrolling axes back into emulated button presses
- * for legacy clients. */
- while ((v_scroll_axis != -1 &&
- fabs(pDev->last.valuators[v_scroll_axis]) >= 1.0) ||
- (h_scroll_axis != -1 &&
- fabs(pDev->last.valuators[h_scroll_axis]) >= 1.0))
- {
- int b = 0;
+ * 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]);
/* fill_pointer_events() generates four events: one normal and one raw
* event each for the emulated button press and release both. */
if (num_events + 4 >= GetMaximumEventsNum())
break;
- if (v_scroll_axis != -1 && pDev->last.valuators[v_scroll_axis] <= -1.0)
- {
- pDev->last.valuators[v_scroll_axis] += 1.0;
- b = 4;
- }
- else if (v_scroll_axis != -1 &&
- pDev->last.valuators[v_scroll_axis] >= 1.0)
- {
- pDev->last.valuators[v_scroll_axis] -= 1.0;
- b = 5;
- }
- else if (h_scroll_axis != -1 &&
- pDev->last.valuators[h_scroll_axis] <= -1.0)
- {
- pDev->last.valuators[h_scroll_axis] += 1.0;
- b = 6;
- }
- else if (h_scroll_axis != -1 &&
- pDev->last.valuators[h_scroll_axis] >= 1.0)
- {
- pDev->last.valuators[h_scroll_axis] -= 1.0;
- b = 7;
- }
-
- nev_tmp = fill_pointer_events(events, pDev, ButtonPress, b, ms,
- POINTER_EMULATED, NULL);
- events += nev_tmp;
- num_events += nev_tmp;
- nev_tmp = fill_pointer_events(events, pDev, ButtonRelease, b, ms,
- POINTER_EMULATED, NULL);
+ nev_tmp = emulate_scroll_button_events(events, pDev, i, &scroll,
+ pDev->last.scroll, ms,
+ GetMaximumEventsNum() - num_events);
events += nev_tmp;
num_events += nev_tmp;
}
diff --git a/include/exevents.h b/include/exevents.h
index 731f31e..4fe6c61 100644
--- a/include/exevents.h
+++ b/include/exevents.h
@@ -37,6 +37,22 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
* Interface available to drivers *
***************************************************************/
+/**
+ * Scroll flags for ::SetScrollValuator.
+ */
+enum ScrollFlags {
+ SCROLL_FLAG_NONE = 0,
+ /**
+ * Do not emulate legacy button events for valuator events on this axis.
+ */
+ SCROLL_FLAG_DONT_EMULATE = (1 << 1),
+ /**
+ * This axis is the preferred axis for valuator emulation for this axis'
+ * scroll type.
+ */
+ SCROLL_FLAG_PREFERRED = (1 << 2)
+};
+
extern _X_EXPORT int InitProximityClassDeviceStruct(
DeviceIntPtr /* dev */);
@@ -51,6 +67,13 @@ extern _X_EXPORT Bool InitValuatorAxisStruct(
int /* max_res */,
int /* mode */);
+extern _X_EXPORT Bool SetScrollValuator(
+ DeviceIntPtr /* dev */,
+ int /* axnum */,
+ enum ScrollType /* type */,
+ double /* increment */,
+ int /* flags */);
+
/* Input device properties */
extern _X_EXPORT void XIDeleteAllDeviceProperties(
DeviceIntPtr /* device */
diff --git a/include/inputstr.h b/include/inputstr.h
index 26327cd..9d4108e 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -75,6 +75,16 @@ extern _X_EXPORT int CountBits(const uint8_t *mask, int len);
#define XI2MASKSIZE ((XI2LASTEVENT + 7)/8) /* no of bits for masks */
/**
+ * Scroll types for ::SetScrollValuator and the scroll type in the
+ * ::ScrollInfoPtr.
+ */
+enum ScrollType {
+ SCROLL_TYPE_NONE = 0, /**< Not a scrolling valuator */
+ SCROLL_TYPE_VERTICAL = 8,
+ SCROLL_TYPE_HORIZONTAL = 9,
+};
+
+/**
* This struct stores the core event mask for each client except the client
* that created the window.
*
@@ -252,6 +262,12 @@ typedef struct _KeyClassRec {
struct _XkbSrvInfo *xkbInfo;
} KeyClassRec, *KeyClassPtr;
+typedef struct _ScrollInfo {
+ enum ScrollType type;
+ double increment;
+ int flags;
+} ScrollInfo, *ScrollInfoPtr;
+
typedef struct _AxisInfo {
int resolution;
int min_resolution;
@@ -260,6 +276,7 @@ typedef struct _AxisInfo {
int max_value;
Atom label;
CARD8 mode;
+ ScrollInfo scroll;
} AxisInfo, *AxisInfoPtr;
typedef struct _ValuatorAccelerationRec {
@@ -526,6 +543,7 @@ typedef struct _DeviceIntRec {
double valuators[MAX_VALUATORS];
int numValuators;
DeviceIntPtr slave;
+ ValuatorMask *scroll;
} last;
/* Input device property handling. */
diff --git a/test/input.c b/test/input.c
index 2501d59..d33fcf8 100644
--- a/test/input.c
+++ b/test/input.c
@@ -52,6 +52,7 @@ static void dix_init_valuators(void)
{
DeviceIntRec dev;
ValuatorClassPtr val;
+ AxisInfoPtr axis;
const int num_axes = 2;
int i;
Atom atoms[MAX_VALUATORS] = { 0 };
@@ -78,6 +79,62 @@ static void dix_init_valuators(void)
}
assert(dev.last.numValuators == num_axes);
+
+ /* invalid increment */
+ assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL, 0.0, SCROLL_FLAG_NONE) == FALSE);
+ /* invalid type */
+ assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL - 1, 1.0, SCROLL_FLAG_NONE) == FALSE);
+ assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_HORIZONTAL + 1, 1.0, SCROLL_FLAG_NONE) == FALSE);
+ /* invalid axisnum */
+ assert(SetScrollValuator(&dev, 2, SCROLL_TYPE_HORIZONTAL, 1.0, SCROLL_FLAG_NONE) == FALSE);
+
+ /* valid */
+ assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL, 3.0, SCROLL_FLAG_NONE) == TRUE);
+ axis = &dev.valuator->axes[0];
+ assert(axis->scroll.increment == 3.0);
+ assert(axis->scroll.type == SCROLL_TYPE_VERTICAL);
+ assert(axis->scroll.flags == 0);
+
+ /* valid */
+ assert(SetScrollValuator(&dev, 1, SCROLL_TYPE_HORIZONTAL, 2.0, SCROLL_FLAG_NONE) == TRUE);
+ axis = &dev.valuator->axes[1];
+ assert(axis->scroll.increment == 2.0);
+ assert(axis->scroll.type == SCROLL_TYPE_HORIZONTAL);
+ assert(axis->scroll.flags == 0);
+
+ /* cannot overwrite with other axis */
+ assert(SetScrollValuator(&dev, 1, SCROLL_TYPE_VERTICAL, 5.0, SCROLL_FLAG_NONE) == FALSE);
+ assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_HORIZONTAL, 5.0, SCROLL_FLAG_NONE) == FALSE);
+
+ /* can overwrite with Preferred */
+ assert(SetScrollValuator(&dev, 1, SCROLL_TYPE_VERTICAL, 5.5, SCROLL_FLAG_PREFERRED) == TRUE);
+ axis = &dev.valuator->axes[1];
+ assert(axis->scroll.increment == 5.5);
+ assert(axis->scroll.type == SCROLL_TYPE_VERTICAL);
+ assert(axis->scroll.flags == SCROLL_FLAG_PREFERRED);
+
+ assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_HORIZONTAL, 8.8, SCROLL_FLAG_PREFERRED) == TRUE);
+ axis = &dev.valuator->axes[0];
+ assert(axis->scroll.increment == 8.8);
+ assert(axis->scroll.type == SCROLL_TYPE_HORIZONTAL);
+ assert(axis->scroll.flags == SCROLL_FLAG_PREFERRED);
+
+ /* can overwrite as none */
+ assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_NONE, 5.0,
+ SCROLL_FLAG_NONE) == TRUE);
+ axis = &dev.valuator->axes[0];
+ assert(axis->scroll.type == SCROLL_TYPE_NONE);
+
+ /* can overwrite axis with new settings */
+ assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL, 5.0, SCROLL_FLAG_NONE) == TRUE);
+ axis = &dev.valuator->axes[0];
+ assert(axis->scroll.type == SCROLL_TYPE_VERTICAL);
+ assert(axis->scroll.increment == 5.0);
+ assert(axis->scroll.flags == SCROLL_FLAG_NONE);
+ assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_VERTICAL, 3.0, SCROLL_FLAG_NONE) == TRUE);
+ assert(axis->scroll.type == SCROLL_TYPE_VERTICAL);
+ assert(axis->scroll.increment == 3.0);
+ assert(axis->scroll.flags == SCROLL_FLAG_NONE);
}
/* just check the known success cases, and that error cases set the client's
diff --git a/test/xi2/protocol-common.c b/test/xi2/protocol-common.c
index 4234533..56d6bd2 100644
--- a/test/xi2/protocol-common.c
+++ b/test/xi2/protocol-common.c
@@ -29,6 +29,8 @@
#include "extinit.h" /* for XInputExtensionInit */
#include "exglobals.h"
#include "xkbsrv.h" /* for XkbInitPrivates */
+#include "xserver-properties.h"
+#include <X11/extensions/XI2.h>
#include "protocol-common.h"
@@ -63,6 +65,65 @@ static void fake_init_sprite(DeviceIntPtr dev)
sprite->physLimits.y2 = screen.height;
}
+/* This is essentially CorePointerProc with ScrollAxes added */
+static int
+TestPointerProc(DeviceIntPtr pDev, int what)
+{
+#define NBUTTONS 10
+#define NAXES 4
+ BYTE map[NBUTTONS + 1];
+ int i = 0;
+ Atom btn_labels[NBUTTONS] = {0};
+ Atom axes_labels[NAXES] = {0};
+
+ switch (what) {
+ case DEVICE_INIT:
+ for (i = 1; i <= NBUTTONS; i++)
+ map[i] = i;
+
+ btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
+ btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
+ btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
+ btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
+ btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
+ btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
+ btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
+ /* don't know about the rest */
+
+ axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
+ axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
+ axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_VSCROLL);
+ axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_HSCROLL);
+
+ if (!InitPointerDeviceStruct((DevicePtr)pDev, map, NBUTTONS, btn_labels,
+ (PtrCtrlProcPtr)NoopDDA,
+ GetMotionHistorySize(), NAXES, axes_labels))
+ {
+ ErrorF("Could not initialize device '%s'. Out of memory.\n",
+ pDev->name);
+ return BadAlloc;
+ }
+ pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2;
+ pDev->last.valuators[0] = pDev->valuator->axisVal[0];
+ pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2;
+ pDev->last.valuators[1] = pDev->valuator->axisVal[1];
+
+ SetScrollValuator(pDev, 2, SCROLL_TYPE_VERTICAL, 2.4, SCROLL_FLAG_NONE);
+ SetScrollValuator(pDev, 3, SCROLL_TYPE_HORIZONTAL, 3.5, SCROLL_FLAG_PREFERRED);
+ break;
+
+ case DEVICE_CLOSE:
+ break;
+
+ default:
+ break;
+ }
+
+ return Success;
+
+#undef NBUTTONS
+#undef NAXES
+}
/**
* Create and init 2 master devices (VCP + VCK) and two slave devices, one
* default mouse, one default keyboard.
@@ -84,7 +145,7 @@ struct devices init_devices(void)
EnableDevice(devices.vck, FALSE);
AllocDevicePair(&client, "", &devices.mouse, &devices.kbd,
- CorePointerProc, CoreKeyboardProc, FALSE);
+ TestPointerProc, CoreKeyboardProc, FALSE);
ActivateDevice(devices.mouse, FALSE);
ActivateDevice(devices.kbd, FALSE);
EnableDevice(devices.mouse, FALSE);
diff --git a/test/xi2/protocol-xiquerydevice.c b/test/xi2/protocol-xiquerydevice.c
index cb1cc81..8bc191a 100644
--- a/test/xi2/protocol-xiquerydevice.c
+++ b/test/xi2/protocol-xiquerydevice.c
@@ -129,7 +129,7 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void
dev = devices.mouse;
assert(info->use == XISlavePointer);
assert(info->attachment == devices.vcp->id);
- assert(info->num_classes == 3); /* 2 axes + button */
+ assert(info->num_classes == 7); /* 4 axes + button + 2 scroll*/
break;
case 5: /* keyboard */
dev = devices.kbd;
@@ -185,11 +185,48 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void
}
break;
}
- case 2: /* VCP and mouse have the same properties */
case 4:
{
assert(any->type == XIButtonClass ||
- any->type == XIValuatorClass);
+ any->type == XIValuatorClass ||
+ any->type == XIScrollClass);
+
+ if (any->type == XIScrollClass)
+ {
+ xXIScrollInfo *si = (xXIScrollInfo*)any;
+
+ if (client->swapped)
+ {
+ swaps(&si->number, n);
+ swaps(&si->scroll_type, n);
+ swapl(&si->increment.integral, n);
+ swapl(&si->increment.frac, n);
+ }
+ assert(si->length == 6);
+ assert(si->number == 2 || si->number == 3);
+ if (si->number == 2) {
+ assert(si->scroll_type == XIScrollTypeVertical);
+ assert(!si->flags);
+ }
+ if (si->number == 3) {
+ assert(si->scroll_type == XIScrollTypeHorizontal);
+ assert(si->flags & XIScrollFlagPreferred);
+ assert(!(si->flags & ~XIScrollFlagPreferred));
+ }
+
+ assert(si->increment.integral == si->number);
+ /* FIXME: frac testing with float/FP issues? */
+ assert(si->increment.frac > 0.3 * (1UL << 32));
+ assert(si->increment.frac < 0.6 * (1UL << 32));
+ }
+
+ }
+ /* fall through */
+ case 2: /* VCP and mouse have the same properties except for scroll */
+ {
+ if (info->deviceid == 2 ) /* VCP */
+ assert(any->type == XIButtonClass ||
+ any->type == XIValuatorClass);
if (any->type == XIButtonClass)
{
@@ -219,8 +256,10 @@ static void reply_XIQueryDevice_data(ClientPtr client, int len, char *data, void
}
assert(vi->length == 11);
- assert(vi->number == 0 ||
- vi->number == 1);
+ assert(vi->number >= 0 && vi->number < 4);
+ if (info->deviceid == 2) /* VCP */
+ assert(vi->number < 2);
+
assert(vi->mode == XIModeRelative);
/* device was set up as relative, so standard
* values here. */
--
1.7.6
More information about the xorg-devel
mailing list