1 /*
2 * Copyright (C) 2017-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 "InputProcessorPointer.h"
10
11 #include "input/mouse/MouseStat.h"
12
13 #include <cmath>
14
15 #include <linux/input-event-codes.h>
16
17 using namespace KODI::WINDOWING::WAYLAND;
18
19 namespace
20 {
21
WaylandToXbmcButton(std::uint32_t button)22 int WaylandToXbmcButton(std::uint32_t button)
23 {
24 // Wayland button is evdev code
25 switch (button)
26 {
27 case BTN_LEFT:
28 return XBMC_BUTTON_LEFT;
29 case BTN_MIDDLE:
30 return XBMC_BUTTON_MIDDLE;
31 case BTN_RIGHT:
32 return XBMC_BUTTON_RIGHT;
33 default:
34 return -1;
35 }
36 }
37
38 }
39
CInputProcessorPointer(wayland::surface_t const & surface,IInputHandlerPointer & handler)40 CInputProcessorPointer::CInputProcessorPointer(wayland::surface_t const& surface, IInputHandlerPointer& handler)
41 : m_surface{surface}, m_handler{handler}
42 {
43 }
44
OnPointerEnter(CSeat * seat,std::uint32_t serial,const wayland::surface_t & surface,double surfaceX,double surfaceY)45 void CInputProcessorPointer::OnPointerEnter(CSeat* seat,
46 std::uint32_t serial,
47 const wayland::surface_t& surface,
48 double surfaceX,
49 double surfaceY)
50 {
51 if (surface == m_surface)
52 {
53 m_pointerOnSurface = true;
54 m_handler.OnPointerEnter(seat->GetGlobalName(), serial);
55 SetMousePosFromSurface({surfaceX, surfaceY});
56 SendMouseMotion();
57 }
58 }
59
OnPointerLeave(CSeat * seat,std::uint32_t serial,const wayland::surface_t & surface)60 void CInputProcessorPointer::OnPointerLeave(CSeat* seat,
61 std::uint32_t serial,
62 const wayland::surface_t& surface)
63 {
64 if (m_pointerOnSurface)
65 {
66 m_handler.OnPointerLeave();
67 m_pointerOnSurface = false;
68 }
69 }
70
OnPointerMotion(CSeat * seat,std::uint32_t time,double surfaceX,double surfaceY)71 void CInputProcessorPointer::OnPointerMotion(CSeat* seat, std::uint32_t time, double surfaceX, double surfaceY)
72 {
73 if (m_pointerOnSurface)
74 {
75 SetMousePosFromSurface({surfaceX, surfaceY});
76 SendMouseMotion();
77 }
78 }
79
OnPointerButton(CSeat * seat,std::uint32_t serial,std::uint32_t time,std::uint32_t button,wayland::pointer_button_state state)80 void CInputProcessorPointer::OnPointerButton(CSeat* seat, std::uint32_t serial, std::uint32_t time, std::uint32_t button, wayland::pointer_button_state state)
81 {
82 if (m_pointerOnSurface)
83 {
84 int xbmcButton = WaylandToXbmcButton(button);
85 if (xbmcButton < 0)
86 {
87 // Button is unmapped
88 return;
89 }
90
91 bool pressed = (state == wayland::pointer_button_state::pressed);
92 SendMouseButton(xbmcButton, pressed);
93 }
94 }
95
OnPointerAxis(CSeat * seat,std::uint32_t time,wayland::pointer_axis axis,double value)96 void CInputProcessorPointer::OnPointerAxis(CSeat* seat, std::uint32_t time, wayland::pointer_axis axis, double value)
97 {
98 if (m_pointerOnSurface)
99 {
100 // For axis events we only care about the vector direction
101 // and not the scalar magnitude. Every axis event callback
102 // generates one scroll button event for XBMC
103
104 // Negative is up
105 auto xbmcButton = static_cast<unsigned char> ((value < 0.0) ? XBMC_BUTTON_WHEELUP : XBMC_BUTTON_WHEELDOWN);
106 // Simulate a single click of the wheel-equivalent "button"
107 SendMouseButton(xbmcButton, true);
108 SendMouseButton(xbmcButton, false);
109 }
110 }
111
ConvertMouseCoordinate(double coord) const112 std::uint16_t CInputProcessorPointer::ConvertMouseCoordinate(double coord) const
113 {
114 return static_cast<std::uint16_t> (std::round(coord * m_coordinateScale));
115 }
116
SetMousePosFromSurface(CPointGen<double> position)117 void CInputProcessorPointer::SetMousePosFromSurface(CPointGen<double> position)
118 {
119 m_pointerPosition = {ConvertMouseCoordinate(position.x), ConvertMouseCoordinate(position.y)};
120 }
121
SendMouseMotion()122 void CInputProcessorPointer::SendMouseMotion()
123 {
124 XBMC_Event event{XBMC_MOUSEMOTION};
125 event.motion = {m_pointerPosition.x, m_pointerPosition.y};
126 m_handler.OnPointerEvent(event);
127 }
128
SendMouseButton(unsigned char button,bool pressed)129 void CInputProcessorPointer::SendMouseButton(unsigned char button, bool pressed)
130 {
131 XBMC_Event event{static_cast<unsigned char> (pressed ? XBMC_MOUSEBUTTONDOWN : XBMC_MOUSEBUTTONUP)};
132 event.button = {button, m_pointerPosition.x, m_pointerPosition.y};
133 m_handler.OnPointerEvent(event);
134 }
135