From 3bc0e8d287ee9656d3f6ea3340b48db3d53e6d77 Mon Sep 17 00:00:00 2001 From: Stephan Raue Date: Tue, 13 Oct 2015 19:42:32 +0200 Subject: [PATCH] kodi: add multitouch support patch, borrowed by popcornmix Signed-off-by: Stephan Raue --- .../kodi-999.52-multitouch-support.patch | 337 ++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 packages/mediacenter/kodi/patches/kodi-999.52-multitouch-support.patch diff --git a/packages/mediacenter/kodi/patches/kodi-999.52-multitouch-support.patch b/packages/mediacenter/kodi/patches/kodi-999.52-multitouch-support.patch new file mode 100644 index 0000000000..a06e554347 --- /dev/null +++ b/packages/mediacenter/kodi/patches/kodi-999.52-multitouch-support.patch @@ -0,0 +1,337 @@ +From 8ff131750e527416274e4f21685312785a8d0bb2 Mon Sep 17 00:00:00 2001 +From: Floris Bos +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 +--- + 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 +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 +--- + 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 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) + {