2.4G无线遥控器鼠标解决办法
来源:互联网 发布:考研作息知乎 编辑:程序博客网 时间:2024/04/27 22:41
接上次讨论的2.4G input校验有问题, frameworks里没有加入对鼠标事件的支持。
1.在EventHub.h文件里:
enum {
/* The input device is a keyboard. */
INPUT_DEVICE_CLASS_KEYBOARD = 0x00000001,
/* The input device is an alpha-numeric keyboard (not just a dial pad). */
INPUT_DEVICE_CLASS_ALPHAKEY = 0x00000002,
/* The input device is a touchscreen (either single-touch or multi-touch). */
INPUT_DEVICE_CLASS_TOUCHSCREEN = 0x00000004,
/* The input device is a trackball. */
INPUT_DEVICE_CLASS_TRACKBALL = 0x00000008,
/* The input device is a multi-touch touchscreen. */
INPUT_DEVICE_CLASS_TOUCHSCREEN_MT= 0x00000010,
/* The input device is a directional pad (implies keyboard, has DPAD keys). */
INPUT_DEVICE_CLASS_DPAD = 0x00000020,
/* The input device is a gamepad (implies keyboard, has BUTTON keys). */
INPUT_DEVICE_CLASS_GAMEPAD = 0x00000040,
/* The input device has switches. */
INPUT_DEVICE_CLASS_SWITCH = 0x00000080,
/* The input device is a mouse. */
INPUT_DEVICE_CLASS_MOUSE = 0x00000100, //加入这行
};
2.在InputReader.h
增加MouseInputMapper类声明
class MouseInputMapper : public InputMapper {
public:
MouseInputMapper(InputDevice* device, int32_t associatedDisplayId);
virtual uint32_t getSources();
virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
virtual void dump(String8& dump);
virtual void reset();
virtual void process(const RawEvent* rawEvent);
virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
private:
Mutex mLock;
int32_t mAssociatedDisplayId;
struct Accumulator {
enum {
FIELD_BTN_LEFT = 1,
FIELD_REL_X = 2,
FIELD_REL_Y = 4,
FIELD_BTN_RIGHT = 8,
FIELD_BTN_MIDDLE = 16,
FIELD_BTN_SIDE = 32,
FIELD_BTN_EXTRA = 64,
FIELD_BTN_FORWARD = 128,
FIELD_BTN_BACK = 256,
FIELD_REL_WHEEL = 512,
};
uint32_t fields;
bool btnLeft;
bool btnRight;
bool btnMiddle;
bool btnSide;
bool btnExtra;
bool btnForward;
bool btnBack;
bool btnScrollUp;
bool btnScrollDown;
int32_t relX;
int32_t relY;
int32_t absX;
int32_t absY;
inline void clear() {
fields = 0;
}
} mAccumulator;
struct LockedState {
bool down;
nsecs_t downTime;
} mLocked;
struct Keyevent {
bool down;
int keycode;
};
void initializeLocked();
void sync(nsecs_t when);
void sendKey();
};
3.EventHub.cpp
// See if this is a trackball (or mouse).
if (test_bit(BTN_MOUSE, key_bitmask)) {
uint8_t rel_bitmask[sizeof_bit_array(REL_MAX + 1)];
memset(rel_bitmask, 0, sizeof(rel_bitmask));
LOGV("Getting relative controllers...");
if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(rel_bitmask)), rel_bitmask) >= 0) {
if (test_bit(REL_X, rel_bitmask) && test_bit(REL_Y, rel_bitmask)) {
device->classes |= (test_bit(BTN_LEFT, key_bitmask) && test_bit(BTN_RIGHT, key_bitmask)) ?
INPUT_DEVICE_CLASS_MOUSE : INPUT_DEVICE_CLASS_TRACKBALL;//增加这行
}
}
}
4.InputDispatcher.cpp
bool isTouchEvent = ! ((entry->source & AINPUT_SOURCE_TOUCHSCREEN) ^ AINPUT_SOURCE_TOUCHSCREEN);
bool isMouseEvent = ! ((entry->source & AINPUT_SOURCE_MOUSE) ^ AINPUT_SOURCE_MOUSE);
bool isDownEvent = (entry->action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_DOWN;
// Identify targets.
if (! mCurrentInputTargetsValid) {
int32_t injectionResult;
if (isTouchEvent || (isMouseEvent && (isDownEvent || mTouchState.down))) {
// Touch-like event. (eg. touchscreen or mouse drag-n-drop )
injectionResult = findTouchedWindowTargetsLocked(currentTime,
entry, nextWakeupTime);
} else {
// Non touch event. (eg. trackball or mouse simple move)
injectionResult = findFocusedWindowTargetsLocked(currentTime,
entry, nextWakeupTime);
}
if (injectionResult == INPUT_EVENT_INJECTION_PENDING) {
return false;
}
setInjectionResultLocked(entry, injectionResult);
if (injectionResult != INPUT_EVENT_INJECTION_SUCCEEDED) {
return true;
}
addMonitoringTargetsLocked();
commitTargetsLocked();
}
5.InputReader.cpp
1).InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
InputDevice* device = new InputDevice(this, deviceId, name);
const int32_t associatedDisplayId = 0; // FIXME: hardcoded for current single-display devices
// Switch-like devices.
if (classes & INPUT_DEVICE_CLASS_SWITCH) {
device->addMapper(new SwitchInputMapper(device));
}
// Keyboard-like devices.
uint32_t keyboardSources = 0;
int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
keyboardSources |= AINPUT_SOURCE_KEYBOARD;
}
if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
}
if (classes & INPUT_DEVICE_CLASS_DPAD) {
keyboardSources |= AINPUT_SOURCE_DPAD;
}
if (keyboardSources != 0) {
device->addMapper(new KeyboardInputMapper(device,
associatedDisplayId, keyboardSources, keyboardType));
}
// Trackball-like devices.
if (classes & INPUT_DEVICE_CLASS_TRACKBALL) {
device->addMapper(new TrackballInputMapper(device, associatedDisplayId));
}
// Touchscreen-like devices.
if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT) {
device->addMapper(new MultiTouchInputMapper(device, associatedDisplayId));
} else if (classes & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
device->addMapper(new SingleTouchInputMapper(device, associatedDisplayId));
}
// Mouse-like devices.
if (classes & INPUT_DEVICE_CLASS_MOUSE) {
device->addMapper(new MouseInputMapper(device, associatedDisplayId));
}
return device;
}
2).
//加入鼠标操作函数
// --- MouseInputMapper ---
MouseInputMapper::MouseInputMapper(InputDevice* device, int32_t associatedDisplayId) :
InputMapper(device), mAssociatedDisplayId(associatedDisplayId) {
initializeLocked();
}
uint32_t MouseInputMapper::getSources() {
return AINPUT_SOURCE_MOUSE;
}
void MouseInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
InputMapper::populateDeviceInfo(info);
}
void MouseInputMapper::dump(String8& dump) {
AutoMutex _l(mLock);
dump.append(INDENT2 "Mouse Input Mapper:\n");
dump.appendFormat(INDENT3 "AssociatedDisplayId: %d\n", mAssociatedDisplayId);
dump.appendFormat(INDENT3 "Down: %s\n", toString(mLocked.down));
dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
}
void MouseInputMapper::reset() {
for (;;) {
{ // acquire lock
AutoMutex _l(mLock);
if (! mLocked.down) {
initializeLocked();
break; // done
}
} // release lock
// Synthesize trackball button up event on reset.
nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
mAccumulator.fields = Accumulator::FIELD_BTN_LEFT;
mAccumulator.btnLeft = false;
mAccumulator.btnScrollUp = false;
mAccumulator.btnScrollDown = false;
sync(when);
}
InputMapper::reset();
}
void MouseInputMapper::process(const RawEvent* rawEvent) {
switch (rawEvent->type) {
case EV_KEY:
switch (rawEvent->scanCode) {
case BTN_LEFT:
mAccumulator.fields |= Accumulator::FIELD_BTN_LEFT;
mAccumulator.btnLeft = rawEvent->value;
break;
case BTN_RIGHT:
mAccumulator.fields |= Accumulator::FIELD_BTN_RIGHT;
mAccumulator.btnRight = rawEvent->value;
break;
case BTN_MIDDLE:
mAccumulator.fields |= Accumulator::FIELD_BTN_MIDDLE;
mAccumulator.btnMiddle = rawEvent->value;
break;
case BTN_SIDE:
mAccumulator.fields |= Accumulator::FIELD_BTN_SIDE;
mAccumulator.btnSide = rawEvent->value;
break;
case BTN_EXTRA:
mAccumulator.fields |= Accumulator::FIELD_BTN_EXTRA;
mAccumulator.btnExtra = rawEvent->value;
break;
case BTN_FORWARD:
mAccumulator.fields |= Accumulator::FIELD_BTN_FORWARD;
mAccumulator.btnForward = rawEvent->value;
break;
case BTN_BACK:
mAccumulator.fields |= Accumulator::FIELD_BTN_BACK;
mAccumulator.btnBack = rawEvent->value;
break;
}
sync(rawEvent->when);
break;
case EV_REL:
switch (rawEvent->scanCode) {
case REL_X:
mAccumulator.fields |= Accumulator::FIELD_REL_X;
mAccumulator.relX = rawEvent->value;
break;
case REL_Y:
mAccumulator.fields |= Accumulator::FIELD_REL_Y;
mAccumulator.relY = rawEvent->value;
break;
case REL_WHEEL:
mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
mAccumulator.btnScrollUp = (rawEvent->value == 1);
mAccumulator.btnScrollDown = (rawEvent->value == -1);
break;
}
break;
case EV_SYN:
switch (rawEvent->scanCode) {
case SYN_REPORT:
sync(rawEvent->when);
break;
}
break;
}
}
int32_t MouseInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
return (scanCode >= BTN_LEFT && scanCode < BTN_JOYSTICK) ?
getEventHub()->getScanCodeState(getDeviceId(), scanCode) : AKEY_STATE_UNKNOWN;
}
void MouseInputMapper::initializeLocked() {
mAccumulator.clear();
mLocked.down = false;
mLocked.downTime = 0;
int32_t screenWidth;
int32_t screenHeight;
if (mAssociatedDisplayId < 0 || ! getPolicy()->getDisplayInfo(mAssociatedDisplayId, &screenWidth, &screenHeight, NULL)) {
mAccumulator.absX = 0;
mAccumulator.absY = 0;
} else {
mAccumulator.absX = screenWidth / 2;
mAccumulator.absY = screenHeight / 2;
}
}
void MouseInputMapper::sync(nsecs_t when) {
uint32_t fields = mAccumulator.fields;
if (fields == 0) {
return; // no new state changes, so nothing to do
}
int motionEventAction;
PointerCoords pointerCoords;
Vector<Keyevent> events;
nsecs_t downTime;
{ // acquire lock
AutoMutex _l(mLock);
if (fields & Accumulator::FIELD_BTN_LEFT) {
if ((mLocked.down = mAccumulator.btnLeft)) {
mLocked.downTime = when;
motionEventAction = AMOTION_EVENT_ACTION_DOWN;
} else {
motionEventAction = AMOTION_EVENT_ACTION_UP;
}
} else {
motionEventAction = AMOTION_EVENT_ACTION_MOVE;
}
Keyevent kevent;
if (fields & Accumulator::FIELD_BTN_RIGHT) {
kevent.down = mAccumulator.btnRight;
kevent.keycode = mLocked.down ? AKEYCODE_HOME : AKEYCODE_BACK;
events.push(kevent);
}
if (fields & Accumulator::FIELD_BTN_MIDDLE) {
kevent.down = mAccumulator.btnMiddle;
kevent.keycode = mLocked.down ? AKEYCODE_ENTER : AKEYCODE_MENU;
events.push(kevent);
}
if (fields & Accumulator::FIELD_BTN_SIDE) {
kevent.down = mAccumulator.btnSide;
kevent.keycode = mLocked.down ? AKEYCODE_DPAD_RIGHT : AKEYCODE_HOME;
events.push(kevent);
}
if (fields & Accumulator::FIELD_BTN_EXTRA) {
kevent.down = mAccumulator.btnExtra;
kevent.keycode = mLocked.down ? AKEYCODE_DPAD_LEFT : AKEYCODE_ENTER;
events.push(kevent);
}
if (fields & Accumulator::FIELD_BTN_FORWARD) {
kevent.down = mAccumulator.btnForward;
kevent.keycode = AKEYCODE_DPAD_RIGHT;
events.push(kevent);
}
if (fields & Accumulator::FIELD_BTN_BACK) {
kevent.down = mAccumulator.btnBack;
kevent.keycode = AKEYCODE_DPAD_LEFT;
events.push(kevent);
}
if (fields & Accumulator::FIELD_REL_WHEEL) {
if (mAccumulator.btnScrollUp) {
kevent.keycode = mLocked.down ? AKEYCODE_MEDIA_NEXT : AKEYCODE_DPAD_UP;
kevent.down = true;
events.push(kevent);
kevent.down = false;
events.push(kevent);
} else if (mAccumulator.btnScrollDown) {
kevent.keycode = mLocked.down ? AKEYCODE_MEDIA_PREVIOUS : AKEYCODE_DPAD_DOWN;
kevent.down = true;
events.push(kevent);
kevent.down = false;
events.push(kevent);
}
}
downTime = mLocked.downTime;
float x = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX : 0.0f;
float y = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY : 0.0f;
int32_t screenWidth;
int32_t screenHeight;
int32_t orientation;
if (mAssociatedDisplayId < 0 || ! getPolicy()->getDisplayInfo(mAssociatedDisplayId, &screenWidth, &screenHeight, &orientation)) {
return;
}
float temp;
if ((orientation == InputReaderPolicyInterface::ROTATION_90) ||
(orientation == InputReaderPolicyInterface::ROTATION_270)) {
temp = screenHeight;
screenHeight = screenWidth;
screenWidth = temp;
}
mAccumulator.absX = (mAccumulator.absX + x) > screenWidth ? screenWidth - 1 : ((mAccumulator.absX + x) < 0 ? 0 : mAccumulator.absX + x);
mAccumulator.absY = (mAccumulator.absY + y) > screenHeight ? screenHeight - 1 : ((mAccumulator.absY + y) < 0 ? 0 : mAccumulator.absY + y);
pointerCoords.x = mAccumulator.absX;
pointerCoords.y = mAccumulator.absY;
pointerCoords.pressure = mLocked.down ? 1.0f : 0.0f;
pointerCoords.size = 0;
pointerCoords.touchMajor = 0;
pointerCoords.touchMinor = 0;
pointerCoords.toolMajor = 0;
pointerCoords.toolMinor = 0;
pointerCoords.orientation = 0;
} // release lock
int32_t metaState = mContext->getGlobalMetaState();
for (size_t i = 0; i < events.size(); ++i) {
getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_DPAD, 0,
events[i].down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
AKEY_EVENT_FLAG_FROM_SYSTEM, events[i].keycode, 0,
metaState, when);
}
int32_t pointerId = 0;
getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_MOUSE, 0,
motionEventAction, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1, &pointerId, &pointerCoords, 1, 1, downTime);
mAccumulator.clear();
}
6.WindowManagerService.java
1).导入其他包的类
import com.android.internal.view.BaseInputHandler;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.InputHandler;
import android.view.InputQueue;
2).
ublic class WindowManagerService extends IWindowManager.Stub
implements Watchdog.Monitor {
....
// Mouse pointer handling
Handler mHandler = new Handler();
Surface mPointerSurface;
boolean mPointerVisible;
int mPointerX;
int mPointerY;
InputChannel mPointerInputChannel;
final InputHandler mPointerInputHandler = new BaseInputHandler() {
@Override
public void handleMotion(MotionEvent event, Runnable finishedCallback) {
finishedCallback.run();
boolean isMouse = ((event.getSource() & InputDevice.SOURCE_MOUSE) ^ InputDevice.SOURCE_MOUSE) == 0;
if (isMouse) {
mPointerX = (int) event.getRawX();
mPointerY = (int) event.getRawY();
showPointer();
} else if (mPointerVisible) {
hidePointer();
}
}
};
...
}
3).
private WindowManagerService(Context context, PowerManagerService pm,
boolean haveInputMethods) {
.....
mInputManager.start();
startMouseMonitor();//启动监听
.....
}
4).show鼠标的指针
private final void performLayoutAndPlaceSurfacesLockedInner(
boolean recoveringMemory) {
....
// Draw the mouse cursor, if necessary
if (mPointerSurface != null) {
if (mPointerVisible) {
WindowState top = (WindowState)mWindows.get(mWindows.size() - 1);
mPointerSurface.setPosition(mPointerX, mPointerY);
mPointerSurface.setLayer(top.mAnimLayer + 1);
mPointerSurface.show();
} else {
mPointerSurface.hide();
}
}
...
}
- 2.4G无线遥控器鼠标解决办法
- 2.4G无线遥控器调试问题
- 2.4G无线鼠标 PK 蓝牙鼠标
- 手机无线遥控器,让手机变成无线鼠标+无线键盘!
- 无线遥控器解码程式
- 笔记本电脑无线鼠标和触控板冲突解决办法
- 2.4G无线
- NRF51822 2.4G无线
- 遥控器鼠标按键流程
- 无线2.4G/5.8G国家信道
- 2.4g无线射频芯片
- 无线鼠标、键盘换上新电池不能用的解决办法
- 无线鼠标
- 2.4G无线模块/无线通讯/无线收发/nRF24L01
- 无线技术知识 2.4G与其他无线技术对比
- 2.4G无线wlan一些计算公式
- 谁来帮我设计2.4G无线产品
- 2.4g无线跳频(一)
- Extjs学习笔记4-propertyGrid
- mysql 添加用户和授权
- hdu1421n中选k个不相邻数的最小值
- inner join 和 left join
- 自行控制loadrunner的socket协议性能测试
- 2.4G无线遥控器鼠标解决办法
- 利用lipo编译合并iPhone模拟器和真机通用的静态类
- Android网络编程—同时上传参数和文件到服务器
- 同为问答网站 Quora能否成为盈利版维基百科
- 第13周任务2.2
- SQL语句修改字段属性
- JNDI全攻略
- 修改Tomcat默认编码
- 网站页面性能优化的34条黄金守则--雅虎团队经验分享