diff --git a/Xi/exevents.c b/Xi/exevents.c index a6455e6ac..74a78ecf2 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -1091,6 +1091,55 @@ 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 902eb918c..9961d1b6f 100644 --- a/Xi/xiquerydevice.c +++ b/Xi/xiquerydevice.c @@ -229,7 +229,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; } @@ -369,6 +378,56 @@ SwapValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info) swaps(&info->sourceid); } +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 << 16) * (1UL << 16)); + 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) +{ + swaps(&info->type); + swaps(&info->length); + swaps(&info->number); + swaps(&info->sourceid); + swaps(&info->scroll_type); + swapl(&info->increment.integral); + swapl(&info->increment.frac); +} + int GetDeviceUse(DeviceIntPtr dev, uint16_t *attachment) { DeviceIntPtr master = GetMaster(dev, MASTER_ATTACHED); @@ -458,6 +517,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; } @@ -484,6 +552,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 02f06591e..9db6aa293 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 ab8a648a9..64557aaf1 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); } @@ -1277,10 +1280,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/dix/getevents.c b/dix/getevents.c index 45243df5c..c42971592 100644 --- a/dix/getevents.c +++ b/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"), @@ -603,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; } @@ -1170,6 +1173,95 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, return num_events; } +/** + * 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 @@ -1193,7 +1285,12 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, int buttons, int flags, const ValuatorMask *mask_in) { CARD32 ms = GetTimeInMillis(); - int num_events = 0; + 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) @@ -1204,8 +1301,73 @@ GetPointerEvents(InternalEvent *events, DeviceIntPtr pDev, int type, events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events); - num_events += fill_pointer_events(events, pDev, type, buttons, ms, flags, - mask_in); + + 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; } diff --git a/include/exevents.h b/include/exevents.h index 731f31eac..4fe6c61a9 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 c25f5c670..9d4108ef5 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -74,6 +74,16 @@ extern _X_EXPORT int CountBits(const uint8_t *mask, int len); #define XI2LASTEVENT 17 /* XI_RawMotion */ #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 { @@ -283,6 +300,8 @@ typedef struct _ValuatorClassRec { unsigned short numAxes; double *axisVal; /* always absolute, but device-coord system */ ValuatorAccelerationRec accelScheme; + int h_scroll_axis; /* horiz smooth-scrolling axis */ + int v_scroll_axis; /* vert smooth-scrolling axis */ } ValuatorClassRec; typedef struct _ButtonClassRec { @@ -524,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 2501d59b7..afc4d4d99 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); + + /* can add another non-preffered axis */ + assert(SetScrollValuator(&dev, 1, SCROLL_TYPE_VERTICAL, 5.0, SCROLL_FLAG_NONE) == TRUE); + assert(SetScrollValuator(&dev, 0, SCROLL_TYPE_HORIZONTAL, 5.0, SCROLL_FLAG_NONE) == TRUE); + + /* 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 423453358..56d6bd268 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 #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 47eb5b14c..63d725f28 100644 --- a/test/xi2/protocol-xiquerydevice.c +++ b/test/xi2/protocol-xiquerydevice.c @@ -127,7 +127,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; @@ -183,11 +183,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); + swaps(&si->scroll_type); + swapl(&si->increment.integral); + swapl(&si->increment.frac); + } + 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) { @@ -217,8 +254,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. */