Skip to content
Permalink
Browse files

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>
  • Loading branch information...
maxnet committed Sep 24, 2015
1 parent fee4018 commit b671fe50cd306c31cf05e3928113a1505cb17229
@@ -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
@@ -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();
}
@@ -663,12 +670,103 @@ bool CLinuxInputDevice::AbsEvent(const struct input_event& levt, XBMC_Event& dev
return true;
}

/*
* 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)
@@ -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
@@ -28,6 +28,7 @@
* \brief Touch input event
*/
typedef enum {
TouchInputUnchanged = 0,
TouchInputAbort,
TouchInputDown,
TouchInputUp,
@@ -79,4 +79,9 @@ size_t CWinEventsLinux::GetQueueSize()
return m_devices.Size();
}

void CWinEventsLinux::MessagePush(XBMC_Event *ev)
{
g_application.OnEvent(*ev);
}

#endif
@@ -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)
{

0 comments on commit b671fe5

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.