diff options
author | Sven Gothel <[email protected]> | 2013-10-17 20:03:04 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2013-10-17 20:03:04 +0200 |
commit | 5b96486da0bcd09d5355f89ec551140e508b567c (patch) | |
tree | a744400564c79bf717d75670975557da18eee983 | |
parent | 0eceb7df4b04a183a738474c0d7f4be41b6bcc0c (diff) |
Bug 800: Add Windows 7 Touch Event Support for NEWT
Native:
- WindowUserData tracks:
- window size
- mouse inside
- pointer touch-down count
and flags whether multiple-touch is supported.
- Suppress WM_*BUTTON* events if within TOUCH operations, e.g. fingers are pressed, or
if event is determined as TOUCH (0 != GetMessageExtraInfo())
- MOUSEMOVE issues NewtWindows_trackPointerLeave(..) directly
if no TOUCH operation is in process.
Removes need for MouseListener on Java side.
- TOUCH events are send as follows:
- PRIMARY first
- 1 MOVE 2nd (if not sent already)
- UP/DOWN (if not sent already)
We only send max. one MOVE event, since Win7 / Win8
assignes MOVE per default, even if no actual move happened.
Hence a single MOVE event shall suffice and is compatible
w/ e.g. Android (AFAIK).
- TOUCH pointer names are mapped to consecutive IDs
on the java side.
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java | 45 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 435 |
2 files changed, 368 insertions, 112 deletions
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java index 393445db0..b2e175415 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java @@ -46,10 +46,12 @@ import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; +import com.jogamp.common.os.Platform; +import com.jogamp.common.util.VersionNumber; import com.jogamp.newt.event.InputEvent; import com.jogamp.newt.event.KeyEvent; -import com.jogamp.newt.event.MouseAdapter; import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.event.MouseEvent.PointerType; public class WindowDriver extends WindowImpl { @@ -134,16 +136,17 @@ public class WindowDriver extends WindowImpl { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } setGraphicsConfiguration(cfg); + final VersionNumber winVer = Platform.getOSVersionNumber(); final int flags = getReconfigureFlags(0, true) & ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ; final long _windowHandle = CreateWindow0(DisplayDriver.getHInstance(), display.getWindowClassName(), display.getWindowClassName(), + winVer.getMajor(), winVer.getMinor(), getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags); if ( 0 == _windowHandle ) { throw new NativeWindowException("Error creating window"); } setWindowHandle(_windowHandle); windowHandleClose = _windowHandle; - addMouseListener(mouseTracker); if(DEBUG_IMPLEMENTATION) { Exception e = new Exception("Info: Window new window handle "+Thread.currentThread().getName()+ @@ -152,11 +155,6 @@ public class WindowDriver extends WindowImpl { e.printStackTrace(); } } - private MouseAdapter mouseTracker = new MouseAdapter() { - public void mouseEntered(MouseEvent e) { - WindowDriver.trackPointerLeave0(WindowDriver.this.getWindowHandle()); - } - }; protected void closeNativeImpl() { if(windowHandleClose != 0) { @@ -266,6 +264,33 @@ public class WindowDriver extends WindowImpl { // nop - using event driven insetsChange(..) } + // + // PointerEvent Handling + // + /** + * Send multiple-pointer {@link MouseEvent.PointerType#TouchScreen} event to be directly consumed + * <p> + * Assumes non normal pointer names and rotation/scroll will be determined by a gesture handler. + * </p> + * <p> + * See {@link #doPointerEvent(boolean, boolean, PointerType[], short, int, int, boolean, int[], int[], int[], float[], float, float[], float)} + * for details. + * </p> + */ + public final void sendTouchScreenEvent(short eventType, int modifiers, + int pActionIdx, int[] pNames, + int[] pX, int[] pY, float[] pPressure, float maxPressure) { + final int pCount = pNames.length; + final MouseEvent.PointerType[] pTypes = new MouseEvent.PointerType[pCount]; + for(int i=pCount-1; i>=0; i--) { pTypes[i] = PointerType.TouchScreen; } + doPointerEvent(false /*enqueue*/, false /*wait*/, + pTypes, eventType, modifiers, pActionIdx, false /*normalPNames*/, pNames, + pX, pY, pPressure, maxPressure, new float[] { 0f, 0f, 0f} /*rotationXYZ*/, 1f/*rotationScale*/); + } + + // + // KeyEvent Handling + // private short repeatedKey = KeyEvent.VK_UNDEFINED; private final boolean handlePressTypedAutoRepeat(boolean isModifierKey, int modifiers, short keyCode, short keySym, char keyChar) { @@ -326,9 +351,8 @@ public class WindowDriver extends WindowImpl { protected static native long getNewtWndProc0(); protected static native boolean initIDs0(long hInstance); - private native long CreateWindow0(long hInstance, String wndClassName, String wndName, - long parentWindowHandle, - int x, int y, int width, int height, boolean autoPosition, int flags); + private native long CreateWindow0(long hInstance, String wndClassName, String wndName, int winMajor, int winMinor, + long parentWindowHandle, int x, int y, int width, int height, boolean autoPosition, int flags); private native long MonitorFromWindow0(long windowHandle); private native void reconfigureWindow0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, int flags); @@ -338,5 +362,4 @@ public class WindowDriver extends WindowImpl { private static native boolean setPointerVisible0(long windowHandle, boolean visible); private static native boolean confinePointer0(long windowHandle, boolean grab, int l, int t, int r, int b); private static native void warpPointer0(long windowHandle, int x, int y); - private static native void trackPointerLeave0(long windowHandle); } diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 4ef2459e8..ec7f5dbab 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -32,6 +32,16 @@ * */ +// +// Min. required version Windows 7 (For WM_TOUCH) +// +#if WINVER < 0x0601 +#error WINVER must be >= 0x0601 +#endif +#if _WIN32_WINNT < 0x0601 +#error _WIN32_WINNT must be >= 0x0601 +#endif + #include <Windows.h> #include <Windowsx.h> #include <tchar.h> @@ -86,6 +96,13 @@ #define WH_MOUSE_LL 14 #endif +#ifndef WM_TOUCH +#define WM_TOUCH 0x0240 +#endif +#ifndef TOUCH_COORD_TO_PIXEL +#define TOUCH_COORD_TO_PIXEL(l) (l/100) +#endif + #ifndef MONITOR_DEFAULTTONULL #define MONITOR_DEFAULTTONULL 0 #endif @@ -136,6 +153,7 @@ static jmethodID visibleChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowRepaintID = NULL; static jmethodID sendMouseEventID = NULL; +static jmethodID sendTouchScreenEventID = NULL; static jmethodID sendKeyEventID = NULL; static jmethodID requestFocusID = NULL; @@ -144,8 +162,15 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd); typedef struct { JNIEnv* jenv; jobject jinstance; + /* client size width */ + int width; + /* client size height */ + int height; /** Tristate: -1 HIDE, 0 NOP, 1 SHOW */ int setPointerVisible; + int mouseInside; + int touchDownCount; + int supportsMTouch; } WindowUserData; typedef struct { @@ -544,14 +569,22 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jb DBG_PRINT("*** WindowsWindow: requestFocus.XX\n"); } -static BOOL NewtWindows_trackPointerLeave(HWND hwnd) { +static void NewtWindows_trackPointerLeave(HWND hwnd) { TRACKMOUSEEVENT tme; memset(&tme, 0, sizeof(TRACKMOUSEEVENT)); tme.cbSize = sizeof(TRACKMOUSEEVENT); tme.dwFlags = TME_LEAVE; tme.hwndTrack = hwnd; tme.dwHoverTime = 0; // we don't use TME_HOVER - return TrackMouseEvent(&tme); + BOOL ok = TrackMouseEvent(&tme); + DBG_PRINT( "*** WindowsWindow: trackPointerLeave: %d\n", ok); + #ifdef VERBOSE_ON + if(!ok) { + int lastError = (int) GetLastError(); + DBG_PRINT( "*** WindowsWindow: trackPointerLeave: lastError 0x%X %d\n", lastError, lastError); + } + #endif + (void)ok; } #if 0 @@ -676,11 +709,11 @@ static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd) #endif -static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type) +static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) { RECT rc; - int w, h; BOOL isVisible = IsWindowVisible(wnd); + jobject window = wud->jinstance; if (type == SIZE_MINIMIZED) { // TODO: deal with minimized window sizing @@ -693,12 +726,12 @@ static void WmSize(JNIEnv *env, jobject window, HWND wnd, UINT type) GetClientRect(wnd, &rc); // we report back the dimensions of the client area - w = (int) ( rc.right - rc.left ); - h = (int) ( rc.bottom - rc.top ); + wud->width = (int) ( rc.right - rc.left ); + wud->height = (int) ( rc.bottom - rc.top ); - DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, w, h, isVisible); + DBG_PRINT("*** WindowsWindow: WmSize window %p, %dx%d, visible %d\n", (void*)wnd, wud->width, wud->height, isVisible); - (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, w, h, JNI_FALSE); + (*env)->CallVoidMethod(env, window, sizeChangedID, JNI_FALSE, wud->width, wud->height, JNI_FALSE); } #ifdef TEST_MOUSE_HOOKS @@ -792,6 +825,39 @@ static BOOL SafeShowCursor(BOOL show) { return b; } +static void sendTouchScreenEvent(JNIEnv *env, jobject window, + short eventType, int modifiers, int actionIdx, + int count, jint* pointerNames, jint* x, jint* y, jfloat* pressure, float maxPressure) { + jintArray jNames = (*env)->NewIntArray(env, count); + if (jNames == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (names) of size %d", count); + } + (*env)->SetIntArrayRegion(env, jNames, 0, count, pointerNames); + + jintArray jX = (*env)->NewIntArray(env, count); + if (jX == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (x) of size %d", count); + } + (*env)->SetIntArrayRegion(env, jX, 0, count, x); + + jintArray jY = (*env)->NewIntArray(env, count); + if (jY == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate int array (y) of size %d", count); + } + (*env)->SetIntArrayRegion(env, jY, 0, count, y); + + jfloatArray jPressure = (*env)->NewFloatArray(env, count); + if (jPressure == NULL) { + NewtCommon_throwNewRuntimeException(env, "Could not allocate float array (pressure) of size %d", count); + } + (*env)->SetFloatArrayRegion(env, jPressure, 0, count, pressure); + + (*env)->CallVoidMethod(env, window, sendTouchScreenEventID, + (jshort)eventType, (jint)modifiers, (jint)actionIdx, + jNames, jX, jY, jPressure, (jfloat)maxPressure); +} + + static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lParam) { LRESULT res = 0; int useDefWindowProc = 0; @@ -885,7 +951,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; case WM_SIZE: - WmSize(env, window, wnd, (UINT)wParam); + WmSize(env, wud, wnd, (UINT)wParam); break; case WM_SETTINGCHANGE: @@ -899,83 +965,139 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; - case WM_LBUTTONDOWN: - DBG_PRINT("*** WindowsWindow: LBUTTONDOWN\n"); - (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_PRESSED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 1, (jfloat) 0.0f); - useDefWindowProc = 1; + case WM_LBUTTONDOWN: { + BOOL isMouse = 0 == GetMessageExtraInfo(); + DBG_PRINT("*** WindowsWindow: WM_LBUTTONDOWN %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n", + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount); + if( isMouse ) { + wud->mouseInside = 1; + (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_PRESSED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 1, (jfloat) 0.0f); + useDefWindowProc = 1; + } + } break; - case WM_LBUTTONUP: - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_RELEASED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 1, (jfloat) 0.0f); - useDefWindowProc = 1; + case WM_LBUTTONUP: { + BOOL isMouse = 0 == GetMessageExtraInfo(); + DBG_PRINT("*** WindowsWindow: WM_LBUTTONUP %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n", + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount); + if( isMouse ) { + wud->mouseInside = 1; + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_RELEASED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 1, (jfloat) 0.0f); + useDefWindowProc = 1; + } + } break; - case WM_MBUTTONDOWN: - DBG_PRINT("*** WindowsWindow: MBUTTONDOWN\n"); - (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_PRESSED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 2, (jfloat) 0.0f); - useDefWindowProc = 1; + case WM_MBUTTONDOWN: { + BOOL isMouse = 0 == GetMessageExtraInfo(); + DBG_PRINT("*** WindowsWindow: WM_MBUTTONDOWN %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n", + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount); + if( isMouse ) { + wud->mouseInside = 1; + (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_PRESSED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 2, (jfloat) 0.0f); + useDefWindowProc = 1; + } + } break; - case WM_MBUTTONUP: - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_RELEASED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 2, (jfloat) 0.0f); - useDefWindowProc = 1; + case WM_MBUTTONUP: { + BOOL isMouse = 0 == GetMessageExtraInfo(); + DBG_PRINT("*** WindowsWindow: WM_MBUTTONUP %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n", + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount); + if( isMouse ) { + wud->mouseInside = 1; + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_RELEASED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 2, (jfloat) 0.0f); + useDefWindowProc = 1; + } + } break; - case WM_RBUTTONDOWN: - DBG_PRINT("*** WindowsWindow: RBUTTONDOWN\n"); - (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_PRESSED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 3, (jfloat) 0.0f); - useDefWindowProc = 1; + case WM_RBUTTONDOWN: { + BOOL isMouse = 0 == GetMessageExtraInfo(); + DBG_PRINT("*** WindowsWindow: WM_RBUTTONDOWN: %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n", + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount); + if( isMouse ) { + wud->mouseInside = 1; + (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_PRESSED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 3, (jfloat) 0.0f); + useDefWindowProc = 1; + } + } break; - case WM_RBUTTONUP: - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_RELEASED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 3, (jfloat) 0.0f); - useDefWindowProc = 1; + case WM_RBUTTONUP: { + BOOL isMouse = 0 == GetMessageExtraInfo(); + DBG_PRINT("*** WindowsWindow: WM_RBUTTONUP %d/%d [%dx%d] inside %d, isMouse %d, tDown %d\n", + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + wud->width, wud->height, wud->mouseInside, isMouse, wud->touchDownCount); + if( isMouse ) { + wud->mouseInside = 1; + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_RELEASED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 3, (jfloat) 0.0f); + useDefWindowProc = 1; + } + } break; - case WM_MOUSEMOVE: - // DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d\n", (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam)); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_MOVED, - GetModifiers( 0 ), - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 0, (jfloat) 0.0f); - useDefWindowProc = 1; + case WM_MOUSEMOVE: { + wud->mouseInside = 1; + DBG_PRINT("*** WindowsWindow: WM_MOUSEMOVE %d/%d [%dx%d] inside %d, tDown %d\n", + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + wud->width, wud->height, wud->mouseInside, wud->touchDownCount); + if( wud->touchDownCount == 0 ) { + NewtWindows_trackPointerLeave(wnd); + (*env)->CallVoidMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_MOVED, + GetModifiers( 0 ), + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 0, (jfloat) 0.0f); + } + useDefWindowProc = 1; + } break; - case WM_MOUSELEAVE: - DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE\n"); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_EXITED, - 0, - (jint) -1, (jint) -1, // fake - (jshort) 0, (jfloat) 0.0f); - useDefWindowProc = 1; + case WM_MOUSELEAVE: { + wud->mouseInside = 0; + DBG_PRINT("*** WindowsWindow: WM_MOUSELEAVE %d/%d [%dx%d] inside %d, tDown %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; + } break; // Java synthesizes EVENT_MOUSE_ENTERED @@ -1036,6 +1158,116 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; } + case WM_TOUCH: if( wud->supportsMTouch ) { + UINT cInputs = LOWORD(wParam); + // DBG_PRINT("*** WindowsWindow: WM_TOUCH window %p, cInputs %d\n", wnd, cInputs); + HTOUCHINPUT hTouch = (HTOUCHINPUT)lParam; + PTOUCHINPUT pInputs = (PTOUCHINPUT) calloc(cInputs, sizeof(TOUCHINPUT)); + if (NULL != pInputs) { + if (GetTouchInputInfo(hTouch, cInputs, pInputs, sizeof(TOUCHINPUT))) { + UINT i; + short eventType[cInputs]; + jint modifiers = GetModifiers( 0 ); + jint actionIdx = -1; + jint pointerNames[cInputs]; + jint x[cInputs], y[cInputs]; + jfloat pressure[cInputs]; + jfloat maxPressure = 1.0F; // FIXME: n/a on windows ? + + 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; + int isMove = pTi->dwFlags & TOUCHEVENTF_MOVE; + + int isPrim = pTi->dwFlags & TOUCHEVENTF_PRIMARY; + int isNoCoalesc = pTi->dwFlags & TOUCHEVENTF_NOCOALESCE; + + #ifdef VERBOSE_ON + const char * touchAction; + if( isDown ) { + touchAction = "down"; + } else if( isUp ) { + touchAction = "_up_"; + } else if( isMove ) { + touchAction = "move"; + } else { + touchAction = "undf"; + } + #endif + + pointerNames[i] = (jint)pTi->dwID; + eventPt.x = TOUCH_COORD_TO_PIXEL(pTi->x); + eventPt.y = TOUCH_COORD_TO_PIXEL(pTi->y); + ScreenToClient(wnd, &eventPt); + x[i] = (jint)eventPt.x; + y[i] = (jint)eventPt.y; + pressure[i] = 1.0F; // FIXME: n/a on windows ? + if(isDown) { + eventType[i] = (jshort) EVENT_MOUSE_PRESSED; + } else if(isUp) { + eventType[i] = (jshort) EVENT_MOUSE_RELEASED; + } else if(isMove) { + eventType[i] = (jshort) EVENT_MOUSE_MOVED; + } 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); + #endif + } + int sentCount = 0, updownCount=0, moveCount=0; + // Primary first, if available! + if( 0 <= actionIdx ) { + sendTouchScreenEvent(env, window, eventType[actionIdx], modifiers, actionIdx, + cInputs, pointerNames, x, y, pressure, maxPressure); + sentCount++; + } + // 1 Move second .. + for (i=0; i < cInputs; i++) { + short et = eventType[i]; + if( (jshort) EVENT_MOUSE_MOVED == et ) { + if( i != actionIdx && 0 == moveCount ) { + sendTouchScreenEvent(env, window, et, modifiers, i, + cInputs, pointerNames, x, y, pressure, maxPressure); + sentCount++; + } + moveCount++; + } + } + // Up and downs last + for (i=0; i < cInputs; i++) { + short et = eventType[i]; + if( (jshort) EVENT_MOUSE_MOVED != et ) { + if( i != actionIdx ) { + sendTouchScreenEvent(env, window, et, modifiers, i, + cInputs, pointerNames, x, y, pressure, maxPressure); + sentCount++; + } + updownCount++; + } + } + DBG_PRINT("*** WindowsWindow: WM_TOUCH.summary pCount %d, prim %d, updown %d, move %d, sent %d\n", + cInputs, actionIdx, updownCount, moveCount, sentCount); + + // Message processed - close it + CloseTouchInputHandle(hTouch); + } else { + useDefWindowProc = 1; + } + free(pInputs); + } + break; + } + case WM_SETFOCUS: DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p\n", wnd, (HWND)wParam); (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE); @@ -1044,6 +1276,8 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP 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; break; @@ -1060,7 +1294,6 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP case WM_PAINT: { RECT r; - useDefWindowProc = 0; if (GetUpdateRect(wnd, &r, FALSE /* do not erase background */)) { // clear the whole client area and issue repaint for it, w/o looping through erase background ValidateRect(wnd, NULL); // clear all! @@ -1075,7 +1308,6 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP case WM_ERASEBKGND: // ignore erase background (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); - useDefWindowProc = 0; res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this break; case WM_SETCURSOR : @@ -1089,7 +1321,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP useDefWindowProc = visibilityChangeSuccessful ? 1 : 0; DBG_PRINT("*** WindowsWindow: WM_SETCURSOR requested visibility: %d success: %d\n", wud->setPointerVisible, visibilityChangeSuccessful); wud->setPointerVisible = 0; - useDefWindowProc = 0; // own signal, consumed + // own signal, consumed } else { useDefWindowProc = 1; // NOP for us, allow parent to act } @@ -1545,6 +1777,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0 windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V"); + sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SII[I[I[I[FF)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); @@ -1556,6 +1789,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0 windowDestroyNotifyID == NULL || windowRepaintID == NULL || sendMouseEventID == NULL || + sendTouchScreenEventID == NULL || sendKeyEventID == NULL || requestFocusID == NULL) { return JNI_FALSE; @@ -1615,9 +1849,8 @@ static void NewtWindow_setVisiblePosSize(HWND hwnd, BOOL atop, BOOL visible, */ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindow0 (JNIEnv *env, jobject obj, - jlong hInstance, jstring jWndClassName, jstring jWndName, - jlong parent, - jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags) + jlong hInstance, jstring jWndClassName, jstring jWndName, jint winMajor, jint winMinor, + jlong parent, jint jx, jint jy, jint defaultWidth, jint defaultHeight, jboolean autoPosition, jint flags) { HWND parentWindow = (HWND) (intptr_t) parent; const TCHAR* wndClassName = NULL; @@ -1659,8 +1892,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo (HINSTANCE) (intptr_t) hInstance, NULL); - DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", - (int)GetCurrentThreadId(), parentWindow, window, x, y, width, height, + DBG_PRINT("*** WindowsWindow: CreateWindow thread 0x%X, win %d.%d parent %p, window %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", + (int)GetCurrentThreadId(), winMajor, winMinor, parentWindow, window, x, y, width, height, TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition); if (NULL == window) { @@ -1671,7 +1904,24 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo WindowUserData * wud = (WindowUserData *) malloc(sizeof(WindowUserData)); wud->jinstance = (*env)->NewGlobalRef(env, obj); wud->jenv = env; + wud->width = width; + wud->height = height; wud->setPointerVisible = 0; + wud->mouseInside = 0; + wud->touchDownCount = 0; + wud->supportsMTouch = 0; + if ( winMajor > 6 || ( winMajor == 6 && winMinor >= 1 ) ) { + int value = GetSystemMetrics(SM_DIGITIZER); + if (value & NID_READY) { /* ready */ + if (value & NID_MULTI_INPUT) { /* multitouch */ + wud->supportsMTouch = 1; + } + if (value & NID_INTEGRATED_TOUCH) { /* Integrated touch */ + } + } + } + DBG_PRINT("*** WindowsWindow: CreateWindow supportsMTouch %d\n", wud->supportsMTouch); + #if !defined(__MINGW64__) && ( defined(UNDER_CE) || _MSC_VER <= 1200 ) SetWindowLong(window, GWL_USERDATA, (intptr_t) wud); #else @@ -1704,6 +1954,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_windows_WindowDriver_CreateWindo NewtWindow_setVisiblePosSize(window, TST_FLAG_IS_ALWAYSONTOP(flags), TRUE, x, y, width, height); } + if( wud->supportsMTouch ) { + RegisterTouchWindow(window, 0); + } } #ifdef UNICODE @@ -1930,23 +2183,3 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_warpPointer0 SetCursorPos(x, y); } -/* - * Class: Java_jogamp_newt_driver_windows_WindowDriver - * Method: trackPointerLeave0 - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_trackPointerLeave0 - (JNIEnv *env, jclass clazz, jlong window) -{ - HWND hwnd = (HWND) (intptr_t) window; - BOOL ok = NewtWindows_trackPointerLeave(hwnd); - DBG_PRINT( "*** WindowsWindow: trackMouseLeave0: %d\n", ok); - #ifdef VERBOSE_ON - if(!ok) { - int lastError = (int) GetLastError(); - DBG_PRINT( "*** WindowsWindow: trackMouseLeave0: lastError 0x%X %d\n", lastError, lastError); - } - #endif - (void)ok; -} - |