aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-10-17 23:02:04 +0200
committerSven Gothel <[email protected]>2013-10-17 23:02:04 +0200
commit3c56d9346b9077b5eb65ec9e111917cfe17e9173 (patch)
tree20e213cbef2a1caff5c7d95efcd196b29d17ece0 /src
parent119133e89831fc837015b3f6fd7b258077c93d46 (diff)
Bug 800: Windows 7 Touch Event Support for NEWT: Fix Focus and LBUTTON[DOWN|UP] issues
- w/ TOUCH, Win8 may steal focus (KILLFOCUS), quickly grab FOCUS again when on TOUCH operation - track 'touchDownLastUp', and don't act on LBUTTON[UP|DOWN] and MOUSEMOVE if just lifted last finger - don't use GetMessageExtraInfo() to distinguish MOUSE/TOUCH, simply use tracked touchDownCount - Also track mouseInside in TOUCH operation, i.e. true if _all_ fingers are inside, otherwise don't send TOUCH event
Diffstat (limited to 'src')
-rw-r--r--src/newt/native/WindowsWindow.c125
1 files changed, 74 insertions, 51 deletions
diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c
index ec7f5dbab..a19efbc7a 100644
--- a/src/newt/native/WindowsWindow.c
+++ b/src/newt/native/WindowsWindow.c
@@ -170,6 +170,7 @@ typedef struct {
int setPointerVisible;
int mouseInside;
int touchDownCount;
+ int touchDownLastUp; // mitigate LBUTTONUP after last TOUCH lift
int supportsMTouch;
} WindowUserData;
@@ -966,11 +967,10 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
case WM_LBUTTONDOWN: {
- BOOL isMouse = 0 == GetMessageExtraInfo();
- DBG_PRINT("*** WindowsWindow: WM_LBUTTONDOWN %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n",
+ DBG_PRINT("*** WindowsWindow: WM_LBUTTONDOWN %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n",
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount);
- if( isMouse ) {
+ wud->width, wud->height, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) {
wud->mouseInside = 1;
(*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
(*env)->CallVoidMethod(env, window, sendMouseEventID,
@@ -984,11 +984,13 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
break;
case WM_LBUTTONUP: {
- BOOL isMouse = 0 == GetMessageExtraInfo();
- DBG_PRINT("*** WindowsWindow: WM_LBUTTONUP %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n",
+ DBG_PRINT("*** WindowsWindow: WM_LBUTTONUP %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n",
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount);
- if( isMouse ) {
+ wud->width, wud->height, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 < wud->touchDownLastUp ) {
+ // mitigate LBUTTONUP after last TOUCH lift
+ wud->touchDownLastUp = 0;
+ } else if( 0 == wud->touchDownCount ) {
wud->mouseInside = 1;
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jshort) EVENT_MOUSE_RELEASED,
@@ -1001,11 +1003,10 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
break;
case WM_MBUTTONDOWN: {
- BOOL isMouse = 0 == GetMessageExtraInfo();
- DBG_PRINT("*** WindowsWindow: WM_MBUTTONDOWN %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n",
+ DBG_PRINT("*** WindowsWindow: WM_MBUTTONDOWN %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n",
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount);
- if( isMouse ) {
+ wud->width, wud->height, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
wud->mouseInside = 1;
(*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
(*env)->CallVoidMethod(env, window, sendMouseEventID,
@@ -1019,11 +1020,10 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
break;
case WM_MBUTTONUP: {
- BOOL isMouse = 0 == GetMessageExtraInfo();
- DBG_PRINT("*** WindowsWindow: WM_MBUTTONUP %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n",
+ DBG_PRINT("*** WindowsWindow: WM_MBUTTONUP %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n",
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount);
- if( isMouse ) {
+ wud->width, wud->height, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
wud->mouseInside = 1;
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jshort) EVENT_MOUSE_RELEASED,
@@ -1036,11 +1036,10 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
break;
case WM_RBUTTONDOWN: {
- BOOL isMouse = 0 == GetMessageExtraInfo();
- DBG_PRINT("*** WindowsWindow: WM_RBUTTONDOWN: %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n",
+ DBG_PRINT("*** WindowsWindow: WM_RBUTTONDOWN %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n",
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount);
- if( isMouse ) {
+ wud->width, wud->height, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
wud->mouseInside = 1;
(*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
(*env)->CallVoidMethod(env, window, sendMouseEventID,
@@ -1054,11 +1053,10 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
break;
case WM_RBUTTONUP: {
- BOOL isMouse = 0 == GetMessageExtraInfo();
- DBG_PRINT("*** WindowsWindow: WM_RBUTTONUP %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n",
+ DBG_PRINT("*** WindowsWindow: WM_RBUTTONUP %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n",
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount);
- if( isMouse ) {
+ wud->width, wud->height, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
wud->mouseInside = 1;
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jshort) EVENT_MOUSE_RELEASED,
@@ -1071,11 +1069,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
break;
case WM_MOUSEMOVE: {
- wud->mouseInside = 1;
- DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d [%dx%d] inside %d, tDown %d\n",
+ DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n",
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- wud->width, wud->height, wud->mouseInside, wud->touchDownCount);
- if( wud->touchDownCount == 0 ) {
+ wud->width, wud->height, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) {
+ wud->mouseInside = 1;
NewtWindows_trackPointerLeave(wnd);
(*env)->CallVoidMethod(env, window, sendMouseEventID,
(jshort) EVENT_MOUSE_MOVED,
@@ -1087,16 +1085,18 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
}
break;
case WM_MOUSELEAVE: {
- wud->mouseInside = 0;
- DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE %d/%d [%dx%d] inside %d, tDown %d\n",
+ DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n",
(jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam),
- wud->width, wud->height, wud->mouseInside, wud->touchDownCount);
- (*env)->CallVoidMethod(env, window, sendMouseEventID,
- (jshort) EVENT_MOUSE_EXITED,
- 0,
- (jint) -1, (jint) -1, // fake
- (jshort) 0, (jfloat) 0.0f);
- useDefWindowProc = 1;
+ wud->width, wud->height, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp);
+ if( 0 == wud->touchDownCount ) {
+ wud->mouseInside = 0;
+ (*env)->CallVoidMethod(env, window, sendMouseEventID,
+ (jshort) EVENT_MOUSE_EXITED,
+ 0,
+ (jint) -1, (jint) -1, // fake
+ (jshort) 0, (jfloat) 0.0f);
+ useDefWindowProc = 1;
+ }
}
break;
// Java synthesizes EVENT_MOUSE_ENTERED
@@ -1173,10 +1173,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
jint x[cInputs], y[cInputs];
jfloat pressure[cInputs];
jfloat maxPressure = 1.0F; // FIXME: n/a on windows ?
+ int allPInside = 0 < cInputs;
+ int sendFocus = 0;
for (i=0; i < cInputs; i++) {
PTOUCHINPUT pTi = & pInputs[i];
- int inside;
POINT eventPt;
int isDown = pTi->dwFlags & TOUCHEVENTF_DOWN;
int isUp = pTi->dwFlags & TOUCHEVENTF_UP;
@@ -1184,6 +1185,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
int isPrim = pTi->dwFlags & TOUCHEVENTF_PRIMARY;
int isNoCoalesc = pTi->dwFlags & TOUCHEVENTF_NOCOALESCE;
+ int isPInside;
#ifdef VERBOSE_ON
const char * touchAction;
@@ -1202,31 +1204,46 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
eventPt.x = TOUCH_COORD_TO_PIXEL(pTi->x);
eventPt.y = TOUCH_COORD_TO_PIXEL(pTi->y);
ScreenToClient(wnd, &eventPt);
+
+ isPInside = 0 <= eventPt.x && 0 <= eventPt.y && eventPt.x < wud->width && eventPt.y < wud->height;
+ allPInside &= isPInside;
+
x[i] = (jint)eventPt.x;
y[i] = (jint)eventPt.y;
pressure[i] = 1.0F; // FIXME: n/a on windows ?
if(isDown) {
+ sendFocus = 0 == wud->touchDownCount;
eventType[i] = (jshort) EVENT_MOUSE_PRESSED;
+ wud->touchDownCount++;
+ wud->touchDownLastUp = 0;
} else if(isUp) {
eventType[i] = (jshort) EVENT_MOUSE_RELEASED;
+ wud->touchDownCount--;
+ // mitigate LBUTTONUP after last TOUCH lift
+ wud->touchDownLastUp = 0 == wud->touchDownCount;
} else if(isMove) {
eventType[i] = (jshort) EVENT_MOUSE_MOVED;
+ wud->touchDownLastUp = 0;
} else {
eventType[i] = (jshort) 0;
}
if(isPrim) {
actionIdx = (jint)i;
}
- inside = 0 <= x[i] && 0 <= y[i] && x[i] < wud->width && y[i] < wud->height;
#ifdef VERBOSE_ON
- DBG_PRINT("*** WindowsWindow: WM_TOUCH[%d/%d].%s name 0x%x, prim %d, nocoalsc %d, %d/%d [%dx%d] inside %d/%d, tDown %d\n",
- (i+1), cInputs, touchAction, (int)(pTi->dwID), isPrim, isNoCoalesc, x[i], y[i], wud->width, wud->height, inside, wud->mouseInside, wud->touchDownCount);
+ DBG_PRINT("*** WindowsWindow: WM_TOUCH[%d/%d].%s name 0x%x, prim %d, nocoalsc %d, %d/%d [%dx%d] inside [%d/%d], tDown [c %d, lastUp %d]\n",
+ (i+1), cInputs, touchAction, (int)(pTi->dwID), isPrim, isNoCoalesc, x[i], y[i], wud->width, wud->height,
+ isPInside, allPInside, wud->touchDownCount, wud->touchDownLastUp);
#endif
}
+ wud->mouseInside = allPInside;
+ if( sendFocus && allPInside ) {
+ (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE);
+ }
int sentCount = 0, updownCount=0, moveCount=0;
// Primary first, if available!
- if( 0 <= actionIdx ) {
+ if( 0 <= actionIdx && allPInside ) {
sendTouchScreenEvent(env, window, eventType[actionIdx], modifiers, actionIdx,
cInputs, pointerNames, x, y, pressure, maxPressure);
sentCount++;
@@ -1235,7 +1252,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
for (i=0; i < cInputs; i++) {
short et = eventType[i];
if( (jshort) EVENT_MOUSE_MOVED == et ) {
- if( i != actionIdx && 0 == moveCount ) {
+ if( i != actionIdx && 0 == moveCount && allPInside ) {
sendTouchScreenEvent(env, window, et, modifiers, i,
cInputs, pointerNames, x, y, pressure, maxPressure);
sentCount++;
@@ -1247,7 +1264,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
for (i=0; i < cInputs; i++) {
short et = eventType[i];
if( (jshort) EVENT_MOUSE_MOVED != et ) {
- if( i != actionIdx ) {
+ if( i != actionIdx && allPInside ) {
sendTouchScreenEvent(env, window, et, modifiers, i,
cInputs, pointerNames, x, y, pressure, maxPressure);
sentCount++;
@@ -1255,8 +1272,8 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
updownCount++;
}
}
- DBG_PRINT("*** WindowsWindow: WM_TOUCH.summary pCount %d, prim %d, updown %d, move %d, sent %d\n",
- cInputs, actionIdx, updownCount, moveCount, sentCount);
+ DBG_PRINT("*** WindowsWindow: WM_TOUCH.summary pCount %d, prim %d, updown %d, move %d, sent %d, inside %d, tDown [c %d, lastUp %d]\n",
+ cInputs, actionIdx, updownCount, moveCount, sentCount, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp);
// Message processed - close it
CloseTouchInputHandle(hTouch);
@@ -1275,11 +1292,16 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP
break;
case WM_KILLFOCUS:
- DBG_PRINT("*** WindowsWindow: WM_KILLFOCUS window %p, received %p\n", wnd, (HWND)wParam);
- wud->touchDownCount=0;
- wud->mouseInside=0;
- (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
- useDefWindowProc = 1;
+ DBG_PRINT("*** WindowsWindow: WM_KILLFOCUS window %p, received %p, inside %d, tDown %d\n",
+ wnd, (HWND)wParam, wud->mouseInside, wud->touchDownCount);
+ if( wud->touchDownCount == 0 ) {
+ wud->mouseInside=0;
+ (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE);
+ useDefWindowProc = 1;
+ } else {
+ // quick focus .. we had it already, are enabled ..
+ SetFocus(wnd);// Sets Keyboard Focus To Window (activates parent window if exist, or this window)
+ }
break;
case WM_SHOWWINDOW:
@@ -1909,6 +1931,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo
wud->setPointerVisible = 0;
wud->mouseInside = 0;
wud->touchDownCount = 0;
+ wud->touchDownLastUp = 0;
wud->supportsMTouch = 0;
if ( winMajor > 6 || ( winMajor == 6 && winMinor >= 1 ) ) {
int value = GetSystemMetrics(SM_DIGITIZER);