diff options
author | Sven Gothel <sgothel@jausoft.com> | 2013-11-17 01:54:32 +0100 |
---|---|---|
committer | Sven Gothel <sgothel@jausoft.com> | 2013-11-17 01:54:32 +0100 |
commit | 88f6e0012b36ca69dedaadb4e403e2a424b20cbf (patch) | |
tree | ee43887c90dda1e02b5bb488a04b5287dfcd4048 /src/newt/native | |
parent | ebed9f0322e2a2279a525e04ee3875c9034a7f45 (diff) |
Bug 903 - NEWT: Support 'Continue Drag on Exit'; Consistent Mouse ENTER/EXIT
- Support 'Continue Drag on Exit'
- Track dragging operation, allow exterior dragging
- Hence track EXIT (see below)
- Windows:
- Capture mouse for exterior dragging
- Only 'NewtWindows_trackPointerLeave' if 'entering'
- Simplify touch: No 'inside' check - Not required.
- Consistent Mouse ENTER/EXIT
- Track ENTER/EXIT and synthesize if required, drop duplicate
- OSX benefits, since it never produced ENTER/EXIT events
- AWT (or other TK) translated events beahve equal now.
- Required for EXIT event after ending exterior dragging and final RELEASE
Tests: Passed unit tests 'junit.run.newt.event' on
- GNU/Linux
- Windows7
- OSX 10.7
Tested exterior tracking manually w/ NEWT TestGearsES2NEWT and TestGearsES2NewtCanvasAWT:
- GNU/Linux
- Windows7 (mouse)
- Windows8.1 (touch)
- OSX 10.7
Diffstat (limited to 'src/newt/native')
-rw-r--r-- | src/newt/native/InputEvent.h | 6 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 132 |
2 files changed, 93 insertions, 45 deletions
diff --git a/src/newt/native/InputEvent.h b/src/newt/native/InputEvent.h index 3fa7dbefe..2de46f82e 100644 --- a/src/newt/native/InputEvent.h +++ b/src/newt/native/InputEvent.h @@ -50,6 +50,12 @@ #define EVENT_BUTTON8_MASK (1 << 12) #define EVENT_BUTTON9_MASK (1 << 13) +/** 16 buttons */ +#define EVENT_BUTTONLAST_MASK (1 << 20) + +/** 16 buttons */ +#define EVENT_BUTTONALL_MASK ( 0xffff << 5 ) + #define EVENT_AUTOREPEAT_MASK (1 << 29) #define EVENT_CONFINED_MASK (1 << 30) #define EVENT_INVISIBLE_MASK (1 << 31) diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 884e538d3..692bb9d4f 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -186,7 +186,8 @@ typedef struct { int height; /** Tristate: -1 HIDE, 0 NOP, 1 SHOW */ int setPointerVisible; - int mouseInside; + int pointerCaptured; + int pointerInside; int touchDownCount; int touchDownLastUp; // mitigate LBUTTONUP after last TOUCH lift int supportsMTouch; @@ -985,11 +986,14 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP case WM_LBUTTONDOWN: { - DBG_PRINT("*** WindowsWindow: WM_LBUTTONDOWN %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n", + DBG_PRINT("*** WindowsWindow: WM_LBUTTONDOWN %d/%d [%dx%d] inside %d, captured %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, wud->touchDownLastUp); + wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) { - wud->mouseInside = 1; + if( 0 == wud->pointerInside ) { + wud->pointerInside = 1; + NewtWindows_trackPointerLeave(wnd); + } (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, @@ -1002,14 +1006,22 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_LBUTTONUP: { - DBG_PRINT("*** WindowsWindow: WM_LBUTTONUP %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n", + DBG_PRINT("*** WindowsWindow: WM_LBUTTONUP %d/%d [%dx%d] inside %d, captured %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, wud->touchDownLastUp); + wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, 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; + jint modifiers = GetModifiers(0); + if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) { + wud->pointerCaptured = 0; + ReleaseCapture(); + } + if( 0 == wud->pointerInside ) { + wud->pointerInside = 1; + NewtWindows_trackPointerLeave(wnd); + } (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, GetModifiers( 0 ), @@ -1021,11 +1033,14 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_MBUTTONDOWN: { - DBG_PRINT("*** WindowsWindow: WM_MBUTTONDOWN %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n", + DBG_PRINT("*** WindowsWindow: WM_MBUTTONDOWN %d/%d [%dx%d] inside %d, captured %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, wud->touchDownLastUp); + wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); if( 0 == wud->touchDownCount ) { - wud->mouseInside = 1; + if( 0 == wud->pointerInside ) { + wud->pointerInside = 1; + NewtWindows_trackPointerLeave(wnd); + } (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, @@ -1038,11 +1053,19 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_MBUTTONUP: { - DBG_PRINT("*** WindowsWindow: WM_MBUTTONUP %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n", + DBG_PRINT("*** WindowsWindow: WM_MBUTTONUP %d/%d [%dx%d] inside %d, captured %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, wud->touchDownLastUp); + wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); if( 0 == wud->touchDownCount ) { - wud->mouseInside = 1; + jint modifiers = GetModifiers(0); + if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) { + wud->pointerCaptured = 0; + ReleaseCapture(); + } + if( 0 == wud->pointerInside ) { + wud->pointerInside = 1; + NewtWindows_trackPointerLeave(wnd); + } (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, GetModifiers( 0 ), @@ -1054,11 +1077,14 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_RBUTTONDOWN: { - DBG_PRINT("*** WindowsWindow: WM_RBUTTONDOWN %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n", + DBG_PRINT("*** WindowsWindow: WM_RBUTTONDOWN %d/%d [%dx%d] inside %d, captured %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, wud->touchDownLastUp); + wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); if( 0 == wud->touchDownCount ) { - wud->mouseInside = 1; + if( 0 == wud->pointerInside ) { + wud->pointerInside = 1; + NewtWindows_trackPointerLeave(wnd); + } (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, @@ -1071,11 +1097,19 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_RBUTTONUP: { - DBG_PRINT("*** WindowsWindow: WM_RBUTTONUP %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n", + DBG_PRINT("*** WindowsWindow: WM_RBUTTONUP %d/%d [%dx%d] inside %d, captured %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, wud->touchDownLastUp); + wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); if( 0 == wud->touchDownCount ) { - wud->mouseInside = 1; + jint modifiers = GetModifiers(0); + if( wud->pointerCaptured && 0 == ( modifiers & EVENT_BUTTONALL_MASK ) ) { + wud->pointerCaptured = 0; + ReleaseCapture(); + } + if( 0 == wud->pointerInside ) { + wud->pointerInside = 1; + NewtWindows_trackPointerLeave(wnd); + } (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, GetModifiers( 0 ), @@ -1087,15 +1121,22 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_MOUSEMOVE: { - DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n", + DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d [%dx%d] inside %d, captured %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, wud->touchDownLastUp); + wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); if( 0 == wud->touchDownLastUp && 0 == wud->touchDownCount ) { - wud->mouseInside = 1; - NewtWindows_trackPointerLeave(wnd); + jint modifiers = GetModifiers(0); + if( 0 == wud->pointerCaptured && 0 != ( modifiers & EVENT_BUTTONALL_MASK ) ) { + wud->pointerCaptured = 1; + SetCapture(wnd); + } + if( 0 == wud->pointerInside ) { + wud->pointerInside = 1; + NewtWindows_trackPointerLeave(wnd); + } (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, - GetModifiers( 0 ), + modifiers, (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), (jshort) 0, (jfloat) 0.0f); } @@ -1103,11 +1144,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP } break; case WM_MOUSELEAVE: { - DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE %d/%d [%dx%d] inside %d, tDown [c %d, lastUp %d]\n", + DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE %d/%d [%dx%d] inside %d, captured %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, wud->touchDownLastUp); + wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); if( 0 == wud->touchDownCount ) { - wud->mouseInside = 0; + wud->pointerInside = 0; (*env)->CallVoidMethod(env, window, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED, 0, @@ -1203,7 +1244,6 @@ 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; @@ -1223,8 +1263,8 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP 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; + int pInside = 0 <= eventPt.x && 0 <= eventPt.y && eventPt.x < wud->width && eventPt.y < wud->height; + allPInside &= pInside; x[i] = (jint)eventPt.x; y[i] = (jint)eventPt.y; @@ -1252,16 +1292,16 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP #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 [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); + pInside, allPInside, wud->touchDownCount, wud->touchDownLastUp); #endif } - wud->mouseInside = allPInside; - if( sendFocus && allPInside ) { + wud->pointerInside = allPInside; + if( sendFocus ) { (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); } int sentCount = 0, updownCount=0, moveCount=0; // Primary first, if available! - if( 0 <= actionIdx && allPInside ) { + if( 0 <= actionIdx ) { sendTouchScreenEvent(env, window, eventType[actionIdx], modifiers, actionIdx, cInputs, pointerNames, x, y, pressure, maxPressure); sentCount++; @@ -1270,7 +1310,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 && allPInside ) { + if( i != actionIdx && 0 == moveCount ) { sendTouchScreenEvent(env, window, et, modifiers, i, cInputs, pointerNames, x, y, pressure, maxPressure); sentCount++; @@ -1282,7 +1322,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 && allPInside ) { + if( i != actionIdx ) { sendTouchScreenEvent(env, window, et, modifiers, i, cInputs, pointerNames, x, y, pressure, maxPressure); sentCount++; @@ -1290,8 +1330,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, inside %d, tDown [c %d, lastUp %d]\n", - cInputs, actionIdx, updownCount, moveCount, sentCount, wud->mouseInside, wud->touchDownCount, wud->touchDownLastUp); + DBG_PRINT("*** WindowsWindow: WM_TOUCH.summary pCount %d, prim %d, updown %d, move %d, sent %d, inside %d, captured %d, tDown [c %d, lastUp %d]\n", + cInputs, actionIdx, updownCount, moveCount, sentCount, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); // Message processed - close it WinTouch_CloseTouchInputHandle(hTouch); @@ -1310,10 +1350,14 @@ 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, inside %d, tDown %d\n", - wnd, (HWND)wParam, wud->mouseInside, wud->touchDownCount); + DBG_PRINT("*** WindowsWindow: WM_KILLFOCUS window %p, received %p, inside %d, captured %d, tDown %d\n", + wnd, (HWND)wParam, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount); if( wud->touchDownCount == 0 ) { - wud->mouseInside=0; + wud->pointerInside = 0; + if( wud->pointerCaptured ) { + wud->pointerCaptured = 0; + ReleaseCapture(); + } (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE); useDefWindowProc = 1; } else { @@ -1963,7 +2007,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo wud->width = width; wud->height = height; wud->setPointerVisible = 0; - wud->mouseInside = 0; + wud->pointerCaptured = 0; + wud->pointerInside = 0; wud->touchDownCount = 0; wud->touchDownLastUp = 0; wud->supportsMTouch = 0; @@ -2214,12 +2259,9 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_confineP jboolean res; if(JNI_TRUE == confine) { - // SetCapture(hwnd); - // res = ( GetCapture() == hwnd ) ? JNI_TRUE : JNI_FALSE; RECT rect = { l, t, r, b }; res = ClipCursor(&rect) ? JNI_TRUE : JNI_FALSE; } else { - // res = ReleaseCapture() ? JNI_TRUE : JNI_FALSE; res = ClipCursor(NULL) ? JNI_TRUE : JNI_FALSE; } DBG_PRINT( "*** WindowsWindow: confinePointer0: %d, [ l %d t %d r %d b %d ], res %d\n", |