TV遥控器模拟鼠标键

需求 : tv上部分app不支持光标选中,如亚马逊,插上鼠标不方便,即可以用遥控器模拟鼠标滚动和点击

1.拦截上下左右键

在WMS::PhoneWindowManager::interceptKeyBeforeQueueing中监听上下左右左右键,进行拦截。

@Override
    public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
    //是否开启鼠标模式
    String mstate = SystemProperties.get("sys.KeyMouse.mKeyMouseState");
    //是否开启鼠标滚轮模式
	String mMode = SystemProperties.get("sys.mouse.mousemode1");
    if (mstate.equals("on") && ((keyCode == KeyEvent.KEYCODE_DPAD_LEFT)
                || (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT)
                || (keyCode == KeyEvent.KEYCODE_DPAD_UP)
                || (keyCode == KeyEvent.KEYCODE_DPAD_DOWN))) {
                
		if(down){
			if (mMode.equals("false")) {
				try{
				// 显示鼠标键
                    mWindowManager.dispatchMouse(0,0);
                    }catch(Exception e){}
				} else {
					Message msg = new Message();
      			    msg.what = keyCode;
      			    Bundle bundle = new Bundle();
      			    bundle.putInt("repeatCount", repeatCount);
      			    msg.setData(bundle);
            	    mKeyMouseHandler.sendMessage(msg);
				}
			}
			return -1;
        }
}

public Handler mKeyMouseHandler = new Handler(){
        public void handleMessage(Message msg){
		  Bundle bundle = msg.getData();
    	  int repeatNum = bundle.getInt("repeatCount");
          switch(msg.what){
                case KeyEvent.KEYCODE_DPAD_LEFT:
					if(repeatNum>0){
						//移动的距离
						mdeltax=-16.0f;mdeltay=0;
					}else{
                    	mdeltax=-8.0f;mdeltay=0;
					}
                    break;
                case KeyEvent.KEYCODE_DPAD_RIGHT:
                	//移动的距离
					if(repeatNum>0){
						mdeltax=16.0f;mdeltay=0;
					}else{
                    	mdeltax=8.0f;mdeltay=0;
					}
                    break;
                case KeyEvent.KEYCODE_DPAD_UP:
                	//移动的距离
					if(repeatNum>0){
						mdeltax=0;mdeltay=-16.0f;
					}else{
                    	mdeltax=0;mdeltay=-8.0f;
					}
                    break;
                case KeyEvent.KEYCODE_DPAD_DOWN:
                	//移动的距离
					if(repeatNum>0){
						mdeltax=0;mdeltay=16.0f;
					}else{
                    	mdeltax=0;mdeltay=8.0f;
					}
                    break;
                case KeyEvent.KEYCODE_MOUSE_SWITCH:
                	//位置不变,重新显示
                    mdeltax=0;mdeltay=0;
                    break;    
                }
           try{
               mWindowManager.dispatchMouse(mdeltax,mdeltay);
                }catch(Exception e){}
       }
     };



2.调整鼠标滚动逻辑

如果只需要鼠标上下移动,上述修改即可,鼠标移动到屏幕周围会自动切为滚动模式,但是如果部分app上下有部分导航栏,即需要主动将鼠标切为滚轮模式。

修改位置 frameworks/native/services/inputflinger/InputReader.cpp

void KeyMouseInputMapper::sync(nsecs_t when) {
     int32_t lastButtonState = mButtonState;
      int32_t currentButtonState = mCursorButtonAccumulator.getButtonState();
     mButtonState = currentButtonState;
 
     char *mKeyLock=new char[PROPERTY_VALUE_MAX];
     memset(mKeyLock,0,5);
      property_get("sys.KeyMouse.mKeyMouseState",mKeyLock,"off");
  		char *mousemode=new char[PROPERTY_VALUE_MAX];
      memset(mousemode,0,5);
     property_get("sys.mouse.mousemode1",mousemode,"true");
  
      bool scrolled = 0;
 	float vscroll,hscroll;
    	int32_t keystate = AKEY_STATE_UNKNOWN;
     bool wasDown = isPointerDown(lastButtonState);
      bool down = isPointerDown(currentButtonState);
  	keystate = getScanCodeState(AINPUT_SOURCE_MOUSE,scrollkey);
      bool downChanged;
      if (!wasDown && down) {
         mDownTime = when;
          downChanged = true;
      } else if (wasDown && !down) {
          downChanged = true;
      } else {
         downChanged = false;
      }
      nsecs_t downTime = mDownTime;
      //int32_t buttonsPressed=0;
      //int32_t buttonsReleased=0;
  	int32_t buttonsPressed = currentButtonState & ~lastButtonState;
      int32_t buttonsReleased = lastButtonState & ~currentButtonState;
     if(strcmp(mKeyLock,"off")==0)  return;
  
      PointerProperties pointerProperties;
     pointerProperties.clear();
      pointerProperties.id = 0;
      pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
  
     PointerCoords pointerCoords;
      pointerCoords.clear();
  
    	int32_t displayId;
     if (mPointerController != NULL) {
          float x, y;
  	   	float minX, minY, maxX, maxY;
         mPointerController->getPosition(&x, &y);
          pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
         pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
  
         displayId = ADISPLAY_ID_DEFAULT;
         
  		//滚动模式后,判断上下左右键即滚动
  		if(strcmp(mousemode,"false")==0) {
  			if(scrollkey == KEY_LEFT)
  			{
  				scrolled = 1;
  				vscroll = 0;
  				hscroll = -3.0f;
  				if(keystate==AKEY_STATE_DOWN)
  					buttonsPressed = 1;
 				else
 					buttonsReleased = 1;
 			}
			else if(scrollkey == KEY_UP)
 			{
  				scrolled = 1;
  				vscroll = 3.0f;
  				hscroll = 0;
  			}
  			else if(scrollkey == KEY_RIGHT)
  			{
  				scrolled = 1;
 				vscroll = 0;
  				hscroll = 3.0f;
  				if(keystate==AKEY_STATE_DOWN)
  					buttonsPressed = 1;
  				else
  					buttonsReleased = 1;
 			}
  			else if(scrollkey == KEY_DOWN)
  			{
  				scrolled = 1;
  				vscroll = -3.0f;
  				hscroll = 0;
  			}
          }else{
  			if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
 				if((x<=minX)&&(scrollkey == KEY_LEFT))
  				{
  					scrolled = 1;
  					vscroll = 0;
  					hscroll = -3.0f;
  					if(keystate==AKEY_STATE_DOWN)
  						buttonsPressed = 1;
  					else
  						buttonsReleased = 1;
  				}
 				else if((y<=minY)&&(scrollkey == KEY_UP))
 				{
  					scrolled = 1;
  					vscroll = 3.0f;
  					hscroll = 0;
  				}
 				else if((x>=maxX)&&(scrollkey == KEY_RIGHT))
  				{
 					scrolled = 1;
  					vscroll = 0;
 					hscroll = 3.0f;
  					if(keystate==AKEY_STATE_DOWN)
  						buttonsPressed = 1;
  					else
  						buttonsReleased = 1;
  				}
  				else if((y>=maxY)&&(scrollkey == KEY_DOWN))
  				{
  					scrolled = 1;
  					vscroll = -3.0f;
  					hscroll = 0;
  				}
 			}
  		}
      }
  
      uint32_t policyFlags = 0;
      if ((buttonsPressed || scrolled) && getDevice()->isExternal()) {
          policyFlags |= POLICY_FLAG_WAKE;
      }
      mSource = AINPUT_SOURCE_MOUSE;
  
      // Send motion event.
      if (downChanged || scrolled) {
          int32_t metaState = mContext->getGlobalMetaState();
          int32_t buttonState = lastButtonState;
          int32_t motionEventAction;
          if (downChanged) {
              motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
          } else  {
              motionEventAction = AMOTION_EVENT_ACTION_MOVE;
          }
  
  		if (buttonsReleased) {
              BitSet32 released(buttonsReleased);
              while (!released.isEmpty()) {
                 int32_t actionButton = BitSet32::valueForBit(released.clearFirstMarkedBit());
                 buttonState &= ~actionButton;
                  NotifyMotionArgs releaseArgs(when, getDeviceId(), mSource, policyFlags,
                          AMOTION_EVENT_ACTION_BUTTON_RELEASE, actionButton, 0,
                          metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                          displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                         1, 1, downTime);
                  getListener()->notifyMotion(&releaseArgs);
  				buttonsReleased = 0;
             }
          }
  
          NotifyMotionArgs args(when, getDeviceId(), mSource, policyFlags,
                  motionEventAction, 0, 0,
                 metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                 displayId, 0, 1, &pointerProperties, &pointerCoords, 1, 1, downTime);
          getListener()->notifyMotion(&args);
  
  		 if (buttonsPressed) {
              BitSet32 pressed(buttonsPressed);
              while (!pressed.isEmpty()) {
                  int32_t actionButton = BitSet32::valueForBit(pressed.clearFirstMarkedBit());
                  buttonState |= actionButton;
                  NotifyMotionArgs pressArgs(when, getDeviceId(), mSource, policyFlags,
                         AMOTION_EVENT_ACTION_BUTTON_PRESS, actionButton, 0,
                         metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
                          displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
                          1, 1, downTime);
                  getListener()->notifyMotion(&pressArgs);
 				buttonsPressed = 0;
              }
          }
      }
  	if ((scrolled)&&(keystate==AKEY_STATE_DOWN)) {
  		pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
  		pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
          int32_t metaState = mContext->getGlobalMetaState();
  		NotifyMotionArgs scrollArgs(when, getDeviceId(), mSource, policyFlags,
  				AMOTION_EVENT_ACTION_SCROLL, 0, 0, metaState, currentButtonState,
  				AMOTION_EVENT_EDGE_FLAG_NONE,
  				displayId, /* deviceTimestamp */ 0, 1, &pointerProperties, &pointerCoords,
  				1, 1, downTime);
  		getListener()->notifyMotion(&scrollArgs);
  
      }
  
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值