aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2011-10-15 10:51:54 +0200
committerSven Gothel <[email protected]>2011-10-15 10:51:54 +0200
commitec2fc482bf97459c57417a8f856345a5836680f3 (patch)
treea0414e9596791e5e3954df6586033e84af2f1d8b
parent50dca7ef60f28711397d40d8daeb8a24dff41dc2 (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.java39
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java12
-rw-r--r--src/newt/native/WindowsWindow.c33
-rw-r--r--src/newt/native/X11Window.c30
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 ;
}