aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFloris Bos <bos@je-eigen-domein.nl>2015-09-25 01:07:30 +0200
committerFloris Bos <bos@je-eigen-domein.nl>2015-09-25 01:07:30 +0200
commitb671fe50cd306c31cf05e3928113a1505cb17229 (patch)
treef78b918d36a08ffdfbece481898af98110ed3d94
parentfee4018a2820233089d97b050487411ec3777e25 (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.in2
-rw-r--r--xbmc/input/linux/LinuxInputDevices.cpp109
-rw-r--r--xbmc/input/linux/LinuxInputDevices.h8
-rw-r--r--xbmc/input/touch/ITouchInputHandler.h1
-rw-r--r--xbmc/windowing/WinEventsLinux.cpp5
-rw-r--r--xbmc/windowing/WinEventsLinux.h1
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)
{