diff options
author | Sven Gothel <[email protected]> | 2011-10-15 10:51:54 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2011-10-15 10:51:54 +0200 |
commit | ec2fc482bf97459c57417a8f856345a5836680f3 (patch) | |
tree | a0414e9596791e5e3954df6586033e84af2f1d8b | |
parent | 50dca7ef60f28711397d40d8daeb8a24dff41dc2 (diff) |
NEWT/Mouse: Skip 'move' event w/ same position. Add Enter/Exit events
Skip 'mouse move' event w/ same position
- On Windows, the OS sends us multiple event w/o change in position, suppress them
Add Enter/Exit events incl. synthesize 'enter' event for windows/osx
- X11: using native Enter/Leave events
- Windows: using native Leave event (tracking) and synthesized enter event
- OSX: TODO (required for the confined feature, etc)
-rw-r--r-- | src/newt/classes/jogamp/newt/WindowImpl.java | 39 | ||||
-rw-r--r-- | src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java | 12 | ||||
-rw-r--r-- | src/newt/native/WindowsWindow.c | 33 | ||||
-rw-r--r-- | src/newt/native/X11Window.c | 30 |
4 files changed, 107 insertions, 7 deletions
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index f0c351048..b8f0929a8 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -119,6 +119,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private int mouseButtonPressed = 0; // current pressed mouse button number private long lastMousePressed = 0; // last time when a mouse button was pressed private int lastMouseClickCount = 0; // last mouse button click count + private boolean mouseInWindow = false;// mouse entered window - is inside the window (may be synthetic) + private Point lastMousePosition = new Point(); private ArrayList<KeyListener> keyListeners = new ArrayList<KeyListener>(); @@ -1893,17 +1895,46 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } private void doMouseEvent(boolean enqueue, boolean wait, int eventType, int modifiers, int x, int y, int button, int rotation) { + if(eventType == MouseEvent.EVENT_MOUSE_ENTERED || + eventType == MouseEvent.EVENT_MOUSE_EXITED) { + if(eventType == MouseEvent.EVENT_MOUSE_EXITED && x==-1 && y==-1) { + x = lastMousePosition.getX(); + y = lastMousePosition.getY(); + } + // clip coordinates to window dimension + x = Math.min(Math.max(x, 0), width-1); + y = Math.min(Math.max(y, 0), height-1); + mouseInWindow = eventType == MouseEvent.EVENT_MOUSE_ENTERED; + } if(x<0||y<0||x>=width||y>=height) { return; // .. invalid .. } if(DEBUG_MOUSE_EVENT) { - System.err.println("doMouseEvent: enqueue"+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+ - ", mod "+modifiers+", pos "+x+"/"+y+", button "+button); + System.err.println("doMouseEvent: enqueue "+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+ + ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+lastMousePosition); + } + long when = System.currentTimeMillis(); + if(eventType == MouseEvent.EVENT_MOUSE_MOVED) { + if(!mouseInWindow) { + mouseInWindow = true; + MouseEvent e = new MouseEvent(MouseEvent.EVENT_MOUSE_ENTERED, this, when, + modifiers, x, y, lastMouseClickCount, button, 0); + if(DEBUG_MOUSE_EVENT) { + System.err.println("doMouseEvent: synthesized MOUSE_ENTERED event: "+e); + } + doEvent(enqueue, wait, e); + } else if(lastMousePosition.getX() == x && lastMousePosition.getY()==y) { + if(DEBUG_MOUSE_EVENT) { + System.err.println("doMouseEvent: skip EVENT_MOUSE_MOVED w/ same position: "+lastMousePosition); + } + return; // skip same position + } + lastMousePosition.setX(x); + lastMousePosition.setY(y); } if(button<0||button>MouseEvent.BUTTON_NUMBER) { throw new NativeWindowException("Invalid mouse button number" + button); } - long when = System.currentTimeMillis(); MouseEvent eClicked = null; MouseEvent e = null; @@ -1951,7 +1982,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer doEvent(enqueue, wait, e); if(null!=eClicked) { if(DEBUG_MOUSE_EVENT) { - System.err.println("doMouseEvent: synthesized MOUSE_CLICKED event"); + System.err.println("doMouseEvent: synthesized MOUSE_CLICKED event: "+eClicked); } doEvent(enqueue, wait, eClicked); } diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java index 6e1444da3..cd5909d42 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java @@ -42,6 +42,9 @@ import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.InsetsImmutable; import javax.media.nativewindow.util.Point; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; + public class WindowsWindow extends WindowImpl { private long hmon; @@ -112,6 +115,8 @@ public class WindowsWindow extends WindowImpl { throw new NativeWindowException("Error creating window"); } windowHandleClose = getWindowHandle(); + addMouseListener(new MouseTracker()); + if(DEBUG_IMPLEMENTATION) { Exception e = new Exception("Info: Window new window handle "+Thread.currentThread().getName()+ " (Parent HWND "+toHexString(getParentWindowHandle())+ @@ -119,6 +124,12 @@ public class WindowsWindow extends WindowImpl { e.printStackTrace(); } } + + class MouseTracker extends MouseAdapter { + public void mouseEntered(MouseEvent e) { + WindowsWindow.trackPointerLeave0(WindowsWindow.this.getWindowHandle()); + } + } protected void closeNativeImpl() { if (hdc != 0) { @@ -251,4 +262,5 @@ public class WindowsWindow 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 3eba0f345..0d969e670 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -617,6 +617,16 @@ static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, jb DBG_PRINT("*** WindowsWindow: requestFocus.XX\n"); } +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 + TrackMouseEvent(&tme); +} + #if 0 static RECT* UpdateInsets(JNIEnv *env, jobject window, HWND hwnd) @@ -925,6 +935,15 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, (jint) 0, (jint) 0); useDefWindowProc = 1; break; + case WM_MOUSELEAVE: + (*env)->CallVoidMethod(env, window, enqueueMouseEventID, JNI_FALSE, + (jint) EVENT_MOUSE_EXITED, + 0, + (jint) -1, (jint) -1, // fake + (jint) 0, (jint) 0); + useDefWindowProc = 1; + break; + // Java synthesizes EVENT_MOUSE_ENTERED case WM_MOUSEWHEEL: { // need to convert the coordinates to component-relative @@ -986,7 +1005,6 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, break; - // FIXME: generate EVENT_MOUSE_ENTERED, EVENT_MOUSE_EXITED default: useDefWindowProc = 1; } @@ -1651,3 +1669,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_warpPointer SetCursorPos(x, y); } +/* + * Class: Java_jogamp_newt_driver_windows_WindowsWindow + * Method: trackPointerLeave0 + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowsWindow_trackPointerLeave0 + (JNIEnv *env, jclass clazz, jlong window) +{ + HWND hwnd = (HWND) (intptr_t) window; + DBG_PRINT( "*** WindowsWindow: trackMouseLeave0\n"); + NewtWindows_trackPointerLeave(hwnd); +} + diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index c7b271188..6b6c1ff6c 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -161,6 +161,8 @@ static jint X11InputState2NewtModifiers(unsigned int xstate) { return modifiers; } +#define X11_MOUSE_EVENT_MASK (ButtonPressMask | ButtonReleaseMask | PointerMotionMask | EnterWindowMask | LeaveWindowMask) + static const char * const ClazzNameNewtWindow = "com/jogamp/newt/Window"; static jclass newtWindowClz=NULL; @@ -837,6 +839,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Display_DispatchMessages0 (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0 /*rotation*/); #endif break; + case EnterNotify: + DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); + #ifdef USE_SENDIO_DIRECT + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, + modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, + modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); + #endif + break; + case LeaveNotify: + DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y); + #ifdef USE_SENDIO_DIRECT + (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, + modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); + #else + (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, + modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0 /*rotation*/); + #endif + break; case KeyPress: #ifdef USE_SENDIO_DIRECT (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, @@ -1586,7 +1612,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0 xswa.backing_store=NotUseful; /* NotUseful, WhenMapped, Always */ xswa.backing_planes=0; /* planes to be preserved if possible */ xswa.backing_pixel=0; /* value to use in restoring planes */ - xswa.event_mask = ButtonPressMask | ButtonReleaseMask | PointerMotionMask ; + xswa.event_mask = X11_MOUSE_EVENT_MASK; xswa.event_mask |= KeyPressMask | KeyReleaseMask ; xswa.event_mask |= FocusChangeMask | SubstructureNotifyMask | StructureNotifyMask | ExposureMask ; @@ -1952,7 +1978,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_X11Window_confinePointer0 if(JNI_TRUE == confine) { return GrabSuccess == XGrabPointer(dpy, w, True, - ButtonPressMask | ButtonReleaseMask | PointerMotionMask, + X11_MOUSE_EVENT_MASK, GrabModeAsync, GrabModeAsync, w, None, CurrentTime) ? JNI_TRUE : JNI_FALSE ; } |