Android9鼠标双屏控制实现

时间:2024-03-30 08:32:27

Android9鼠标双屏控制实现

首先上一张思维导图来简单梳理一下鼠标事件的上报,以及native层和java层的关联,以及InputManagerService和WindowManagerService的关联以及互调。

其实最初的关联是在SystemServer启动的时候实现,在实例化wm的时候将IMS传入如下代码:

wm = WindowManagerService.main(context, inputManager,
mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
!mFirstBoot, mOnlyCore, new PhoneWindowManager());

并且IMS将wm中的InputMonitor作为回调传入,代码如下:

  inputManager.setWindowManagerCallbacks(wm.getInputMonitor());

通过回调我们可以从native层获取到java层的一些信息。

 

鼠标事件同其他输入事件的流程基本一致,都是从event事件中获取到信息,并通过InputReader.cpp来进行监听,然后处理相关的事件,比如按键,鼠标移动,和

鼠标经过等事件,然后通过dispatch将事件进行分发,再让上层处理。

 

我们实现双屏鼠标的思路是获取到双屏的显示id,然后根据id进行鼠标的绘制,以及事件的分发,其实在Android9已经默认支持副屏事件的鼠标处理,但是显示还不支持,

所以我们工作的重心在于如何在副屏绘制鼠标,已经鼠标动作的控制。

 

实现的方式参考windows的双屏控制,甩鼠标进行左右屏切换,可以通过判断鼠标拖动的力度来实现。

 

关于鼠标事件左右屏切换参考如下代码:


diff --git a/frameworks/native/services/inputflinger/InputReader.cpp b/frameworks/native/services/inputflinger/InputReader.cpp
old mode 100644
new mode 100755
index e0cd8a0..be87e6d
--- a/frameworks/native/services/inputflinger/InputReader.cpp
+++ b/frameworks/native/services/inputflinger/InputReader.cpp
@@ -2786,7 +2786,6 @@ void CursorInputMapper::sync(nsecs_t when) {
int32_t lastButtonState = mButtonState;
int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
mButtonState = currentButtonState;
-
bool wasDown = isPointerDown(lastButtonState);
bool down = isPointerDown(currentButtonState);
bool downChanged;
index e0cd8a0..be87e6d
--- a/frameworks/native/services/inputflinger/InputReader.cpp
+++ b/frameworks/native/services/inputflinger/InputReader.cpp
@@ -2786,7 +2786,6 @@ void CursorInputMapper::sync(nsecs_t when) {
int32_t lastButtonState = mButtonState;
int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
mButtonState = currentButtonState;
-
bool wasDown = isPointerDown(lastButtonState);
bool down = isPointerDown(currentButtonState);
bool downChanged;
@@ -2807,6 +2806,8 @@ void CursorInputMapper::sync(nsecs_t when) {
float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
bool moved = deltaX != 0 || deltaY != 0;

+ ALOGE("liangchao deltaX %f and deltaY %f",deltaX,deltaY);
+
// Rotate delta according to orientation if needed.
if (mParameters.orientationAware && mParameters.hasAssociatedDisplay
&& (deltaX != 0.0f || deltaY != 0.0f)) {
@@ -2832,11 +2833,26 @@ void CursorInputMapper::sync(nsecs_t when) {
mPointerVelocityControl.move(when, &deltaX, &deltaY);

int32_t displayId;
+
if (mSource == AINPUT_SOURCE_MOUSE) {
if (moved || scrolled || buttonsChanged) {
+ if(deltaX < -80.0){
+ pointerToSecond = false;
+ }else if(deltaX > 80.0){
+ pointerToSecond = true;
+ }else {
+ //displayId = ADISPLAY_ID_DEFAULT;
+ }
+ if(pointerToSecond){
+ displayId = getPolicy()->getPointerDisplayIdPolicy();
+ }else{
+ displayId = ADISPLAY_ID_DEFAULT;
+ }
+
+ mPointerController->setPointerDisplayId(displayId);
mPointerController->setPresentation(
PointerControllerInterface::PRESENTATION_POINTER);
-
+
if (moved) {
mPointerController->move(deltaX, deltaY);
}
@@ -2854,7 +2870,7 @@ void CursorInputMapper::sync(nsecs_t when) {
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_X, deltaX);
pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_RELATIVE_Y, deltaY);
- displayId = ADISPLAY_ID_DEFAULT;
+

通过判断鼠标移动的距离来决定鼠标事件的displayId.

 

还有就是鼠标的绘制具体的代码已经做成patch。