summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-10-17 20:03:04 +0200
committerSven Gothel <[email protected]>2013-10-17 20:03:04 +0200
commit5b96486da0bcd09d5355f89ec551140e508b567c (patch)
treea744400564c79bf717d75670975557da18eee983
parent0eceb7df4b04a183a738474c0d7f4be41b6bcc0c (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.java45
-rw-r--r--src/newt/native/WindowsWindow.c435
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;
-}
-