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 <[email protected]> --- 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 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel
