mirror of
https://github.com/LibreELEC/LibreELEC.tv.git
synced 2025-07-29 13:46:49 +00:00
kodi: add multitouch support patch, borrowed by popcornmix
Signed-off-by: Stephan Raue <stephan@openelec.tv>
This commit is contained in:
parent
651fa5f390
commit
3bc0e8d287
@ -0,0 +1,337 @@
|
|||||||
|
From 8ff131750e527416274e4f21685312785a8d0bb2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Floris Bos <bos@je-eigen-domein.nl>
|
||||||
|
Date: Wed, 23 Sep 2015 22:34:20 +0200
|
||||||
|
Subject: [PATCH 1/3] Fix Linux touchscreen support
|
||||||
|
|
||||||
|
Touch devices tend to send a key event first and coordinates later.
|
||||||
|
|
||||||
|
==
|
||||||
|
Event: type 1 (EV_KEY), code 330 (BTN_TOUCH), value 1
|
||||||
|
Event: type 3 (EV_ABS), code 0 (ABS_X), value 45
|
||||||
|
Event: type 3 (EV_ABS), code 1 (ABS_Y), value 27
|
||||||
|
==
|
||||||
|
|
||||||
|
This does not go along well with the XBMC mouse handling code that
|
||||||
|
expects to already have the coordinates when processing the EV_KEY.
|
||||||
|
Fetch the current coordinates with ioctl() as workaround.
|
||||||
|
|
||||||
|
Signed-off-by: Floris Bos <bos@je-eigen-domein.nl>
|
||||||
|
---
|
||||||
|
xbmc/input/linux/LinuxInputDevices.cpp | 24 ++++++++++++++++++++++++
|
||||||
|
1 file changed, 24 insertions(+)
|
||||||
|
|
||||||
|
diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp
|
||||||
|
index b028cd1..b8f13d3 100644
|
||||||
|
--- a/xbmc/input/linux/LinuxInputDevices.cpp
|
||||||
|
+++ b/xbmc/input/linux/LinuxInputDevices.cpp
|
||||||
|
@@ -275,6 +275,7 @@ typedef enum
|
||||||
|
LI_CAPS_KEYS = 1,
|
||||||
|
LI_CAPS_BUTTONS = 2,
|
||||||
|
LI_CAPS_AXES = 4,
|
||||||
|
+ LI_CAPS_ABS = 8
|
||||||
|
} LinuxInputCapsType;
|
||||||
|
|
||||||
|
static char remoteStatus = 0xFF; // paired, battery OK
|
||||||
|
@@ -470,6 +471,23 @@ bool CLinuxInputDevice::KeyEvent(const struct input_event& levt, XBMC_Event& dev
|
||||||
|
if (levt.value == 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
+ /* touch devices tend to send the key event before the coordinates, so we
|
||||||
|
+ cannot rely on m_mouseX and m_mouseY already having the correct values */
|
||||||
|
+ if (m_deviceCaps & LI_CAPS_ABS)
|
||||||
|
+ {
|
||||||
|
+ struct input_absinfo absinfo;
|
||||||
|
+
|
||||||
|
+ if (ioctl(m_fd, EVIOCGABS(ABS_X), &absinfo) == 0)
|
||||||
|
+ {
|
||||||
|
+ m_mouseX = absinfo.value;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ioctl(m_fd, EVIOCGABS(ABS_Y), &absinfo) == 0)
|
||||||
|
+ {
|
||||||
|
+ m_mouseY = absinfo.value;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
devt.type = levt.value ? XBMC_MOUSEBUTTONDOWN : XBMC_MOUSEBUTTONUP;
|
||||||
|
devt.button.state = levt.value ? XBMC_PRESSED : XBMC_RELEASED;
|
||||||
|
devt.button.type = devt.type;
|
||||||
|
@@ -954,6 +972,12 @@ void CLinuxInputDevice::GetInfo(int fd)
|
||||||
|
m_deviceMaxAxis = std::max(num_rels, num_abs) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ /* Absolute X,Y coordinates */
|
||||||
|
+ if (num_abs >= 2 && num_rels == 0)
|
||||||
|
+ {
|
||||||
|
+ m_deviceCaps |= LI_CAPS_ABS;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
/* Decide which primary input device to be. */
|
||||||
|
if (m_deviceType & LI_DEVICE_KEYBOARD)
|
||||||
|
m_devicePreferredId = LI_DEVICE_KEYBOARD;
|
||||||
|
|
||||||
|
From a7b5f1489dbfcb577e12c747626fe7d45ff2009d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Floris Bos <bos@je-eigen-domein.nl>
|
||||||
|
Date: Fri, 25 Sep 2015 01:07:30 +0200
|
||||||
|
Subject: [PATCH 2/3] LinuxInputDevice: add support for multi-touch devices
|
||||||
|
|
||||||
|
Adds support for multi-touch devices on Linux.
|
||||||
|
Support is limited to devices that are capable of
|
||||||
|
tracking identifiable contacts, and use the type B events of:
|
||||||
|
|
||||||
|
https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt
|
||||||
|
|
||||||
|
Signed-off-by: Floris Bos <bos@je-eigen-domein.nl>
|
||||||
|
---
|
||||||
|
Makefile.in | 2 +
|
||||||
|
xbmc/input/linux/LinuxInputDevices.cpp | 109 ++++++++++++++++++++++++++++++++-
|
||||||
|
xbmc/input/linux/LinuxInputDevices.h | 8 +++
|
||||||
|
xbmc/input/touch/ITouchInputHandler.h | 1 +
|
||||||
|
xbmc/windowing/WinEventsLinux.cpp | 5 ++
|
||||||
|
xbmc/windowing/WinEventsLinux.h | 1 +
|
||||||
|
6 files changed, 125 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/Makefile.in b/Makefile.in
|
||||||
|
index d579e11..2d4b1c8 100644
|
||||||
|
--- a/Makefile.in
|
||||||
|
+++ b/Makefile.in
|
||||||
|
@@ -157,6 +157,8 @@ DIRECTORY_ARCHIVES += xbmc/storage/android/storage_android.a
|
||||||
|
DIRECTORY_ARCHIVES += xbmc/windowing/X11/windowing_X11.a
|
||||||
|
else
|
||||||
|
DIRECTORY_ARCHIVES += xbmc/input/linux/input_linux.a
|
||||||
|
+DIRECTORY_ARCHIVES += xbmc/input/touch/input_touch.a
|
||||||
|
+DIRECTORY_ARCHIVES += xbmc/input/touch/generic/input_touch_generic.a
|
||||||
|
DIRECTORY_ARCHIVES += xbmc/network/linux/network_linux.a
|
||||||
|
DIRECTORY_ARCHIVES += xbmc/powermanagement/linux/powermanagement_linux.a
|
||||||
|
DIRECTORY_ARCHIVES += xbmc/storage/linux/storage_linux.a
|
||||||
|
diff --git a/xbmc/input/linux/LinuxInputDevices.cpp b/xbmc/input/linux/LinuxInputDevices.cpp
|
||||||
|
index b8f13d3..6e1cd1d 100644
|
||||||
|
--- a/xbmc/input/linux/LinuxInputDevices.cpp
|
||||||
|
+++ b/xbmc/input/linux/LinuxInputDevices.cpp
|
||||||
|
@@ -96,6 +96,8 @@ typedef unsigned long kernel_ulong_t;
|
||||||
|
#include "LinuxInputDevices.h"
|
||||||
|
#include "input/MouseStat.h"
|
||||||
|
#include "utils/log.h"
|
||||||
|
+#include "input/touch/generic/GenericTouchActionHandler.h"
|
||||||
|
+#include "input/touch/generic/GenericTouchInputHandler.h"
|
||||||
|
|
||||||
|
#ifndef BITS_PER_LONG
|
||||||
|
#define BITS_PER_LONG (sizeof(long) * 8)
|
||||||
|
@@ -267,7 +269,8 @@ typedef enum
|
||||||
|
LI_DEVICE_MOUSE = 1,
|
||||||
|
LI_DEVICE_JOYSTICK = 2,
|
||||||
|
LI_DEVICE_KEYBOARD = 4,
|
||||||
|
- LI_DEVICE_REMOTE = 8
|
||||||
|
+ LI_DEVICE_REMOTE = 8,
|
||||||
|
+ LI_DEVICE_MULTITOUCH = 16
|
||||||
|
} LinuxInputDeviceType;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
@@ -302,6 +305,10 @@ CLinuxInputDevice::CLinuxInputDevice(const std::string& fileName, int index):
|
||||||
|
m_deviceMaxKeyCode = 0;
|
||||||
|
m_deviceMaxAxis = 0;
|
||||||
|
m_bUnplugged = false;
|
||||||
|
+ m_mt_currentSlot = 0;
|
||||||
|
+ memset(&m_mt_x, 0, sizeof(m_mt_x));
|
||||||
|
+ memset(&m_mt_y, 0, sizeof(m_mt_y));
|
||||||
|
+ memset(&m_mt_event, 0, sizeof(m_mt_event));
|
||||||
|
|
||||||
|
Open();
|
||||||
|
}
|
||||||
|
@@ -681,11 +688,102 @@ bool CLinuxInputDevice::AbsEvent(const struct input_event& levt, XBMC_Event& dev
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
+ * Process multi-touch absolute events
|
||||||
|
+ * Only store the information, do not fire event until we receive an EV_SYN
|
||||||
|
+ */
|
||||||
|
+bool CLinuxInputDevice::mtAbsEvent(const struct input_event& levt)
|
||||||
|
+{
|
||||||
|
+ switch (levt.code)
|
||||||
|
+ {
|
||||||
|
+ case ABS_MT_SLOT:
|
||||||
|
+ m_mt_currentSlot = levt.value;
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case ABS_MT_TRACKING_ID:
|
||||||
|
+ if (m_mt_currentSlot < TOUCH_MAX_POINTERS)
|
||||||
|
+ {
|
||||||
|
+ if (levt.value == -1)
|
||||||
|
+ m_mt_event[m_mt_currentSlot] = TouchInputUp;
|
||||||
|
+ else
|
||||||
|
+ m_mt_event[m_mt_currentSlot] = TouchInputDown;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case ABS_MT_POSITION_X:
|
||||||
|
+ if (m_mt_currentSlot < TOUCH_MAX_POINTERS)
|
||||||
|
+ {
|
||||||
|
+ m_mt_x[m_mt_currentSlot] = levt.value;
|
||||||
|
+ if (m_mt_event[m_mt_currentSlot] == TouchInputUnchanged)
|
||||||
|
+ m_mt_event[m_mt_currentSlot] = TouchInputMove;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ case ABS_MT_POSITION_Y:
|
||||||
|
+ if (m_mt_currentSlot < TOUCH_MAX_POINTERS)
|
||||||
|
+ {
|
||||||
|
+ m_mt_y[m_mt_currentSlot] = levt.value;
|
||||||
|
+ if (m_mt_event[m_mt_currentSlot] == TouchInputUnchanged)
|
||||||
|
+ m_mt_event[m_mt_currentSlot] = TouchInputMove;
|
||||||
|
+ }
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Process stored multi-touch events
|
||||||
|
+ */
|
||||||
|
+bool CLinuxInputDevice::mtSynEvent(const struct input_event& levt)
|
||||||
|
+{
|
||||||
|
+ float size = 10.0f;
|
||||||
|
+ int64_t nanotime = levt.time.tv_sec * 1000000000LL + levt.time.tv_usec * 1000LL;
|
||||||
|
+
|
||||||
|
+ for (int ptr=0; ptr < TOUCH_MAX_POINTERS; ptr++)
|
||||||
|
+ {
|
||||||
|
+ /* While the comments of ITouchInputHandler::UpdateTouchPointer() say
|
||||||
|
+ "If there's an event for every touch action this method does not need to be called at all"
|
||||||
|
+ gesture detection currently doesn't work properly without this call. */
|
||||||
|
+ CGenericTouchInputHandler::Get().UpdateTouchPointer(ptr, m_mt_x[ptr], m_mt_y[ptr], nanotime, size);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (int ptr=0; ptr < TOUCH_MAX_POINTERS; ptr++)
|
||||||
|
+ {
|
||||||
|
+ if (m_mt_event[ptr] != TouchInputUnchanged)
|
||||||
|
+ {
|
||||||
|
+ CGenericTouchInputHandler::Get().HandleTouchInput(m_mt_event[ptr], m_mt_x[ptr], m_mt_y[ptr], nanotime, ptr, size);
|
||||||
|
+ m_mt_event[ptr] = TouchInputUnchanged;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
* Translates a Linux input event into a DirectFB input event.
|
||||||
|
*/
|
||||||
|
bool CLinuxInputDevice::TranslateEvent(const struct input_event& levt,
|
||||||
|
XBMC_Event& devt)
|
||||||
|
{
|
||||||
|
+ if (m_devicePreferredId == LI_DEVICE_MULTITOUCH)
|
||||||
|
+ {
|
||||||
|
+ switch (levt.type)
|
||||||
|
+ {
|
||||||
|
+ case EV_ABS:
|
||||||
|
+ return mtAbsEvent(levt);
|
||||||
|
+
|
||||||
|
+ case EV_SYN:
|
||||||
|
+ return mtSynEvent(levt);
|
||||||
|
+
|
||||||
|
+ default:
|
||||||
|
+ // Ignore legacy (key) events
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
switch (levt.type)
|
||||||
|
{
|
||||||
|
case EV_KEY:
|
||||||
|
@@ -930,6 +1028,10 @@ void CLinuxInputDevice::GetInfo(int fd)
|
||||||
|
for (i = 0; i < ABS_PRESSURE; i++)
|
||||||
|
if (test_bit( i, absbit ))
|
||||||
|
num_abs++;
|
||||||
|
+
|
||||||
|
+ /* test if it is a multi-touch type B device */
|
||||||
|
+ if (test_bit(ABS_MT_SLOT, absbit))
|
||||||
|
+ m_deviceType |= LI_DEVICE_MULTITOUCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mouse, Touchscreen or Smartpad ? */
|
||||||
|
@@ -981,6 +1083,11 @@ void CLinuxInputDevice::GetInfo(int fd)
|
||||||
|
/* Decide which primary input device to be. */
|
||||||
|
if (m_deviceType & LI_DEVICE_KEYBOARD)
|
||||||
|
m_devicePreferredId = LI_DEVICE_KEYBOARD;
|
||||||
|
+ else if (m_deviceType & LI_DEVICE_MULTITOUCH)
|
||||||
|
+ {
|
||||||
|
+ m_devicePreferredId = LI_DEVICE_MULTITOUCH;
|
||||||
|
+ CGenericTouchInputHandler::Get().RegisterHandler(&CGenericTouchActionHandler::Get());
|
||||||
|
+ }
|
||||||
|
else if (m_deviceType & LI_DEVICE_REMOTE)
|
||||||
|
m_devicePreferredId = LI_DEVICE_REMOTE;
|
||||||
|
else if (m_deviceType & LI_DEVICE_JOYSTICK)
|
||||||
|
diff --git a/xbmc/input/linux/LinuxInputDevices.h b/xbmc/input/linux/LinuxInputDevices.h
|
||||||
|
index 954d823..8c88a1d 100644
|
||||||
|
--- a/xbmc/input/linux/LinuxInputDevices.h
|
||||||
|
+++ b/xbmc/input/linux/LinuxInputDevices.h
|
||||||
|
@@ -26,6 +26,8 @@
|
||||||
|
#include "windowing/XBMC_events.h"
|
||||||
|
#include "input/XBMC_keyboard.h"
|
||||||
|
#include "threads/SingleLock.h"
|
||||||
|
+#include "input/touch/ITouchInputHandler.h"
|
||||||
|
+#include "input/touch/generic/IGenericTouchGestureDetector.h"
|
||||||
|
|
||||||
|
struct KeymapEntry
|
||||||
|
{
|
||||||
|
@@ -60,6 +62,8 @@ class CLinuxInputDevice
|
||||||
|
XBMCMod UpdateModifiers(XBMC_Event& devt);
|
||||||
|
bool GetKeymapEntry(KeymapEntry& entry);
|
||||||
|
int KeyboardGetSymbol(unsigned short value);
|
||||||
|
+ bool mtAbsEvent(const struct input_event& levt);
|
||||||
|
+ bool mtSynEvent(const struct input_event& levt);
|
||||||
|
|
||||||
|
int m_fd;
|
||||||
|
int m_vt_fd;
|
||||||
|
@@ -81,6 +85,10 @@ class CLinuxInputDevice
|
||||||
|
bool m_bSkipNonKeyEvents;
|
||||||
|
bool m_bUnplugged;
|
||||||
|
std::deque<XBMC_Event> m_equeue;
|
||||||
|
+ int m_mt_currentSlot;
|
||||||
|
+ int m_mt_x[TOUCH_MAX_POINTERS];
|
||||||
|
+ int m_mt_y[TOUCH_MAX_POINTERS];
|
||||||
|
+ TouchInput m_mt_event[TOUCH_MAX_POINTERS];
|
||||||
|
};
|
||||||
|
|
||||||
|
class CLinuxInputDevices
|
||||||
|
diff --git a/xbmc/input/touch/ITouchInputHandler.h b/xbmc/input/touch/ITouchInputHandler.h
|
||||||
|
index 6ea47db..43c7a76 100644
|
||||||
|
--- a/xbmc/input/touch/ITouchInputHandler.h
|
||||||
|
+++ b/xbmc/input/touch/ITouchInputHandler.h
|
||||||
|
@@ -28,6 +28,7 @@
|
||||||
|
* \brief Touch input event
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
+ TouchInputUnchanged = 0,
|
||||||
|
TouchInputAbort,
|
||||||
|
TouchInputDown,
|
||||||
|
TouchInputUp,
|
||||||
|
diff --git a/xbmc/windowing/WinEventsLinux.cpp b/xbmc/windowing/WinEventsLinux.cpp
|
||||||
|
index 89aca2b..04e3544 100644
|
||||||
|
--- a/xbmc/windowing/WinEventsLinux.cpp
|
||||||
|
+++ b/xbmc/windowing/WinEventsLinux.cpp
|
||||||
|
@@ -241,4 +241,9 @@ size_t CWinEventsLinux::GetQueueSize()
|
||||||
|
return m_devices.Size();
|
||||||
|
}
|
||||||
|
|
||||||
|
+void CWinEventsLinux::MessagePush(XBMC_Event *ev)
|
||||||
|
+{
|
||||||
|
+ g_application.OnEvent(*ev);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
#endif
|
||||||
|
diff --git a/xbmc/windowing/WinEventsLinux.h b/xbmc/windowing/WinEventsLinux.h
|
||||||
|
index 5c2b583..dc73b39 100644
|
||||||
|
--- a/xbmc/windowing/WinEventsLinux.h
|
||||||
|
+++ b/xbmc/windowing/WinEventsLinux.h
|
||||||
|
@@ -31,6 +31,7 @@ class CWinEventsLinux : public IWinEvents
|
||||||
|
CWinEventsLinux();
|
||||||
|
bool MessagePump();
|
||||||
|
size_t GetQueueSize();
|
||||||
|
+ void MessagePush(XBMC_Event *ev);
|
||||||
|
void RefreshDevices();
|
||||||
|
void Notify(const Observable &obs, const ObservableMessage msg)
|
||||||
|
{
|
Loading…
x
Reference in New Issue
Block a user