aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--system/keymaps/touchscreen.xml16
-rw-r--r--xbmc/Application.cpp13
-rw-r--r--xbmc/guilib/Key.h42
-rw-r--r--xbmc/input/ButtonTranslator.cpp170
-rw-r--r--xbmc/input/ButtonTranslator.h9
-rw-r--r--xbmc/windowing/XBMC_events.h11
-rw-r--r--xbmc/windowing/android/WinEventsAndroid.cpp7
7 files changed, 250 insertions, 18 deletions
diff --git a/system/keymaps/touchscreen.xml b/system/keymaps/touchscreen.xml
new file mode 100644
index 0000000000..fbd934c6b0
--- /dev/null
+++ b/system/keymaps/touchscreen.xml
@@ -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>
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
index cac91dbd34..cd8a5aba3b 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -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;
}
diff --git a/xbmc/guilib/Key.h b/xbmc/guilib/Key.h
index 04a8ff3062..3f7f11f8ca 100644
--- a/xbmc/guilib/Key.h
+++ b/xbmc/guilib/Key.h
@@ -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...
@@ -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
@@ -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
diff --git a/xbmc/input/ButtonTranslator.cpp b/xbmc/input/ButtonTranslator.cpp
index d5ff66a6e2..8fb69080a2 100644
--- a/xbmc/input/ButtonTranslator.cpp
+++ b/xbmc/input/ButtonTranslator.cpp
@@ -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}
};
@@ -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 },
@@ -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
*/
@@ -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);
@@ -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)
@@ -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;
+}
diff --git a/xbmc/input/ButtonTranslator.h b/xbmc/input/ButtonTranslator.h
index 79a8c8a818..4fd02be7cb 100644
--- a/xbmc/input/ButtonTranslator.h
+++ b/xbmc/input/ButtonTranslator.h
@@ -97,6 +97,8 @@ public:
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
@@ -105,6 +107,7 @@ private:
// 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> >
@@ -145,6 +148,12 @@ private:
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;
};
diff --git a/xbmc/windowing/XBMC_events.h b/xbmc/windowing/XBMC_events.h
index 8ab192894d..f4a188eb92 100644
--- a/xbmc/windowing/XBMC_events.h
+++ b/xbmc/windowing/XBMC_events.h
@@ -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 */
@@ -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;
@@ -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 */
diff --git a/xbmc/windowing/android/WinEventsAndroid.cpp b/xbmc/windowing/android/WinEventsAndroid.cpp
index 8554961a0f..eb7c5078c8 100644
--- a/xbmc/windowing/android/WinEventsAndroid.cpp
+++ b/xbmc/windowing/android/WinEventsAndroid.cpp
@@ -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;
@@ -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;