aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/classes/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/classes/com')
-rw-r--r--src/newt/classes/com/jogamp/newt/NewtFactory.java8
-rw-r--r--src/newt/classes/com/jogamp/newt/Window.java73
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java22
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java2
-rw-r--r--src/newt/classes/com/jogamp/newt/javafx/NewtCanvasJFX.java670
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java10
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java530
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java95
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MainThread.java20
-rw-r--r--src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java98
-rw-r--r--src/newt/classes/com/jogamp/newt/util/applet3/JOGLNewtApplet3Run.java2
11 files changed, 1382 insertions, 148 deletions
diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java
index 2ed2194d8..dd15eb3ea 100644
--- a/src/newt/classes/com/jogamp/newt/NewtFactory.java
+++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java
@@ -59,6 +59,7 @@ public class NewtFactory {
public static final String DRIVER_DEFAULT_ROOT_PACKAGE = "jogamp.newt.driver";
private static IOUtil.ClassResources defaultWindowIcons;
+ private static String sysPaths = "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png";
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@@ -67,12 +68,11 @@ public class NewtFactory {
NativeWindowFactory.initSingleton(); // last resort ..
{
/** See API Doc in {@link Window} ! */
- final String[] paths = PropertyAccess.getProperty("newt.window.icons", true, "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png").split("\\s");
+ final String[] paths = PropertyAccess.getProperty("newt.window.icons", true, sysPaths).split("[\\s,]");
if( paths.length < 2 ) {
throw new IllegalArgumentException("Property 'newt.window.icons' did not specify at least two PNG icons, but "+Arrays.toString(paths));
}
- final Class<?> clazz = NewtFactory.class;
- defaultWindowIcons = new IOUtil.ClassResources(clazz, paths);
+ defaultWindowIcons = new IOUtil.ClassResources(paths, NewtFactory.class.getClassLoader(), null);
}
return null;
} } );
@@ -81,7 +81,7 @@ public class NewtFactory {
/**
* Returns the application window icon resources to be used.
* <p>
- * Property <code>newt.window.icons</code> may define a list of PNG icons separated by a whitespace character.
+ * Property <code>newt.window.icons</code> may define a list of PNG icons separated by one whitespace or one comma character.
* Shall reference at least two PNG icons, from lower (16x16) to higher (>= 32x32) resolution.
* </p>
* <p>
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index d46afd1cd..30b02cb61 100644
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -83,16 +83,22 @@ import com.jogamp.nativewindow.util.SurfaceSize;
* <a name="customwindowicons"><h5>Custom Window Icons</h5></a>
* <p>
* Custom window icons can be defined via system property <code>newt.window.icons</code>,
- * which shall contain a space separated list of PNG icon locations from low- to high-resolution.
+ * which shall contain a list of PNG icon locations from low- to high-resolution,
+ * separated by one whitespace or one comma character.
* The location must be resolvable via classpath, i.e. shall reference a location within the jar file.
* Example (our default):
* <pre>
- * -Dnewt.window.icons="newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png"
- * -Djnlp.newt.window.icons="newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png"
+ * -Dnewt.window.icons="newt/data/jogamp-16x16.png,newt/data/jogamp-32x32.png"
+ * -Djnlp.newt.window.icons="newt/data/jogamp-16x16.png,newt/data/jogamp-32x32.png"
* </pre>
* The property can also be set programmatically, which must happen before any NEWT classes are <i>touched</i>:
* <pre>
- * System.setProperty("newt.window.icons", "newt/data/jogamp-16x16.png newt/data/jogamp-32x32.png");
+ * System.setProperty("newt.window.icons", "newt/data/jogamp-16x16.png, newt/data/jogamp-32x32.png");
+ * </pre>
+ * To disable even Jogamp's own window icons in favor of system icons,
+ * simply set a non-existing location, e.g.:
+ * <pre>
+ * -Dnewt.window.icons="null,null"
* </pre>
* </p>
*
@@ -216,6 +222,10 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
public static final int STATE_BIT_MAXIMIZED_HORZ = 10; // reconfig-flag
/**
* Set if window is in <i>fullscreen mode</i>, otherwise cleared.
+ * <p>
+ * Usually fullscreen mode implies {@link #STATE_BIT_UNDECORATED},
+ * however, an implementation is allowed to ignore this if unavailable.
+ * </p>
* <p>Bit number {@value}.</p>
* <p>Defaults to {@code false}.</p>
* @see #getStateMask()
@@ -223,9 +233,6 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
*/
public static final int STATE_BIT_FULLSCREEN = 11; // reconfig-flag
- // Hidden in WindowImpl:
- // static final int STATE_BIT_FULLSCREEN_SPAN = 12;
-
/**
* Set if the <i>pointer is visible</i> when inside the window, otherwise cleared.
* <p>Bit number {@value}.</p>
@@ -233,7 +240,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
* @see #getStateMask()
* @since 2.3.2
*/
- public static final int STATE_BIT_POINTERVISIBLE = 13;
+ public static final int STATE_BIT_POINTERVISIBLE = 12;
/**
* Set if the <i>pointer is confined</i> to the window, otherwise cleared.
* <p>Bit number {@value}.</p>
@@ -241,7 +248,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
* @see #getStateMask()
* @since 2.3.2
*/
- public static final int STATE_BIT_POINTERCONFINED = 14;
+ public static final int STATE_BIT_POINTERCONFINED = 13;
/**
* Bitmask for {@link #STATE_BIT_VISIBLE}, {@value}.
@@ -330,6 +337,7 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
/**
* Returns the current status mask of this instance.
+ * @see #getSupportedStateMask()
* @see #STATE_MASK_VISIBLE
* @see #STATE_MASK_AUTOPOSITION
* @see #STATE_MASK_CHILDWIN
@@ -354,6 +362,52 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
*/
String getStateMaskString();
+ /**
+ * Returns the supported {@link #getStateMask() state mask} of the implementation.
+ * <p>
+ * Implementation provides supported {@link #getStateMask() state mask} values at runtime
+ * <i>after</i> native window creation, i.e. first visibility.
+ * </p>
+ * <p>
+ * Please note that a window's size shall also be allowed to change, i.e. {@link #setSize(int, int)}.
+ * </p>
+ * <p>
+ * Default value is {@link #STATE_MASK_VISIBLE} | {@link #STATE_MASK_FOCUSED} | {@link #STATE_MASK_FULLSCREEN},
+ * i.e. the <b>minimum requirement</b> for all implementations.
+ * </p>
+ * <p>
+ * Before native window creation {@link #getStatePublicBitmask()} is returned,
+ * i.e. it is assumed all features are supported.
+ * </p>
+ * <p>
+ * Semantic of the supported state-mask bits (after native creation, i.e. 1st visibility):
+ * <ul>
+ * <li>{@link #STATE_MASK_VISIBLE}: {@link #setVisible(boolean) Visibility} can be toggled. <b>Minimum requirement</b>.</li>
+ * <li>{@link #STATE_MASK_CHILDWIN}: {@link #reparentWindow(NativeWindow, int, int, int) Native window parenting} is supported.</li>
+ * <li>{@link #STATE_MASK_FOCUSED}: Window {@link #requestFocus() focus management} is supported. <b>Minimum requirement</b>.</li>
+ * <li>{@link #STATE_MASK_UNDECORATED}: {@link #setUndecorated(boolean) Window decoration} can be toggled.</li>
+ * <li>{@link #STATE_MASK_ALWAYSONTOP}: Window can be set {@link #setAlwaysOnTop(boolean) always-on-top}. </li>
+ * <li>{@link #STATE_MASK_ALWAYSONBOTTOM}: Window can be set {@link #setAlwaysOnBottom(boolean) always-on-bottom}. </li>
+ * <li>{@link #STATE_MASK_STICKY}: Window can be set {@link #setSticky(boolean) sticky}.</li>
+ * <li>{@link #STATE_MASK_RESIZABLE}: Window {@link #setResizable(boolean) resizability} can be toggled.</li>
+ * <li>{@link #STATE_MASK_MAXIMIZED_VERT}: Window can be {@link #setMaximized(boolean, boolean) maximized-vertically}. </li>
+ * <li>{@link #STATE_MASK_MAXIMIZED_HORZ}: Window can be {@link #setMaximized(boolean, boolean) maximized-horizontally}. </li>
+ * <li>{@link #STATE_MASK_FULLSCREEN}: Window {@link #setFullscreen(boolean) fullscreen} can be toggled. </li>
+ * <li>{@link #STATE_MASK_POINTERVISIBLE}: Window {@link #setPointerVisible(boolean) pointer visibility} can be toggled. </li>
+ * <li>{@link #STATE_MASK_POINTERCONFINED}: Window {@link #confinePointer(boolean) pointer can be confined}. </li>
+ * </ul>
+ * </p>
+ * @see #getStateMask()
+ * @since 2.3.2
+ */
+ int getSupportedStateMask();
+
+ /**
+ * Returns a string representation of the {@link #getSupportedStateMask() supported state mask}.
+ * @since 2.3.2
+ */
+ String getSupportedStateMaskString();
+
//
// Lifecycle
//
@@ -697,7 +751,6 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
boolean isSticky();
/**
- * <p>Operation is ignored in {@link #isFullscreen() fullscreen mode}.</p>
* <p>Operation is ignored if this instance {@link #isChildWindow() is a child window}.</p>
* @see {@link #STATE_BIT_MAXIMIZED_HORZ}
* @see {@link #STATE_BIT_MAXIMIZED_VERT}
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index ae32fd164..a0083b4ea 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -49,7 +49,9 @@ import java.security.PrivilegedAction;
import java.util.Set;
import com.jogamp.nativewindow.CapabilitiesImmutable;
+import com.jogamp.nativewindow.NativeSurface;
import com.jogamp.nativewindow.NativeWindow;
+import com.jogamp.nativewindow.NativeWindowHolder;
import com.jogamp.nativewindow.OffscreenLayerOption;
import com.jogamp.nativewindow.WindowClosingProtocol;
import com.jogamp.opengl.GLAnimatorControl;
@@ -100,7 +102,7 @@ import com.jogamp.opengl.util.TileRenderer;
* the underlying JAWT mechanism to composite the image, if supported.
*/
@SuppressWarnings("serial")
-public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption, AWTPrintLifecycle {
+public class NewtCanvasAWT extends java.awt.Canvas implements NativeWindowHolder, WindowClosingProtocol, OffscreenLayerOption, AWTPrintLifecycle {
public static final boolean DEBUG = Debug.debug("Window");
private final Object sync = new Object();
@@ -110,7 +112,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
private Window newtChild = null;
private boolean newtChildAttached = false;
private boolean isOnscreen = true;
- private WindowClosingMode newtChildCloseOp;
+ private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE;
private final AWTParentWindowAdapter awtWinAdapter;
private final AWTAdapter awtMouseAdapter;
private final AWTAdapter awtKeyAdapter;
@@ -420,10 +422,22 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
return newtChild;
}
- /** @return this AWT Canvas NativeWindow representation, may be null in case {@link #removeNotify()} has been called,
- * or {@link #addNotify()} hasn't been called yet.*/
+ /**
+ * {@inheritDoc}
+ * @return this AWT Canvas {@link NativeWindow} representation, may be null in case {@link #removeNotify()} has been called,
+ * or {@link #addNotify()} hasn't been called yet.
+ */
+ @Override
public NativeWindow getNativeWindow() { return jawtWindow; }
+ /**
+ * {@inheritDoc}
+ * @return this AWT Canvas {@link NativeSurface} representation, may be null in case {@link #removeNotify()} has been called,
+ * or {@link #addNotify()} hasn't been called yet.
+ */
+ @Override
+ public NativeSurface getNativeSurface() { return jawtWindow; }
+
@Override
public WindowClosingMode getDefaultCloseOperation() {
return awtWindowClosingProtocol.getDefaultCloseOperation();
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
index cd53294a1..6bf9f41a6 100644
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
@@ -115,7 +115,7 @@ public class JOGLNewtApplet1Run extends Applet {
String glEventListenerClazzName=null;
String glProfileName=null;
- int glSwapInterval=0;
+ int glSwapInterval=1;
boolean glDebug=false;
boolean glTrace=false;
boolean glUndecorated=false;
diff --git a/src/newt/classes/com/jogamp/newt/javafx/NewtCanvasJFX.java b/src/newt/classes/com/jogamp/newt/javafx/NewtCanvasJFX.java
new file mode 100644
index 000000000..e04ed326d
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/javafx/NewtCanvasJFX.java
@@ -0,0 +1,670 @@
+/**
+ * Copyright 2019 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.newt.javafx;
+
+import com.jogamp.common.util.PropertyAccess;
+import com.jogamp.nativewindow.AbstractGraphicsConfiguration;
+import com.jogamp.nativewindow.AbstractGraphicsScreen;
+import com.jogamp.nativewindow.Capabilities;
+import com.jogamp.nativewindow.CapabilitiesImmutable;
+import com.jogamp.nativewindow.GraphicsConfigurationFactory;
+import com.jogamp.nativewindow.NativeSurface;
+import com.jogamp.nativewindow.NativeWindow;
+import com.jogamp.nativewindow.NativeWindowException;
+import com.jogamp.nativewindow.NativeWindowFactory;
+import com.jogamp.nativewindow.NativeWindowHolder;
+import com.jogamp.nativewindow.SurfaceUpdatedListener;
+import com.jogamp.nativewindow.WindowClosingProtocol;
+import com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode;
+import com.jogamp.nativewindow.util.Insets;
+import com.jogamp.nativewindow.util.InsetsImmutable;
+import com.jogamp.nativewindow.util.Point;
+import com.jogamp.nativewindow.util.Rectangle;
+import com.jogamp.opengl.GLCapabilities;
+
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.event.EventHandler;
+import javafx.geometry.Bounds;
+import javafx.scene.Scene;
+import javafx.scene.canvas.Canvas;
+import jogamp.newt.Debug;
+import jogamp.newt.javafx.JFXEDTUtil;
+
+import com.jogamp.nativewindow.javafx.JFXAccessor;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.event.WindowEvent;
+import com.jogamp.newt.util.EDTUtil;
+
+/**
+ * A NEWT based JFX {@link Canvas} specialization allowing a NEWT child {@link Window} to be attached using native parenting.
+ * <p>
+ * {@link NewtCanvasJFX} allows utilizing custom {@link GLCapabilities} settings independent from the JavaFX's window
+ * as well as independent rendering from JavaFX's thread.
+ * </p>
+ * <p>
+ * {@link NewtCanvasJFX} allows native parenting operations before and after
+ * it's belonging Group's Scene has been attached to the JavaFX {@link javafx.stage.Window Window}'s actual native window,
+ * i.e. becoming fully realized and visible.
+ * </p>
+ * <p>
+ * Note that {@link JFXAccessor#runOnJFXThread(boolean, Runnable)} is still used to for certain
+ * mandatory JavaFX lifecycle operation on the JavaFX thread.
+ * </p>
+ */
+public class NewtCanvasJFX extends Canvas implements NativeWindowHolder, WindowClosingProtocol {
+ private static final boolean DEBUG = Debug.debug("Window");
+ private static final boolean USE_JFX_EDT = PropertyAccess.getBooleanProperty("jogamp.newt.javafx.UseJFXEDT", true, true);
+ private volatile javafx.stage.Window parentWindow = null;
+ private volatile AbstractGraphicsScreen screen = null;
+
+ private WindowClosingMode newtChildClosingMode = WindowClosingMode.DISPOSE_ON_CLOSE;
+ private WindowClosingMode closingMode = WindowClosingMode.DISPOSE_ON_CLOSE;
+ private final Rectangle clientArea = new Rectangle();
+
+ private volatile JFXNativeWindow nativeWindow = null;
+ private volatile Window newtChild = null;
+ private volatile boolean newtChildReady = false; // ready if JFXEDTUtil is set and newtChild parented
+ private volatile boolean postSetSize = false; // pending resize
+ private volatile boolean postSetPos = false; // pending pos
+
+ private final EventHandler<javafx.stage.WindowEvent> windowClosingListener = new EventHandler<javafx.stage.WindowEvent>() {
+ public final void handle(final javafx.stage.WindowEvent e) {
+ if( DEBUG ) {
+ System.err.println("NewtCanvasJFX.Event.DISPOSE, "+e+", closeOp "+closingMode);
+ }
+ if( WindowClosingMode.DISPOSE_ON_CLOSE == closingMode ) {
+ NewtCanvasJFX.this.destroy();
+ } else {
+ // avoid JavaFX closing operation
+ e.consume();
+ }
+ } };
+ private final EventHandler<javafx.stage.WindowEvent> windowShownListener = new EventHandler<javafx.stage.WindowEvent>() {
+ public final void handle(final javafx.stage.WindowEvent e) {
+ if( DEBUG ) {
+ System.err.println("NewtCanvasJFX.Event.SHOWN, "+e);
+ }
+ repaintAction(true);
+ } };
+
+ /**
+ * Instantiates a NewtCanvas with a NEWT child.
+ *
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an JFX conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ * @param child optional preassigned {@link #Window}, maybe null
+ */
+ public NewtCanvasJFX(final Window child) {
+ super();
+
+ updateParentWindowAndScreen();
+
+ final ChangeListener<Number> sizeListener = new ChangeListener<Number>() {
+ @Override public void changed(final ObservableValue<? extends Number> observable, final Number oldValue, final Number newValue) {
+ if( DEBUG ) {
+ System.err.println("NewtCanvasJFX.Event.Size, "+oldValue.doubleValue()+" -> "+newValue.doubleValue()+", has "+getWidth()+"x"+getHeight());
+ }
+ updateSizeCheck((int)getWidth(), (int)getHeight());
+ repaintAction(isVisible());
+ } };
+ this.widthProperty().addListener(sizeListener);
+ this.heightProperty().addListener(sizeListener);
+ this.visibleProperty().addListener(new ChangeListener<Boolean>() {
+ @Override public void changed(final ObservableValue<? extends Boolean> observable, final Boolean oldValue, final Boolean newValue) {
+ if( DEBUG ) {
+ System.err.println("NewtCanvasJFX.Event.Visible, "+oldValue.booleanValue()+" -> "+newValue.booleanValue()+", has "+isVisible());
+ }
+ repaintAction(newValue.booleanValue());
+ }
+ });
+ this.sceneProperty().addListener(new ChangeListener<Scene>() {
+ @Override public void changed(final ObservableValue<? extends Scene> observable, final Scene oldValue, final Scene newValue) {
+ if( DEBUG ) {
+ System.err.println("NewtCanvasJFX.Event.Scene, "+oldValue+" -> "+newValue+", has "+getScene());
+ if(null != newValue) {
+ final javafx.stage.Window w = newValue.getWindow();
+ System.err.println("NewtCanvasJFX.Event.Scene window "+w+" (showing "+(null!=w?w.isShowing():0)+")");
+ }
+ }
+ if( updateParentWindowAndScreen() ) {
+ repaintAction(isVisible());
+ }
+ }
+ });
+
+ if(null != child) {
+ setNEWTChild(child);
+ }
+ }
+
+ private final void repaintAction(final boolean visible) {
+ if( visible && ( null != nativeWindow || validateNative(true /* completeReparent */) ) ) {
+ if( newtChildReady ) {
+ if( postSetSize ) {
+ newtChild.setSize(clientArea.getWidth(), clientArea.getHeight());
+ postSetSize = false;
+ }
+ if( postSetPos ) {
+ newtChild.setPosition(clientArea.getX(), clientArea.getY());
+ postSetPos = false;
+ }
+ newtChild.windowRepaint(0, 0, clientArea.getWidth(), clientArea.getHeight());
+ }
+ }
+ }
+
+ private final void updatePosSizeCheck() {
+ final Bounds b = localToScene(getBoundsInLocal());
+ updatePosCheck((int)b.getMinX(), (int)b.getMinY());
+ updateSizeCheck((int)getWidth(), (int)getHeight());
+ }
+ private final void updatePosCheck(final int newX, final int newY) {
+ final boolean posChanged;
+ {
+ final Rectangle oClientArea = clientArea;
+ posChanged = newX != oClientArea.getX() || newY != oClientArea.getY();
+ if( posChanged ) {
+ clientArea.setX(newX);
+ clientArea.setY(newY);
+ }
+ }
+ if(DEBUG) {
+ final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
+ System.err.println("NewtCanvasJFX.updatePosCheck: posChanged "+posChanged+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+clientArea.getX()+"/"+clientArea.getY()+" "+clientArea.getWidth()+"x"+clientArea.getHeight()+" - surfaceHandle 0x"+Long.toHexString(nsh));
+ }
+ if( posChanged ) {
+ if( newtChildReady ) {
+ newtChild.setPosition(clientArea.getX(), clientArea.getY());
+ } else {
+ postSetPos = true;
+ }
+ }
+ }
+ private final void updateSizeCheck(final int newWidth, final int newHeight) {
+ final boolean sizeChanged;
+ {
+ final Rectangle oClientArea = clientArea;
+ sizeChanged = newWidth != oClientArea.getWidth() || newHeight != oClientArea.getHeight();
+ if( sizeChanged ) {
+ clientArea.setWidth(newWidth);
+ clientArea.setHeight(newHeight);
+ }
+ }
+ if(DEBUG) {
+ final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
+ System.err.println("NewtCanvasJFX.updateSizeCheck: sizeChanged "+sizeChanged+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+clientArea.getX()+"/"+clientArea.getY()+" "+clientArea.getWidth()+"x"+clientArea.getHeight()+" - surfaceHandle 0x"+Long.toHexString(nsh));
+ }
+ if( sizeChanged ) {
+ if( newtChildReady ) {
+ newtChild.setSize(clientArea.getWidth(), clientArea.getHeight());
+ } else {
+ postSetSize = true;
+ }
+ }
+ }
+
+ private final ChangeListener<javafx.stage.Window> sceneWindowChangeListener = new ChangeListener<javafx.stage.Window>() {
+ @Override public void changed(final ObservableValue<? extends javafx.stage.Window> observable, final javafx.stage.Window oldValue, final javafx.stage.Window newValue) {
+ if( DEBUG ) {
+ System.err.println("NewtCanvasJFX.Event.Window, "+oldValue+" -> "+newValue);
+ }
+ if( updateParentWindowAndScreen() ) {
+ repaintAction(isVisible());
+ }
+ } };
+
+ private boolean updateParentWindowAndScreen() {
+ final Scene s = this.getScene();
+ if( null != s ) {
+ final javafx.stage.Window w = s.getWindow();
+ if( DEBUG ) {
+ System.err.println("NewtCanvasJFX.updateParentWindowAndScreen: Scene "+s+", Window "+w+" (showing "+(null!=w?w.isShowing():0)+")");
+ }
+ if( w != parentWindow ) {
+ destroyImpl(false);
+ }
+ parentWindow = w;
+ if( null != w ) {
+ screen = JFXAccessor.getScreen(JFXAccessor.getDevice(parentWindow), -1 /* default */);
+ parentWindow.addEventHandler(javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST, windowClosingListener);
+ parentWindow.addEventHandler(javafx.stage.WindowEvent.WINDOW_SHOWN, windowShownListener);
+ return true;
+ } else {
+ s.windowProperty().addListener(sceneWindowChangeListener);
+ }
+ } else {
+ if( DEBUG ) {
+ System.err.println("NewtCanvasJFX.updateParentWindowAndScreen: Null Scene");
+ }
+ if( null != parentWindow ) {
+ destroyImpl(false);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Destroys this resource:
+ * <ul>
+ * <li> Make the NEWT Child invisible </li>
+ * <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
+ * <li> Issues {@link Window#destroy()} on the NEWT Child</li>
+ * <li> Remove reference to the NEWT Child</li>
+ * </ul>
+ * JavaFX will issue this call when sending out the {@link javafx.stage.WindowEvent#WINDOW_CLOSE_REQUEST} automatically,
+ * if the user has not overridden the default {@link WindowClosingMode#DISPOSE_ON_CLOSE} to {@link WindowClosingMode#DO_NOTHING_ON_CLOSE}
+ * via {@link #setDefaultCloseOperation(com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode)}.
+ * @see Window#destroy()
+ * @see #setDefaultCloseOperation(com.jogamp.nativewindow.WindowClosingProtocol.WindowClosingMode)
+ */
+ public void destroy() {
+ destroyImpl(true);
+ }
+ private void destroyImpl(final boolean disposeNewtChild) {
+ if(DEBUG) {
+ System.err.println("NewtCanvasJFX.dispose: (has parent "+(null!=parentWindow)+", hasNative "+(null!=nativeWindow)+",\n\t"+newtChild);
+ }
+ if( null != newtChild ) {
+ if(DEBUG) {
+ System.err.println("NewtCanvasJFX.dispose.1: EDTUtil cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
+ if( null != nativeWindow ) {
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+ newtChild.reparentWindow(null, -1, -1, 0 /* hint */);
+ }
+ if( disposeNewtChild ) {
+ newtChild.destroy();
+ newtChild = null;
+ }
+ }
+ if( null != parentWindow ) {
+ parentWindow.getScene().windowProperty().removeListener(sceneWindowChangeListener);
+ parentWindow.removeEventHandler(javafx.stage.WindowEvent.WINDOW_CLOSE_REQUEST, windowClosingListener);
+ parentWindow.removeEventHandler(javafx.stage.WindowEvent.WINDOW_SHOWN, windowShownListener);
+ parentWindow = null;
+ }
+ if( null != screen ) {
+ screen.getDevice().close();
+ screen = null;
+ }
+ nativeWindow = null;
+ }
+
+ private final boolean validateNative(final boolean completeReparent) {
+ if( null == parentWindow ) {
+ return false;
+ }
+ assert null == nativeWindow;
+ updatePosSizeCheck();
+ if(0 >= clientArea.getWidth() || 0 >= clientArea.getHeight()) {
+ return false;
+ }
+ final long nativeWindowHandle = JFXAccessor.getWindowHandle(parentWindow);
+ if( 0 == nativeWindowHandle ) {
+ return false;
+ }
+ screen.getDevice().open();
+
+ /* Native handle for the control, used to associate with GLContext */
+ final int visualID = JFXAccessor.getNativeVisualID(screen.getDevice(), nativeWindowHandle);
+ final boolean visualIDValid = NativeWindowFactory.isNativeVisualIDValidForProcessing(visualID);
+ if(DEBUG) {
+ System.err.println("NewtCanvasJFX.validateNative() windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", valid "+visualIDValid);
+ }
+ if( visualIDValid ) {
+ /* Get the nativewindow-Graphics Device associated with this control (which is determined by the parent Composite).
+ * Note: JFX is owner of the native handle, hence no closing operation will be a NOP. */
+ final CapabilitiesImmutable caps = new Capabilities();
+ final GraphicsConfigurationFactory factory = GraphicsConfigurationFactory.getFactory(screen.getDevice(), caps);
+ final AbstractGraphicsConfiguration config = factory.chooseGraphicsConfiguration( caps, caps, null, screen, visualID );
+ if(DEBUG) {
+ System.err.println("NewtCanvasJFX.validateNative() factory: "+factory+", windowHandle 0x"+Long.toHexString(nativeWindowHandle)+", visualID 0x"+Integer.toHexString(visualID)+", chosen config: "+config);
+ // Thread.dumpStack();
+ }
+ if (null == config) {
+ throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
+ }
+
+ nativeWindow = new JFXNativeWindow(config, nativeWindowHandle);
+ if( completeReparent ) {
+ reparentWindow( true );
+ }
+ }
+
+ return null != nativeWindow;
+ }
+
+ /**
+ * Sets a new NEWT child, provoking reparenting.
+ * <p>
+ * A previously detached <code>newChild</code> will be released to top-level status
+ * and made invisible.
+ * </p>
+ * <p>
+ * Note: When switching NEWT child's, detaching the previous first via <code>setNEWTChild(null)</code>
+ * produced much cleaner visual results.
+ * </p>
+ * <p>
+ * Note: The NEWT child {@link Display}'s {@link EDTUtil} is being set to an JFX conform implementation
+ * via {@link Display#setEDTUtil(EDTUtil)}.
+ * </p>
+ * @return the previous attached newt child.
+ */
+ public Window setNEWTChild(final Window newChild) {
+ final Window prevChild = newtChild;
+ if(DEBUG) {
+ System.err.println("NewtCanvasJFX.setNEWTChild.0: win "+newtWinHandleToHexString(prevChild)+" -> "+newtWinHandleToHexString(newChild));
+ }
+ // remove old one
+ if(null != newtChild) {
+ reparentWindow( false );
+ newtChild = null;
+ }
+ // add new one, reparent only if ready
+ newtChild = newChild;
+ if( null != newtChild && ( null != nativeWindow || validateNative(false /* completeReparent */) ) ) {
+ reparentWindow( true );
+ }
+ return prevChild;
+ }
+
+ private void reparentWindow(final boolean add) {
+ if( null == newtChild ) {
+ return; // nop
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasJFX.reparentWindow.0: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
+
+ newtChild.setFocusAction(null); // no AWT focus traversal ..
+ if(add) {
+ assert null != nativeWindow && null != parentWindow;
+ updatePosSizeCheck();
+ final int x = clientArea.getX();
+ final int y = clientArea.getY();
+ final int w = clientArea.getWidth();
+ final int h = clientArea.getHeight();
+
+ if(USE_JFX_EDT) {
+ // setup JFX EDT and start it
+ final Display newtDisplay = newtChild.getScreen().getDisplay();
+ final EDTUtil oldEDTUtil = newtDisplay.getEDTUtil();
+ if( ! ( oldEDTUtil instanceof JFXEDTUtil ) ) {
+ final EDTUtil newEDTUtil = new JFXEDTUtil(newtDisplay);
+ if(DEBUG) {
+ System.err.println("NewtCanvasJFX.reparentWindow.1: replacing EDTUtil "+oldEDTUtil+" -> "+newEDTUtil);
+ }
+ newEDTUtil.start();
+ newtDisplay.setEDTUtil( newEDTUtil );
+ }
+ }
+
+ newtChild.setSize(w, h);
+ newtChild.reparentWindow(nativeWindow, x, y, Window.REPARENT_HINT_BECOMES_VISIBLE);
+ newtChild.setPosition(x, y);
+ newtChild.setVisible(true);
+ configureNewtChild(true);
+ newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
+
+ // force this JFX Canvas to be focus-able,
+ // since it is completely covered by the newtChild (z-order).
+ // FIXME ??? super.requestFocus();
+ } else {
+ configureNewtChild(false);
+ newtChild.setVisible(false);
+ newtChild.reparentWindow(null, -1, -1, 0 /* hints */);
+ }
+ if(DEBUG) {
+ System.err.println("NewtCanvasJFX.reparentWindow.X: add="+add+", win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil());
+ }
+ }
+
+ private void configureNewtChild(final boolean attach) {
+ newtChildReady = attach;
+ if( null != newtChild ) {
+ newtChild.setKeyboardFocusHandler(null);
+ if(attach) {
+ newtChildClosingMode = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ } else {
+ newtChild.setFocusAction(null);
+ newtChild.setDefaultCloseOperation(newtChildClosingMode);
+ }
+ }
+ }
+
+ /** @return the current NEWT child */
+ public Window getNEWTChild() {
+ return newtChild;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @return this JFX Canvas {@link NativeWindow} representation, may be null in case it has not been realized
+ */
+ @Override
+ public NativeWindow getNativeWindow() { return nativeWindow; }
+
+ /**
+ * {@inheritDoc}
+ * @return this JFX Canvas {@link NativeSurface} representation, may be null in case it has not been realized
+ */
+ @Override
+ public NativeSurface getNativeSurface() { return nativeWindow; }
+
+ @Override
+ public WindowClosingMode getDefaultCloseOperation() {
+ return closingMode;
+ }
+
+ @Override
+ public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
+ final WindowClosingMode old = closingMode;
+ closingMode = op;
+ return old;
+ }
+
+
+ boolean isParent() {
+ return null!=newtChild ;
+ }
+
+ boolean isFullscreen() {
+ return null != newtChild && newtChild.isFullscreen();
+ }
+
+ private final void requestFocusNEWTChild() {
+ if( newtChildReady ) {
+ newtChild.setFocusAction(null);
+ newtChild.requestFocus();
+ }
+ }
+
+ @Override
+ public void requestFocus() {
+ NewtCanvasJFX.super.requestFocus();
+ requestFocusNEWTChild();
+ }
+
+ private class JFXNativeWindow implements NativeWindow {
+ private final AbstractGraphicsConfiguration config;
+ private final long nativeWindowHandle;
+ private final InsetsImmutable insets; // only required to allow proper client position calculation on OSX
+
+ public JFXNativeWindow(final AbstractGraphicsConfiguration config, final long nativeWindowHandle) {
+ this.config = config;
+ this.nativeWindowHandle = nativeWindowHandle;
+ this.insets = new Insets(0, 0, 0, 0);
+ }
+
+ @Override
+ public int lockSurface() throws NativeWindowException, RuntimeException {
+ return NativeSurface.LOCK_SUCCESS;
+ }
+
+ @Override
+ public void unlockSurface() { }
+
+ @Override
+ public boolean isSurfaceLockedByOtherThread() {
+ return false;
+ }
+
+ @Override
+ public Thread getSurfaceLockOwner() {
+ return null;
+ }
+
+ @Override
+ public boolean surfaceSwap() {
+ return false;
+ }
+
+ @Override
+ public void addSurfaceUpdatedListener(final SurfaceUpdatedListener l) { }
+
+ @Override
+ public void addSurfaceUpdatedListener(final int index, final SurfaceUpdatedListener l) throws IndexOutOfBoundsException {
+ }
+
+ @Override
+ public void removeSurfaceUpdatedListener(final SurfaceUpdatedListener l) { }
+
+ @Override
+ public long getSurfaceHandle() {
+ return 0;
+ }
+
+ @Override
+ public int getWidth() {
+ return getSurfaceWidth(); // FIXME: Use 'scale' or an actual window-width
+ }
+
+ @Override
+ public int getHeight() {
+ return getSurfaceHeight(); // FIXME: Use 'scale' or an actual window-width
+ }
+
+ @Override
+ public final int[] convertToWindowUnits(final int[] pixelUnitsAndResult) {
+ return pixelUnitsAndResult; // FIXME HiDPI: use 'pixelScale'
+ }
+
+ @Override
+ public final int[] convertToPixelUnits(final int[] windowUnitsAndResult) {
+ return windowUnitsAndResult; // FIXME HiDPI: use 'pixelScale'
+ }
+
+ @Override
+ public int getSurfaceWidth() {
+ return clientArea.getWidth();
+ }
+
+ @Override
+ public int getSurfaceHeight() {
+ return clientArea.getHeight();
+ }
+
+ @Override
+ public final NativeSurface getNativeSurface() { return this; }
+
+ @Override
+ public AbstractGraphicsConfiguration getGraphicsConfiguration() {
+ return config;
+ }
+
+ @Override
+ public long getDisplayHandle() {
+ return config.getScreen().getDevice().getHandle();
+ }
+
+ @Override
+ public int getScreenIndex() {
+ return config.getScreen().getIndex();
+ }
+
+ @Override
+ public void surfaceUpdated(final Object updater, final NativeSurface ns, final long when) { }
+
+ @Override
+ public void destroy() { }
+
+ @Override
+ public NativeWindow getParent() {
+ return null;
+ }
+
+ @Override
+ public long getWindowHandle() {
+ return nativeWindowHandle;
+ }
+
+ @Override
+ public InsetsImmutable getInsets() {
+ return insets;
+ }
+
+ @Override
+ public int getX() {
+ return NewtCanvasJFX.this.clientArea.getX();
+ }
+
+ @Override
+ public int getY() {
+ return NewtCanvasJFX.this.clientArea.getY();
+ }
+
+ @Override
+ public Point getLocationOnScreen(final Point point) {
+ final Point los = NativeWindowFactory.getLocationOnScreen(this); // client window location on screen
+ if(null!=point) {
+ return point.translate(los);
+ } else {
+ return los;
+ }
+ }
+
+ @Override
+ public boolean hasFocus() {
+ return isFocused();
+ }
+ };
+
+ static String newtWinHandleToHexString(final Window w) {
+ return null != w ? toHexString(w.getWindowHandle()) : "nil";
+ }
+ static String toHexString(final long l) {
+ return "0x"+Long.toHexString(l);
+ }
+}
+
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index f15c87beb..569780311 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -246,6 +246,16 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
@Override
+ public final int getSupportedStateMask() {
+ return window.getSupportedStateMask();
+ }
+
+ @Override
+ public final String getSupportedStateMaskString() {
+ return window.getSupportedStateMaskString();
+ }
+
+ @Override
public CapabilitiesChooser setCapabilitiesChooser(final CapabilitiesChooser chooser) {
return window.setCapabilitiesChooser(chooser);
}
diff --git a/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java b/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java
new file mode 100644
index 000000000..568b5d0bb
--- /dev/null
+++ b/src/newt/classes/com/jogamp/newt/opengl/util/NEWTDemoListener.java
@@ -0,0 +1,530 @@
+/**
+ * Copyright 2015 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.newt.opengl.util;
+
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.jogamp.common.util.IOUtil;
+import com.jogamp.nativewindow.CapabilitiesImmutable;
+import com.jogamp.nativewindow.ScalableSurface;
+import com.jogamp.newt.Window;
+import com.jogamp.newt.Display;
+import com.jogamp.newt.Display.PointerIcon;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.KeyListener;
+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.FPSCounter;
+import com.jogamp.opengl.GL;
+import com.jogamp.opengl.GLAnimatorControl;
+import com.jogamp.opengl.GLAutoDrawable;
+import com.jogamp.opengl.GLDrawable;
+import com.jogamp.opengl.GLRunnable;
+import com.jogamp.opengl.util.Gamma;
+import com.jogamp.opengl.util.PNGPixelRect;
+
+import jogamp.newt.driver.PNGIcon;
+
+/**
+ * NEWT {@link GLWindow} Demo functionality
+ * <ul>
+ * <li>SPACE: Toggle animator {@link GLAnimatorControl#pause() pause}/{@link GLAnimatorControl#resume() resume}</li>
+ * <li>A: Toggle window {@link Window#setAlwaysOnTop(boolean) always on top}</li>
+ * <li>B: Toggle window {@link Window#setAlwaysOnBottom(boolean) always on bottom}</li>
+ * <li>C: Toggle different {@link Window#setPointerIcon(PointerIcon) pointer icons}</li>
+ * <li>D: Toggle window {@link Window#setUndecorated(boolean) decoration on/off}</li>
+ * <li>F: Toggle window {@link Window#setFullscreen(boolean) fullscreen on/off}</li>
+ * <li>Three-Finger Double-Tap: Toggle window {@link Window#setFullscreen(boolean) fullscreen on/off}</li>
+ * <li>G: Increase {@link Gamma#setDisplayGamma(GLDrawable, float, float, float) gamma} by 0.1, +SHIFT decrease gamma by 0.1</li>
+ * <li>I: Toggle {@link Window#setPointerVisible(boolean) pointer visbility}</li>
+ * <li>J: Toggle {@link Window#confinePointer(boolean) pointer jail (confine to window)}</li>
+ * <li>M: Toggle {@link Window#setMaximized(boolean, boolean) window maximized}: Y, +CTRL off, +SHIFT toggle X+Y, +ALT X</li>
+ * <li>P: Set window {@link Window#setPosition(int, int) position to 100/100}</li>
+ * <li>Q: Quit</li>
+ * <li>R: Toggle window {@link Window#setResizable(boolean) resizable}</li>
+ * <li>S: Toggle window {@link Window#setSticky(boolean) sticky}</li>
+ * <li>V: Toggle window {@link Window#setVisible(boolean) visibility} for 5s</li>
+ * <li>V: +CTRL: Rotate {@link GL#setSwapInterval(int) swap interval} -1, 0, 1</li>
+ * <li>W: {@link Window#warpPointer(int, int) Warp pointer} to center of window</li>
+ * <li>X: Toggle {@link ScalableSurface#setSurfaceScale(float[]) [{@link ScalableSurface#IDENTITY_PIXELSCALE}, {@link ScalableSurface#AUTOMAX_PIXELSCALE}]</li>
+ * </ul>
+ */
+public class NEWTDemoListener extends WindowAdapter implements KeyListener, MouseListener {
+ protected final GLWindow glWindow;
+ final PointerIcon[] pointerIcons;
+ int pointerIconIdx = 0;
+ float gamma = 1f;
+ float brightness = 0f;
+ float contrast = 1f;
+ boolean confinedFixedCenter = false;
+
+ public NEWTDemoListener(final GLWindow glWin, final PointerIcon[] pointerIcons) {
+ this.glWindow = glWin;
+ if( null != pointerIcons ) {
+ this.pointerIcons = pointerIcons;
+ } else {
+ this.pointerIcons = createPointerIcons(glWindow.getScreen().getDisplay());
+ }
+ }
+ public NEWTDemoListener(final GLWindow glWin) {
+ this(glWin, null);
+ }
+
+ protected void printlnState(final String prelude) {
+ System.err.println(prelude+": "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()+", state "+glWindow.getStateMaskString());
+ }
+ protected void printlnState(final String prelude, final String post) {
+ System.err.println(prelude+": "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets()+", state "+glWindow.getStateMaskString()+", "+post);
+ }
+
+ @Override
+ public void keyPressed(final KeyEvent e) {
+ if( e.isAutoRepeat() || e.isConsumed() ) {
+ return;
+ }
+ final int keySymbol = e.getKeySymbol();
+ switch(keySymbol) {
+ case KeyEvent.VK_SPACE:
+ e.setConsumed(true);
+ glWindow.invokeOnCurrentThread(new Runnable() {
+ public void run() {
+ if(glWindow.getAnimator().isPaused()) {
+ glWindow.getAnimator().resume();
+ } else {
+ glWindow.getAnimator().pause();
+ }
+ } } );
+ break;
+ case KeyEvent.VK_A:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set alwaysontop pre]");
+ glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
+ printlnState("[set alwaysontop post]");
+ } } );
+ break;
+ case KeyEvent.VK_B:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set alwaysonbottom pre]");
+ glWindow.setAlwaysOnBottom(!glWindow.isAlwaysOnBottom());
+ printlnState("[set alwaysonbottom post]");
+ } } );
+ break;
+ case KeyEvent.VK_C:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ if( null != pointerIcons ) {
+ printlnState("[set pointer-icon pre]");
+ final PointerIcon currentPI = glWindow.getPointerIcon();
+ final PointerIcon newPI;
+ if( pointerIconIdx >= pointerIcons.length ) {
+ newPI=null;
+ pointerIconIdx=0;
+ } else {
+ newPI=pointerIcons[pointerIconIdx++];
+ }
+ glWindow.setPointerIcon( newPI );
+ printlnState("[set pointer-icon post]", currentPI+" -> "+glWindow.getPointerIcon());
+ }
+ } } );
+ break;
+ case KeyEvent.VK_D:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set undecorated pre]");
+ glWindow.setUndecorated(!glWindow.isUndecorated());
+ printlnState("[set undecorated post]");
+ } } );
+ break;
+ case KeyEvent.VK_F:
+ e.setConsumed(true);
+ quitAdapterOff();
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set fullscreen pre]");
+ if( glWindow.isFullscreen() ) {
+ glWindow.setFullscreen( false );
+ } else {
+ if( e.isAltDown() ) {
+ glWindow.setFullscreen( null );
+ } else {
+ glWindow.setFullscreen( true );
+ }
+ }
+ printlnState("[set fullscreen post]");
+ quitAdapterOn();
+ } } );
+ break;
+ case KeyEvent.VK_G:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ final float newGamma = gamma + ( e.isShiftDown() ? -0.1f : 0.1f );
+ System.err.println("[set gamma]: "+gamma+" -> "+newGamma);
+ if( Gamma.setDisplayGamma(glWindow, newGamma, brightness, contrast) ) {
+ gamma = newGamma;
+ }
+ } } );
+ break;
+ case KeyEvent.VK_I:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set pointer-visible pre]");
+ glWindow.setPointerVisible(!glWindow.isPointerVisible());
+ printlnState("[set pointer-visible post]");
+ } } );
+ break;
+ case KeyEvent.VK_J:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set pointer-confined pre]", "warp-center: "+e.isShiftDown());
+ final boolean confine = !glWindow.isPointerConfined();
+ glWindow.confinePointer(confine);
+ printlnState("[set pointer-confined post]", "warp-center: "+e.isShiftDown());
+ if( e.isShiftDown() ) {
+ setConfinedFixedCenter(confine);
+ } else if( !confine ) {
+ setConfinedFixedCenter(false);
+ }
+ } } );
+ break;
+ case KeyEvent.VK_M:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ // none: max-v
+ // alt: max-h
+ // shift: max-hv
+ // ctrl: max-off
+ final boolean horz, vert;
+ if( e.isControlDown() ) {
+ horz = false;
+ vert = false;
+ } else if( e.isShiftDown() ) {
+ final boolean bothMax = glWindow.isMaximizedHorz() && glWindow.isMaximizedVert();
+ horz = !bothMax;
+ vert = !bothMax;
+ } else if( !e.isAltDown() ) {
+ horz = glWindow.isMaximizedHorz();
+ vert = !glWindow.isMaximizedVert();
+ } else if( e.isAltDown() ) {
+ horz = !glWindow.isMaximizedHorz();
+ vert = glWindow.isMaximizedVert();
+ } else {
+ vert = glWindow.isMaximizedVert();
+ horz = glWindow.isMaximizedHorz();
+ }
+ printlnState("[set maximize pre]", "max[vert "+vert+", horz "+horz+"]");
+ glWindow.setMaximized(horz, vert);
+ printlnState("[set maximize post]", "max[vert "+vert+", horz "+horz+"]");
+ } } );
+ break;
+ case KeyEvent.VK_P:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set position pre]");
+ glWindow.setPosition(100, 100);
+ printlnState("[set position post]");
+ } } );
+ break;
+ case KeyEvent.VK_Q:
+ if( quitAdapterEnabled && 0 == e.getModifiers() ) {
+ System.err.println("QUIT Key "+Thread.currentThread());
+ quitAdapterShouldQuit = true;
+ }
+ break;
+ case KeyEvent.VK_R:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set resizable pre]");
+ glWindow.setResizable(!glWindow.isResizable());
+ printlnState("[set resizable post]");
+ } } );
+ break;
+ case KeyEvent.VK_S:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set sticky pre]");
+ glWindow.setSticky(!glWindow.isSticky());
+ printlnState("[set sticky post]");
+ } } );
+ break;
+ case KeyEvent.VK_V:
+ e.setConsumed(true);
+ if( e.isControlDown() ) {
+ glWindow.invoke(false, new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ final GL gl = drawable.getGL();
+ final int _i = gl.getSwapInterval();
+ final int i;
+ switch(_i) {
+ case 0: i = -1; break;
+ case -1: i = 1; break;
+ case 1: i = 0; break;
+ default: i = 1; break;
+ }
+ gl.setSwapInterval(i);
+
+ final GLAnimatorControl a = drawable.getAnimator();
+ if( null != a ) {
+ a.resetFPSCounter();
+ }
+ if(drawable instanceof FPSCounter) {
+ ((FPSCounter)drawable).resetFPSCounter();
+ }
+ System.err.println("Swap Interval: "+_i+" -> "+i+" -> "+gl.getSwapInterval());
+ return true;
+ }
+ });
+ } else {
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ final boolean wasVisible = glWindow.isVisible();
+ {
+ printlnState("[set visible pre]");
+ glWindow.setVisible(!wasVisible);
+ printlnState("[set visible post]");
+ }
+ if( wasVisible && !e.isShiftDown() ) {
+ try {
+ java.lang.Thread.sleep(5000);
+ } catch (final InterruptedException e) {
+ e.printStackTrace();
+ }
+ printlnState("[reset visible pre]");
+ glWindow.setVisible(true);
+ printlnState("[reset visible post]");
+ }
+ } } );
+ }
+ break;
+ case KeyEvent.VK_W:
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
+ public void run() {
+ printlnState("[set pointer-pos pre]");
+ glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2);
+ printlnState("[set pointer-pos post]");
+ } } );
+ break;
+ case KeyEvent.VK_X:
+ e.setConsumed(true);
+ final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]);
+ final float[] reqSurfacePixelScale;
+ if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
+ reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
+ } else {
+ reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
+ }
+ System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
+ glWindow.setSurfaceScale(reqSurfacePixelScale);
+ final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
+ final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]);
+ System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
+ reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
+ valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
+ hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
+ setTitle();
+ }
+ }
+ @Override
+ public void keyReleased(final KeyEvent e) { }
+
+ public void setConfinedFixedCenter(final boolean v) {
+ confinedFixedCenter = v;
+ }
+ @Override
+ public void mouseMoved(final MouseEvent e) {
+ if( e.isConfined() ) {
+ mouseCenterWarp(e);
+ }
+ }
+ @Override
+ public void mouseDragged(final MouseEvent e) {
+ if( e.isConfined() ) {
+ mouseCenterWarp(e);
+ }
+ }
+ @Override
+ public void mouseClicked(final MouseEvent e) {
+ if(e.getClickCount() == 2 && e.getPointerCount() == 3) {
+ glWindow.setFullscreen(!glWindow.isFullscreen());
+ System.err.println("setFullscreen: "+glWindow.isFullscreen());
+ }
+ }
+ private void mouseCenterWarp(final MouseEvent e) {
+ if(e.isConfined() && confinedFixedCenter ) {
+ final int x=glWindow.getSurfaceWidth()/2;
+ final int y=glWindow.getSurfaceHeight()/2;
+ glWindow.warpPointer(x, y);
+ }
+ }
+ @Override
+ public void mouseEntered(final MouseEvent e) {}
+ @Override
+ public void mouseExited(final MouseEvent e) {}
+ @Override
+ public void mousePressed(final MouseEvent e) {}
+ @Override
+ public void mouseReleased(final MouseEvent e) {}
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {}
+
+ /////////////////////////////////////////////////////////////
+
+ private boolean quitAdapterShouldQuit = false;
+ private boolean quitAdapterEnabled = false;
+ private boolean quitAdapterEnabled2 = true;
+
+ protected void quitAdapterOff() {
+ quitAdapterEnabled2 = false;
+ }
+ protected void quitAdapterOn() {
+ clearQuitAdapter();
+ quitAdapterEnabled2 = true;
+ }
+ public void quitAdapterEnable(final boolean v) { quitAdapterEnabled = v; }
+ public void clearQuitAdapter() { quitAdapterShouldQuit = false; }
+ public boolean shouldQuit() { return quitAdapterShouldQuit; }
+ public void doQuit() { quitAdapterShouldQuit=true; }
+
+ public void windowDestroyNotify(final WindowEvent e) {
+ if( quitAdapterEnabled && quitAdapterEnabled2 ) {
+ System.err.println("QUIT Window "+Thread.currentThread());
+ quitAdapterShouldQuit = true;
+ }
+ }
+
+ /////////////////////////////////////////////////////////////
+
+ public void setTitle() {
+ setTitle(glWindow);
+ }
+ public static void setTitle(final GLWindow win) {
+ final CapabilitiesImmutable chosenCaps = win.getChosenCapabilities();
+ final CapabilitiesImmutable reqCaps = win.getRequestedCapabilities();
+ final CapabilitiesImmutable caps = null != chosenCaps ? chosenCaps : reqCaps;
+ final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
+ final float[] sDPI = win.getPixelsPerMM(new float[2]);
+ sDPI[0] *= 25.4f;
+ sDPI[1] *= 25.4f;
+ final float[] minSurfacePixelScale = win.getMinimumSurfaceScale(new float[2]);
+ final float[] maxSurfacePixelScale = win.getMaximumSurfaceScale(new float[2]);
+ final float[] reqSurfacePixelScale = win.getRequestedSurfaceScale(new float[2]);
+ final float[] hasSurfacePixelScale = win.getCurrentSurfaceScale(new float[2]);
+ win.setTitle("GLWindow["+capsA+"], win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]+
+ ", scale[min "+minSurfacePixelScale[0]+"x"+minSurfacePixelScale[1]+", max "+
+ maxSurfacePixelScale[0]+"x"+maxSurfacePixelScale[1]+", req "+
+ reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" -> has "+
+ hasSurfacePixelScale[0]+"x"+hasSurfacePixelScale[1]+"]");
+ }
+
+ public static PointerIcon[] createPointerIcons(final Display disp) {
+ final List<PointerIcon> pointerIcons = new ArrayList<PointerIcon>();
+ {
+ disp.createNative();
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "newt/data/cross-grey-alpha-16x16.png" }, disp.getClass().getClassLoader(), null);
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 8, 8);
+ pointerIcons.add(_pointerIcon);
+ System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString());
+ } catch (final Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "newt/data/pointer-grey-alpha-16x24.png" }, disp.getClass().getClassLoader(), null);
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 0, 0);
+ pointerIcons.add(_pointerIcon);
+ System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString());
+ } catch (final Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "arrow-red-alpha-64x64.png" }, disp.getClass().getClassLoader(), null);
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 0, 0);
+ pointerIcons.add(_pointerIcon);
+ System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString());
+ } catch (final Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "arrow-blue-alpha-64x64.png" }, disp.getClass().getClassLoader(), null);
+ try {
+ _pointerIcon = disp.createPointerIcon(res, 0, 0);
+ pointerIcons.add(_pointerIcon);
+ System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString());
+ } catch (final Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ if( PNGIcon.isAvailable() ) {
+ PointerIcon _pointerIcon = null;
+ final IOUtil.ClassResources res = new IOUtil.ClassResources(new String[] { "jogamp-pointer-64x64.png" }, disp.getClass().getClassLoader(), null);
+ try {
+ final URLConnection urlConn = res.resolve(0);
+ if( null != urlConn ) {
+ final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
+ System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size()+1, image.toString());
+ _pointerIcon = disp.createPointerIcon(image, 32, 0);
+ pointerIcons.add(_pointerIcon);
+ System.err.printf("Create PointerIcon #%02d: %s%n", pointerIcons.size(), _pointerIcon.toString());
+ }
+ } catch (final Exception e) {
+ System.err.println(e.getMessage());
+ }
+ }
+ }
+ return pointerIcons.toArray(new PointerIcon[pointerIcons.size()]);
+ }
+} \ No newline at end of file
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
index 186ffb162..bd5c43d6c 100644
--- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
+++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
@@ -38,6 +38,7 @@ import com.jogamp.nativewindow.NativeSurface;
import com.jogamp.nativewindow.NativeWindow;
import com.jogamp.nativewindow.NativeWindowException;
import com.jogamp.nativewindow.NativeWindowFactory;
+import com.jogamp.nativewindow.NativeWindowHolder;
import com.jogamp.nativewindow.SurfaceUpdatedListener;
import com.jogamp.nativewindow.WindowClosingProtocol;
import com.jogamp.nativewindow.util.Insets;
@@ -52,6 +53,7 @@ import jogamp.newt.Debug;
import jogamp.newt.swt.SWTEDTUtil;
import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
@@ -70,13 +72,14 @@ import com.jogamp.newt.util.EDTUtil;
* Implementation allows use of custom {@link GLCapabilities}.
* </p>
*/
-public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
+public class NewtCanvasSWT extends Canvas implements NativeWindowHolder, WindowClosingProtocol {
private static final boolean DEBUG = Debug.debug("Window");
private final AbstractGraphicsScreen screen;
- private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE;
- private volatile Rectangle clientArea;
+ private WindowClosingMode newtChildClosingMode = WindowClosingMode.DISPOSE_ON_CLOSE;
+ private final WindowClosingMode closingMode = WindowClosingMode.DISPOSE_ON_CLOSE;
+ private volatile Rectangle clientAreaPixels, clientAreaWindow;
private volatile SWTNativeWindow nativeWindow;
private volatile Window newtChild = null;
@@ -126,7 +129,8 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
SWTAccessor.setRealized(this, true);
- clientArea = getClientArea();
+ clientAreaPixels = SWTAccessor.getClientAreaInPixels(this);
+ clientAreaWindow = getClientArea();
final AbstractGraphicsDevice device = SWTAccessor.getDevice(this);
screen = SWTAccessor.getScreen(device, -1 /* default */);
@@ -136,6 +140,10 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
setNEWTChild(child);
}
+ // Bug 1362 fix or workaround: Seems SWT/GTK3 at least performs lazy initialization
+ // Minimal action required: setBackground of the parent canvas before reparenting!
+ setBackground(new Color(parent.getDisplay(), 255, 255, 255));
+
final Listener listener = new Listener () {
@Override
public void handleEvent (final Event event) {
@@ -147,14 +155,14 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
if( null != nativeWindow || validateNative() ) {
if( newtChildReady ) {
if( postSetSize ) {
- newtChild.setSize(clientArea.width, clientArea.height);
+ newtChild.setSize(clientAreaPixels.width, clientAreaPixels.height);
postSetSize = false;
}
if( postSetPos ) {
- newtChild.setPosition(clientArea.x, clientArea.y);
+ newtChild.setPosition(clientAreaPixels.x, clientAreaPixels.y);
postSetPos = false;
}
- newtChild.windowRepaint(0, 0, clientArea.width, clientArea.height);
+ newtChild.windowRepaint(0, 0, clientAreaPixels.width, clientAreaPixels.height);
}
}
break;
@@ -168,7 +176,7 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
if( DEBUG ) {
System.err.println("NewtCanvasSWT.Event.RESIZE, "+event);
}
- updateSizeCheck();
+ updatePosSizeCheck(false);
break;
case SWT.Dispose:
if( DEBUG ) {
@@ -197,14 +205,14 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
}
if( SWTAccessor.isOSX ) {
// Force newtChild to update its size and position (OSX only)
- updatePosSizeCheck(x, y, width, height, true /* updatePos */);
+ updatePosSizeCheck(true /* updatePos */);
}
}
/** assumes nativeWindow == null ! */
protected final boolean validateNative() {
- updateSizeCheck();
- final Rectangle nClientArea = clientArea;
+ updatePosSizeCheck(false);
+ final Rectangle nClientArea = clientAreaPixels;
if(0 >= nClientArea.width || 0 >= nClientArea.height) {
return false;
}
@@ -242,46 +250,34 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
return null != nativeWindow;
}
- protected final void updateSizeCheck() {
- final Rectangle nClientArea = getClientArea();
- if( null != nClientArea ) {
- updatePosSizeCheck(nClientArea.x, nClientArea.y, nClientArea.width, nClientArea.height, false /* updatePos */);
- }
- }
- protected final void updatePosSizeCheck() {
- final Rectangle nClientArea = getClientArea();
- if( null != nClientArea ) {
- updatePosSizeCheck(nClientArea.x, nClientArea.y, nClientArea.width, nClientArea.height, true /* updatePos */);
- }
- }
- protected final void updatePosSizeCheck(final int newX, final int newY, final int newWidth, final int newHeight, final boolean updatePos) {
+ protected final void updatePosSizeCheck(final boolean updatePos) {
final boolean sizeChanged, posChanged;
- final Rectangle nClientArea;
+ Rectangle nClientAreaPixels = SWTAccessor.getClientAreaInPixels(this);
{
- final Rectangle oClientArea = clientArea;
- sizeChanged = newWidth != oClientArea.width || newHeight != oClientArea.height;
- posChanged = newX != oClientArea.x || newY != oClientArea.y;
+ final Rectangle oClientAreaPixels = clientAreaPixels;
+ sizeChanged = nClientAreaPixels.width != oClientAreaPixels.width || nClientAreaPixels.height != oClientAreaPixels.height;
+ posChanged = nClientAreaPixels.x != oClientAreaPixels.x || nClientAreaPixels.y != oClientAreaPixels.y;
if( sizeChanged || posChanged ) {
- nClientArea = new Rectangle(updatePos ? newX : oClientArea.x, updatePos ? newY : oClientArea.y, newWidth, newHeight);
- clientArea = nClientArea;
+ clientAreaPixels = nClientAreaPixels;
+ clientAreaWindow = getClientArea();
} else {
- nClientArea = clientArea;
+ nClientAreaPixels = clientAreaPixels;
}
}
if(DEBUG) {
final long nsh = newtChildReady ? newtChild.getSurfaceHandle() : 0;
- System.err.println("NewtCanvasSWT.updatePosSizeCheck: sizeChanged "+sizeChanged+", posChanged "+posChanged+", updatePos "+updatePos+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientArea.x+"/"+nClientArea.y+" "+nClientArea.width+"x"+nClientArea.height+" - surfaceHandle 0x"+Long.toHexString(nsh));
+ System.err.println("NewtCanvasSWT.updatePosSizeCheck: sizeChanged "+sizeChanged+", posChanged "+posChanged+", updatePos "+updatePos+", ("+Thread.currentThread().getName()+"): newtChildReady "+newtChildReady+", "+nClientAreaPixels.x+"/"+nClientAreaPixels.y+" "+nClientAreaPixels.width+"x"+nClientAreaPixels.height+" - surfaceHandle 0x"+Long.toHexString(nsh));
}
if( sizeChanged ) {
if( newtChildReady ) {
- newtChild.setSize(nClientArea.width, nClientArea.height);
+ newtChild.setSize(nClientAreaPixels.width, nClientAreaPixels.height);
} else {
postSetSize = true;
}
}
if( updatePos && posChanged ) {
if( newtChildReady ) {
- newtChild.setPosition(nClientArea.x, nClientArea.y);
+ newtChild.setPosition(nClientAreaPixels.x, nClientAreaPixels.y);
} else {
postSetPos = true;
}
@@ -330,17 +326,28 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
return new Point(parentLoc[0].x, parentLoc[0].y);
}
- /** @return this SWT Canvas NativeWindow representation, may be null in case it has not been realized. */
+ /**
+ * {@inheritDoc}
+ * @return this SWT Canvas {@link NativeWindow} representation, may be null in case it has not been realized
+ */
+ @Override
public NativeWindow getNativeWindow() { return nativeWindow; }
+ /**
+ * {@inheritDoc}
+ * @return this SWT Canvas {@link NativeSurface} representation, may be null in case it has not been realized
+ */
+ @Override
+ public NativeSurface getNativeSurface() { return nativeWindow; }
+
@Override
public WindowClosingMode getDefaultCloseOperation() {
- return newtChildCloseOp; // TODO: implement ?!
+ return closingMode;
}
@Override
public WindowClosingMode setDefaultCloseOperation(final WindowClosingMode op) {
- return newtChildCloseOp = op; // TODO: implement ?!
+ return closingMode; // TODO: implement!
}
@@ -401,10 +408,10 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
if( null != newtChild ) {
newtChild.setKeyboardFocusHandler(null);
if(attach) {
- newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
+ newtChildClosingMode = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
} else {
newtChild.setFocusAction(null);
- newtChild.setDefaultCloseOperation(newtChildCloseOp);
+ newtChild.setDefaultCloseOperation(newtChildClosingMode);
}
}
}
@@ -419,9 +426,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
newtChild.setFocusAction(null); // no AWT focus traversal ..
if(add) {
- updateSizeCheck();
- final int w = clientArea.width;
- final int h = clientArea.height;
+ updatePosSizeCheck(false);
+ final int w = clientAreaPixels.width;
+ final int h = clientAreaPixels.height;
// set SWT EDT and start it
{
@@ -539,12 +546,12 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
@Override
public int getSurfaceWidth() {
- return clientArea.width;
+ return clientAreaPixels.width;
}
@Override
public int getSurfaceHeight() {
- return clientArea.height;
+ return clientAreaPixels.height;
}
@Override
diff --git a/src/newt/classes/com/jogamp/newt/util/MainThread.java b/src/newt/classes/com/jogamp/newt/util/MainThread.java
index 8bf4bc20f..05df63794 100644
--- a/src/newt/classes/com/jogamp/newt/util/MainThread.java
+++ b/src/newt/classes/com/jogamp/newt/util/MainThread.java
@@ -45,6 +45,7 @@ import java.util.List;
import com.jogamp.nativewindow.NativeWindowFactory;
import com.jogamp.common.os.Platform;
+import com.jogamp.common.util.InterruptSource;
import com.jogamp.common.util.PropertyAccess;
import com.jogamp.common.util.ReflectionUtil;
@@ -171,15 +172,14 @@ public class MainThread {
return res;
}
- static class UserApp extends Thread {
+ static class UserApp extends InterruptSource.Thread {
private final String mainClassNameShort;
private final String mainClassName;
private final String[] mainClassArgs;
private final Method mainClassMain;
- private List<Thread> nonDaemonThreadsAtStart;
+ private List<java.lang.Thread> nonDaemonThreadsAtStart;
public UserApp(final String mainClassName, final String[] mainClassArgs) throws SecurityException, NoSuchMethodException, ClassNotFoundException {
- super();
this.mainClassName=mainClassName;
this.mainClassArgs=mainClassArgs;
@@ -200,10 +200,10 @@ public class MainThread {
@Override
public void run() {
nonDaemonThreadsAtStart = getNonDaemonThreads();
- if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" start, nonDaemonThreadsAtStart "+nonDaemonThreadsAtStart);
+ if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" start, nonDaemonThreadsAtStart "+nonDaemonThreadsAtStart);
// start user app ..
try {
- if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" invoke "+mainClassName);
+ if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" invoke "+mainClassName);
mainClassMain.invoke(null, new Object[] { mainClassArgs } );
} catch (final InvocationTargetException ite) {
ite.getTargetException().printStackTrace();
@@ -219,30 +219,30 @@ public class MainThread {
while( 0 < ( ndtr = getNonDaemonThreadCount(nonDaemonThreadsAtStart) ) ) {
if(DEBUG) System.err.println("MainAction.run(): post user app, non daemon threads alive: "+ndtr);
try {
- Thread.sleep(1000);
+ java.lang.Thread.sleep(1000);
} catch (final InterruptedException e) {
e.printStackTrace();
}
}
- if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" user app fin: "+ndtr);
+ if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" user app fin: "+ndtr);
}
if ( useMainThread ) {
if(isMacOSX) {
try {
if(DEBUG) {
- System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.0");
+ System.err.println("MainAction.main(): "+java.lang.Thread.currentThread()+" MainAction fin - stopNSApp.0");
}
ReflectionUtil.callStaticMethod(MACOSXDisplayClassName, "stopNSApplication",
null, null, MainThread.class.getClassLoader());
if(DEBUG) {
- System.err.println("MainAction.main(): "+Thread.currentThread()+" MainAction fin - stopNSApp.X");
+ System.err.println("MainAction.main(): "+java.lang.Thread.currentThread()+" MainAction fin - stopNSApp.X");
}
} catch (final Exception e) {
e.printStackTrace();
}
} else {
- if(DEBUG) System.err.println("MainAction.run(): "+Thread.currentThread().getName()+" MainAction fin - System.exit(0)");
+ if(DEBUG) System.err.println("MainAction.run(): "+java.lang.Thread.currentThread().getName()+" MainAction fin - System.exit(0)");
System.exit(0);
}
}
diff --git a/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java
index cc159e6ed..c30576ff4 100644
--- a/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java
+++ b/src/newt/classes/com/jogamp/newt/util/applet/JOGLNewtAppletBase.java
@@ -42,10 +42,8 @@ import com.jogamp.opengl.GLPipelineFactory;
import jogamp.newt.Debug;
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.newt.Display;
+import com.jogamp.common.util.InterruptSource;
import com.jogamp.newt.Window;
-import com.jogamp.newt.Display.PointerIcon;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseListener;
@@ -53,13 +51,18 @@ import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.newt.opengl.util.NEWTDemoListener;
import com.jogamp.opengl.util.Animator;
import com.jogamp.opengl.util.AnimatorBase;
-/** Shows how to deploy an applet using JOGL. This demo must be
- referenced from a web page via an &lt;applet&gt; tag. */
-
+/**
+ * Shows how to deploy an applet using JOGL.
+ * This demo must be referenced from a web page via an &lt;applet&gt; tag.
+ * <p>
+ * The demo code uses {@link NEWTDemoListener} functionality.
+ * </p>
+ */
public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
public static final boolean DEBUG = Debug.debug("Applet");
@@ -69,7 +72,6 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
boolean glClosable;
boolean glDebug;
boolean glTrace;
- PointerIcon pointerIconTest = null;
GLEventListener glEventListener = null;
GLWindow glWindow = null;
@@ -193,8 +195,13 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
glWindow.addKeyListener((KeyListener)glEventListener);
}
+ glWindow.addWindowListener(reparentHomeListener);
+
if(!noDefaultKeyListener) {
glWindow.addKeyListener(this);
+ final NEWTDemoListener newtDemoListener = new NEWTDemoListener(glWindow);
+ glWindow.addKeyListener(newtDemoListener);
+ glWindow.addMouseListener(newtDemoListener);
}
glWindow.setUpdateFPSFrames(FPSCounter.DEFAULT_FRAMES_PER_INTERVAL, System.err);
@@ -220,7 +227,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
null == glWindow.getParent() && null != parentWin && 0 != parentWin.getWindowHandle() )
{
// we may be called directly by the native EDT
- new Thread(new Runnable() {
+ new InterruptSource.Thread(null, new Runnable() {
@Override
public void run() {
if( glWindow.isNativeValid() && null != parentWin && 0 != parentWin.getWindowHandle() ) {
@@ -235,24 +242,13 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
if(isValid) {
glWindow.setVisible(true);
glWindow.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED);
- if( null == pointerIconTest ) {
- final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } );
- final Display disp = glWindow.getScreen().getDisplay();
- try {
- pointerIconTest = disp.createPointerIcon(res, 8, 8);
- } catch (final Exception e) {
- e.printStackTrace();
- }
- }
glAnimator.start();
parentWin = glWindow.getParent();
- glWindow.addWindowListener(reparentHomeListener);
}
}
public void stop() {
if(null!=glAnimator) {
- glWindow.removeWindowListener(reparentHomeListener);
glAnimator.stop();
glWindow.setVisible(false);
}
@@ -291,10 +287,7 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
_gl = _gl.getContext().setGL( GLPipelineFactory.create("com.jogamp.opengl.Trace", null, _gl, new Object[] { System.err } ) );
} catch (final Exception e) {e.printStackTrace();}
}
-
- if(glSwapInterval>=0) {
- _gl.setSwapInterval(glSwapInterval);
- }
+ _gl.setSwapInterval(glSwapInterval);
}
@Override
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int width, final int height) {
@@ -315,27 +308,14 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
if( !e.isPrintableKey() || e.isAutoRepeat() ) {
return;
}
- if(e.getKeyChar()=='d') {
- new Thread() {
- public void run() {
- glWindow.setUndecorated(!glWindow.isUndecorated());
- } }.start();
- } if(e.getKeyChar()=='f') {
- new Thread() {
- public void run() {
- glWindow.setFullscreen(!glWindow.isFullscreen());
- } }.start();
- } else if(e.getKeyChar()=='a') {
- new Thread() {
- public void run() {
- glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
- } }.start();
- } else if(e.getKeyChar()=='r' && null!=parentWin) {
- new Thread() {
+
+ if(e.getKeyChar()=='r' && 0==e.getModifiers() && null!=parentWin) {
+ e.setConsumed(true);
+ glWindow.invokeOnNewThread(null, false, new Runnable() {
public void run() {
if(null == glWindow.getParent()) {
- glWindow.reparentWindow(parentWin, -1, -1, 0 /* hints */);
- } else {
+ glWindow.reparentWindow(parentWin, -1, -1, 0 /* hints */);
+ } else {
final InsetsImmutable insets = glWindow.getInsets();
final int x, y;
if ( 0 >= insets.getTopHeight() ) {
@@ -349,43 +329,13 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
glWindow.reparentWindow(null, x, y, 0 /* hints */);
glWindow.setDefaultCloseOperation( glClosable ? WindowClosingMode.DISPOSE_ON_CLOSE : WindowClosingMode.DO_NOTHING_ON_CLOSE );
}
- } }.start();
- } else if(e.getKeyChar()=='c') {
- new Thread() {
- public void run() {
- System.err.println("[set pointer-icon pre]");
- final PointerIcon currentPI = glWindow.getPointerIcon();
- glWindow.setPointerIcon( currentPI == pointerIconTest ? null : pointerIconTest);
- System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
- } }.start();
- } else if(e.getKeyChar()=='i') {
- new Thread() {
- public void run() {
- System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible());
- glWindow.setPointerVisible(!glWindow.isPointerVisible());
- System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible());
- } }.start();
- } else if(e.getKeyChar()=='j') {
- new Thread() {
- public void run() {
- final Thread t = glWindow.setExclusiveContextThread(null);
- System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
- glWindow.confinePointer(!glWindow.isPointerConfined());
- System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
- glWindow.setExclusiveContextThread(t);
- } }.start();
- } else if(e.getKeyChar()=='w') {
- new Thread() {
- public void run() {
- System.err.println("[set mouse pos pre]");
- glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2);
- System.err.println("[set mouse pos post]");
- } }.start();
+ } } );
}
}
@Override
public void keyReleased(final KeyEvent e) {
}
+
}
diff --git a/src/newt/classes/com/jogamp/newt/util/applet3/JOGLNewtApplet3Run.java b/src/newt/classes/com/jogamp/newt/util/applet3/JOGLNewtApplet3Run.java
index 9b9b7d532..fce43d71f 100644
--- a/src/newt/classes/com/jogamp/newt/util/applet3/JOGLNewtApplet3Run.java
+++ b/src/newt/classes/com/jogamp/newt/util/applet3/JOGLNewtApplet3Run.java
@@ -243,7 +243,7 @@ public class JOGLNewtApplet3Run implements Applet3 {
}
this.ctx = ctx;
String glEventListenerClazzName=null;
- int glSwapInterval=0;
+ int glSwapInterval=1;
boolean glDebug=false;
boolean glTrace=false;
boolean glNoDefaultKeyListener = false;