1 /*
2  *  Copyright (C) 2012-2018 Team Kodi
3  *  This file is part of Kodi - https://kodi.tv
4  *
5  *  SPDX-License-Identifier: GPL-2.0-or-later
6  *  See LICENSES/README.md for more information.
7  */
8 
9 #include "AndroidMouse.h"
10 
11 #include "AndroidExtra.h"
12 #include "AppInboundProtocol.h"
13 #include "ServiceBroker.h"
14 #include "XBMCApp.h"
15 #include "guilib/GUIWindowManager.h"
16 #include "input/mouse/MouseStat.h"
17 #include "windowing/android/WinSystemAndroid.h"
18 
19 //#define DEBUG_VERBOSE
20 
onMouseEvent(AInputEvent * event)21 bool CAndroidMouse::onMouseEvent(AInputEvent* event)
22 {
23   if (event == NULL)
24     return false;
25 
26   int32_t eventAction = AMotionEvent_getAction(event);
27   int8_t mouseAction = eventAction & AMOTION_EVENT_ACTION_MASK;
28   size_t mousePointerIdx = eventAction >> AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
29 
30 #ifdef DEBUG_VERBOSE
31   int32_t mousePointerId = AMotionEvent_getPointerId(event, mousePointerIdx);
32   CXBMCApp::android_printf("%s idx:%i, id:%i", __PRETTY_FUNCTION__, mousePointerIdx, mousePointerId);
33 #endif
34   float x = AMotionEvent_getX(event, mousePointerIdx);
35   float y = AMotionEvent_getY(event, mousePointerIdx);
36 
37   switch (mouseAction)
38   {
39     case AMOTION_EVENT_ACTION_UP:
40     case AMOTION_EVENT_ACTION_DOWN:
41       MouseButton(x,y,mouseAction,AMotionEvent_getButtonState(event));
42       return true;
43     case AMOTION_EVENT_ACTION_SCROLL:
44       MouseWheel(x, y, AMotionEvent_getAxisValue(event, AMOTION_EVENT_AXIS_VSCROLL, mousePointerIdx));
45       return true;
46     default:
47       MouseMove(x,y);
48       return true;
49   }
50   return false;
51 }
52 
MouseMove(float x,float y)53 void CAndroidMouse::MouseMove(float x, float y)
54 {
55 #ifdef DEBUG_VERBOSE
56   CXBMCApp::android_printf("%s: x:%f, y:%f", __PRETTY_FUNCTION__, x, y);
57 #endif
58   XBMC_Event newEvent;
59 
60   memset(&newEvent, 0, sizeof(newEvent));
61 
62   newEvent.type = XBMC_MOUSEMOTION;
63   newEvent.motion.x = x;
64   newEvent.motion.y = y;
65   std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
66   if (appPort)
67     appPort->OnEvent(newEvent);
68 }
69 
MouseButton(float x,float y,int32_t action,int32_t buttons)70 void CAndroidMouse::MouseButton(float x, float y, int32_t action, int32_t buttons)
71 {
72 #ifdef DEBUG_VERBOSE
73   CXBMCApp::android_printf("%s: x:%f, y:%f, action:%i, buttons:%i", __PRETTY_FUNCTION__, x, y, action, buttons);
74 #endif
75   XBMC_Event newEvent;
76 
77   memset(&newEvent, 0, sizeof(newEvent));
78 
79   int32_t checkButtons = buttons;
80   if (action ==  AMOTION_EVENT_ACTION_UP)
81     checkButtons = m_lastButtonState;
82 
83   newEvent.type = (action ==  AMOTION_EVENT_ACTION_DOWN) ? XBMC_MOUSEBUTTONDOWN : XBMC_MOUSEBUTTONUP;
84   newEvent.button.x = x;
85   newEvent.button.y = y;
86   if (checkButtons & AMOTION_EVENT_BUTTON_PRIMARY)
87     newEvent.button.button = XBMC_BUTTON_LEFT;
88   else if (checkButtons & AMOTION_EVENT_BUTTON_SECONDARY)
89     newEvent.button.button = XBMC_BUTTON_RIGHT;
90   else if (checkButtons & AMOTION_EVENT_BUTTON_TERTIARY)
91     newEvent.button.button = XBMC_BUTTON_MIDDLE;
92 
93   std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
94   if (appPort)
95     appPort->OnEvent(newEvent);
96 
97   m_lastButtonState = buttons;
98 }
99 
MouseWheel(float x,float y,float value)100 void CAndroidMouse::MouseWheel(float x, float y, float value)
101 {
102 #ifdef DEBUG_VERBOSE
103   CXBMCApp::android_printf("%s: val:%f", __PRETTY_FUNCTION__, value);
104 #endif
105   XBMC_Event newEvent;
106 
107   memset(&newEvent, 0, sizeof(newEvent));
108 
109   if (value > 0.0f)
110   {
111     newEvent.type = XBMC_MOUSEBUTTONDOWN;
112     newEvent.button.button = XBMC_BUTTON_WHEELUP;
113   }
114   else if (value < 0.0f)
115   {
116     newEvent.type = XBMC_MOUSEBUTTONDOWN;
117     newEvent.button.button = XBMC_BUTTON_WHEELDOWN;
118   }
119   else
120     return;
121 
122   newEvent.button.x = x;
123   newEvent.button.y = y;
124 
125   std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
126   if (appPort)
127     appPort->OnEvent(newEvent);
128 
129   newEvent.type = XBMC_MOUSEBUTTONUP;
130 
131   dynamic_cast<CWinSystemAndroid*>(CServiceBroker::GetWinSystem())->MessagePush(&newEvent);
132 }
133