Skip to content

Commit

Permalink
input: implement touch input through mappable actions
Browse files Browse the repository at this point in the history
  • Loading branch information
Montellese committed Mar 5, 2013
1 parent e6d8e60 commit 50d25a5
Show file tree
Hide file tree
Showing 7 changed files with 250 additions and 18 deletions.
16 changes: 16 additions & 0 deletions system/keymaps/touchscreen.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<keymap>
<global>
<touch>
<tap>LeftClick</tap>
<longpress>RightClick</longpress>
<tap pointers="2">RightClick</tap>
<pan>PanGesture</pan>
</touch>
</global>
<SlideShow>
<touch>
<zoom>ZoomGesture</zoom>
<rotate>RotateGesture</rotate>
</touch>
</SlideShow>
</keymap>
13 changes: 13 additions & 0 deletions xbmc/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -522,6 +522,19 @@ bool CApplication::OnEvent(XBMC_Event& newEvent)
break;
case XBMC_APPCOMMAND:
return g_application.OnAppCommand(newEvent.appcommand.action);
case XBMC_TOUCH:
{
int windowId = g_windowManager.GetActiveWindow() & WINDOW_ID_MASK;
int actionId = 0;
if (newEvent.touch.action == ACTION_GESTURE_BEGIN || newEvent.touch.action == ACTION_GESTURE_END)
actionId = newEvent.touch.action;
else if (!CButtonTranslator::GetInstance().TranslateTouchAction(windowId, newEvent.touch.action, newEvent.touch.pointers, actionId) ||
actionId <= 0)
return false;

CApplicationMessenger::Get().SendAction(CAction(actionId, 0, newEvent.touch.x, newEvent.touch.y, newEvent.touch.x2, newEvent.touch.y2), WINDOW_INVALID, false);
break;
}
}
return true;
}
Expand Down
42 changes: 31 additions & 11 deletions xbmc/guilib/Key.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@
// 0xD000 -> 0xD0FF is reserved for WM_APPCOMMAND messages
#define KEY_APPCOMMAND 0xD000

// 0xF000 -> 0xF0FF is reserved for mouse actions
#define KEY_TOUCH 0xF000

#define KEY_INVALID 0xFFFF

// actions that we have defined...
Expand Down Expand Up @@ -293,22 +296,11 @@
#define ACTION_INCREASE_PAR 219
#define ACTION_DECREASE_PAR 220

#define ACTION_GESTURE_NOTIFY 221
#define ACTION_GESTURE_BEGIN 222
#define ACTION_GESTURE_ZOOM 223 //sendaction with point and currentPinchScale (fingers together < 1.0 -> fingers apart > 1.0)
#define ACTION_GESTURE_ROTATE 224
#define ACTION_GESTURE_PAN 225
#define ACTION_GESTURE_END 226
#define ACTION_VSHIFT_UP 227 // shift up video image in DVDPlayer
#define ACTION_VSHIFT_DOWN 228 // shift down video image in DVDPlayer

#define ACTION_PLAYER_PLAYPAUSE 229 // Play/pause. If playing it pauses, if paused it plays.

// The NOOP action can be specified to disable an input event. This is
// useful in user keyboard.xml etc to disable actions specified in the
// system mappings.
#define ACTION_NOOP 999

#define ACTION_SUBTITLE_VSHIFT_UP 230 // shift up subtitles in DVDPlayer
#define ACTION_SUBTITLE_VSHIFT_DOWN 231 // shift down subtitles in DVDPlayer
#define ACTION_SUBTITLE_ALIGN 232 // toggle vertical alignment of subtitles
Expand All @@ -317,6 +309,34 @@

#define ACTION_SWITCH_PLAYER 234

// touch actions
#define ACTION_TOUCH_TAP 401
#define ACTION_TOUCH_TAP_TEN 410
#define ACTION_TOUCH_LONGPRESS 411
#define ACTION_TOUCH_LONGPRESS_TEN 420

#define ACTION_GESTURE_NOTIFY 500
#define ACTION_GESTURE_BEGIN 501
#define ACTION_GESTURE_ZOOM 502 //sendaction with point and currentPinchScale (fingers together < 1.0 -> fingers apart > 1.0)
#define ACTION_GESTURE_ROTATE 503
#define ACTION_GESTURE_PAN 504

#define ACTION_GESTURE_SWIPE_LEFT 511
#define ACTION_GESTURE_SWIPE_LEFT_TEN 520
#define ACTION_GESTURE_SWIPE_RIGHT 521
#define ACTION_GESTURE_SWIPE_RIGHT_TEN 530
#define ACTION_GESTURE_SWIPE_UP 531
#define ACTION_GESTURE_SWIPE_UP_TEN 540
#define ACTION_GESTURE_SWIPE_DOWN 541
#define ACTION_GESTURE_SWIPE_DOWN_TEN 550
// 5xx is reserved for additional gesture actions
#define ACTION_GESTURE_END 599

// The NOOP action can be specified to disable an input event. This is
// useful in user keyboard.xml etc to disable actions specified in the
// system mappings.
#define ACTION_NOOP 999

// Window ID defines to make the code a bit more readable
#define WINDOW_INVALID 9999
#define WINDOW_HOME 10000
Expand Down
170 changes: 170 additions & 0 deletions xbmc/input/ButtonTranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,17 @@ static const ActionMapping actions[] =
{"mousedrag" , ACTION_MOUSE_DRAG},
{"mousemove" , ACTION_MOUSE_MOVE},

// Touch
{"tap" , ACTION_TOUCH_TAP},
{"longpress" , ACTION_TOUCH_LONGPRESS},
{"pangesture" , ACTION_GESTURE_PAN},
{"zoomgesture" , ACTION_GESTURE_ZOOM},
{"rotategesture" , ACTION_GESTURE_ROTATE},
{"swipeleft" , ACTION_GESTURE_SWIPE_LEFT},
{"swiperight" , ACTION_GESTURE_SWIPE_RIGHT},
{"swipeup" , ACTION_GESTURE_SWIPE_UP},
{"swipedown" , ACTION_GESTURE_SWIPE_DOWN},

// Do nothing action
{ "noop" , ACTION_NOOP}
};
Expand Down Expand Up @@ -366,6 +377,19 @@ static const ActionMapping mousecommands[] =
{ "mousemove", ACTION_MOUSE_MOVE }
};

static const ActionMapping touchcommands[] =
{
{ "tap", ACTION_TOUCH_TAP },
{ "longpress", ACTION_TOUCH_LONGPRESS },
{ "pan", ACTION_GESTURE_PAN },
{ "zoom", ACTION_GESTURE_ZOOM },
{ "rotate", ACTION_GESTURE_ROTATE },
{ "swipeleft", ACTION_GESTURE_SWIPE_LEFT },
{ "swiperight", ACTION_GESTURE_SWIPE_RIGHT },
{ "swipeup", ACTION_GESTURE_SWIPE_UP },
{ "swipedown", ACTION_GESTURE_SWIPE_DOWN }
};

static const WindowMapping fallbackWindows[] =
{
{ WINDOW_FULLSCREEN_LIVETV, WINDOW_FULLSCREEN_VIDEO },
Expand Down Expand Up @@ -841,6 +865,35 @@ bool CButtonTranslator::TranslateJoystickString(int window, const char* szDevice
return (action > 0);
}

bool CButtonTranslator::TranslateTouchAction(int window, int touchAction, int touchPointers, int &action)
{
action = 0;
if (touchPointers <= 0)
touchPointers = 1;

touchAction += touchPointers - 1;
touchAction |= KEY_TOUCH;

action = GetTouchActionCode(window, touchAction);
if (action <= 0)
action = GetTouchActionCode(-1, touchAction);

return action > 0;
}

int CButtonTranslator::GetActionCode(int window, int action)
{
map<int, buttonMap>::const_iterator it = m_translatorMap.find(window);
if (it == m_translatorMap.end())
return 0;

buttonMap::const_iterator it2 = it->second.find(action);
if (it2 == it->second.end())
return 0;

return it2->second.id;
}

/*
* Translates a joystick input to an action code
*/
Expand Down Expand Up @@ -962,6 +1015,7 @@ void CButtonTranslator::MapAction(uint32_t buttonCode, const char *szAction, but
int action = ACTION_NONE;
if (!TranslateActionString(szAction, action) || !buttonCode)
return; // no valid action, or an invalid buttoncode

// have a valid action, and a valid button - map it.
// check to see if we've already got this (button,action) pair defined
buttonMap::iterator it = map.find(buttonCode);
Expand Down Expand Up @@ -1046,6 +1100,16 @@ void CButtonTranslator::MapWindowActions(TiXmlNode *pWindow, int windowID)
}
}
#endif

if ((pDevice = pWindow->FirstChild("touch")) != NULL)
{
// map touch actions
while (pDevice)
{
MapTouchActions(windowID, pDevice);
pDevice = pDevice->NextSibling("touch");
}
}
}

bool CButtonTranslator::TranslateActionString(const char *szAction, int &action)
Expand Down Expand Up @@ -1366,3 +1430,109 @@ void CButtonTranslator::Clear()

m_Loaded = false;
}

uint32_t CButtonTranslator::TranslateTouchCommand(TiXmlElement *pButton, CButtonAction &action)
{
const char *szButton = pButton->Value();
if (szButton == NULL || pButton->FirstChild() == NULL)
return ACTION_NONE;

const char *szAction = pButton->FirstChild()->Value();
if (szAction == NULL)
return ACTION_NONE;

CStdString strTouchCommand = szButton;
strTouchCommand.ToLower();

std::string strTmp;
if (pButton->QueryStringAttribute("direction", &strTmp) == TIXML_SUCCESS)
strTouchCommand += strTmp;

uint32_t actionId = ACTION_NONE;
for (unsigned int i = 0; i < sizeof(touchcommands)/sizeof(touchcommands[0]); i++)
{
if (strTouchCommand.Equals(touchcommands[i].name))
{
actionId = touchcommands[i].action;
break;
}
}

if (actionId <= ACTION_NONE)
{
CLog::Log(LOGERROR, "%s: Can't find touch command %s", __FUNCTION__, szButton);
return ACTION_NONE;
}

strTmp.clear();
if (pButton->QueryStringAttribute("pointers", &strTmp) == TIXML_SUCCESS)
{
int pointers = (int)strtol(strTmp.c_str(), NULL, 0);
if (pointers >= 1)
actionId += pointers - 1;
}

action.strID = szAction;
if (!TranslateActionString(szAction, action.id) || action.id <= ACTION_NONE)
return ACTION_NONE;

return actionId | KEY_TOUCH;
}

void CButtonTranslator::MapTouchActions(int windowID, TiXmlNode *pTouch)
{
if (pTouch == NULL)
return;

buttonMap map;
// check if there already is a touch map for the window ID
std::map<int, buttonMap>::iterator it = m_touchMap.find(windowID);
if (it != m_touchMap.end())
{
// get the existing touch map and remove it from the window mapping
// as it will be inserted later on
map = it->second;
m_touchMap.erase(it);
}

uint32_t actionId = 0;
TiXmlElement *pTouchElem = pTouch->ToElement();
if (pTouchElem == NULL)
return;

TiXmlElement *pButton = pTouchElem->FirstChildElement();
while (pButton != NULL)
{
CButtonAction action;
actionId = TranslateTouchCommand(pButton, action);
if (actionId > 0)
{
// check if there already is a mapping for the parsed action
// and remove it if necessary
buttonMap::iterator actionIt = map.find(actionId);
if (actionIt != map.end())
map.erase(actionIt);

map.insert(std::make_pair(actionId, action));
}

pButton = pButton->NextSiblingElement();
}

// add the modified touch map with the window ID
if (map.size() > 0)
m_touchMap.insert(std::pair<int, buttonMap>(windowID, map));
}

int CButtonTranslator::GetTouchActionCode(int window, int action)
{
std::map<int, buttonMap>::const_iterator windowIt = m_touchMap.find(window);
if (windowIt == m_touchMap.end())
return ACTION_NONE;

buttonMap::const_iterator touchIt = windowIt->second.find(action);
if (touchIt == windowIt->second.end())
return ACTION_NONE;

return touchIt->second.id;
}
9 changes: 9 additions & 0 deletions xbmc/input/ButtonTranslator.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ class CButtonTranslator
bool &fullrange);
#endif

bool TranslateTouchAction(int window, int touchAction, int touchPointers, int &action);

private:
typedef std::multimap<uint32_t, CButtonAction> buttonMap; // our button map to fill in

Expand All @@ -105,6 +107,7 @@ class CButtonTranslator
// m_deviceList contains the list of connected HID devices
std::list<CStdString> m_deviceList;

int GetActionCode(int window, int action);
int GetActionCode(int window, const CKey &key, CStdString &strAction) const;
#if defined(HAS_SDL_JOYSTICK) || defined(HAS_EVENT_SERVER)
typedef std::map<int, std::map<int, std::string> > JoystickMap; // <window, <button/axis, action> >
Expand Down Expand Up @@ -145,6 +148,12 @@ class CButtonTranslator
std::map<std::string, JoystickMap> m_joystickHatMap; // <joy name, hat map>
#endif

void MapTouchActions(int windowID, TiXmlNode *pTouch);
static uint32_t TranslateTouchCommand(TiXmlElement *pButton, CButtonAction &action);
int GetTouchActionCode(int window, int action);

std::map<int, buttonMap> m_touchMap;

bool m_Loaded;
};

Expand Down
11 changes: 11 additions & 0 deletions xbmc/windowing/XBMC_events.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ typedef enum {
XBMC_VIDEOMOVE, /* User moved the window */
XBMC_VIDEOEXPOSE, /* Screen needs to be redrawn */
XBMC_APPCOMMAND, /* Media commands, such as WM_APPCOMMAND on Windows for media keys. */
XBMC_TOUCH,
XBMC_USEREVENT,

XBMC_MAXEVENT = 256 /* XBMC_EventType is represented as uchar */
Expand Down Expand Up @@ -179,6 +180,15 @@ typedef struct XBMC_AppCommandEvent {
unsigned int action; /* One of ACTION_... */
} XBMC_AppCommandEvent;

/* Mouse motion event structure */
typedef struct XBMC_TouchEvent {
unsigned char type; /* XBMC_TOUCH */
int action; /* action ID */
float x, y; /* The X/Y coordinates of the mouse */
float x2, y2; /* Additional X/Y coordinates */
int pointers; /* number of touch pointers */
} XBMC_TouchEvent;

/* General event structure */
typedef union XBMC_Event {
unsigned char type;
Expand All @@ -197,6 +207,7 @@ typedef union XBMC_Event {
XBMC_UserEvent user;
XBMC_SysWMEvent syswm;
XBMC_AppCommandEvent appcommand;
XBMC_TouchEvent touch;
} XBMC_Event;

#endif /* _XBMC_events_h */
7 changes: 0 additions & 7 deletions xbmc/windowing/android/WinEventsAndroid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@
#include <list>
#include "windowing/WinEvents.h"
#include "WinEventsAndroid.h"
#include "input/XBMC_vkeys.h"
#include "Application.h"
#include "windowing/WindowingFactory.h"
#include "threads/CriticalSection.h"
#include "utils/log.h"
#include "guilib/GUIWindowManager.h"

static CCriticalSection g_inputCond;

Expand Down Expand Up @@ -70,9 +66,6 @@ bool CWinEventsAndroid::MessagePump()
}

ret |= g_application.OnEvent(pumpEvent);

if (pumpEvent.type == XBMC_MOUSEBUTTONUP)
g_windowManager.SendMessage(GUI_MSG_UNFOCUS_ALL, 0, 0, 0, 0);
}

return ret;
Expand Down

0 comments on commit 50d25a5

Please sign in to comment.