--- old/modules/graphics/src/main/java/com/sun/glass/ui/TouchInputSupport.java 2015-05-26 13:37:12.384963117 -0400 +++ new/modules/graphics/src/main/java/com/sun/glass/ui/TouchInputSupport.java 2015-05-26 13:37:12.204965380 -0400 @@ -77,13 +77,16 @@ int touchEventCount) { if (curView != null && view != curView && touchCount != 0 && touch != null) { - // Release the currently pressed touch points - curView.notifyBeginTouchEvent(0, true, touchCount); - for (Map.Entry e : touch.entrySet()) { - TouchCoord coord = e.getValue(); - curView.notifyNextTouchEvent(TouchEvent.TOUCH_RELEASED, e.getKey(), coord.x, coord.y, coord.xAbs, coord.yAbs); - } - curView.notifyEndTouchEvent(); + if (!curView.isClosed()) { + // Release the currently pressed touch points + curView.notifyBeginTouchEvent(0, true, touchCount); + for (Map.Entry e : touch.entrySet()) { + TouchCoord coord = e.getValue(); + curView.notifyNextTouchEvent(TouchEvent.TOUCH_RELEASED, e.getKey(), coord.x, coord.y, coord.xAbs, coord.yAbs); + } + curView.notifyEndTouchEvent(); + } + touch.clear(); touchCount = 0; if (listener != null ) { listener.touchCountChanged(this, curView, 0, true); --- old/modules/graphics/src/main/native-glass/win/GlassWindow.cpp 2015-05-26 13:37:12.924956328 -0400 +++ new/modules/graphics/src/main/native-glass/win/GlassWindow.cpp 2015-05-26 13:37:12.744958591 -0400 @@ -59,6 +59,7 @@ unsigned int GlassWindow::sm_instanceCounter = 0; HHOOK GlassWindow::sm_hCBTFilter = NULL; HWND GlassWindow::sm_grabWindow = NULL; +static HWND activeTouchWindow = NULL; GlassWindow::GlassWindow(jobject jrefThis, bool isTransparent, bool isDecorated, bool isUnified, bool isChild, HWND parentOrOwner) : BaseWnd(parentOrOwner), @@ -575,7 +576,14 @@ break; case WM_TOUCH: if (IsEnabled()) { - HandleViewTouchEvent(GetHWND(), msg, wParam, lParam); + if (activeTouchWindow == 0 || activeTouchWindow == GetHWND()) { + if(HandleViewTouchEvent(GetHWND(), msg, wParam, lParam) > 0) { + activeTouchWindow = GetHWND(); + } else { + activeTouchWindow = 0; + } + } + fflush(stdout); return 0; } break; @@ -1278,6 +1286,10 @@ ENTER_MAIN_THREAD() { GlassWindow *pWindow = GlassWindow::FromHandle(hWnd); + + if (activeTouchWindow == hWnd) { + activeTouchWindow = 0; + } pWindow->ResetMouseTracking(hWnd); pWindow->SetGlassView(view); // The condition below may be restricted to WS_POPUP windows @@ -1565,6 +1577,11 @@ pWindow->UngrabFocus(); } } + + if (!visible && activeTouchWindow == hWnd) { + pWindow->HandleViewTouchEvent(hWnd, 0, 0, 0); + activeTouchWindow = 0; + } ::ShowWindow(hWnd, visible ? SW_SHOW : SW_HIDE); --- old/modules/graphics/src/main/native-glass/win/ViewContainer.cpp 2015-05-26 13:37:13.516948886 -0400 +++ new/modules/graphics/src/main/native-glass/win/ViewContainer.cpp 2015-05-26 13:37:13.332951199 -0400 @@ -92,6 +92,7 @@ m_kbLayout = ::GetKeyboardLayout(0); m_idLang = LOWORD(m_kbLayout); m_codePage = LangToCodePage(m_idLang); + m_lastTouchInputCount = 0; } jobject ViewContainer::GetView() @@ -1216,6 +1217,21 @@ } }; +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) @@ -1295,36 +1311,147 @@ } // 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 dynamicTouchInputBuf; - PTOUCHINPUT pInputs = staticTouchInputBuf; - - const UINT cInputs = static_cast(LOWORD(wParam)); - if (ARRAYSIZE(staticTouchInputBuf) < cInputs) { - dynamicTouchInputBuf.resize(cInputs); - pInputs = &*dynamicTouchInputBuf.begin(); - } - - do { - AutoTouchInputHandle inputInfo(lParam); - if (!::GetTouchInputInfo(inputInfo, cInputs, - pInputs, sizeof(TOUCHINPUT))) { - return; + const UINT newCount = static_cast(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, 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; + + // 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; + } } - } while(0); // scope for 'inputInfo' - NotifyTouchInput(hWnd, GetView(), m_gestureSupportCls, pInputs, cInputs); + 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); + if (m_manipProc) { + 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) --- old/modules/graphics/src/main/native-glass/win/ViewContainer.h 2015-05-26 13:37:14.092941645 -0400 +++ new/modules/graphics/src/main/native-glass/win/ViewContainer.h 2015-05-26 13:37:13.908943958 -0400 @@ -47,6 +47,10 @@ LPARAM m_lastMouseMovePosition; // or -1 unsigned int m_mouseButtonDownCounter; + UINT m_lastTouchInputCount; + std::vector m_lastTouchInputBuf; + std::vector m_thisTouchInputBuf; + void WmImeComposition(HWND hwnd, WPARAM wParam, LPARAM lParam); void WmImeNotify(HWND hwnd, WPARAM wParam, LPARAM lParam); void SendInputMethodEvent(jstring text, @@ -67,7 +71,6 @@ void HandleViewTypedEvent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); BOOL HandleViewMouseEvent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); BOOL HandleViewInputMethodEvent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); - void HandleViewTouchEvent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); LRESULT HandleViewGetAccessible(HWND hwnd, WPARAM wParam, LPARAM lParam); virtual void HandleViewTimerEvent(HWND hwnd, UINT_PTR timerID); @@ -101,6 +104,8 @@ void ResetMouseTracking(HWND hwnd); + unsigned int HandleViewTouchEvent(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + void NotifyViewSize(HWND hwnd); void NotifyGesturePerformed(HWND hWnd,