1 /*
2  *  Copyright (C) 2005-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 "LibInputPointer.h"
10 
11 #include "AppInboundProtocol.h"
12 #include "ServiceBroker.h"
13 #include "input/mouse/MouseStat.h"
14 #include "utils/log.h"
15 #include "windowing/GraphicContext.h"
16 
17 #include <algorithm>
18 #include <string.h>
19 
20 #include <linux/input.h>
21 
ProcessButton(libinput_event_pointer * e)22 void CLibInputPointer::ProcessButton(libinput_event_pointer *e)
23 {
24   const uint32_t b = libinput_event_pointer_get_button(e);
25   const bool pressed = libinput_event_pointer_get_button_state(e) == LIBINPUT_BUTTON_STATE_PRESSED;
26   unsigned char xbmc_button = 0;
27 
28   switch (b)
29   {
30     case BTN_LEFT:
31       xbmc_button = XBMC_BUTTON_LEFT;
32       break;
33     case BTN_RIGHT:
34       xbmc_button = XBMC_BUTTON_RIGHT;
35       break;
36     case BTN_MIDDLE:
37       xbmc_button = XBMC_BUTTON_MIDDLE;
38       break;
39     case BTN_SIDE:
40       xbmc_button = XBMC_BUTTON_X1;
41       break;
42     case BTN_EXTRA:
43       xbmc_button = XBMC_BUTTON_X2;
44        break;
45     case BTN_FORWARD:
46       xbmc_button = XBMC_BUTTON_X3;
47       break;
48     case BTN_BACK:
49       xbmc_button = XBMC_BUTTON_X4;
50       break;
51     default:
52       break;
53   }
54 
55   XBMC_Event event;
56   memset(&event, 0, sizeof(event));
57 
58   event.type = pressed ? XBMC_MOUSEBUTTONDOWN : XBMC_MOUSEBUTTONUP;
59   event.button.button = xbmc_button;
60   event.button.x = static_cast<uint16_t>(m_pos.X);
61   event.button.y = static_cast<uint16_t>(m_pos.Y);
62 
63   CLog::Log(LOGDEBUG, "CLibInputPointer::%s - event.type: %i, event.button.button: %i, event.button.x: %i, event.button.y: %i", __FUNCTION__, event.type, event.button.button, event.button.x, event.button.y);
64 
65   std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
66   if (appPort)
67     appPort->OnEvent(event);
68 }
69 
ProcessMotion(libinput_event_pointer * e)70 void CLibInputPointer::ProcessMotion(libinput_event_pointer *e)
71 {
72   const double dx = libinput_event_pointer_get_dx(e);
73   const double dy = libinput_event_pointer_get_dy(e);
74 
75   m_pos.X += static_cast<int>(dx);
76   m_pos.Y += static_cast<int>(dy);
77 
78   // limit the mouse to the screen width
79   m_pos.X = std::min(CServiceBroker::GetWinSystem()->GetGfxContext().GetWidth(), m_pos.X);
80   m_pos.X = std::max(0, m_pos.X);
81 
82   // limit the mouse to the screen height
83   m_pos.Y = std::min(CServiceBroker::GetWinSystem()->GetGfxContext().GetHeight(), m_pos.Y);
84   m_pos.Y = std::max(0, m_pos.Y);
85 
86   XBMC_Event event;
87   memset(&event, 0, sizeof(event));
88 
89   event.type = XBMC_MOUSEMOTION;
90   event.motion.x = static_cast<uint16_t>(m_pos.X);
91   event.motion.y = static_cast<uint16_t>(m_pos.Y);
92 
93   CLog::Log(LOGDEBUG, "CLibInputPointer::%s - event.type: %i, event.motion.x: %i, event.motion.y: %i", __FUNCTION__, event.type, event.motion.x, event.motion.y);
94 
95   std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
96   if (appPort)
97     appPort->OnEvent(event);
98 }
99 
ProcessMotionAbsolute(libinput_event_pointer * e)100 void CLibInputPointer::ProcessMotionAbsolute(libinput_event_pointer *e)
101 {
102   m_pos.X = static_cast<int>(libinput_event_pointer_get_absolute_x_transformed(e, CServiceBroker::GetWinSystem()->GetGfxContext().GetWidth()));
103   m_pos.Y = static_cast<int>(libinput_event_pointer_get_absolute_y_transformed(e, CServiceBroker::GetWinSystem()->GetGfxContext().GetHeight()));
104 
105   XBMC_Event event;
106   event.type = XBMC_MOUSEMOTION;
107   event.motion.x = static_cast<uint16_t>(m_pos.X);
108   event.motion.y = static_cast<uint16_t>(m_pos.Y);
109 
110   CLog::Log(LOGDEBUG, "CLibInputPointer::%s - event.type: %i, event.motion.x: %i, event.motion.y: %i", __FUNCTION__, event.type, event.motion.x, event.motion.y);
111 
112   std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
113   if (appPort)
114     appPort->OnEvent(event);
115 }
116 
ProcessAxis(libinput_event_pointer * e)117 void CLibInputPointer::ProcessAxis(libinput_event_pointer *e)
118 {
119   unsigned char scroll = 0;
120   if (!libinput_event_pointer_has_axis(e, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL))
121     return;
122 
123   const double v = libinput_event_pointer_get_axis_value(e, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
124   if (v < 0)
125     scroll = XBMC_BUTTON_WHEELUP;
126   else
127     scroll = XBMC_BUTTON_WHEELDOWN;
128 
129   XBMC_Event event;
130   memset(&event, 0, sizeof(event));
131 
132   event.type = XBMC_MOUSEBUTTONDOWN;
133   event.button.button = scroll;
134   event.button.x = static_cast<uint16_t>(m_pos.X);
135   event.button.y = static_cast<uint16_t>(m_pos.Y);
136 
137   CLog::Log(LOGDEBUG, "CLibInputPointer::%s - scroll: %s, event.button.x: %i, event.button.y: %i", __FUNCTION__, scroll == XBMC_BUTTON_WHEELUP ? "up" : "down", event.button.x, event.button.y);
138 
139   std::shared_ptr<CAppInboundProtocol> appPort = CServiceBroker::GetAppPort();
140   if (appPort)
141     appPort->OnEvent(event);
142 
143   event.type = XBMC_MOUSEBUTTONUP;
144 
145   if (appPort)
146     appPort->OnEvent(event);
147 }
148