summaryrefslogtreecommitdiff
path: root/src/player/Win7TouchInputDevice.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/player/Win7TouchInputDevice.cpp')
-rw-r--r--src/player/Win7TouchInputDevice.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/src/player/Win7TouchInputDevice.cpp b/src/player/Win7TouchInputDevice.cpp
new file mode 100644
index 0000000..b7a5691
--- /dev/null
+++ b/src/player/Win7TouchInputDevice.cpp
@@ -0,0 +1,186 @@
+//
+// libavg - Media Playback Engine.
+// Copyright (C) 2003-2014 Ulrich von Zadow
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// Current versions can be found at www.libavg.de
+//
+
+#include "Win7TouchInputDevice.h"
+#include "TouchEvent.h"
+#include "Player.h"
+#include "AVGNode.h"
+#include "TouchStatus.h"
+#include "TouchEvent.h"
+#include "SDLDisplayEngine.h"
+
+#include "../base/Logger.h"
+#include "../base/ObjectCounter.h"
+#include "../base/Exception.h"
+
+using namespace std;
+
+namespace avg {
+
+Win7TouchInputDevice* Win7TouchInputDevice::s_pInstance(0);
+
+Win7TouchInputDevice::Win7TouchInputDevice()
+ : m_LastID(0)
+{
+ s_pInstance = this;
+}
+
+Win7TouchInputDevice::~Win7TouchInputDevice()
+{
+ SetWindowLong(m_Hwnd, GWL_WNDPROC, (LONG)m_OldWndProc);
+ s_pInstance = 0;
+}
+
+typedef bool (WINAPI* PRTWPROC)(HWND, ULONG);
+
+void Win7TouchInputDevice::start()
+{
+#ifdef SM_DIGITIZER
+ AVG_TRACE(Logger::category::CONFIG, Logger::severity::INFO,
+ "Using Windows 7 Touch driver.");
+ // We need to do runtime dynamic linking for the Win7 touch functions because they
+ // aren't present on pre-Win7 systems.
+ HMODULE hUser32 = GetModuleHandle(TEXT("user32.dll"));
+ PRTWPROC pRegisterTouchWindowProc = (PRTWPROC) GetProcAddress(hUser32,
+ "RegisterTouchWindow");
+ if (!pRegisterTouchWindowProc) {
+ throw Exception(AVG_ERR_UNSUPPORTED,
+ "This version of windows does not support Multitouch input.");
+ }
+ m_pGetTouchInputInfoProc = (GTIIPROC) GetProcAddress(hUser32, "GetTouchInputInfo");
+ m_pCloseTouchInputHandleProc = (CTIHPROC) GetProcAddress(hUser32,
+ "CloseTouchInputHandle");
+
+ int multitouchCaps = GetSystemMetrics(SM_DIGITIZER);
+ if (multitouchCaps & NID_MULTI_INPUT) {
+ MultitouchInputDevice::start();
+ SDL_SysWMinfo info;
+ SDL_VERSION(&info.version);
+ int err = SDL_GetWMInfo(&info);
+ AVG_ASSERT(err == 1);
+ m_Hwnd = info.window;
+ bool bOk = pRegisterTouchWindowProc(m_Hwnd, TWF_FINETOUCH | TWF_WANTPALM);
+ AVG_ASSERT(bOk);
+ m_OldWndProc = (WNDPROC)SetWindowLong(m_Hwnd, GWL_WNDPROC, (LONG)touchWndSubclassProc);
+ m_ClientAreaOffset = calcClientAreaOffset();
+ } else {
+ throw Exception(AVG_ERR_UNSUPPORTED, "No windows 7 multitouch device connected.");
+ }
+#else
+ throw Exception(AVG_ERR_UNSUPPORTED,
+ "Windows multitouch not supported by this version of libavg.");
+#endif
+}
+
+#define MOUSEEVENTF_FROMTOUCH 0xFF515700
+
+LRESULT APIENTRY Win7TouchInputDevice::touchWndSubclassProc(HWND hwnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
+{
+#ifdef SM_DIGITIZER
+ Win7TouchInputDevice * pThis = Win7TouchInputDevice::s_pInstance;
+ bool bIgnore = false;
+ switch(uMsg) {
+ case WM_TOUCH:
+ pThis->onTouch(hwnd, wParam, lParam);
+ break;
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ if (GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) {
+ // Click was generated by wisptis / Windows Touch
+ bIgnore = true;
+ }
+ break;
+ case WM_MOUSEMOVE:
+ // Workaround for Win7 bug: There is no way to figure out if a WM_MOUSEMOVE
+ // originates from a touch, so we ignore all mousemove events as long as
+ // something is touching the screen.
+ bIgnore = (pThis->getNumTouches() > 0);
+ break;
+ default:
+ break;
+ }
+ if (!bIgnore) {
+ return CallWindowProc(pThis->m_OldWndProc, hwnd, uMsg, wParam, lParam);
+ } else {
+ return 0;
+ }
+#else
+ return 0;
+#endif
+}
+
+void Win7TouchInputDevice::onTouch(HWND hWnd, WPARAM wParam, LPARAM lParam)
+{
+#ifdef SM_DIGITIZER
+ unsigned numInputs = LOWORD(wParam);
+ PTOUCHINPUT pInputs = new TOUCHINPUT[numInputs];
+ BOOL bOk = m_pGetTouchInputInfoProc((HTOUCHINPUT)lParam, numInputs, pInputs,
+ sizeof(TOUCHINPUT));
+ AVG_ASSERT(bOk);
+ RECT winRect;
+ bOk = GetWindowRect(m_Hwnd, &winRect);
+ AVG_ASSERT(bOk);
+ for (unsigned i = 0; i < numInputs; i++) {
+ TOUCHINPUT *pTouchInput = &(pInputs[i]);
+ IntPoint pos(int(pTouchInput->x/100+0.5), int(pTouchInput->y/100+0.5));
+ if (!(Player::get()->getDisplayEngine())->isFullscreen()) {
+ pos -= IntPoint(winRect.left, winRect.top)+m_ClientAreaOffset;
+ IntPoint winSize = IntPoint(Player::get()->getRootNode()->getSize());
+ // Restrict coords to be inside window.
+ pos.x = min(max(pos.x, 0), winSize.x-1);
+ pos.y = min(max(pos.y, 0), winSize.y-1);
+ }
+
+ if (pTouchInput->dwFlags & TOUCHEVENTF_DOWN) {
+// cerr << "down: " << pos << endl;
+ m_LastID++;
+ TouchEventPtr pEvent (new TouchEvent(m_LastID, Event::CURSOR_DOWN, pos,
+ Event::TOUCH));
+ addTouchStatus((long)pTouchInput->dwID, pEvent);
+ } else if (pTouchInput->dwFlags & TOUCHEVENTF_UP) {
+// cerr << "up: " << pos << endl;
+ TouchStatusPtr pTouchStatus = getTouchStatus(pTouchInput->dwID);
+ TouchEventPtr pOldEvent = pTouchStatus->getLastEvent();
+ TouchEventPtr pUpEvent(new TouchEvent(pOldEvent->getCursorID(),
+ Event::CURSOR_UP, pos, Event::TOUCH));
+ pTouchStatus->pushEvent(pUpEvent);
+ } else if (pTouchInput->dwFlags & TOUCHEVENTF_MOVE) {
+// cerr << "motion: " << pos << endl;
+ TouchEventPtr pEvent(new TouchEvent(0, Event::CURSOR_MOTION, pos,
+ Event::TOUCH));
+ TouchStatusPtr pTouchStatus = getTouchStatus((long)pTouchInput->dwID);
+ AVG_ASSERT(pTouchStatus);
+ pTouchStatus->pushEvent(pEvent);
+ }
+ }
+ delete [] pInputs;
+ m_pCloseTouchInputHandleProc((HTOUCHINPUT)lParam);
+#endif
+}
+
+IntPoint Win7TouchInputDevice::calcClientAreaOffset() const
+{
+ // TODO: This might work for now, but the x offset should probably be SM_CXBORDER.
+ return IntPoint(GetSystemMetrics(SM_CYBORDER)+2, GetSystemMetrics(SM_CYCAPTION)+3);
+}
+
+}