diff options
Diffstat (limited to 'src')
25 files changed, 814 insertions, 380 deletions
diff --git a/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java b/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java index b2f1a56b6..b6e8c26d5 100644 --- a/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java +++ b/src/demos/com/jogamp/opengl/demos/util/MiscUtils.java @@ -260,6 +260,10 @@ public class MiscUtils { System.err.println("Destroying window from thread "+Thread.currentThread()); // Thread.dumpStack(); glad.destroy(); + final GLAnimatorControl animator = glad.getAnimator(); + if( null != animator ) { + animator.stop(); // Avoiding a ThreadDeath of animator at shutdown + } } } } diff --git a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java index 9d1490300..8483250b5 100644 --- a/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java +++ b/src/jogl/classes/jogamp/opengl/GLAutoDrawableBase.java @@ -632,6 +632,7 @@ public abstract class GLAutoDrawableBase implements GLAutoDrawable, GLStateKeepe public final RunnableTask invokeOnNewThread(final ThreadGroup tg, final boolean waitUntilDone, final Runnable runnable) { return RunnableTask.invokeOnNewThread(tg, null, waitUntilDone, new Runnable() { + @Override public final void run() { helper.runOutsideOfExclusiveContextThread(context, runnable); } }); diff --git a/src/jogl/classes/jogamp/opengl/GLContextImpl.java b/src/jogl/classes/jogamp/opengl/GLContextImpl.java index bbd9b40e0..8a60b65f9 100644 --- a/src/jogl/classes/jogamp/opengl/GLContextImpl.java +++ b/src/jogl/classes/jogamp/opengl/GLContextImpl.java @@ -480,7 +480,7 @@ public abstract class GLContextImpl extends GLContext { final int lockRes = drawable.lockSurface(); if ( NativeSurface.LOCK_SURFACE_NOT_READY >= lockRes ) { // this would be odd .. - throw new GLException("Surface not ready to lock: "+drawable); + throw new GLException("Surface not ready to lock: res "+lockRes+", "+drawable+", "+toString()); } Throwable associateDrawableException = null; try { diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index e43961e98..82f878a98 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -1029,8 +1029,9 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur * @param y dirty-region x-pos in pixel units * @param width dirty-region width in pixel units * @param height dirty-region height in pixel units + * @return true if window {@link #isNativeValid()} */ - void windowRepaint(int x, int y, int width, int height); + boolean windowRepaint(int x, int y, int width, int height); /** * Enqueues a {@link com.jogamp.newt.event.NEWTEvent NEWT event}. diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index cbac22e26..09f5e1ebf 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -844,8 +844,8 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind // Window completion // @Override - public final void windowRepaint(final int x, final int y, final int width, final int height) { - window.windowRepaint(x, y, width, height); + public final boolean windowRepaint(final int x, final int y, final int width, final int height) { + return window.windowRepaint(x, y, width, height); } @Override diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index ff713410b..26a2544c7 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -146,10 +146,14 @@ public class DefaultEDTUtil implements EDTUtil { @Override public final boolean invokeStop(final boolean wait, final Runnable task) { if(DEBUG) { - System.err.println(Thread.currentThread()+": Default-EDT.invokeStop wait "+wait); + System.err.println(Thread.currentThread()+": Default-EDT.invokeStop.0 wait "+wait+" "+this); ExceptionUtils.dumpStack(System.err); } - return invokeImpl(wait, task, true /* stop */, false /* provokeError */); + final boolean res = invokeImpl(wait, task, true /* stop */, false /* provokeError */); + if(DEBUG) { + System.err.println(Thread.currentThread()+": Default-EDT.invokeStop.X wait "+wait+" "+this); + } + return res; } public final boolean invokeAndWaitError(final Runnable task) { @@ -202,7 +206,8 @@ public class DefaultEDTUtil implements EDTUtil { if( !edt.isRunning ) { if( null != task ) { if( stop ) { - System.err.println(Thread.currentThread()+": Warning: Default-EDT is about (3) to stop and stopped already, dropping task. Remaining tasks: "+edt.tasks.size()+" - "+edt); + System.err.println(Thread.currentThread()+": Warning: Default-EDT is about (3) to stop and stopped already, executing stop-task. Remaining tasks: "+edt.tasks.size()+" - "+edt); + task.run(); } else { System.err.println(Thread.currentThread()+": Warning: Default-EDT is not running, dropping task. NEDT "+edt); } @@ -210,7 +215,7 @@ public class DefaultEDTUtil implements EDTUtil { ExceptionUtils.dumpStack(System.err); } } - return false; + return stop; // OK if invokeStop } else if( stop && null == task ) { task = nullTask; // ensures execution triggering stop } diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index aea42b66d..cea779d0b 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -821,6 +821,6 @@ public abstract class DisplayImpl extends Display { protected int hashCode; protected int refCount; // number of Display references by Screen protected boolean exclusive; // do not share this display, uses NullLock! - protected AbstractGraphicsDevice aDevice; + protected volatile AbstractGraphicsDevice aDevice; } diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 75c1e9474..ff333f720 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -69,7 +69,6 @@ import com.jogamp.common.ExceptionUtils; import com.jogamp.common.os.Clock; import com.jogamp.common.util.ArrayHashSet; import com.jogamp.common.util.Bitfield; -import com.jogamp.common.util.InterruptSource; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.ReflectionUtil; import com.jogamp.common.util.locks.LockFactory; @@ -2363,7 +2362,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return stateMask.get(STATE_BIT_MAXIMIZED_HORZ); } /** Triggered by implementation's WM events to update maximized window state. */ - protected final void maximizedChanged(final boolean newMaxHorz, final boolean newMaxVert) { + protected final boolean maximizedChanged(final boolean newMaxHorz, final boolean newMaxVert) { if( !isFullscreen() ) { final String stateMask0 = DEBUG_IMPLEMENTATION ? getStateMaskString() : null; final boolean changedHorz = stateMask.put(STATE_BIT_MAXIMIZED_HORZ, newMaxHorz) != newMaxHorz; @@ -2381,6 +2380,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer System.err.println("Window.maximizedChanged.ignored: "+stateMask0+" -> max["+(newMaxHorz?"":"!")+"h, "+(newMaxVert?"":"!")+"v]"); } } + return isNativeValid(); } /** * Manually calculate maximized and de-maximized position and size @@ -3756,14 +3756,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // Native MouseEvents pre-processed to be enqueued or consumed directly // - public final void sendMouseEvent(final short eventType, final int modifiers, - final int x, final int y, final short button, final float rotation) { + public final boolean 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); + return isNativeValid(); } - public final void enqueueMouseEvent(final boolean wait, final short eventType, final int modifiers, + public final boolean 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); + return isNativeValid(); } 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) { @@ -4543,14 +4545,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return false; } - public void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { + public boolean sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { // Always add currently pressed mouse buttons to modifier mask consumeKeyEvent( KeyEvent.create(eventType, this, System.currentTimeMillis(), modifiers | pState1.buttonPressedMask, keyCode, keySym, keyChar) ); + return isNativeValid(); } - public void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { + public boolean enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { // Always add currently pressed mouse buttons to modifier mask enqueueEvent(wait, KeyEvent.create(eventType, this, System.currentTimeMillis(), modifiers | pState1.buttonPressedMask, keyCode, keySym, keyChar) ); + return isNativeValid(); } @Override @@ -4779,7 +4783,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // /** Triggered by implementation's WM events to update the focus state. */ - protected void focusChanged(final boolean defer, final boolean focusGained) { + protected boolean focusChanged(final boolean defer, final boolean focusGained) { if( stateMask.get(PSTATE_BIT_FOCUS_CHANGE_BROKEN) || stateMask.get(STATE_BIT_FOCUSED) != focusGained ) { @@ -4797,15 +4801,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer enqueueWindowEvent(false, evt); } } + return isNativeValid(); } /** Triggered by implementation's WM events to update the visibility state. */ - protected final void visibleChanged(final boolean visible) { + protected final boolean visibleChanged(final boolean visible) { if( stateMask.put(STATE_BIT_VISIBLE, visible) != visible ) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window.visibleChanged ("+getThreadName()+"): visible "+(!visible)+" -> state "+getStateMaskString()+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); } } + return isNativeValid(); } /** Triggered by implementation's WM events to update the client-area size in window units w/o insets/decorations. */ @@ -4840,10 +4846,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_RESIZED); } } - return true; - } else { - return false; } + return isNativeValid(); } /** Triggered by implementation's WM events to update the position. */ @@ -4871,11 +4875,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } else { enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED); } - return true; } else { stateMask.clear(STATE_BIT_AUTOPOSITION); // ensure it's off even w/ same position - return false; } + return isNativeValid(); } /** @@ -4888,7 +4891,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @see #getInsets() * @see #updateInsetsImpl(Insets) */ - protected final void insetsChanged(final boolean windowUnits, final int leftU, final int rightU, final int topU, final int bottomU) { + protected final boolean insetsChanged(final boolean windowUnits, final int leftU, final int rightU, final int topU, final int bottomU) { if ( leftU >= 0 && rightU >= 0 && topU >= 0 && bottomU >= 0 ) { final int[] tl_win; final int[] br_win; @@ -4915,6 +4918,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer insets.set(tl_win[0], br_win[0], tl_win[1], br_win[1]); } } + return isNativeValid(); } /** @@ -4925,7 +4929,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @param width dirty-region width in pixel units * @param height dirty-region height in pixel units */ - protected final void windowRepaint(final boolean defer, final int x, final int y, int width, int height) { + protected final boolean windowRepaint(final boolean defer, final int x, final int y, int width, int height) { width = ( 0 >= width ) ? getSurfaceWidth() : width; height = ( 0 >= height ) ? getSurfaceHeight() : height; if(DEBUG_IMPLEMENTATION) { @@ -4936,6 +4940,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer final NEWTEvent e = new WindowUpdateEvent(WindowEvent.EVENT_WINDOW_REPAINT, this, System.currentTimeMillis(), new Rectangle(x, y, width, height)); doEvent(defer, false, e); + return true; + } else { + return false; } } @@ -5002,19 +5009,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @param button * @param rotation */ - protected final void visibleChangedSendMouseEvent(final boolean defer, final int visibleChange, - final short eventType, final int modifiers, - final int x, final int y, final short button, final float rotation) { + protected final boolean visibleChangedSendMouseEvent(final boolean defer, final int visibleChange, + final short eventType, final int modifiers, + final int x, final int y, final short button, final float rotation) { + boolean res = true; if( 0 <= visibleChange ) { // ignore visible < 0 - visibleChanged(0 < visibleChange); + res = visibleChanged(0 < visibleChange); } if( 0 < eventType ) { if( defer ) { - enqueueMouseEvent(false /* wait */, eventType, modifiers, x, y, button, rotation); + res = res && enqueueMouseEvent(false /* wait */, eventType, modifiers, x, y, button, rotation); } else { - sendMouseEvent(eventType, modifiers, x, y, button, rotation); + res = res && sendMouseEvent(eventType, modifiers, x, y, button, rotation); } } + return res; } /** @@ -5026,12 +5035,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @param width dirty-region width in pixel units * @param height dirty-region height in pixel units */ - protected final void visibleChangedWindowRepaint(final boolean defer, final int visibleChange, - final int x, final int y, final int width, final int height) { + protected final boolean visibleChangedWindowRepaint(final boolean defer, final int visibleChange, + final int x, final int y, final int width, final int height) { + boolean res = true; if( 0 <= visibleChange ) { // ignore visible < 0 - visibleChanged(0 < visibleChange); + res = visibleChanged(0 < visibleChange); } - windowRepaint(defer, x, y, width, height); + return res && windowRepaint(defer, x, y, width, height); } /** @@ -5041,15 +5051,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @param focusChange -1 ignored, 0 unfocused, > 0 focused * @param visibleChange -1 ignored, 0 invisible, > 0 visible */ - protected final void focusVisibleChanged(final boolean defer, - final int focusChange, - final int visibleChange) { + protected final boolean focusVisibleChanged(final boolean defer, + final int focusChange, + final int visibleChange) { + boolean res = true; if( 0 <= focusChange ) { // ignore focus < 0 - focusChanged(defer, 0 < focusChange); + res = focusChanged(defer, 0 < focusChange); } if( 0 <= visibleChange ) { // ignore visible < 0 - visibleChanged(0 < visibleChange); + res = res && visibleChanged(0 < visibleChange); } + return res && isNativeValid(); } /** @@ -5061,12 +5073,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @param bottom insets, -1 ignored * @param visibleChange -1 ignored, 0 invisible, > 0 visible */ - protected final void insetsVisibleChanged(final boolean windowUnits, - final int left, final int right, final int top, final int bottom, final int visibleChange) { - insetsChanged(windowUnits, left, right, top, bottom); + protected final boolean insetsVisibleChanged(final boolean windowUnits, + final int left, final int right, final int top, final int bottom, final int visibleChange) { + boolean res = insetsChanged(windowUnits, left, right, top, bottom); if( 0 <= visibleChange ) { // ignore visible < 0 - visibleChanged(0 < visibleChange); + res = res && visibleChanged(0 < visibleChange); } + return res; } /** @@ -5086,21 +5099,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @param visibleChange -1 ignored, 0 invisible, > 0 visible * @param force */ - protected final void sizePosInsetsFocusVisibleChanged(final boolean defer, - final boolean windowUnits, - final int newX, final int newY, final int newWidth, final int newHeight, - final int left, final int right, final int top, final int bottom, - final int focusChange, - final int visibleChange, final boolean force) { - sizeChanged(defer, windowUnits, newWidth, newHeight, force); - positionChanged(defer, windowUnits, newX, newY); - insetsChanged(windowUnits, left, right, top, bottom); + protected final boolean sizePosInsetsFocusVisibleChanged(final boolean defer, + final boolean windowUnits, + final int newX, final int newY, final int newWidth, final int newHeight, + final int left, final int right, final int top, final int bottom, + final int focusChange, + final int visibleChange, final boolean force) { + boolean res = sizeChanged(defer, windowUnits, newWidth, newHeight, force); + res = res && positionChanged(defer, windowUnits, newX, newY); + res = res && insetsChanged(windowUnits, left, right, top, bottom); if( 0 <= focusChange ) { // ignore focus < 0 - focusChanged(defer, 0 < focusChange); + res = res && focusChanged(defer, 0 < focusChange); } if( 0 <= visibleChange ) { // ignore visible < 0 - visibleChanged(0 < visibleChange); + res = res && visibleChanged(0 < visibleChange); } + return res; } /** @@ -5122,20 +5136,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * @param force * @param windowUnits if true, values are given in window units, otherwise in pixel units. */ - protected final void sizePosMaxInsetsVisibleChanged(final boolean defer, final boolean windowUnits, - final int newX, final int newY, final int newWidth, final int newHeight, - final int maxHorzChange, final int maxVertChange, - final int left, final int right, final int top, final int bottom, - final int visibleChange, final boolean force) { - sizeChanged(defer, windowUnits, newWidth, newHeight, force); - positionChanged(defer, windowUnits, newX, newY); + protected final boolean sizePosMaxInsetsVisibleChanged(final boolean defer, final boolean windowUnits, + final int newX, final int newY, final int newWidth, final int newHeight, + final int maxHorzChange, final int maxVertChange, + final int left, final int right, final int top, final int bottom, + final int visibleChange, final boolean force) { + boolean res = sizeChanged(defer, windowUnits, newWidth, newHeight, force); + res = res && positionChanged(defer, windowUnits, newX, newY); if( 0 <= maxHorzChange && 0 <= maxVertChange ) { - maximizedChanged(0 < maxHorzChange, 0 < maxVertChange); + res = res && maximizedChanged(0 < maxHorzChange, 0 < maxVertChange); } - insetsChanged(false, left, right, top, bottom); + res = res && insetsChanged(false, left, right, top, bottom); if( 0 <= visibleChange ) { // ignore visible < 0 - visibleChanged(0 < visibleChange); + res = res && visibleChanged(0 < visibleChange); } + return res; } // @@ -5261,19 +5276,23 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // @Override - public final void windowRepaint(final int x, final int y, final int width, final int height) { - windowRepaint(false, x, y, width, height); + public final boolean windowRepaint(final int x, final int y, final int width, final int height) { + return windowRepaint(false, x, y, width, height); } // // Accumulated actions // - /** Triggered by implementation. */ - protected final void sendMouseEventRequestFocus(final short eventType, final int modifiers, - final int x, final int y, final short button, final float rotation) { - sendMouseEvent(eventType, modifiers, x, y, button, rotation); - requestFocus(false /* wait */); + /** Triggered by implementation or event dispatcher. */ + protected final boolean sendMouseEventRequestFocus(final short eventType, final int modifiers, + final int x, final int y, final short button, final float rotation) { + if( sendMouseEvent(eventType, modifiers, x, y, button, rotation) ) { + requestFocus(false /* wait */); + return true; + } else { + return false; + } } // diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java index 9ffeaffa2..33155ad67 100644 --- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java @@ -245,6 +245,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { } if( enable ) { androidView.post(new Runnable() { + @Override public void run() { androidView.setClickable(false); androidView.setFocusable(true); @@ -300,6 +301,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { if( null != viewGroup && !added2StaticViewGroup ) { added2StaticViewGroup = true; viewGroup.post(new Runnable() { + @Override public void run() { if(null == androidView) { setupAndroidView( StaticContext.getContext() ); @@ -324,7 +326,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { } @Override - protected final void createNativeImpl(boolean[] positionModified) { + protected final void createNativeImpl(final boolean[] positionModified) { // Create own screen/device resource instance allowing independent ownership, // while still utilizing shared EGL resources. final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); @@ -412,6 +414,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { final ViewGroup viewGroup = StaticContext.getContentViewGroup(); if( null != viewGroup) { viewGroup.post(new Runnable() { + @Override public void run() { viewGroup.removeView(androidView); Log.d(MD.TAG, "closeNativeImpl: removed from static ViewGroup - on thread "+Thread.currentThread().getName()); @@ -437,8 +440,8 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { * {@inheritDoc} */ @Override - public final void focusChanged(final boolean defer, final boolean focusGained) { - super.focusChanged(defer, focusGained); + public final boolean focusChanged(final boolean defer, final boolean focusGained) { + return super.focusChanged(defer, focusGained); } @Override @@ -446,6 +449,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { if(null != androidView) { Log.d(MD.TAG, "requestFocusImpl: reparented "+reparented); androidView.post(new Runnable() { + @Override public void run() { androidView.requestFocus(); androidView.bringToFront(); diff --git a/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java index 454b2200f..6aa4fdc9c 100644 --- a/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/ios/WindowDriver.java @@ -526,15 +526,16 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } /** Callback for native screen position change event of the client area. */ - protected void screenPositionChanged(final boolean defer, final int newX, final int newY) { + protected boolean screenPositionChanged(final boolean defer, final int newX, final int newY) { // passed coordinates are in screen position of the client area if( isNativeValid() ) { + final boolean[] res = { true }; final NativeWindow parent = getParent(); if( !useParent(parent) || isOffscreenInstance ) { if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); } - positionChanged(defer, true, newX, newY); + res[0] = positionChanged(defer, true, newX, newY); } else { final Runnable action = new Runnable() { @Override @@ -547,18 +548,19 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos); } - positionChanged(false, true, absPos.getX(), absPos.getY()); + res[0] = positionChanged(false, true, absPos.getX(), absPos.getY()); } }; if( defer ) { new InterruptSource.Thread(null, action).start(); } else { action.run(); } - } + return res[0]; } else if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); } + return false; } @Override @@ -609,25 +611,26 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl // /** Triggered by implementation's WM events to update the client-area position, size and insets. */ - protected void sizeScreenPosInsetsChanged(final boolean defer, - final int newX, final int newY, - final int newWidth, final int newHeight, - final int left, final int right, final int top, final int bottom, - final boolean force, - final boolean withinLiveResize) { + protected boolean sizeScreenPosInsetsChanged(final boolean defer, + final int newX, final int newY, + final int newWidth, final int newHeight, + final int left, final int right, final int top, final int bottom, + final boolean force, + final boolean withinLiveResize) { final LifecycleHook lh = getLifecycleHook(); if( withinLiveResize && !resizeAnimatorPaused && null!=lh ) { resizeAnimatorPaused = lh.pauseRenderingAction(); } - sizeChanged(defer, false, newWidth, newHeight, force); - screenPositionChanged(defer, newX, newY); - insetsChanged(false, left, right, top, bottom); - if( !withinLiveResize && resizeAnimatorPaused ) { + boolean res = sizeChanged(defer, false, newWidth, newHeight, force); + res = res && screenPositionChanged(defer, newX, newY); + res = res && insetsChanged(false, left, right, top, bottom); + if( !withinLiveResize && resizeAnimatorPaused && res ) { resizeAnimatorPaused = false; if( null!=lh ) { lh.resumeRenderingAction(); } } + return res; } @Override @@ -638,9 +641,9 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl SurfaceScaleUtils.scale(y, getPixelScaleY()), button, rotationXYZ, rotationScale); } - public final void sendTouchScreenEvent(final short eventType, final int modifiers, - final int[] pActionIdx, final short[] pNames, - final int[] pTypesI, final int[] pX, final int[] pY, final float[] pPressure, final float maxPressure) { + public final boolean sendTouchScreenEvent(final short eventType, final int modifiers, + final int[] pActionIdx, final short[] pNames, + final int[] pTypesI, final int[] pX, final int[] pY, final float[] pPressure, final float maxPressure) { final int pCount = pNames.length; final MouseEvent.PointerType[] pTypes = new MouseEvent.PointerType[pCount]; for(int i=0; i<pCount; i++) { @@ -651,19 +654,20 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl pTypes, eventType, modifiers, pActionIdx[i], true /*normalPNames*/, pNames, pX, pY, pPressure, maxPressure, new float[] { 0f, 0f, 0f} /*rotationXYZ*/, 1f/*rotationScale*/); } + return isNativeValid(); } @Override - public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { + public final boolean sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { throw new InternalError("XXX: Adapt Java Code to Native Code Changes"); } @Override - public final void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short _keyCode, final short _keySym, final char keyChar) { + public final boolean enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short _keyCode, final short _keySym, final char keyChar) { throw new InternalError("XXX: Adapt Java Code to Native Code Changes"); } - protected final void enqueueKeyEvent(final boolean wait, final short eventType, int modifiers, final short _keyCode, final char keyChar, final char keySymChar) { + protected final boolean enqueueKeyEvent(final boolean wait, final short eventType, int modifiers, final short _keyCode, final char keyChar, final char keySymChar) { // Note that we send the key char for the key code on this // platform -- we do not get any useful key codes out of the system final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar); @@ -685,6 +689,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1) // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED + boolean res = true; switch(eventType) { case KeyEvent.EVENT_KEY_RELEASED: if( isKeyCodeTracked(keyCode) ) { @@ -696,12 +701,12 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if( setKeyPressed(keyCode, true) ) { // key was already pressed modifiers |= InputEvent.AUTOREPEAT_MASK; - super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED + res = super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED } } break; } - super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar); + return res && super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar); } protected int getDisplayID() { diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 79951e5a6..e8383916e 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -556,16 +556,17 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } /** Callback for native screen position change event of the client area. */ - protected void screenPositionChanged(final boolean defer, final int newX, final int newY) { + protected boolean screenPositionChanged(final boolean defer, final int newX, final int newY) { // passed coordinates are in screen position of the client area if( isNativeValid() ) { + final boolean[] res = { true }; final NativeWindow parent = getParent(); final boolean useParentLoc = useParentLocation(parent); if( !useParentLoc || isOffscreenInstance ) { if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.positionChanged.0 (Screen Pos - TOP): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); } - positionChanged(defer, true, newX, newY); + res[0] = positionChanged(defer, true, newX, newY); } else if( useParentLoc && !isVisible() ) { // Fake invisible child window: drop fake position update for fake invisibility if(DEBUG_IMPLEMENTATION) { @@ -590,18 +591,19 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.positionChanged.1 (Screen Pos - CHILD): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> absPos "+newX+"/"+newY+", parentOnScreen "+parentOnScreen+" -> "+absPos); } - positionChanged(false, true, absPos.getX(), absPos.getY()); + res[0] = positionChanged(false, true, absPos.getX(), absPos.getY()); } }; if( defer ) { new InterruptSource.Thread(null, action).start(); } else { action.run(); } - } + return res[0]; } else if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.positionChanged.2 (Screen Pos - IGN): ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY); } + return false; } @Override @@ -654,25 +656,26 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl // /** Triggered by implementation's WM events to update the client-area position, size and insets. */ - protected void sizeScreenPosInsetsChanged(final boolean defer, - final int newX, final int newY, - final int newWidth, final int newHeight, - final int left, final int right, final int top, final int bottom, - final boolean force, - final boolean withinLiveResize) { + protected boolean sizeScreenPosInsetsChanged(final boolean defer, + final int newX, final int newY, + final int newWidth, final int newHeight, + final int left, final int right, final int top, final int bottom, + final boolean force, + final boolean withinLiveResize) { final LifecycleHook lh = getLifecycleHook(); if( withinLiveResize && !resizeAnimatorPaused && null!=lh ) { resizeAnimatorPaused = lh.pauseRenderingAction(); } - sizeChanged(defer, true /* windowUnits */, newWidth, newHeight, force); - screenPositionChanged(defer, newX, newY); - insetsChanged(false, left, right, top, bottom); - if( !withinLiveResize && resizeAnimatorPaused ) { + boolean res = sizeChanged(defer, true /* windowUnits */, newWidth, newHeight, force); + res = res && screenPositionChanged(defer, newX, newY); + res = res && insetsChanged(false, left, right, top, bottom); + if( !withinLiveResize && resizeAnimatorPaused && res ) { resizeAnimatorPaused = false; if( null!=lh ) { lh.resumeRenderingAction(); } } + return res; } @Override @@ -727,16 +730,16 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl } @Override - public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { + public final boolean sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { throw new InternalError("XXX: Adapt Java Code to Native Code Changes"); } @Override - public final void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short _keyCode, final short _keySym, final char keyChar) { + public final boolean enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short _keyCode, final short _keySym, final char keyChar) { throw new InternalError("XXX: Adapt Java Code to Native Code Changes"); } - protected final void enqueueKeyEvent(final boolean wait, final short eventType, int modifiers, final short _keyCode, final char keyChar, final char keySymChar) { + protected final boolean enqueueKeyEvent(final boolean wait, final short eventType, int modifiers, final short _keyCode, final char keyChar, final char keySymChar) { // Note that we send the key char for the key code on this // platform -- we do not get any useful key codes out of the system final short keyCode = MacKeyUtil.validateKeyCode(_keyCode, keyChar); @@ -758,6 +761,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1) // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED + boolean res = true; switch(eventType) { case KeyEvent.EVENT_KEY_RELEASED: if( isKeyCodeTracked(keyCode) ) { @@ -769,12 +773,12 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl if( setKeyPressed(keyCode, true) ) { // key was already pressed modifiers |= InputEvent.AUTOREPEAT_MASK; - super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED + res = super.enqueueKeyEvent(wait, KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); // RELEASED } } break; } - super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar); + return res && super.enqueueKeyEvent(wait, eventType, modifiers, keyCode, keySym, keyChar); } protected int getDisplayID() { diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java index b95911adf..fb88c77df 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java @@ -194,9 +194,9 @@ public class WindowDriver extends WindowImpl { if( !cfg.getChosenCapabilities().isBackgroundOpaque() ) { GDIUtil.DwmSetupTranslucency(_windowHandle, true); } - InitWindow0(_windowHandle, flags); setWindowHandle(_windowHandle); windowHandleClose = _windowHandle; + InitWindow0(_windowHandle, flags); if( 0 == ( STATE_MASK_CHILDWIN & flags ) && 1 <= maxCount ) { reconfigureWindowImpl(xy_pix[0], xy_pix[1], sz_pix[0], sz_pix[1], flags); @@ -411,15 +411,16 @@ public class WindowDriver extends WindowImpl { * for details. * </p> */ - public final void sendTouchScreenEvent(final short eventType, final int modifiers, - final int pActionIdx, final short[] pNames, - final int[] pX, final int[] pY, final float[] pPressure, final float maxPressure) { + public final boolean sendTouchScreenEvent(final short eventType, final int modifiers, + final int pActionIdx, final short[] pNames, + final int[] pX, final int[] pY, final float[] pPressure, final 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*/); + return isNativeValid(); } // @@ -447,35 +448,37 @@ public class WindowDriver extends WindowImpl { } @Override - public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { + public final boolean sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { final boolean isModifierKey = KeyEvent.isModifierKey(keySym); // System.err.println("*** sendKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar+">, mods "+toHexString(modifiers)+ // ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", printableKey "+KeyEvent.isPrintableKey(keyCode, false)+" [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis()); // Reorder: WINDOWS delivery order is PRESSED (t0), TYPED (t0) and RELEASED (t1) -> NEWT order: PRESSED (t0) and RELEASED (t1) // Auto-Repeat: WINDOWS delivers only PRESSED (t0) and TYPED (t0). + boolean res = true; switch(eventType) { case KeyEvent.EVENT_KEY_RELEASED: if( isKeyCodeTracked(keyCode) ) { if( repeatedKey == keyCode && !isModifierKey ) { // AR out - send out missing PRESSED - super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keySym, keyChar); + res = super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers | InputEvent.AUTOREPEAT_MASK, keyCode, keySym, keyChar); } setKeyPressed(keyCode, false); repeatedKey = KeyEvent.VK_UNDEFINED; } - super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); + res = res && super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); break; case KeyEvent.EVENT_KEY_PRESSED: if( !handlePressTypedAutoRepeat(isModifierKey, modifiers, keyCode, keySym, keyChar) ) { - super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar); + res = super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar); } break; } + return res; } @Override - public final void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { + public final boolean enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { throw new InternalError("XXX: Adapt Java Code to Native Code Changes"); } diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java index e0fd20e2b..2957df93a 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java @@ -154,10 +154,11 @@ public class DisplayDriver extends DisplayImpl { this.randr_error_base = randr_error_base; this.xi_opcode = xi_opcode; } - private void sendRRScreenChangeNotify(final long event) { + private boolean sendRRScreenChangeNotify(final long event) { if( null != rAndR ) { rAndR.sendRRScreenChangeNotify(getHandle(), event); } + return isNativeValidAsync(); } void registerRandR(final RandR rAndR) { this.rAndR = rAndR; diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java index e939edeae..501adee9c 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java @@ -204,12 +204,15 @@ public class WindowDriver extends WindowImpl { @Override protected void closeNativeImpl() { - if(0!=javaWindowHandle && null!=getScreen() ) { + final long _javaWindowHandle = javaWindowHandle; + if(0!=_javaWindowHandle && null!=getScreen() ) { final DisplayDriver display = (DisplayDriver) getScreen().getDisplay(); final AbstractGraphicsDevice edtDevice = display.getGraphicsDevice(); edtDevice.lock(); try { - CloseWindow0(edtDevice.getHandle(), javaWindowHandle /* , display.getKbdHandle() */, // XKB disabled for now + setWindowHandle(0); // dispose native window handle ASAP + javaWindowHandle = 0; // dispose our javaWindow handle ASAP + CloseWindow0(display, edtDevice.getHandle(), _javaWindowHandle /* , display.getKbdHandle() */, // XKB disabled for now display.getRandREventBase(), display.getRandRErrorBase(), display.getXiOpcode()); } catch (final Throwable t) { if(DEBUG_IMPLEMENTATION) { @@ -218,7 +221,6 @@ public class WindowDriver extends WindowImpl { } } finally { edtDevice.unlock(); - javaWindowHandle = 0; last_monitor = null; } } @@ -304,7 +306,7 @@ public class WindowDriver extends WindowImpl { * {@inheritDoc} */ @Override - protected void focusChanged(final boolean defer, final boolean focusGained) { + protected boolean focusChanged(final boolean defer, final boolean focusGained) { if( isNativeValid() && isFullscreen() && !isAlwaysOnBottom() && tempFSAlwaysOnTop && hasFocus() != focusGained ) { final int flags = getReconfigureMask(CHANGE_MASK_ALWAYSONTOP, isVisible()) | ( focusGained ? STATE_MASK_ALWAYSONTOP : 0 ); @@ -320,7 +322,7 @@ public class WindowDriver extends WindowImpl { } }); } - super.focusChanged(defer, focusGained); + return super.focusChanged(defer, focusGained); } @Override @@ -349,11 +351,12 @@ public class WindowDriver extends WindowImpl { return res; } - protected void reparentNotify(final long newParentWindowHandle) { + protected boolean reparentNotify(final long newParentWindowHandle) { if(DEBUG_IMPLEMENTATION) { final long p0 = getParentWindowHandle(); System.err.println("Window.reparentNotify ("+getThreadName()+"): "+toHexString(p0)+" -> "+toHexString(newParentWindowHandle)); } + return isNativeValid(); } @Override @@ -490,7 +493,7 @@ public class WindowDriver extends WindowImpl { } /** Called by native TK */ - protected final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar0, final String keyString) { + protected final boolean sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar0, final String keyString) { // handleKeyEvent(true, false, eventType, modifiers, keyCode, keyChar); final boolean isModifierKey = KeyEvent.isModifierKey(keyCode); final boolean isAutoRepeat = 0 != ( InputEvent.AUTOREPEAT_MASK & modifiers ); @@ -498,22 +501,24 @@ public class WindowDriver extends WindowImpl { // System.err.println("*** sendKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar0+">/<"+keyChar+">, keyString "+keyString+", mods "+toHexString(modifiers)+ // ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isAutoRepeat+", [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis()); + boolean res = true; if( !isAutoRepeat || !isModifierKey ) { // ! ( isModifierKey && isAutoRepeat ) switch(eventType) { case KeyEvent.EVENT_KEY_PRESSED: - super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar); + res = super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar); break; case KeyEvent.EVENT_KEY_RELEASED: - super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); + res = super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar); break; } } + return res; } - public final void sendTouchScreenEvent(final short eventType, final int modifiers, - final int pActionIdx, final short[] pNames, - final int[] pX, final int[] pY, final float[] pPressure, final float maxPressure) { + public final boolean sendTouchScreenEvent(final short eventType, final int modifiers, + final int pActionIdx, final short[] pNames, + final int[] pX, final int[] pY, final float[] pPressure, final float maxPressure) { final int pCount = pNames.length; final MouseEvent.PointerType[] pTypes = new MouseEvent.PointerType[pCount]; for(int i=0; i<pCount; i++) { @@ -522,14 +527,15 @@ public class WindowDriver extends WindowImpl { doPointerEvent(false /*enqueue*/, false /*wait*/, pTypes, eventType, modifiers, pActionIdx, true /*normalPNames*/, pNames, pX, pY, pPressure, maxPressure, new float[] { 0f, 0f, 0f} /*rotationXYZ*/, 1f/*rotationScale*/); + return isNativeValid(); } @Override - public final void sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { + public final boolean sendKeyEvent(final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { throw new InternalError("XXX: Adapt Java Code to Native Code Changes"); } @Override - public final void enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { + public final boolean enqueueKeyEvent(final boolean wait, final short eventType, final int modifiers, final short keyCode, final short keySym, final char keyChar) { throw new InternalError("XXX: Adapt Java Code to Native Code Changes"); } @@ -565,7 +571,7 @@ public class WindowDriver extends WindowImpl { int pixelDataSize, Object pixels, int pixels_byte_offset, boolean pixels_is_direct, boolean verbose); private static native int GetSupportedReconfigMask0(long javaWindowHandle); - private native void CloseWindow0(long display, long javaWindowHandle /*, long kbdHandle*/, // XKB disabled for now + private native void CloseWindow0(DisplayDriver disbplayDriver, long display, long javaWindowHandle /*, long kbdHandle*/, // XKB disabled for now final int randr_event_base, final int randr_error_base, final int xi_opcode); private static native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long javaWindowHandle, int x, int y, int width, int height, int flags); diff --git a/src/newt/native/IOSNewtUIWindow.m b/src/newt/native/IOSNewtUIWindow.m index 6e3e362a7..2efd7a25c 100644 --- a/src/newt/native/IOSNewtUIWindow.m +++ b/src/newt/native/IOSNewtUIWindow.m @@ -1,5 +1,5 @@ /** - * Copyright 2019 JogAmp Community. All rights reserved. + * Copyright 2019-2023 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: @@ -219,7 +219,7 @@ static jmethodID windowRepaintID = NULL; CGRect viewFrame = [self frame]; - (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE /* defer */, + (*env)->CallBooleanMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE /* defer */, (int)dirtyRect.origin.x, (int)viewFrame.size.height - (int)dirtyRect.origin.y, (int)dirtyRect.size.width, (int)dirtyRect.size.height); @@ -440,16 +440,16 @@ static jmethodID windowRepaintID = NULL; + (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz { - sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SI[I[S[I[I[I[FF)V"); + sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SI[I[S[I[I[I[FF)Z"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFFFZ)V"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); - insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); - sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)V"); - screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)Z"); + sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)Z"); + screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)Z"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); - windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); + windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)Z"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (sendTouchScreenEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && insetsChangedID && sizeScreenPosInsetsChangedID && @@ -691,7 +691,7 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); if( NULL != env && NULL != javaWin ) { - (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); + (*env)->CallBooleanMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); } } @@ -709,13 +709,13 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT( "updatePos: [ x %d, y %d ]\n", (jint) pS.x, (jint) pS.y); if( NULL != env && NULL != javaWin ) { - (*env)->CallVoidMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer, - (jint) pS.x, (jint) pS.y, - (jint) frameRect.size.width, (jint) frameRect.size.height, - cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3], - JNI_FALSE, // force - withinLiveResize - ); + (*env)->CallBooleanMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer, + (jint) pS.x, (jint) pS.y, + (jint) frameRect.size.width, (jint) frameRect.size.height, + cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3], + JNI_FALSE, // force + withinLiveResize + ); } } @@ -799,7 +799,7 @@ static jmethodID windowRepaintID = NULL; return; } - (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); + (*env)->CallBooleanMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -823,7 +823,7 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT("visibilityChanged: null JNIEnv\n"); return; } - (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, (visible == YES) ? JNI_TRUE : JNI_FALSE); + (*env)->CallBooleanMethod(env, javaWindowObject, visibleChangedID, (visible == YES) ? JNI_TRUE : JNI_FALSE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -922,7 +922,7 @@ static jmethodID windowRepaintID = NULL; CGPoint p0 = { 0, 0 }; p0 = [self getLocationOnScreen: p0]; DBG_PRINT( "windowDidMove: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y); - (*env)->CallVoidMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); + (*env)->CallBooleanMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); diff --git a/src/newt/native/KDWindow.c b/src/newt/native/KDWindow.c index 972267088..db34560a8 100644 --- a/src/newt/native/KDWindow.c +++ b/src/newt/native/KDWindow.c @@ -87,10 +87,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages (JNIEnv *env, jobject obj) { const KDEvent * evt; - int numEvents = 0; + int num_events = 100; // Periodically take a break - while( numEvents<100 && NULL!=(evt=kdWaitEvent(0)) ) { + while( num_events > 0 && NULL!=(evt=kdWaitEvent(0)) ) { KDWindow *kdWindow; jobject javaWindow; JOGLKDUserdata * userData = (JOGLKDUserdata *)(intptr_t)evt->userptr; @@ -102,7 +102,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages javaWindow = userData->javaWindow; DBG_PRINT( "[DispatchMessages]: userData %p, evt type: 0x%X\n", userData, evt->type); - numEvents++; + num_events--; // FIXME: support resize and window re-positioning events @@ -120,6 +120,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages DBG_PRINT( "event window close : src: %p .. \n", userData); closed = (*env)->CallBooleanMethod(env, javaWindow, windowDestroyNotifyID, JNI_FALSE); DBG_PRINT( "event window close : src: %p, closed %d\n", userData, (int)closed); + num_events=0; // end loop } break; case KD_EVENT_WINDOWPROPERTY_CHANGE: @@ -131,7 +132,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages KDint32 v[2]; if(!kdGetWindowPropertyiv(kdWindow, KD_WINDOWPROPERTY_SIZE, v)) { DBG_PRINT( "event window size change : src: %p %dx%d\n", userData, v[0], v[1]); - (*env)->CallBooleanMethod(env, javaWindow, sizeChangedID, JNI_FALSE, JNI_FALSE, (jint) v[0], (jint) v[1], JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, javaWindow, sizeChangedID, JNI_FALSE, JNI_FALSE, (jint) v[0], (jint) v[1], JNI_FALSE) ) { + num_events=0; // end loop + } } else { DBG_PRINT( "event window size change error: src: %p %dx%d\n", userData, v[0], v[1]); } @@ -145,7 +148,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages KDboolean visible; kdGetWindowPropertybv(kdWindow, KD_WINDOWPROPERTY_VISIBILITY, &visible); DBG_PRINT( "event window visibility: src: %p, v:%d\n", userData, visible); - (*env)->CallVoidMethod(env, javaWindow, visibleChangedID, visible?JNI_TRUE:JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, javaWindow, visibleChangedID, visible?JNI_TRUE:JNI_FALSE) ) { + num_events=0; // end loop + } } break; default: @@ -161,15 +166,19 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_DisplayDriver_DispatchMessages // time = ev->timestamp if(KD_INPUT_POINTER_SELECT==ptr->index) { DBG_PRINT( "event mouse click: src: %p, s:%d, (%d,%d)\n", userData, ptr->select, ptr->x, ptr->y); - (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, - (ptr->select==0) ? (jshort) EVENT_MOUSE_RELEASED : (jshort) EVENT_MOUSE_PRESSED, - (jint) 0, - (jint) ptr->x, (jint) ptr->y, (short)1, 0.0f); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, javaWindow, sendMouseEventID, + (ptr->select==0) ? (jshort) EVENT_MOUSE_RELEASED : (jshort) EVENT_MOUSE_PRESSED, + (jint) 0, + (jint) ptr->x, (jint) ptr->y, (short)1, 0.0f) ) { + num_events=0; // end loop + } } else { DBG_PRINT( "event mouse: src: %d, s:%p, i:0x%X (%d,%d)\n", userData, ptr->select, ptr->index, ptr->x, ptr->y); - (*env)->CallVoidMethod(env, javaWindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, - 0, - (jint) ptr->x, (jint) ptr->y, (jshort)0, 0.0f); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, javaWindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, + 0, + (jint) ptr->x, (jint) ptr->y, (jshort)0, 0.0f) ) { + num_events=0; // end loop + } } } break; @@ -192,10 +201,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_kd_WindowDriver_initIDs #endif windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); - sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)V"); - sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)Z"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)Z"); if (windowCreatedID == NULL || sizeChangedID == NULL || visibleChangedID == NULL || @@ -277,7 +286,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setVisible0 KDboolean v = (visible==JNI_TRUE)?KD_TRUE:KD_FALSE; kdSetWindowPropertybv(w, KD_WINDOWPROPERTY_VISIBILITY, &v); DBG_PRINT( "[setVisible] v=%d\n", visible); - (*env)->CallVoidMethod(env, obj, visibleChangedID, visible); + (*env)->CallBooleanMethod(env, obj, visibleChangedID, visible); } JNIEXPORT void JNICALL Java_jogamp_newt_driver_kd_WindowDriver_setFullScreen0 diff --git a/src/newt/native/MacNewtNSWindow.m b/src/newt/native/MacNewtNSWindow.m index e543f96e1..73bcaddcc 100644 --- a/src/newt/native/MacNewtNSWindow.m +++ b/src/newt/native/MacNewtNSWindow.m @@ -1,6 +1,6 @@ /* + * Copyright (c) 2011-2023 JogAmp Community. All rights reserved. * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2011 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -377,7 +377,7 @@ static jmethodID windowRepaintID = NULL; NSRect viewFrame = [self frame]; - (*env)->CallVoidMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE /* defer */, + (*env)->CallBooleanMethod(env, javaWindowObject, windowRepaintID, JNI_TRUE /* defer */, (int)dirtyRect.origin.x, (int)viewFrame.size.height - (int)dirtyRect.origin.y, (int)dirtyRect.size.width, (int)dirtyRect.size.height); @@ -398,7 +398,7 @@ static jmethodID windowRepaintID = NULL; return; } - (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE); + (*env)->CallBooleanMethod(env, javaWindowObject, visibleChangedID, JNI_FALSE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -419,7 +419,7 @@ static jmethodID windowRepaintID = NULL; return; } - (*env)->CallVoidMethod(env, javaWindowObject, visibleChangedID, JNI_TRUE); + (*env)->CallBooleanMethod(env, javaWindowObject, visibleChangedID, JNI_TRUE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -727,10 +727,10 @@ static jmethodID windowRepaintID = NULL; NSPoint location = [self screenPos2NewtClientWinPos: [NSEvent mouseLocation]]; - (*env)->CallVoidMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE, - evType, javaMods[0], - (jint) location.x, (jint) location.y, - javaButtonNum, scrollDeltaY); + (*env)->CallBooleanMethod(env, javaWindowObject, enqueueMouseEventID, JNI_FALSE, + evType, javaMods[0], + (jint) location.x, (jint) location.y, + javaButtonNum, scrollDeltaY); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -809,8 +809,8 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT("sendKeyEvent: %d/%d code 0x%X, char 0x%X, mods 0x%X/0x%X -> keySymChar 0x%X\n", i, len, (int)keyCode, (int)keyChar, (int)mods, (int)javaMods, (int)keySymChar); - (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar); + (*env)->CallBooleanMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, + evType, javaMods, keyCode, (jchar)keyChar, (jchar)keySymChar); } } else { // non-printable chars @@ -818,8 +818,8 @@ static jmethodID windowRepaintID = NULL; DBG_PRINT("sendKeyEvent: code 0x%X\n", (int)keyCode); - (*env)->CallVoidMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, - evType, javaMods, keyCode, keyChar, keyChar); + (*env)->CallBooleanMethod(env, javaWindowObject, enqueueKeyEventID, JNI_FALSE, + evType, javaMods, keyCode, keyChar, keyChar); } // detaching thread not required - daemon @@ -875,17 +875,17 @@ NS_ENDHANDLER + (BOOL) initNatives: (JNIEnv*) env forClass: (jclass) clazz { - enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)V"); - enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)V"); + enqueueMouseEventID = (*env)->GetMethodID(env, clazz, "enqueueMouseEvent", "(ZSIIISF)Z"); + enqueueKeyEventID = (*env)->GetMethodID(env, clazz, "enqueueKeyEvent", "(ZSISCC)Z"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); updatePixelScaleID = (*env)->GetMethodID(env, clazz, "updatePixelScale", "(ZFFFZ)V"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); - insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); - sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)V"); - screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)V"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)Z"); + sizeScreenPosInsetsChangedID = (*env)->GetMethodID(env, clazz, "sizeScreenPosInsetsChanged", "(ZIIIIIIIIZZ)Z"); + screenPositionChangedID = (*env)->GetMethodID(env, clazz, "screenPositionChanged", "(ZII)Z"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); - windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)V"); + windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)Z"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (enqueueMouseEventID && enqueueKeyEventID && sizeChangedID && updatePixelScaleID && visibleChangedID && insetsChangedID && sizeScreenPosInsetsChangedID && @@ -1015,7 +1015,7 @@ NS_ENDHANDLER DBG_PRINT( "updateInsets: [ l %d, r %d, t %d, b %d ]\n", cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); if( NULL != env && NULL != javaWin ) { - (*env)->CallVoidMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); + (*env)->CallBooleanMethod(env, javaWin, insetsChangedID, JNI_FALSE, cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3]); } } @@ -1035,13 +1035,13 @@ NS_ENDHANDLER DBG_PRINT( "updatePos: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y); if( NULL != env && NULL != javaWin ) { - (*env)->CallVoidMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer, - (jint) p0.x, (jint) p0.y, - (jint) contentRect.size.width, (jint) contentRect.size.height, - cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3], - JNI_FALSE, // force - withinLiveResize - ); + (*env)->CallBooleanMethod(env, javaWin, sizeScreenPosInsetsChangedID, defer, + (jint) p0.x, (jint) p0.y, + (jint) contentRect.size.width, (jint) contentRect.size.height, + cachedInsets[0], cachedInsets[1], cachedInsets[2], cachedInsets[3], + JNI_FALSE, // force + withinLiveResize + ); } } @@ -1214,7 +1214,7 @@ NS_ENDHANDLER return; } - (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); + (*env)->CallBooleanMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); @@ -1373,7 +1373,7 @@ NS_ENDHANDLER NSPoint p0 = { 0, 0 }; p0 = [self getLocationOnScreen: p0]; DBG_PRINT( "windowDidMove: [ x %d, y %d ]\n", (jint) p0.x, (jint) p0.y); - (*env)->CallVoidMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); + (*env)->CallBooleanMethod(env, javaWindowObject, screenPositionChangedID, JNI_TRUE, (jint) p0.x, (jint) p0.y); // detaching thread not required - daemon // NewtCommon_ReleaseJNIEnv(shallBeDetached); diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 4ce5567e1..201304dd9 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -1,6 +1,6 @@ /* + * Copyright (c) 2010-2023 JogAmp Community. All rights reserved. * Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved. - * Copyright (c) 2010 JogAmp Community. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -246,7 +246,7 @@ typedef struct { int supportsMTouch; } WindowUserData; -static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd); +static jboolean UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd); typedef struct { USHORT javaKey; @@ -594,9 +594,9 @@ static int WmKeyDown(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE modifiers = GetModifiers( javaVKeyUS ); - (*env)->CallVoidMethod(env, window, sendKeyEventID, - (jshort) EVENT_KEY_PRESSED, - (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char); + (*env)->CallBooleanMethod(env, window, sendKeyEventID, + (jshort) EVENT_KEY_PRESSED, + (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char); return 0; } @@ -612,9 +612,9 @@ static int WmKeyUp(JNIEnv *env, jobject window, USHORT wkey, WORD repCnt, BYTE s modifiers = GetModifiers( javaVKeyUS ); - (*env)->CallVoidMethod(env, window, sendKeyEventID, - (jshort) EVENT_KEY_RELEASED, - (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char); + (*env)->CallBooleanMethod(env, window, sendKeyEventID, + (jshort) EVENT_KEY_RELEASED, + (jint) modifiers, (jshort) javaVKeyUS, (jshort) javaVKeyXX, (jchar) utf16Char); return 0; } @@ -700,7 +700,7 @@ static jboolean NewtWindows_setFullScreen(jboolean fullscreen) return ( DISP_CHANGE_SUCCESSFUL == ChangeDisplaySettings(&dm, flags) ) ? JNI_TRUE : JNI_FALSE; } -static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { +static jboolean UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { jobject window = wud->jinstance; RECT outside; RECT inside; @@ -708,7 +708,7 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { if (IsIconic(hwnd)) { wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = -1; - return; + return JNI_TRUE; } wud->insets.left = wud->insets.top = wud->insets.right = wud->insets.bottom = 0; @@ -760,9 +760,10 @@ static void UpdateInsets(JNIEnv *env, WindowUserData *wud, HWND hwnd) { (void*)hwnd, strategy, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom, (int) ( wud->insets.left + wud->insets.right ), (int) (wud->insets.top + wud->insets.bottom), wud->isInCreation); if( !wud->isInCreation ) { - (*env)->CallVoidMethod(env, window, insetsChangedID, - JNI_FALSE, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom); + return (*env)->CallBooleanMethod(env, window, insetsChangedID, + JNI_FALSE, (int)wud->insets.left, (int)wud->insets.right, (int)wud->insets.top, (int)wud->insets.bottom); } + return JNI_TRUE; } static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) @@ -793,7 +794,10 @@ static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) } // make sure insets are up to date - UpdateInsets(env, wud, wnd); + if( JNI_FALSE == UpdateInsets(env, wud, wnd) ) { + DBG_PRINT( "WindowsWindow: WmSize.X window %p - Leave J, UpdateInsets\n", (void*)wnd); + return; + } GetClientRect(wnd, &rc); @@ -807,9 +811,15 @@ static void WmSize(JNIEnv *env, WindowUserData * wud, HWND wnd, UINT type) if( !wud->isInCreation ) { if( maxChanged ) { jboolean v = wud->isMaximized ? JNI_TRUE : JNI_FALSE; - (*env)->CallVoidMethod(env, window, maximizedChangedID, v, v); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, window, maximizedChangedID, v, v) ) { + DBG_PRINT( "WindowsWindow: WmSize.X window %p - Leave J, maximized\n", (void*)wnd); + return; + } + } + if( JNI_FALSE == (*env)->CallBooleanMethod(env, window, sizeChangedID, JNI_FALSE, JNI_FALSE, wud->width, wud->height, JNI_FALSE) ) { + DBG_PRINT( "WindowsWindow: WmSize.X window %p - Leave J, sizeChanged\n", (void*)wnd); + return; } - (*env)->CallBooleanMethod(env, window, sizeChangedID, JNI_FALSE, JNI_FALSE, wud->width, wud->height, JNI_FALSE); } } @@ -904,9 +914,9 @@ static BOOL SafeShowCursor(BOOL show) { return b; } -static void sendTouchScreenEvent(JNIEnv *env, jobject window, - short eventType, int modifiers, int actionIdx, - int count, jshort* pointerNames, jint* x, jint* y, jfloat* pressure, float maxPressure) { +static jboolean sendTouchScreenEvent(JNIEnv *env, jobject window, + short eventType, int modifiers, int actionIdx, + int count, jshort* pointerNames, jint* x, jint* y, jfloat* pressure, float maxPressure) { jshortArray jNames = (*env)->NewShortArray(env, count); if (jNames == NULL) { NewtCommon_throwNewRuntimeException(env, "Could not allocate short array (names) of size %d", count); @@ -931,9 +941,9 @@ static void sendTouchScreenEvent(JNIEnv *env, jobject window, } (*env)->SetFloatArrayRegion(env, jPressure, 0, count, pressure); - (*env)->CallVoidMethod(env, window, sendTouchScreenEventID, - (jshort)eventType, (jint)modifiers, (jint)actionIdx, - jNames, jX, jY, jPressure, (jfloat)maxPressure); + return (*env)->CallBooleanMethod(env, window, sendTouchScreenEventID, + (jshort)eventType, (jint)modifiers, (jint)actionIdx, + jNames, jX, jY, jPressure, (jfloat)maxPressure); } // #define DO_ERASEBKGND 1 @@ -1062,7 +1072,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP DBG_PRINT("*** WindowsWindow: WM_SHOWWINDOW window %p: %d, at-init %d\n", wnd, wParam==TRUE, wud->isInCreation); wud->visible = wParam==TRUE; if( !wud->isInCreation ) { - (*env)->CallVoidMethod(env, window, visibleChangedID, wParam==TRUE?JNI_TRUE:JNI_FALSE); + (*env)->CallBooleanMethod(env, window, visibleChangedID, wParam==TRUE?JNI_TRUE:JNI_FALSE); } break; @@ -1082,12 +1092,14 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP if (GetUpdateRect(wnd, NULL, TRUE /* erase background */)) { DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (dirty)\n"); // WM_ERASEBKGND sent! + } #else if (GetUpdateRect(wnd, NULL, FALSE /* do not erase background */)) { DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (dirty)\n"); ValidateRect(wnd, NULL); // clear all! + } #endif - } else { + else { DBG_PRINT("*** WindowsWindow: WM_PAINT.0 (clean)\n"); } } else { @@ -1095,7 +1107,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP DBG_PRINT("*** WindowsWindow: WM_PAINT.1 (dirty)\n"); // Let NEWT render the whole client area by issueing repaint for it, w/o looping through erase background ValidateRect(wnd, NULL); // clear all! - (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); + (*env)->CallBooleanMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); } else { DBG_PRINT("*** WindowsWindow: WM_PAINT.1 (clean)\n"); // shall not happen ? @@ -1129,7 +1141,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP // ignore erase background, but let NEWT render the whole client area DBG_PRINT("*** WindowsWindow: WM_ERASEBKGND.1 (repaint)\n"); ValidateRect(wnd, NULL); // clear all! - (*env)->CallVoidMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); + (*env)->CallBooleanMethod(env, window, windowRepaintID, JNI_FALSE, 0, 0, -1, -1); res = 1; // return 1 == done, OpenGL, etc .. erases the background, hence we claim to have just done this } break; @@ -1183,7 +1195,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP DBG_PRINT("*** WindowsWindow: WM_SETFOCUS window %p, lost %p, at-init %d\n", wnd, (HWND)wParam, wud->isInCreation); wud->focused = TRUE; if( !wud->isInCreation ) { - (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE); + (*env)->CallBooleanMethod(env, window, focusChangedID, JNI_FALSE, JNI_TRUE); } useDefWindowProc = 1; break; @@ -1199,7 +1211,7 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP } wud->focused = FALSE; if( !wud->isInCreation ) { - (*env)->CallVoidMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE); + (*env)->CallBooleanMethod(env, window, focusChangedID, JNI_FALSE, JNI_FALSE); } useDefWindowProc = 1; } else { @@ -1261,11 +1273,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP NewtWindows_trackPointerLeave(wnd); } (*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); + (*env)->CallBooleanMethod(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; } } @@ -1288,11 +1300,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP wud->pointerInside = 1; NewtWindows_trackPointerLeave(wnd); } - (*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); + (*env)->CallBooleanMethod(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; } } @@ -1308,11 +1320,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP NewtWindows_trackPointerLeave(wnd); } (*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); + (*env)->CallBooleanMethod(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; } } @@ -1332,11 +1344,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP wud->pointerInside = 1; NewtWindows_trackPointerLeave(wnd); } - (*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); + (*env)->CallBooleanMethod(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; } } @@ -1352,11 +1364,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP NewtWindows_trackPointerLeave(wnd); } (*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); + (*env)->CallBooleanMethod(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; } } @@ -1376,11 +1388,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP wud->pointerInside = 1; NewtWindows_trackPointerLeave(wnd); } - (*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); + (*env)->CallBooleanMethod(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; } } @@ -1401,11 +1413,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP NewtWindows_trackPointerLeave(wnd); SetCursor(wud->setPointerHandle); } - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_MOVED, - modifiers, - (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), - (jshort) 0, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_MOVED, + modifiers, + (jint) GET_X_LPARAM(lParam), (jint) GET_Y_LPARAM(lParam), + (jshort) 0, (jfloat) 0.0f); } useDefWindowProc = 1; } @@ -1416,11 +1428,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP wud->width, wud->height, wud->pointerInside, wud->pointerCaptured, wud->touchDownCount, wud->touchDownLastUp); if( 0 == wud->touchDownCount ) { wud->pointerInside = 0; - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_EXITED, - 0, - (jint) -1, (jint) -1, // fake - (jshort) 0, (jfloat) 0.0f); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_EXITED, + 0, + (jint) -1, (jint) -1, // fake + (jshort) 0, (jfloat) 0.0f); useDefWindowProc = 1; } } @@ -1446,11 +1458,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP break; } DBG_PRINT("*** WindowsWindow: WM_HSCROLL 0x%X, rotation %f, mods 0x%X\n", sb, rotation, modifiers); - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_WHEEL_MOVED, - modifiers, - (jint) 0, (jint) 0, - (jshort) 1, (jfloat) rotation); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_WHEEL_MOVED, + modifiers, + (jint) 0, (jint) 0, + (jshort) 1, (jfloat) rotation); useDefWindowProc = 1; break; } @@ -1475,11 +1487,11 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP DBG_PRINT("*** WindowsWindow: WM_MOUSEWHEEL %d/%d, rotation %f, vKeys 0x%X, mods 0x%X\n", (int)eventPt.x, (int)eventPt.y, rotationOrTilt, vKeys, modifiers); } - (*env)->CallVoidMethod(env, window, sendMouseEventID, - (jshort) EVENT_MOUSE_WHEEL_MOVED, - modifiers, - (jint) eventPt.x, (jint) eventPt.y, - (jshort) 1, (jfloat) rotationOrTilt); + (*env)->CallBooleanMethod(env, window, sendMouseEventID, + (jshort) EVENT_MOUSE_WHEEL_MOVED, + modifiers, + (jint) eventPt.x, (jint) eventPt.y, + (jshort) 1, (jfloat) rotationOrTilt); useDefWindowProc = 1; break; } @@ -1563,35 +1575,37 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP #endif } wud->pointerInside = allPInside; + jboolean winOK = JNI_TRUE; + if( sendFocus ) { (*env)->CallVoidMethod(env, window, requestFocusID, JNI_FALSE); } 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); + winOK = sendTouchScreenEvent(env, window, eventType[actionIdx], modifiers, actionIdx, + cInputs, pointerNames, x, y, pressure, maxPressure); sentCount++; } // 1 Move second .. - for (i=0; i < cInputs; i++) { + for (i=0; i < cInputs && JNI_TRUE == winOK; 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); + winOK = sendTouchScreenEvent(env, window, et, modifiers, i, + cInputs, pointerNames, x, y, pressure, maxPressure); sentCount++; } moveCount++; } } // Up and downs last - for (i=0; i < cInputs; i++) { + for (i=0; i < cInputs && JNI_TRUE == winOK; 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); + winOK = sendTouchScreenEvent(env, window, et, modifiers, i, + cInputs, pointerNames, x, y, pressure, maxPressure); sentCount++; } updownCount++; @@ -1614,7 +1628,6 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, WPARAM wParam, LPARAM lP useDefWindowProc = 1; } - if (useDefWindowProc) { return DefWindowProc(wnd, message, wParam, lParam); } @@ -2162,18 +2175,18 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_windows_WindowDriver_initIDs0 { NewtCommon_init(env); - insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)V"); + insetsChangedID = (*env)->GetMethodID(env, clazz, "insetsChanged", "(ZIIII)Z"); sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); - maximizedChangedID = (*env)->GetMethodID(env, clazz, "maximizedChanged", "(ZZ)V"); + maximizedChangedID = (*env)->GetMethodID(env, clazz, "maximizedChanged", "(ZZ)Z"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZZII)Z"); - focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)V"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); - sizePosInsetsFocusVisibleChangedID = (*env)->GetMethodID(env, clazz, "sizePosInsetsFocusVisibleChanged", "(ZZIIIIIIIIIIZ)V"); + focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(ZZ)Z"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); + sizePosInsetsFocusVisibleChangedID = (*env)->GetMethodID(env, clazz, "sizePosInsetsFocusVisibleChanged", "(ZZIIIIIIIIIIZ)Z"); 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[S[I[I[FF)V"); - sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)V"); + windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(ZIIII)Z"); + sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(SIIISF)Z"); + sendTouchScreenEventID = (*env)->GetMethodID(env, clazz, "sendTouchScreenEvent", "(SII[S[I[I[FF)Z"); + sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(SISSC)Z"); requestFocusID = (*env)->GetMethodID(env, clazz, "requestFocus", "(Z)V"); if (insetsChangedID == NULL || @@ -2448,9 +2461,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_InitWindow0 wud->xpos, wud->ypos, wud->width, wud->height, wud->focused, wud->visible); if( wud->isMaximized ) { - (*env)->CallVoidMethod(env, wud->jinstance, maximizedChangedID, JNI_TRUE, JNI_TRUE); + (*env)->CallBooleanMethod(env, wud->jinstance, maximizedChangedID, JNI_TRUE, JNI_TRUE); } - (*env)->CallVoidMethod(env, wud->jinstance, sizePosInsetsFocusVisibleChangedID, JNI_FALSE, JNI_FALSE, + (*env)->CallBooleanMethod(env, wud->jinstance, sizePosInsetsFocusVisibleChangedID, JNI_FALSE, JNI_FALSE, (jint)wud->xpos, (jint)wud->ypos, (jint)wud->width, (jint)wud->height, (jint)wud->insets.left, (jint)wud->insets.right, (jint)wud->insets.top, (jint)wud->insets.bottom, diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index a2fba9b7f..9ab49088a 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -40,6 +40,7 @@ jmethodID insetsVisibleChangedID = NULL; static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver"; static jmethodID displayCompletedID = NULL; +static jmethodID isNativeValidID = NULL; static jmethodID sendRRScreenChangeNotifyID = NULL; static jmethodID getCurrentThreadNameID = NULL; @@ -250,27 +251,29 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0 // displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJJIII)V"); // Variant using XKB displayCompletedID = (*env)->GetMethodID(env, clazz, "displayCompleted", "(JJIII)V"); - sendRRScreenChangeNotifyID = (*env)->GetMethodID(env, clazz, "sendRRScreenChangeNotify", "(J)V"); + isNativeValidID = (*env)->GetMethodID(env, clazz, "isNativeValidAsync", "()Z"); + sendRRScreenChangeNotifyID = (*env)->GetMethodID(env, clazz, "sendRRScreenChangeNotify", "(J)Z"); getCurrentThreadNameID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "getCurrentThreadName", "()Ljava/lang/String;"); dumpStackID = (*env)->GetStaticMethodID(env, X11NewtWindowClazz, "dumpStack", "()V"); - insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)V"); + insetsChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsChanged", "(ZIIII)Z"); sizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizeChanged", "(ZZIIZ)Z"); positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZZII)Z"); - focusVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusVisibleChanged", "(ZII)V"); - visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(Z)V"); - insetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsVisibleChanged", "(ZIIIII)V"); - sizePosMaxInsetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizePosMaxInsetsVisibleChanged", "(ZZIIIIIIIIIIIZ)V"); - reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V"); + focusVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusVisibleChanged", "(ZII)Z"); + visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(Z)Z"); + insetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "insetsVisibleChanged", "(ZIIIII)Z"); + sizePosMaxInsetsVisibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sizePosMaxInsetsVisibleChanged", "(ZZIIIIIIIIIIIZ)Z"); + reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z"); - windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V"); - visibleChangedWindowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedWindowRepaint", "(ZIIIII)V"); - sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)V"); - sendMouseEventRequestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEventRequestFocus", "(SIIISF)V"); - visibleChangedSendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedSendMouseEvent", "(ZISIIISF)V"); - sendTouchScreenEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendTouchScreenEvent", "(SII[S[I[I[FF)V"); - sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)V"); + windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)Z"); + visibleChangedWindowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedWindowRepaint", "(ZIIIII)Z"); + sendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEvent", "(SIIISF)Z"); + sendMouseEventRequestFocusID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendMouseEventRequestFocus", "(SIIISF)Z"); + visibleChangedSendMouseEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChangedSendMouseEvent", "(ZISIIISF)Z"); + sendTouchScreenEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendTouchScreenEvent", "(SII[S[I[I[FF)Z"); + sendKeyEventID = (*env)->GetMethodID(env, X11NewtWindowClazz, "sendKeyEvent", "(SISSCLjava/lang/String;)Z"); if (displayCompletedID == NULL || + isNativeValidID == NULL || sendRRScreenChangeNotifyID == NULL || getCurrentThreadNameID == NULL || dumpStackID == NULL || @@ -391,10 +394,10 @@ static int NewtWindows_updateVisibility(JNIEnv *env, Display *dpy, JavaWindow *j return visibleChange; } -static void sendTouchScreenEvent(JNIEnv *env, JavaWindow *jw, - short eventType, // MouseEvent.EVENT_MOUSE_PRESSED, MouseEvent.EVENT_MOUSE_RELEASED, MouseEvent.EVENT_MOUSE_MOVED - int modifiers, // 0! - int actionId) // index of multiple-pointer arrays representing the pointer which triggered the event +static jboolean sendTouchScreenEvent(JNIEnv *env, JavaWindow *jw, + short eventType, // MouseEvent.EVENT_MOUSE_PRESSED, MouseEvent.EVENT_MOUSE_RELEASED, MouseEvent.EVENT_MOUSE_MOVED + int modifiers, // 0! + int actionId) // index of multiple-pointer arrays representing the pointer which triggered the event { jshort pointerNames[XI_TOUCHCOORD_COUNT]; jint x[XI_TOUCHCOORD_COUNT]; @@ -445,10 +448,11 @@ static void sendTouchScreenEvent(JNIEnv *env, JavaWindow *jw, } (*env)->SetFloatArrayRegion(env, jPressure, 0, cnt, pressure); - (*env)->CallVoidMethod(env, jw->jwindow, sendTouchScreenEventID, - (jshort)eventType, (jint)modifiers, (jint)actionIdx, - jNames, jX, jY, jPressure, (jfloat)1.0f); + jboolean res = (*env)->CallBooleanMethod(env, jw->jwindow, sendTouchScreenEventID, + (jshort)eventType, (jint)modifiers, (jint)actionIdx, + jNames, jX, jY, jPressure, (jfloat)1.0f); NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: XI: Exception occured at sendTouchScreenEvent(..)"); + return res; } /* @@ -467,6 +471,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage int autoRepeatModifiers = 0; if ( NULL == dpy ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 0\n", dpy); return; } @@ -489,12 +494,25 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage jstring keyString = NULL; char text[255]; + // Don't use explicit Java callback, we simply break loop if regular Java callback on event returns JNI_FALSE + #if 0 + if( JNIInvalidRefType == (*env)->GetObjectRefType(env, obj) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1, invalidated DisplayDriver Object %p\n", dpy, obj); + return; + } + if( JNI_FALSE == (*env)->CallBooleanMethod(env, obj, isNativeValidID) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 2, closed DisplayDriver %p\n", dpy, obj); + return; + } + NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: Exception occured at isNativeValid()"); + #endif + // XEventsQueued(dpy, X): // QueuedAlready == XQLength(): No I/O Flush or system call doesn't work on some cards (eg ATI) ?) // QueuedAfterFlush == XPending(): I/O Flush only if no already queued events are available // QueuedAfterReading : QueuedAlready + if queue==0, attempt to read more .. if ( 0 >= XEventsQueued(dpy, QueuedAfterFlush) ) { - // DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 1\n", dpy); + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 3\n", dpy); return; } @@ -502,13 +520,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage num_events--; if(dpy!=evt.xany.display) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 4, wrong display\n", dpy); NewtCommon_throwNewRuntimeException(env, "wrong display, bail out!"); return ; } if( randr_event_base > 0 && RRScreenChangeNotify == ( evt.type - randr_event_base ) ) { DBG_PRINT( "X11: DispatchMessages dpy %p, Event RRScreenChangeNotify %p\n", (void*)dpy, (void*)&evt); - (*env)->CallVoidMethod(env, obj, sendRRScreenChangeNotifyID, (jlong)(intptr_t)&evt); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, obj, sendRRScreenChangeNotifyID, (jlong)(intptr_t)&evt) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, RRScreen\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: RR: Exception occured at sendRRScreenChangeNotify(..)"); continue; // next event } @@ -523,13 +545,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage XGenericEventCookie *evtCookie = &evt.xcookie; // hacks: https://keithp.com/blogs/Cursor_tracking/ int isXiEvent = GenericEvent == evtCookie->type && xi_opcode == evtCookie->extension && XGetEventData(dpy, evtCookie); XIDeviceEvent *xiDevEv; + int xiDetail; Window windowPointer; if( !isXiEvent ) { xiDevEv = NULL; + xiDetail = 0; windowPointer = evt.xany.window; DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)windowPointer, (int)evt.type); } else { xiDevEv = evtCookie->data; + xiDetail = xiDevEv->detail; windowPointer = xiDevEv->event; } @@ -563,7 +588,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage } DBG_PRINT( "X11: XI event - XI_TouchBegin Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid, i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y); - sendTouchScreenEvent(env, jw, EVENT_MOUSE_PRESSED, 0, xiDevEv->detail % 32767); + XFreeEventData(dpy, evtCookie); + if( JNI_FALSE == sendTouchScreenEvent(env, jw, EVENT_MOUSE_PRESSED, 0, xiDetail % 32767) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, touch-begin\n", dpy); + num_events = 0; // end loop in case of destroyed display + } break; case XI_TouchUpdate: @@ -576,7 +605,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage } DBG_PRINT( "X11: XI event - XI_TouchUpdate: Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid, i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y); - sendTouchScreenEvent(env, jw, EVENT_MOUSE_MOVED, 0, xiDevEv->detail % 32767); + XFreeEventData(dpy, evtCookie); + if( JNI_FALSE == sendTouchScreenEvent(env, jw, EVENT_MOUSE_MOVED, 0, xiDetail % 32767) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, touch-update\n", dpy); + num_events = 0; // end loop in case of destroyed display + } break; case XI_TouchEnd: @@ -587,14 +620,20 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage } DBG_PRINT( "X11: XI event - XI_TouchEnd: Window %p, devid %d, touchid[%d] %d @ %d/%d\n", (void*)windowPointer, xiDevEv->deviceid, i, jw->xiTouchCoords[i].id, jw->xiTouchCoords[i].x, jw->xiTouchCoords[i].y); - sendTouchScreenEvent(env, jw, EVENT_MOUSE_RELEASED, 0, xiDevEv->detail % 32767); + XFreeEventData(dpy, evtCookie); + if( JNI_FALSE == sendTouchScreenEvent(env, jw, EVENT_MOUSE_RELEASED, 0, xiDetail % 32767) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, touch-end\n", dpy); + num_events = 0; // end loop in case of destroyed display + } if ( i < XI_TOUCHCOORD_COUNT ) { jw->xiTouchCoords[i].id = -1; } break; + + default: + XFreeEventData(dpy, evtCookie); } } - XFreeEventData(dpy, evtCookie); continue; // next event, skip evt.type handling below } @@ -686,21 +725,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage switch(evt.type) { case ButtonPress: - (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventRequestFocusID, (jshort) EVENT_MOUSE_PRESSED, - modifiers, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendMouseEventRequestFocusID, (jshort) EVENT_MOUSE_PRESSED, + modifiers, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, press-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: ButtonPress: Exception occured at sendMouseEventRequestFocus(..)"); break; case ButtonRelease: - (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, - modifiers, - (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, + modifiers, + (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, release-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: ButtonRelease: Exception occured at sendMouseEvent(..)"); break; case MotionNotify: - (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, - modifiers, - (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, + modifiers, + (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, motion-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: MotionNotify: Exception occured at sendMouseEvent(..)"); break; case EnterNotify: @@ -708,9 +756,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "EnterNotify"); - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, - (jshort) EVENT_MOUSE_ENTERED, modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, + (jshort) EVENT_MOUSE_ENTERED, modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, enter-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: EnterNotify: Exception occured at visibleChangedSendMouseEvent(..)"); } break; @@ -719,9 +770,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "LeaveNotify"); - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, - (jshort) EVENT_MOUSE_EXITED, modifiers, - (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedSendMouseEventID, JNI_FALSE, (jint)visibleChange, + (jshort) EVENT_MOUSE_EXITED, modifiers, + (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, leave-mouseEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: LeaveNotify: Exception occured at visibleChangedSendMouseEvent(..)"); } break; @@ -730,13 +784,19 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage XRefreshKeyboardMapping(&evt.xmapping); break; case KeyPress: - (*env)->CallVoidMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, - modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, + modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, press-keyEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: KeyPress: Exception occured at sendKeyEvent(..)"); break; case KeyRelease: - (*env)->CallVoidMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, - modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, + modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, release-keyEvent\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: KeyRelease: Exception occured at sendKeyEvent(..)"); break; case DestroyNotify: @@ -787,14 +847,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "ConfigureNotify"); NewtWindows_updateInsets(dpy, jw, False /* wait */, &left, &right, &top, &bottom); Bool maxChanged = NewtWindows_updateMaximized(dpy, jw, netWMState); - (*env)->CallVoidMethod(env, jw->jwindow, sizePosMaxInsetsVisibleChangedID, JNI_FALSE, JNI_FALSE, - (jint) x_pos, (jint) y_pos, - (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, - (jint)(maxChanged ? ( jw->maxHorz ? 1 : 0 ) : -1), - (jint)(maxChanged ? ( jw->maxVert ? 1 : 0 ) : -1), - (jint)left, (jint)right, (jint)top, (jint)bottom, - (jint)visibleChange, - JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, sizePosMaxInsetsVisibleChangedID, JNI_FALSE, JNI_FALSE, + (jint) x_pos, (jint) y_pos, + (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, + (jint)(maxChanged ? ( jw->maxHorz ? 1 : 0 ) : -1), + (jint)(maxChanged ? ( jw->maxVert ? 1 : 0 ) : -1), + (jint)left, (jint)right, (jint)top, (jint)bottom, + (jint)visibleChange, + JNI_FALSE) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, sizePosMaxInsetsVis\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: ConfigureNotify: Exception occured at sizePosMaxInsetsVisibleChanged(..)"); } break; @@ -808,6 +871,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage closed = (*env)->CallBooleanMethod(env, jw->jwindow, windowDestroyNotifyID, JNI_FALSE); DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, closed: %d\n", (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, (int)closed); + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave 5, windowDeleteAtom received\n", dpy); // Called by Window.java: CloseWindow(); num_events = 0; // end loop in case of destroyed display } @@ -818,7 +882,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "FocusIn"); - (*env)->CallVoidMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)1, (jint)visibleChange); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)1, (jint)visibleChange) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, focus-in\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: FocusIn: Exception occured at focusVisibleChanged(..)"); } break; @@ -828,7 +895,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage { uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "FocusOut"); - (*env)->CallVoidMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)0, (jint)visibleChange); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, focusVisibleChangedID, JNI_FALSE, (jint)0, (jint)visibleChange) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, focus-out\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: FocusOut: Exception occured at focusVisibleChanged(..)"); } break; @@ -840,7 +910,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "VisibilityNotify"); if( 0 <= visibleChange ) { - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, 0 < visibleChange ? JNI_TRUE : JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedID, 0 < visibleChange ? JNI_TRUE : JNI_FALSE) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, vis-notify\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: VisibilityNotify: Exception occured at visibleChanged(..)"); } #endif @@ -852,14 +925,20 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage DBG_PRINT( "X11: event . Expose call %p %d/%d %dx%d count %d\n", (void*)evt.xexpose.window, evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count); if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) { - (*env)->CallVoidMethod(env, jw->jwindow, windowRepaintID, JNI_FALSE, - evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, windowRepaintID, JNI_FALSE, + evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, expose\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: Expose: Exception occured at windowRepaint(..)"); #if 0 uint32_t netWMState = NewtWindows_getNET_WM_STATE(dpy, jw); int visibleChange = NewtWindows_updateVisibility(env, dpy, jw, netWMState, "Expose"); - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedWindowRepaintID, JNI_FALSE, (jint)visibleChange, - evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedWindowRepaintID, JNI_FALSE, (jint)visibleChange, + evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, focus-in-vis-repaint\n", dpy); + num_events = 0; // end loop in case of destroyed display + } #endif } break; @@ -874,10 +953,16 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage // insets: negative values are ignored int left=-1, right=-1, top=-1, bottom=-1; if( NewtWindows_updateInsets(dpy, jw, False /* wait */, &left, &right, &top, &bottom) ) { - (*env)->CallVoidMethod(env, jw->jwindow, insetsVisibleChangedID, JNI_FALSE, left, right, top, bottom, 1); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, insetsVisibleChangedID, JNI_FALSE, left, right, top, bottom, 1) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, map-insets\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: MapNotify: Exception occured at insetsVisibleChanged(..)"); } else { - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_TRUE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedID, JNI_TRUE) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, map\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: MapNotify: Exception occured at visibleChanged(..)"); } } @@ -890,7 +975,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage if( evt.xunmap.event == evt.xunmap.window ) { // ignore child window notification jw->isMapped = False; - (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, unmap\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: UnmapNotify: Exception occured at visibleChanged(..)"); } break; @@ -924,7 +1012,10 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent, (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent); #endif - (*env)->CallVoidMethod(env, jw->jwindow, reparentNotifyID, (jlong)evt.xreparent.parent); + if( JNI_FALSE == (*env)->CallBooleanMethod(env, jw->jwindow, reparentNotifyID, (jlong)evt.xreparent.parent) ) { + DBG_PRINT( "X11: DispatchMessages 0x%X - Leave J, reparent-notify\n", dpy); + num_events = 0; // end loop in case of destroyed display + } NewtCommon_ExceptionCheck1_throwNewRuntimeException(env, "X11Display.DispatchMessages0: ReparentNotify: Exception occured at reparentNotify(..)"); } break; diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index b53b596cc..142c59137 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -382,16 +382,15 @@ static Status NewtWindows_getFrameExtends(Display *dpy, JavaWindow *javaWin, Boo } if( wait && tD < TIMEOUT_MS && evtCount < MAX_ATTEMPTS ) { // wait for next X event to arrive, then we may try again + evtCount++; #if 0 XEvent e; XPeekEvent(dpy, &e); // FIXME: Blocks if queue is empty - evtCount++; DBG_PRINT( "NEWT FrameExtends: Waiting: #%d %ldms: evt %d, window %p (this=%d)\n", evtCount, tD, e.type, (void*)e.xany.window, (javaWin->window == e.xany.window)); #else struct timespec req = { .tv_sec = 0, .tv_nsec = 1000000L }; // 1ms nanosleep(&req, NULL); - evtCount++; DBG_PRINT( "NEWT FrameExtends: Waiting: #%d %ldms ...\n", evtCount, tD ); #endif } else { @@ -635,6 +634,19 @@ static void NewtWindows_sendNET_WM_DESKTOP(Display *dpy, Window root, JavaWindow XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev ); } +static void NewtWindows_sendDeleteAtom(Display *dpy, JavaWindow * w) { + XEvent xev; + memset ( &xev, 0, sizeof(xev) ); + + xev.type = ClientMessage; + xev.xclient.window = w->window; + xev.xclient.message_type = w->javaObjectAtom; + xev.xclient.format = 32; + xev.xclient.data.l[0] = w->windowDeleteAtom; + xev.xclient.data.l[1] = 1; //source indication for normal applications + XSendEvent ( dpy, w->window, False, 0, &xev ); +} + /** * Set fullscreen using Extended Window Manager Hints (EWMH) @@ -1099,7 +1111,7 @@ JNIEXPORT jint JNICALL Java_jogamp_newt_driver_x11_WindowDriver_GetSupportedReco * Signature: (JJ)V */ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 - (JNIEnv *env, jobject obj, jlong display, jlong javaWindow /*, jlong kbdHandle*/, // XKB disabled for now + (JNIEnv *env, jobject obj, jobject displayDriver, jlong display, jlong javaWindow /*, jlong kbdHandle*/, // XKB disabled for now jint randr_event_base, jint randr_error_base, jint xi_opcode) { Display * dpy = (Display *) (intptr_t) display; @@ -1135,8 +1147,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0 XUnmapWindow(dpy, jw->window); jw->isMapped=False; - // Drain all events related to this window .. - Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, + // Notify potential running dispatcher and drain all events related to this window .. + NewtWindows_sendDeleteAtom(dpy, jw); + Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, displayDriver, display, (jlong)(intptr_t)jw->javaObjectAtom, (jlong)(intptr_t)jw->windowDeleteAtom /*, kbdHandle */, // XKB disabled for now randr_event_base, randr_error_base, xi_opcode); diff --git a/src/newt/native/bcm_vc_iv.c b/src/newt/native/bcm_vc_iv.c index 03a52c787..3a853fc5c 100644 --- a/src/newt/native/bcm_vc_iv.c +++ b/src/newt/native/bcm_vc_iv.c @@ -332,7 +332,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_initID { sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZZII)Z"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); if (sizeChangedID == NULL || positionChangedID == NULL || @@ -397,7 +397,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_bcm_vc_iv_WindowDriver_CreateWin vc_dispmanx_update_submit_sync( dispman_update ); - (*env)->CallVoidMethod(env, obj, visibleChangedID, JNI_TRUE); + (*env)->CallBooleanMethod(env, obj, visibleChangedID, JNI_TRUE); DBG_PRINT( "BCM.Display Window.Create.X %p, element %p\n", (void*)(intptr_t)dispman_display, (void*)(intptr_t)p->handle); diff --git a/src/newt/native/drm_gbm.c b/src/newt/native/drm_gbm.c index 7f2b7de88..722c11a49 100644 --- a/src/newt/native/drm_gbm.c +++ b/src/newt/native/drm_gbm.c @@ -223,7 +223,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_egl_gbm_WindowDriver_initIDs { sizeChangedID = (*env)->GetMethodID(env, clazz, "sizeChanged", "(ZZIIZ)Z"); positionChangedID = (*env)->GetMethodID(env, clazz, "positionChanged", "(ZZII)Z"); - visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)Z"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "(Z)Z"); if (sizeChangedID == NULL || positionChangedID == NULL || diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestDestroyGLAutoDrawableNewtAWT.java b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestDestroyGLAutoDrawableNewtAWT.java new file mode 100644 index 000000000..152c98eb3 --- /dev/null +++ b/src/test/com/jogamp/opengl/test/junit/jogl/acore/TestDestroyGLAutoDrawableNewtAWT.java @@ -0,0 +1,255 @@ +/** + * Copyright 2010-2023 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, are + * permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND + * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The views and conclusions contained in the software and documentation are those of the + * authors and should not be interpreted as representing official policies, either expressed + * or implied, of JogAmp Community. + */ + +package com.jogamp.opengl.test.junit.jogl.acore; + +import java.awt.AWTException; +import java.awt.Robot; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import com.jogamp.opengl.GLAutoDrawable; +import com.jogamp.opengl.GLCapabilities; +import com.jogamp.opengl.GLException; +import com.jogamp.opengl.GLProfile; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; + +import com.jogamp.common.util.InterruptSource; +import com.jogamp.newt.event.KeyEvent; +import com.jogamp.newt.event.KeyListener; +import com.jogamp.newt.event.MouseAdapter; +import com.jogamp.newt.event.MouseEvent; +import com.jogamp.newt.event.MouseListener; +import com.jogamp.newt.event.WindowAdapter; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.opengl.GLWindow; +import com.jogamp.opengl.test.junit.jogl.demos.es2.RedSquareES2; +import com.jogamp.opengl.test.junit.util.AWTRobotUtil; +import com.jogamp.opengl.test.junit.util.NewtTestUtil; +import com.jogamp.opengl.test.junit.util.UITestCase; +import com.jogamp.opengl.util.Animator; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class TestDestroyGLAutoDrawableNewtAWT extends UITestCase { + + static long duration = 100; // ms + + static void destroyGLAD(final GLAutoDrawable glad, final int mode) { + final String tname = Thread.currentThread().toString(); + System.err.println(tname+": Destroy mode "+mode+": Start: Realised "+glad.isRealized()); + glad.destroy(); + System.err.println(tname+": Destroy mode "+mode+": End: Realised "+glad.isRealized()); + } + + /** + * + * @param destroyMode 0 on-thread, 1 render-thread, 2 edt-thread, 3 external-thread, 10 key-press, 11 mouse-click + * @throws InterruptedException + * @throws AWTException + * @throws InvocationTargetException + */ + protected void runTestGL(final int destroyMode) throws InterruptedException, InvocationTargetException, AWTException { + final Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + + final GLCapabilities caps = new GLCapabilities(GLProfile.getGL2ES2()); + + final GLWindow glWindow = GLWindow.create(caps); + Assert.assertNotNull(glWindow); + glWindow.setTitle("TestDestroyGLAutoDrawableNewtAWT Mode "+destroyMode); + glWindow.addGLEventListener(new RedSquareES2().setVerbose(false)); + + final short quitKey = KeyEvent.VK_Q; + + glWindow.addWindowListener(new WindowAdapter() { + @Override + public void windowDestroyNotify(final WindowEvent e) { + System.err.println("Window DestroyNotify: "+e); + } + + @Override + public void windowDestroyed(final WindowEvent e) { + System.err.println("Window Destroyed: "+e); + } + + @Override + public void windowGainedFocus(final WindowEvent e) { + System.err.println("Window Focus Gained: "+e); + } + + @Override + public void windowLostFocus(final WindowEvent e) { + System.err.println("Window Focus Lost: "+e); + } + }); + final KeyListener keyAction = new KeyListener() { + @Override + public void keyPressed(final KeyEvent e) { + System.err.println("KEY PRESSED: "+e); + } + @Override + public void keyReleased(final KeyEvent e) { + System.err.println("KEY RELEASED: "+e); + if( e.isAutoRepeat() ) { + return; + } + switch(e.getKeyCode()) { + case quitKey: + destroyGLAD(glWindow, 10); + break; + } + } + }; + final MouseListener mouseAction = new MouseAdapter() { + @Override + public void mousePressed(final MouseEvent e) { + System.err.println("MOUSE PRESSED: "+e); + } + @Override + public void mouseReleased(final MouseEvent e) { + System.err.println("MOUSE RELEASED: "+e); + } + @Override + public void mouseClicked(final MouseEvent e) { + System.err.println("MOUSE CLICKED: "+e); + destroyGLAD(glWindow, 11); + } + }; + + glWindow.setSize(256, 256); + glWindow.setVisible(true); + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, true, null)); + + final Animator animator = new Animator(glWindow); + animator.setUpdateFPSFrames(30, null); + animator.start(); + + while(animator.isAnimating() && animator.getTotalFPSDuration()<duration) { + Thread.sleep(30); + } + + System.err.println("AWT Robot Init"); + final java.awt.Point objCenter; + { + final int[] oc = AWTRobotUtil.getCenterLocation(glWindow, false /* onTitleBarIfWindow */); + objCenter = new java.awt.Point(oc[0], oc[1]); + } + AWTRobotUtil.awtRobotMouseMove(robot, objCenter.x, objCenter.y); // Bug 919: Reset mouse position + AWTRobotUtil.assertRequestFocusAndWait(null, glWindow, glWindow, null, null); // programmatic + AWTRobotUtil.awtRobotMouseMove(robot, objCenter.x, objCenter.y); // Bug 919: Reset mouse position + AWTRobotUtil.waitForIdle(robot); + System.err.println("AWT Robot OK"); + + switch( destroyMode ) { + case 1: { + // Since we pull the resources under the GLAutoDrawable + // while destroying it within the display call - it causes an exception: + // - WindowImpl.getGraphicsConfiguration(WindowImpl.java:1173) (NPE this.config) + // - ... + // - GLDrawableImpl.unlockSurface(GLDrawableImpl.java:340) -> + animator.stop(); // let's have the exception thrown here to catch it, not on animator + try { + glWindow.invoke(true, (final GLAutoDrawable glad) -> { destroyGLAD(glad, 1); return true; } ); + } catch( final GLException gle ) { + // OK, since + System.err.println("Expected exception: "+gle.getMessage()); + } + } + break; + case 2: { + glWindow.runOnEDTIfAvail(true, () -> { destroyGLAD(glWindow, 2); } ); + } + break; + case 3: { + new InterruptSource.Thread( () -> { destroyGLAD(glWindow, 3); } ).start(); + } + break; + case 10: { + glWindow.addKeyListener(keyAction); + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.newtKeyPress(0, robot, true, quitKey, 10); + AWTRobotUtil.newtKeyPress(0, robot, false, quitKey, 100); + } + break; + case 11: { + glWindow.addMouseListener(mouseAction); + AWTRobotUtil.waitForIdle(robot); + AWTRobotUtil.mouseClick(robot, objCenter, 1, AWTRobotUtil.ROBOT_DELAY, 0); + } + break; + default: { + destroyGLAD(glWindow, 0); + } + break; + } + Assert.assertEquals(true, NewtTestUtil.waitForRealized(glWindow, false, null)); + Assert.assertEquals(false, glWindow.isNativeValid()); + animator.stop(); // Avoiding a ThreadDeath of animator at shutdown + Assert.assertEquals(false, animator.isAnimating()); + } + + @Test + public void test00OnThread() throws InterruptedException, InvocationTargetException, AWTException { + runTestGL(0); + } + + @Test + public void test01RenderThread() throws InterruptedException, InvocationTargetException, AWTException { + runTestGL(1); + } + + @Test + public void test02EDTThread() throws InterruptedException, InvocationTargetException, AWTException { + runTestGL(2); + } + + @Test + public void test03ExtThread() throws InterruptedException, InvocationTargetException, AWTException { + runTestGL(3); + } + + @Test + public void test10EDTKeyEvent() throws InterruptedException, InvocationTargetException, AWTException { + runTestGL(10); + } + + @Test + public void test11EDTMouseEvent() throws InterruptedException, InvocationTargetException, AWTException { + runTestGL(11); + } + + public static void main(final String args[]) throws IOException { + final String tstname = TestDestroyGLAutoDrawableNewtAWT.class.getName(); + org.junit.runner.JUnitCore.main(tstname); + } + +} diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java index 1ffa30560..816f21b9f 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java @@ -131,7 +131,7 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen public void setIgnoreFocus(final boolean v) { ignoreFocus = v; } public void setDoRotation(final boolean rotate) { this.doRotate = rotate; } public void setClearBuffers(final boolean v) { clearBuffers = v; } - public void setVerbose(final boolean v) { verbose = v; } + public GearsES2 setVerbose(final boolean v) { verbose = v; return this; } public void setFlipVerticalInGLOrientation(final boolean v) { flipVerticalInGLOrientation=v; } /** float[4] */ diff --git a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java index f6d0b6876..83873fc24 100644 --- a/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java +++ b/src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/RedSquareES2.java @@ -88,7 +88,7 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende public void setAspect(final float aspect) { this.aspect = aspect; } public void setDoRotation(final boolean rotate) { this.doRotate = rotate; } public void setClearBuffers(final boolean v) { clearBuffers = v; } - public void setVerbose(final boolean v) { verbose = v; } + public RedSquareES2 setVerbose(final boolean v) { verbose = v; return this; } @Override public void init(final GLAutoDrawable glad) { @@ -108,7 +108,7 @@ public class RedSquareES2 implements GLEventListener, TileRendererBase.TileRende return; } st = new ShaderState(); - st.setVerbose(true); + st.setVerbose(verbose); final ShaderCode vp0 = ShaderCode.create(gl, GL2ES2.GL_VERTEX_SHADER, this.getClass(), "shader", "shader/bin", "RedSquareShader", true); final ShaderCode fp0 = ShaderCode.create(gl, GL2ES2.GL_FRAGMENT_SHADER, this.getClass(), "shader", |