modules/graphics/src/main/native-glass/win/ViewContainer.cpp
Print this page
@@ -90,10 +90,11 @@
m_deadKeyWParam(0)
{
m_kbLayout = ::GetKeyboardLayout(0);
m_idLang = LOWORD(m_kbLayout);
m_codePage = LangToCodePage(m_idLang);
+ m_lastTouchInputCount = 0;
}
jobject ViewContainer::GetView()
{
return GetGlassView() != NULL ? GetGlassView()->GetView() : NULL;
@@ -1214,10 +1215,25 @@
operator HTOUCHINPUT() const {
return m_h;
}
};
+static BOOL debugTouch = false;
+
+static char * touchEventName(unsigned int dwFlags) {
+ if (dwFlags & TOUCHEVENTF_MOVE) {
+ return "MOVE";
+ }
+ if (dwFlags & TOUCHEVENTF_DOWN) {
+ return "PRESS";
+ }
+ if (dwFlags & TOUCHEVENTF_UP) {
+ return "RELEASE";
+ }
+ return "UNKOWN";
+}
+
void NotifyTouchInput(
HWND hWnd, jobject view, jclass gestureSupportCls,
const TOUCHINPUT* ti, unsigned count)
{
@@ -1293,40 +1309,151 @@
}
}
} // namespace
-void ViewContainer::HandleViewTouchEvent(
+unsigned int ViewContainer::HandleViewTouchEvent(
HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
- // Preallocated arrays. One element per finger. Though so far
- // Win 7 can handle at most four touch points simultaneously,
- // so the buffer is excessive.
- TOUCHINPUT staticTouchInputBuf[10];
-
- std::vector<TOUCHINPUT> dynamicTouchInputBuf;
- PTOUCHINPUT pInputs = staticTouchInputBuf;
-
- const UINT cInputs = static_cast<UINT>(LOWORD(wParam));
- if (ARRAYSIZE(staticTouchInputBuf) < cInputs) {
- dynamicTouchInputBuf.resize(cInputs);
- pInputs = &*dynamicTouchInputBuf.begin();
+ const UINT newCount = static_cast<UINT>(LOWORD(wParam));
+ TOUCHINPUT * tempTouchInputBuf;
+
+ unsigned int bufsz = newCount > 10 ? newCount : 10;
+ if (m_thisTouchInputBuf.size() < bufsz) {
+ m_thisTouchInputBuf.resize(bufsz);
}
+ if (newCount > 0) {
+ tempTouchInputBuf = new TOUCHINPUT[newCount];
do {
AutoTouchInputHandle inputInfo(lParam);
- if (!::GetTouchInputInfo(inputInfo, cInputs,
- pInputs, sizeof(TOUCHINPUT))) {
- return;
+ if (!::GetTouchInputInfo(inputInfo, newCount,
+ tempTouchInputBuf, sizeof(TOUCHINPUT))) {
+ return 0;
}
} while(0); // scope for 'inputInfo'
+ }
+
+ // Fix up the touch point stream. Some drivers seem to lose touch events,
+ // dropping PRESS, MOVE, UP, so we need to add them back in.
+
+ unsigned int activeCount = 0;
+ unsigned int pointsCount = 0;
- NotifyTouchInput(hWnd, GetView(), m_gestureSupportCls, pInputs, cInputs);
+ // check first for any "lost" touches
+ // these need to get added to the send list of points
+ for (unsigned int i = 0 ; i < m_lastTouchInputCount; i++) {
+ if (!(m_lastTouchInputBuf[i].dwFlags & TOUCHEVENTF_UP)) {
+ // looking for a dwID that is
+ // not present in the new batch
+ // was not UP in the old batch
+ bool found = false;
+ for (unsigned int j = 0; j < newCount; j++) {
+ if (m_lastTouchInputBuf[i].dwID == tempTouchInputBuf[j].dwID) {
+ found = true;
+ //break;
+ }
+ }
+ if (!found) {
+ // We have a old event but not a new one, so release it
+ m_thisTouchInputBuf[pointsCount].dwFlags = TOUCHEVENTF_UP;
+ m_thisTouchInputBuf[pointsCount].dwID = m_lastTouchInputBuf[i].dwID;
+ m_thisTouchInputBuf[pointsCount].x = m_lastTouchInputBuf[i].x;
+ m_thisTouchInputBuf[pointsCount].y = m_lastTouchInputBuf[i].y;
+ if (newCount > 0) {
+ //use the time of the first new element for our inserted event
+ m_thisTouchInputBuf[pointsCount].dwTime = tempTouchInputBuf[0].dwTime;
+ } else {
+ m_thisTouchInputBuf[pointsCount].dwTime = m_lastTouchInputBuf[i].dwTime;
+ }
+ m_thisTouchInputBuf[pointsCount].dwMask = m_lastTouchInputBuf[i].dwMask;
+
+ if (debugTouch) {
+ printf("TOUCH FIX UP %d, %s\n", m_lastTouchInputBuf[i].dwID, touchEventName(m_lastTouchInputBuf[i].dwFlags));
+ }
+
+ pointsCount++;
+ }
+ }
+ }
+
+ if (pointsCount + newCount > m_thisTouchInputBuf.size()) {
+ bufsz = pointsCount + newCount;
+ m_thisTouchInputBuf.resize(bufsz);
+ }
+
+ // now fold in the current touch points
+ for (unsigned int i = 0 ; i < newCount; i++) {
+ bool found = false;
+ for (unsigned int j = 0 ; j < m_lastTouchInputCount; j++) {
+ if (m_lastTouchInputBuf[j].dwID == tempTouchInputBuf[i].dwID) {
+ found = true;
+ break;
+ }
+ }
+
+ m_thisTouchInputBuf[pointsCount].dwFlags = tempTouchInputBuf[i].dwFlags;
+ m_thisTouchInputBuf[pointsCount].dwID = tempTouchInputBuf[i].dwID;
+ m_thisTouchInputBuf[pointsCount].dwTime = tempTouchInputBuf[i].dwTime;
+ m_thisTouchInputBuf[pointsCount].dwMask = tempTouchInputBuf[i].dwMask;
+ m_thisTouchInputBuf[pointsCount].x = tempTouchInputBuf[i].x;
+ m_thisTouchInputBuf[pointsCount].y = tempTouchInputBuf[i].y;
+
+ if (m_thisTouchInputBuf[pointsCount].dwFlags & TOUCHEVENTF_DOWN) {
+ pointsCount++;
+ activeCount ++;
+ } else if (m_thisTouchInputBuf[pointsCount].dwFlags & TOUCHEVENTF_MOVE) {
+ if (!found) {
+ if (debugTouch) {
+ printf("TOUCH FIX MV->DOWN %d, %s\n", m_thisTouchInputBuf[pointsCount].dwID, touchEventName(m_thisTouchInputBuf[pointsCount].dwFlags));
+ }
+ m_thisTouchInputBuf[pointsCount].dwFlags = TOUCHEVENTF_DOWN;
+ }
+ pointsCount++;
+ activeCount ++;
+ } else if (m_thisTouchInputBuf[pointsCount].dwFlags & TOUCHEVENTF_UP) {
+ if (found) {
+ pointsCount++;
+ } else {
+ // UP without a previous DOWN, ignore it
+ }
+ }
+ }
+
+ if (debugTouch) {
+ printf("Touch Sequence %d/%d win=%d view=%d %d,%d,%d\n",pointsCount,activeCount,
+ hWnd, GetView(),
+ m_lastTouchInputCount, newCount, pointsCount);
+ for (unsigned int i = 0 ; i < m_lastTouchInputCount; i++) {
+ printf(" old %d, %s\n", m_lastTouchInputBuf[i].dwID, touchEventName(m_lastTouchInputBuf[i].dwFlags));
+ }
+ for (unsigned int i = 0 ; i < newCount; i++) {
+ printf(" in %d, %s\n", tempTouchInputBuf[i].dwID, touchEventName(tempTouchInputBuf[i].dwFlags));
+ }
+ for (unsigned int i = 0 ; i < pointsCount; i++) {
+ printf(" this %d, %d\n", m_thisTouchInputBuf[i].dwID, m_thisTouchInputBuf[i].dwFlags & 0x07);
+ }
+ printf(" ---\n");
+ fflush(stdout);
+ }
+
+ if (pointsCount > 0) {
+ NotifyTouchInput(hWnd, GetView(), m_gestureSupportCls, &m_thisTouchInputBuf[0], pointsCount);
if (m_manipProc) {
- NotifyManipulationProcessor(*m_manipProc, pInputs, cInputs);
+ NotifyManipulationProcessor(*m_manipProc, &m_thisTouchInputBuf[0], pointsCount);
}
+
+ std::swap(m_lastTouchInputBuf, m_thisTouchInputBuf);
+ m_lastTouchInputCount = pointsCount;
+ }
+
+ if ( newCount > 0) {
+ delete [] tempTouchInputBuf;
+ }
+
+ return activeCount;
}
void ViewContainer::HandleViewTimerEvent(HWND hwnd, UINT_PTR timerID)
{
if (IDT_GLASS_INERTIAPROCESSOR == timerID) {