diff options
author | Floris Bos <bos@je-eigen-domein.nl> | 2015-09-25 01:07:30 +0200 |
---|---|---|
committer | Floris Bos <bos@je-eigen-domein.nl> | 2015-09-25 01:07:30 +0200 |
commit | b671fe50cd306c31cf05e3928113a1505cb17229 (patch) | |
tree | f78b918d36a08ffdfbece481898af98110ed3d94 | |
parent | fee4018a2820233089d97b050487411ec3777e25 (diff) |
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>
-rw-r--r-- | Makefile.in | 2 | ||||
-rw-r--r-- | xbmc/input/linux/LinuxInputDevices.cpp | 109 | ||||
-rw-r--r-- | xbmc/input/linux/LinuxInputDevices.h | 8 | ||||
-rw-r--r-- | xbmc/input/touch/ITouchInputHandler.h | 1 | ||||
-rw-r--r-- | xbmc/windowing/WinEventsLinux.cpp | 5 | ||||
-rw-r--r-- | xbmc/windowing/WinEventsLinux.h | 1 |
6 files changed, 125 insertions, 1 deletions
diff --git a/Makefile.in b/Makefile.in index e7276bfe1e..8ead761782 100644 --- a/Makefile.in +++ b/Makefile.in @@ -158,6 +158,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 0b9a2c736b..723f7ae80a 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) @@ -268,7 +270,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(); } @@ -664,11 +671,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::GetInstance().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::GetInstance().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: @@ -913,6 +1011,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 ? */ @@ -958,6 +1060,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::GetInstance().RegisterHandler(&CGenericTouchActionHandler::GetInstance()); + } 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 954d823540..8c88a1df5f 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 @@ private: 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 @@ private: 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 6ea47dbc8d..43c7a76cdf 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 6f97e9e4f7..aaba119d54 100644 --- a/xbmc/windowing/WinEventsLinux.cpp +++ b/xbmc/windowing/WinEventsLinux.cpp @@ -79,4 +79,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 f6c8df05b1..a17e9878e2 100644 --- a/xbmc/windowing/WinEventsLinux.h +++ b/xbmc/windowing/WinEventsLinux.h @@ -31,6 +31,7 @@ public: CWinEventsLinux(); bool MessagePump(); size_t GetQueueSize(); + void MessagePush(XBMC_Event *ev); void RefreshDevices(); void Notify(const Observable &obs, const ObservableMessage msg) { |