inputflinger: Initial support for rotary encoders.
This change introduces support for rotary encoder input devices. We also define a new input source (namely, AINPUT_SOURCE_ROTARY_ENCODER) and a new axis of input (namely, AXIS_SCROLL), since the rotary encoder motion doesn't necessarily tie to a horizontal or vertical scroll motion. A ROTARY_ENCODER input device class is also introduced, corresponding to the new input source. A new input source can be defined as producing rotary encoder motion events, if its corresponding .idc file contains the following declaration: device.type = rotaryEncoder Bug: 18707397 Change-Id: I8ccd540908311d1ff44fdfeba81b691895413641 Signed-off-by: Prashant Malani <pmalani@google.com>
This commit is contained in:
parent
4baa69ddd2
commit
ac72bbf4e4
@ -643,6 +643,13 @@ enum {
|
||||
* against the surface.
|
||||
*/
|
||||
AMOTION_EVENT_AXIS_TILT = 25,
|
||||
/**
|
||||
* Axis constant: Generic scroll axis of a motion event.
|
||||
*
|
||||
* - This is used for scroll axis motion events that can't be classified as strictly
|
||||
* vertical or horizontal. The movement of a rotating scroller is an example of this.
|
||||
*/
|
||||
AMOTION_EVENT_AXIS_SCROLL = 26,
|
||||
/**
|
||||
* Axis constant: Generic 1 axis of a motion event.
|
||||
* The interpretation of a generic axis is device-specific.
|
||||
@ -817,6 +824,8 @@ enum {
|
||||
AINPUT_SOURCE_TOUCH_NAVIGATION = 0x00200000 | AINPUT_SOURCE_CLASS_NONE,
|
||||
/** joystick */
|
||||
AINPUT_SOURCE_JOYSTICK = 0x01000000 | AINPUT_SOURCE_CLASS_JOYSTICK,
|
||||
/** rotary encoder */
|
||||
AINPUT_SOURCE_ROTARY_ENCODER = 0x00400000 | AINPUT_SOURCE_CLASS_NONE,
|
||||
|
||||
/** any */
|
||||
AINPUT_SOURCE_ANY = 0xffffff00,
|
||||
|
@ -1177,6 +1177,15 @@ status_t EventHub::openDeviceLocked(const char *devicePath) {
|
||||
device->classes |= INPUT_DEVICE_CLASS_CURSOR;
|
||||
}
|
||||
|
||||
// See if this is a rotary encoder type device.
|
||||
String8 deviceType = String8();
|
||||
if (device->configuration &&
|
||||
device->configuration->tryGetProperty(String8("device.type"), deviceType)) {
|
||||
if (!deviceType.compare(String8("rotaryEncoder"))) {
|
||||
device->classes |= INPUT_DEVICE_CLASS_ROTARY_ENCODER;
|
||||
}
|
||||
}
|
||||
|
||||
// See if this is a touch pad.
|
||||
// Is this a new modern multi-touch driver?
|
||||
if (test_bit(ABS_MT_POSITION_X, device->absBitmask)
|
||||
|
@ -137,6 +137,9 @@ enum {
|
||||
/* The input device is an external stylus (has data we want to fuse with touch data). */
|
||||
INPUT_DEVICE_CLASS_EXTERNAL_STYLUS = 0x00000800,
|
||||
|
||||
/* The input device has a rotary encoder */
|
||||
INPUT_DEVICE_CLASS_ROTARY_ENCODER = 0x00001000,
|
||||
|
||||
/* The input device is virtual (not a real device, not part of UI configuration). */
|
||||
INPUT_DEVICE_CLASS_VIRTUAL = 0x40000000,
|
||||
|
||||
|
@ -450,6 +450,11 @@ InputDevice* InputReader::createDeviceLocked(int32_t deviceId, int32_t controlle
|
||||
device->addMapper(new SwitchInputMapper(device));
|
||||
}
|
||||
|
||||
// Scroll wheel-like devices.
|
||||
if (classes & INPUT_DEVICE_CLASS_ROTARY_ENCODER) {
|
||||
device->addMapper(new RotaryEncoderInputMapper(device));
|
||||
}
|
||||
|
||||
// Vibrator-like devices.
|
||||
if (classes & INPUT_DEVICE_CLASS_VIBRATOR) {
|
||||
device->addMapper(new VibratorInputMapper(device));
|
||||
@ -2718,6 +2723,92 @@ void CursorInputMapper::fadePointer() {
|
||||
}
|
||||
}
|
||||
|
||||
// --- RotaryEncoderInputMapper ---
|
||||
|
||||
RotaryEncoderInputMapper::RotaryEncoderInputMapper(InputDevice* device) :
|
||||
InputMapper(device) {
|
||||
mSource = AINPUT_SOURCE_ROTARY_ENCODER;
|
||||
}
|
||||
|
||||
RotaryEncoderInputMapper::~RotaryEncoderInputMapper() {
|
||||
}
|
||||
|
||||
uint32_t RotaryEncoderInputMapper::getSources() {
|
||||
return mSource;
|
||||
}
|
||||
|
||||
void RotaryEncoderInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
|
||||
InputMapper::populateDeviceInfo(info);
|
||||
|
||||
if (mRotaryEncoderScrollAccumulator.haveRelativeVWheel()) {
|
||||
info->addMotionRange(AMOTION_EVENT_AXIS_SCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void RotaryEncoderInputMapper::dump(String8& dump) {
|
||||
dump.append(INDENT2 "Rotary Encoder Input Mapper:\n");
|
||||
dump.appendFormat(INDENT3 "HaveWheel: %s\n",
|
||||
toString(mRotaryEncoderScrollAccumulator.haveRelativeVWheel()));
|
||||
}
|
||||
|
||||
void RotaryEncoderInputMapper::configure(nsecs_t when,
|
||||
const InputReaderConfiguration* config, uint32_t changes) {
|
||||
InputMapper::configure(when, config, changes);
|
||||
if (!changes) {
|
||||
mRotaryEncoderScrollAccumulator.configure(getDevice());
|
||||
}
|
||||
}
|
||||
|
||||
void RotaryEncoderInputMapper::reset(nsecs_t when) {
|
||||
mRotaryEncoderScrollAccumulator.reset(getDevice());
|
||||
|
||||
InputMapper::reset(when);
|
||||
}
|
||||
|
||||
void RotaryEncoderInputMapper::process(const RawEvent* rawEvent) {
|
||||
mRotaryEncoderScrollAccumulator.process(rawEvent);
|
||||
|
||||
if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
|
||||
sync(rawEvent->when);
|
||||
}
|
||||
}
|
||||
|
||||
void RotaryEncoderInputMapper::sync(nsecs_t when) {
|
||||
PointerCoords pointerCoords;
|
||||
pointerCoords.clear();
|
||||
|
||||
PointerProperties pointerProperties;
|
||||
pointerProperties.clear();
|
||||
pointerProperties.id = 0;
|
||||
pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
|
||||
|
||||
float scroll = mRotaryEncoderScrollAccumulator.getRelativeVWheel();
|
||||
bool scrolled = scroll != 0;
|
||||
|
||||
// This is not a pointer, so it's not associated with a display.
|
||||
int32_t displayId = ADISPLAY_ID_NONE;
|
||||
|
||||
// Moving the rotary encoder should wake the device (if specified).
|
||||
uint32_t policyFlags = 0;
|
||||
if (scrolled && getDevice()->isExternal()) {
|
||||
policyFlags |= POLICY_FLAG_WAKE;
|
||||
}
|
||||
|
||||
// Send motion event.
|
||||
if (scrolled) {
|
||||
int32_t metaState = mContext->getGlobalMetaState();
|
||||
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_SCROLL, scroll);
|
||||
|
||||
NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
|
||||
AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, 0,
|
||||
AMOTION_EVENT_EDGE_FLAG_NONE,
|
||||
displayId, 1, &pointerProperties, &pointerCoords,
|
||||
0, 0, 0);
|
||||
getListener()->notifyMotion(&scrollArgs);
|
||||
}
|
||||
|
||||
mRotaryEncoderScrollAccumulator.finishSync();
|
||||
}
|
||||
|
||||
// --- TouchInputMapper ---
|
||||
|
||||
|
@ -1232,6 +1232,26 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class RotaryEncoderInputMapper : public InputMapper {
|
||||
public:
|
||||
RotaryEncoderInputMapper(InputDevice* device);
|
||||
virtual ~RotaryEncoderInputMapper();
|
||||
|
||||
virtual uint32_t getSources();
|
||||
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
|
||||
virtual void dump(String8& dump);
|
||||
virtual void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
|
||||
virtual void reset(nsecs_t when);
|
||||
virtual void process(const RawEvent* rawEvent);
|
||||
|
||||
private:
|
||||
CursorScrollAccumulator mRotaryEncoderScrollAccumulator;
|
||||
|
||||
int32_t mSource;
|
||||
|
||||
void sync(nsecs_t when);
|
||||
};
|
||||
|
||||
class TouchInputMapper : public InputMapper {
|
||||
public:
|
||||
TouchInputMapper(InputDevice* device);
|
||||
|
Loading…
Reference in New Issue
Block a user