aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2013-11-17 01:54:32 +0100
committerSven Gothel <[email protected]>2013-11-17 01:54:32 +0100
commit88f6e0012b36ca69dedaadb4e403e2a424b20cbf (patch)
treeee43887c90dda1e02b5bb488a04b5287dfcd4048 /src
parentebed9f0322e2a2279a525e04ee3875c9034a7f45 (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')
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MouseEvent.java2
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MouseListener.java2
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java236
-rw-r--r--src/newt/native/InputEvent.h6
-rw-r--r--src/newt/native/WindowsWindow.c132
5 files changed, 257 insertions, 121 deletions
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
index 635bdba52..272e4beb0 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
@@ -589,7 +589,9 @@ public class MouseEvent extends InputEvent
private static final PointerType[] constMousePointerTypes = new PointerType[] { PointerType.Mouse };
public static final short EVENT_MOUSE_CLICKED = 200;
+ /** Only generated for {@link PointerType#Mouse} */
public static final short EVENT_MOUSE_ENTERED = 201;
+ /** Only generated for {@link PointerType#Mouse} */
public static final short EVENT_MOUSE_EXITED = 202;
public static final short EVENT_MOUSE_PRESSED = 203;
public static final short EVENT_MOUSE_RELEASED = 204;
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseListener.java b/src/newt/classes/com/jogamp/newt/event/MouseListener.java
index 5378080b9..6e5142044 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseListener.java
@@ -44,7 +44,9 @@ import com.jogamp.newt.event.MouseEvent.PointerType;
public interface MouseListener extends NEWTEventListener
{
public void mouseClicked(MouseEvent e);
+ /** Only generated for {@link PointerType#Mouse} */
public void mouseEntered(MouseEvent e);
+ /** Only generated for {@link PointerType#Mouse} */
public void mouseExited(MouseEvent e);
public void mousePressed(MouseEvent e);
public void mouseReleased(MouseEvent e);
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 246c288d0..99e863a0e 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -186,37 +186,45 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
/** from event passing: {@link WindowImpl#consumePointerEvent(MouseEvent)}. */
private static class PointerState0 {
- /** mouse entered window - is inside the window (may be synthetic) */
+ /** Pointer entered window - is inside the window (may be synthetic) */
boolean insideWindow = false;
+ /** Mouse EXIT has been sent (only for MOUSE type enter/exit)*/
+ boolean exitSent = false;
- /** last time when a mouse button was pressed */
+ /** last time when a pointer button was pressed */
long lastButtonPressTime = 0;
+ /** Pointer in dragging mode */
+ boolean dragging = false;
+
void clearButton() {
lastButtonPressTime = 0;
}
+ public String toString() { return "PState0[inside "+insideWindow+", exitSent "+exitSent+", lastPress "+lastButtonPressTime+", dragging "+dragging+"]"; }
}
private final PointerState0 pState0 = new PointerState0();
/** from direct input: {@link WindowImpl#doPointerEvent(boolean, boolean, int[], short, int, int, boolean, short[], int[], int[], float[], float, float[], float)}. */
private static class PointerState1 extends PointerState0 {
- /** current pressed mouse button number */
+ /** Current pressed mouse button number */
short buttonPressed = (short)0;
- /** current pressed mouse button modifier mask */
+ /** Current pressed mouse button modifier mask */
int buttonPressedMask = 0;
- /** last mouse button click count */
+ /** Last mouse button click count */
short lastButtonClickCount = (short)0;
@Override
final void clearButton() {
super.clearButton();
- lastButtonPressTime = 0;
lastButtonClickCount = (short)0;
- buttonPressed = 0;
- buttonPressedMask = 0;
+ if( !dragging || 0 == buttonPressedMask ) {
+ buttonPressed = 0;
+ buttonPressedMask = 0;
+ dragging = false;
+ }
}
- /** last pointer-move position for 8 touch-down pointers */
+ /** Last pointer-move position for 8 touch-down pointers */
final Point[] movePositions = new Point[] {
new Point(), new Point(), new Point(), new Point(),
new Point(), new Point(), new Point(), new Point() };
@@ -226,10 +234,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
return null;
}
+ public final String toString() { return "PState1[inside "+insideWindow+", exitSent "+exitSent+", lastPress "+lastButtonPressTime+
+ ", pressed [button "+buttonPressed+", mask "+buttonPressedMask+", dragging "+dragging+", clickCount "+lastButtonClickCount+"]"; }
}
private final PointerState1 pState1 = new PointerState1();
- /** pointer names -> pointer ID (consecutive index, starting w/ 0) */
+ /** Pointer names -> pointer ID (consecutive index, starting w/ 0) */
private final ArrayHashSet<Integer> pName2pID = new ArrayHashSet<Integer>();
private boolean defaultGestureHandlerEnabled = true;
@@ -2365,25 +2375,25 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Native MouseEvents pre-processed to be enqueued or consumed directly
//
- public final void sendMouseEvent(short eventType, int modifiers,
- int x, int y, short button, float rotation) {
+ public final void sendMouseEvent(final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
doMouseEvent(false, false, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
}
- public final void enqueueMouseEvent(boolean wait, short eventType, int modifiers,
- int x, int y, short button, float rotation) {
+ public final void enqueueMouseEvent(final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
doMouseEvent(true, wait, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
}
- protected final void doMouseEvent(boolean enqueue, boolean wait, short eventType, int modifiers,
- int x, int y, short button, float rotation) {
+ protected final void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float rotation) {
doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, MouseEvent.getRotationXYZ(rotation, modifiers), 1f);
}
/**
- public final void sendMouseEvent(short eventType, int modifiers,
- int x, int y, short button, float[] rotationXYZ, float rotationScale) {
+ public final void sendMouseEvent(final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
doMouseEvent(false, false, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
}
- public final void enqueueMouseEvent(boolean wait, short eventType, int modifiers,
- int x, int y, short button, float[] rotationXYZ, float rotationScale) {
+ public final void enqueueMouseEvent(final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
doMouseEvent(true, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
} */
@@ -2394,8 +2404,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
* otherwise {@link #consumeEvent(NEWTEvent) consumed} directly.
* @param wait if true wait until {@link #consumeEvent(NEWTEvent) consumed}.
*/
- protected void doMouseEvent(boolean enqueue, boolean wait, short eventType, int modifiers,
- int x, int y, short button, final float[] rotationXYZ, float rotationScale) {
+ protected void doMouseEvent(final boolean enqueue, final boolean wait, final short eventType, final int modifiers,
+ final int x, final int y, final short button, final float[] rotationXYZ, final float rotationScale) {
if( 0 > button || button > MouseEvent.BUTTON_COUNT ) {
throw new NativeWindowException("Invalid mouse button number" + button);
}
@@ -2437,10 +2447,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
* @param pPressure Pressure for each pointer (multiple pointer)
* @param maxPressure Maximum pointer pressure for all pointer
*/
- public final void doPointerEvent(boolean enqueue, boolean wait,
- final PointerType[] pTypes, short eventType, int modifiers,
- int actionIdx, boolean normalPNames, final int[] pNames,
- final int[] pX, final int[] pY, float[] pPressure,
+ public final void doPointerEvent(final boolean enqueue, final boolean wait,
+ final PointerType[] pTypes, final short eventType, final int modifiers,
+ final int actionIdx, final boolean normalPNames, final int[] pNames,
+ final int[] pX, final int[] pY, final float[] pPressure,
float maxPressure, final float[] rotationXYZ, final float rotationScale) {
final int pCount = pNames.length;
final short[] pIDs = new short[pCount];
@@ -2511,10 +2521,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
* @param pPressure Pressure for each pointer (multiple pointer)
* @param maxPressure Maximum pointer pressure for all pointer
*/
- public final void doPointerEvent(boolean enqueue, boolean wait,
- final PointerType[] pTypes, short eventType, int modifiers,
- int pActionIdx, final short[] pID, final int[] pX, final int[] pY, final float[] pPressure,
- float maxPressure, final float[] rotationXYZ, float rotationScale) {
+ public final void doPointerEvent(final boolean enqueue, final boolean wait,
+ final PointerType[] pTypes, final short eventType, int modifiers,
+ final int pActionIdx, final short[] pID, final int[] pX, final int[] pY, final float[] pPressure,
+ final float maxPressure, final float[] rotationXYZ, final float rotationScale) {
final long when = System.currentTimeMillis();
final int pCount = pTypes.length;
@@ -2565,9 +2575,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
//
int x = pX[0];
int y = pY[0];
+ final boolean insideWindow = x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
final Point movePositionP0 = pState1.getMovePosition(id);
switch( eventType ) {
case MouseEvent.EVENT_MOUSE_EXITED:
+ if( pState1.dragging ) {
+ // Drop mouse EXIT if dragging, i.e. due to exterior dragging outside of window.
+ // NOTE-1: X11 produces the 'premature' EXIT, however it also produces 'EXIT' after exterior dragging!
+ // NOTE-2: consumePointerEvent(MouseEvent) will synthesize a missing EXIT event!
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop "+MouseEvent.getEventTypeString(eventType)+" due to dragging: "+pState1);
+ }
+ return;
+ }
if( null != movePositionP0 ) {
if( x==-1 && y==-1 ) {
x = movePositionP0.getX();
@@ -2578,21 +2598,35 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Fall through intended!
case MouseEvent.EVENT_MOUSE_ENTERED:
+ if( eventType == MouseEvent.EVENT_MOUSE_ENTERED ) {
+ pState1.insideWindow = true;
+ pState1.exitSent = false;
+ } else {
+ pState1.insideWindow = false;
+ pState1.exitSent = true;
+ }
+ pState1.clearButton();
+ if( pTypes[0] != PointerType.Mouse ) {
+ // Drop !MOUSE ENTER/EXIT Events - Safeguard for non compliant implementations only.
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("doPointerEvent: drop "+MouseEvent.getEventTypeString(eventType)+" due to !Mouse but "+pTypes[0]+": "+pState1);
+ }
+ return;
+ }
// clip coordinates to window dimension
x = Math.min(Math.max(x, 0), getWidth()-1);
y = Math.min(Math.max(y, 0), getHeight()-1);
- pState1.insideWindow = eventType == MouseEvent.EVENT_MOUSE_ENTERED;
- pState1.clearButton();
break;
case MouseEvent.EVENT_MOUSE_MOVED:
case MouseEvent.EVENT_MOUSE_DRAGGED:
if( null != movePositionP0 ) {
- if( pState1.insideWindow && movePositionP0.getX() == x && movePositionP0.getY() == y ) {
+ if( movePositionP0.getX() == x && movePositionP0.getY() == y ) {
+ // Drop same position
if(DEBUG_MOUSE_EVENT) {
- System.err.println("doPointerEvent: skip "+MouseEvent.getEventTypeString(eventType)+" w/ same position: "+movePositionP0);
+ System.err.println("doPointerEvent: drop "+MouseEvent.getEventTypeString(eventType)+" w/ same position: "+movePositionP0+", "+pState1);
}
- return; // skip same position
+ return;
}
movePositionP0.set(x, y);
}
@@ -2600,25 +2634,30 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Fall through intended !
default:
- if(!pState1.insideWindow) {
- pState1.insideWindow = true;
+ if( pState1.insideWindow != insideWindow ) {
+ // ENTER/EXIT!
+ pState1.insideWindow = insideWindow;
+ if( insideWindow ) {
+ pState1.exitSent = false;
+ }
pState1.clearButton();
}
}
//
- // Drop exterior events
+ // Drop exterior events if not dragging pointer and not EXIT event
+ // Safeguard for non compliant implementations!
//
- if( x < 0 || y < 0 || x >= getWidth() || y >= getHeight() ) {
+ if( !pState1.dragging && !insideWindow && MouseEvent.EVENT_MOUSE_EXITED != eventType ) {
if(DEBUG_MOUSE_EVENT) {
System.err.println("doPointerEvent: drop: "+MouseEvent.getEventTypeString(eventType)+
- ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+movePositionP0);
+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+movePositionP0+", insideWindow "+insideWindow+", "+pState1);
}
return; // .. invalid ..
}
if(DEBUG_MOUSE_EVENT) {
System.err.println("doPointerEvent: enqueue "+enqueue+", wait "+wait+", "+MouseEvent.getEventTypeString(eventType)+
- ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+movePositionP0);
+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button+", lastMousePosition: "+movePositionP0+", "+pState1);
}
final int buttonMask = InputEvent.getButtonMask(button);
@@ -2668,6 +2707,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
break;
case MouseEvent.EVENT_MOUSE_RELEASED:
+ pState1.buttonPressedMask &= ~buttonMask;
if( 1 == pCount ) {
e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
pX, pY, pPressure, maxPressure, button, pState1.lastButtonClickCount, rotationXYZ, rotationScale);
@@ -2676,11 +2716,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
pState1.lastButtonPressTime = 0;
}
pState1.buttonPressed = 0;
+ pState1.dragging = false;
} else {
e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
pX, pY, pPressure, maxPressure, button, (short)1, rotationXYZ, rotationScale);
+ if( 0 == pState1.buttonPressedMask ) {
+ pState1.clearButton();
+ }
}
- pState1.buttonPressedMask &= ~buttonMask;
if( null != movePositionP0 ) {
movePositionP0.set(0, 0);
}
@@ -2689,6 +2732,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if ( 0 != pState1.buttonPressedMask ) { // any button or pointer move -> drag
e = new MouseEvent(MouseEvent.EVENT_MOUSE_DRAGGED, this, when, modifiers, pTypes, pID,
pX, pY, pPressure, maxPressure, pState1.buttonPressed, (short)1, rotationXYZ, rotationScale);
+ pState1.dragging = true;
} else {
e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
pX, pY, pPressure, maxPressure, button, (short)0, rotationXYZ, rotationScale);
@@ -2698,6 +2742,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if( 0 >= pPressure[0] ) {
pPressure[0] = maxPressure;
}
+ pState1.dragging = true;
// Fall through intended!
default:
e = new MouseEvent(eventType, this, when, modifiers, pTypes, pID,
@@ -2831,7 +2876,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
* <ul>
* <li>Validate</li>
* <li>Handle gestures</li>
- * <li>Synthesize events ENTERED, CLICK and gestures.</li>
+ * <li>Synthesize events [ENTERED, EXIT, CLICK] and gestures.</li>
* <li>Drop exterior events</li>
* <li>Dispatch event to listener</li>
* </ul>
@@ -2842,50 +2887,84 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
int y = pe.getY();
if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumePointerEvent.in: "+pe);
+ System.err.println("consumePointerEvent.in: "+pe+", "+pState0+", pos "+x+"/"+y+" clientSize["+getWidth()+"x"+getHeight()+"]");
}
//
// - Determine ENTERED/EXITED state
- // - Synthesize ENTERED event
+ // - Synthesize ENTERED and EXIT event
// - Reset states if applicable
//
final long when = pe.getWhen();
- int eventType = pe.getEventType();
- final MouseEvent eEntered;
+ final int eventType = pe.getEventType();
+ final boolean insideWindow;
+ boolean eExitAllowed = false;
+ MouseEvent eEntered = null, eExited = null;
switch( eventType ) {
case MouseEvent.EVENT_MOUSE_EXITED:
+ if( pState0.exitSent || pState0.dragging ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent: drop "+(pState0.exitSent?"already sent":"due to dragging")+": "+pe+", "+pState0);
+ }
+ return;
+ }
+ // Fall through intended !
case MouseEvent.EVENT_MOUSE_ENTERED:
// clip coordinates to window dimension
x = Math.min(Math.max(x, 0), getWidth()-1);
y = Math.min(Math.max(y, 0), getHeight()-1);
- pState0.insideWindow = eventType == MouseEvent.EVENT_MOUSE_ENTERED;
pState0.clearButton();
- eEntered = null;
+ if( eventType == MouseEvent.EVENT_MOUSE_ENTERED ) {
+ insideWindow = true;
+ pState0.insideWindow = true;
+ pState0.exitSent = false;
+ pState0.dragging = false;
+ } else {
+ insideWindow = false;
+ pState0.insideWindow = false;
+ pState0.exitSent = true;
+ }
break;
+ case MouseEvent.EVENT_MOUSE_MOVED:
+ case MouseEvent.EVENT_MOUSE_RELEASED:
+ if( 1 >= pe.getButtonDownCount() ) { // MOVE or RELEASE last button
+ eExitAllowed = !pState0.exitSent;
+ pState0.dragging = false;
+ }
+ // Fall through intended !
+
default:
- if(!pState0.insideWindow) {
- pState0.insideWindow = true;
+ insideWindow = x >= 0 && y >= 0 && x < getWidth() && y < getHeight();
+ if( pe.getPointerType(0) == PointerType.Mouse ) {
+ if( !pState0.insideWindow && insideWindow ) {
+ // ENTER .. use clipped coordinates
+ eEntered = new MouseEvent(MouseEvent.EVENT_MOUSE_ENTERED, pe.getSource(), pe.getWhen(), pe.getModifiers(),
+ Math.min(Math.max(x, 0), getWidth()-1),
+ Math.min(Math.max(y, 0), getHeight()-1),
+ (short)0, (short)0, pe.getRotation(), pe.getRotationScale());
+ pState0.exitSent = false;
+ } else if( !insideWindow && eExitAllowed ) {
+ // EXIT .. use clipped coordinates
+ eExited = new MouseEvent(MouseEvent.EVENT_MOUSE_EXITED, pe.getSource(), pe.getWhen(), pe.getModifiers(),
+ Math.min(Math.max(x, 0), getWidth()-1),
+ Math.min(Math.max(y, 0), getHeight()-1),
+ (short)0, (short)0, pe.getRotation(), pe.getRotationScale());
+ pState0.exitSent = true;
+ }
+ }
+ if( pState0.insideWindow != insideWindow || null != eEntered || null != eExited) {
pState0.clearButton();
- eEntered = pe.createVariant(MouseEvent.EVENT_MOUSE_ENTERED);
- } else {
- eEntered = null;
}
+ pState0.insideWindow = insideWindow;
}
if( null != eEntered ) {
if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumePointerEvent.send.0: "+eEntered);
+ System.err.println("consumePointerEvent.send.0: "+eEntered+", "+pState0);
}
dispatchMouseEvent(eEntered);
- } else if( x < 0 || y < 0 || x >= getWidth() || y >= getHeight() ) {
- //
- // Drop exterior events
- //
- if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumePointerEvent.drop: "+pe);
- }
- return; // .. invalid ..
+ } else if( DEBUG_MOUSE_EVENT && !insideWindow ) {
+ System.err.println("INFO consumePointerEvent.exterior: "+pState0+", "+pe);
}
//
@@ -2906,7 +2985,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
scaledScrollSlop = Math.round(DoubleTapScrollGesture.SCROLL_SLOP_MM * pixPerMM);
scaledDoubleTapSlop = Math.round(DoubleTapScrollGesture.DOUBLE_TAP_SLOP_MM * pixPerMM);
if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumePointerEvent.gscroll: scrollSlop "+scaledScrollSlop+", doubleTapSlop "+scaledDoubleTapSlop+", pixPerMM "+pixPerMM+", "+monitor);
+ System.err.println("consumePointerEvent.gscroll: scrollSlop "+scaledScrollSlop+", doubleTapSlop "+scaledDoubleTapSlop+", pixPerMM "+pixPerMM+", "+monitor+", "+pState0);
}
} else {
scaledScrollSlop = DoubleTapScrollGesture.SCROLL_SLOP_PIXEL;
@@ -2919,7 +2998,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
pe = (MouseEvent) gesture2PtrTouchScroll.getGestureEvent();
gesture2PtrTouchScroll.clear(false);
if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumePointerEvent.gscroll: "+pe);
+ System.err.println("consumePointerEvent.gscroll: "+pe+", "+pState0);
}
dispatchMouseEvent(pe);
return;
@@ -2962,46 +3041,51 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// - Synthesize mouse CLICKED
// - Ignore sent CLICKED
//
- final MouseEvent eClicked;
+ MouseEvent eClicked = null;
switch( eventType ) {
case MouseEvent.EVENT_MOUSE_PRESSED:
if( 1 == pe.getPointerCount() ) {
pState0.lastButtonPressTime = when;
}
- eClicked = null;
break;
case MouseEvent.EVENT_MOUSE_RELEASED:
if( 1 == pe.getPointerCount() && when - pState0.lastButtonPressTime < MouseEvent.getClickTimeout() ) {
eClicked = pe.createVariant(MouseEvent.EVENT_MOUSE_CLICKED);
} else {
- eClicked = null;
pState0.lastButtonPressTime = 0;
}
break;
case MouseEvent.EVENT_MOUSE_CLICKED:
// ignore - synthesized here ..
if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumePointerEvent: drop recv'ed (synth here) "+pe);
+ System.err.println("consumePointerEvent: drop recv'ed (synth here) "+pe+", "+pState0);
}
pe = null;
- eClicked = null;
break;
- default:
- eClicked = null;
+
+ case MouseEvent.EVENT_MOUSE_DRAGGED:
+ pState0.dragging = true;
+ break;
}
if( null != pe ) {
if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumePointerEvent.send.1: "+pe);
+ System.err.println("consumePointerEvent.send.1: "+pe+", "+pState0);
}
dispatchMouseEvent(pe); // actual mouse event
}
if( null != eClicked ) {
if(DEBUG_MOUSE_EVENT) {
- System.err.println("consumePointerEvent.send.2: "+eClicked);
+ System.err.println("consumePointerEvent.send.2: "+eClicked+", "+pState0);
}
dispatchMouseEvent(eClicked);
}
+ if( null != eExited ) {
+ if(DEBUG_MOUSE_EVENT) {
+ System.err.println("consumePointerEvent.send.3: "+eExited+", "+pState0);
+ }
+ dispatchMouseEvent(eExited);
+ }
}
private final void dispatchMouseEvent(MouseEvent e) {
@@ -3205,11 +3289,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
//
@Override
public void sendWindowEvent(int eventType) {
- consumeWindowEvent( new WindowEvent((short)eventType, this, System.currentTimeMillis()) ); // FIXME
+ consumeWindowEvent( new WindowEvent((short)eventType, this, System.currentTimeMillis()) );
}
public void enqueueWindowEvent(boolean wait, int eventType) {
- enqueueEvent( wait, new WindowEvent((short)eventType, this, System.currentTimeMillis()) ); // FIXME
+ enqueueEvent( wait, new WindowEvent((short)eventType, this, System.currentTimeMillis()) );
}
@Override
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",