aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/classes/com/jogamp
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/classes/com/jogamp')
-rw-r--r--src/newt/classes/com/jogamp/newt/Display.java83
-rw-r--r--src/newt/classes/com/jogamp/newt/MonitorDevice.java4
-rw-r--r--src/newt/classes/com/jogamp/newt/MonitorMode.java119
-rw-r--r--src/newt/classes/com/jogamp/newt/Screen.java62
-rw-r--r--src/newt/classes/com/jogamp/newt/Window.java6
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java37
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java37
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java20
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyAdapter.java2
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyEvent.java64
-rw-r--r--src/newt/classes/com/jogamp/newt/event/KeyListener.java18
-rw-r--r--src/newt/classes/com/jogamp/newt/event/MouseEvent.java27
-rw-r--r--src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java4
-rw-r--r--src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java7
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java107
-rw-r--r--src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java4
-rw-r--r--src/newt/classes/com/jogamp/newt/util/EDTUtil.java58
-rw-r--r--src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java11
18 files changed, 483 insertions, 187 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 993aa33eb..c618405c2 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -31,6 +31,7 @@ package com.jogamp.newt;
import com.jogamp.newt.util.EDTUtil;
import jogamp.newt.Debug;
+import java.lang.ref.WeakReference;
import java.util.*;
import javax.media.nativewindow.AbstractGraphicsDevice;
@@ -153,41 +154,40 @@ public abstract class Display {
/**
* Sets a new {@link EDTUtil} and returns the previous one.
* <p>
- * If <code>newEDTUtil</code> is <code>null</code>,
+ * If <code>usrEDTUtil</code> is <code>null</code>,
* the device's default EDTUtil is created and used.
* </p>
* <p>
- * If a previous one exists and it differs from the new one,
- * it's being stopped, wait-until-idle and reset to allow a restart at a later time.
+ * If a previous one exists and it differs from <code>usrEDTUtil</code>,
+ * it's being stopped, wait-until-idle.
* </p>
* <p>
- * If <code>newEDTUtil</code> is not null and equals the previous one,
+ * If <code>usrEDTUtil</code> is not null and equals the previous one,
* no change is being made.
* </p>
- * <p>
- * Note that <code>newEDTUtil</code> will be started by this method,
- * if it is not running yet.
- * </p>
*/
- public abstract EDTUtil setEDTUtil(EDTUtil newEDTUtil);
+ public abstract EDTUtil setEDTUtil(EDTUtil usrEDTUtil);
public abstract EDTUtil getEDTUtil();
+ /**
+ * @return true if EDT is running and not subject to be stopped, otherwise false.
+ */
public abstract boolean isEDTRunning();
public abstract void dispatchMessages();
// Global Displays
- protected static ArrayList<Display> displayList = new ArrayList<Display>();
+ protected static final ArrayList<WeakReference<Display>> displayList = new ArrayList<WeakReference<Display>>();
protected static int displaysActive = 0;
public static void dumpDisplayList(String prefix) {
synchronized(displayList) {
- Iterator<Display> i = displayList.iterator();
System.err.println(prefix+" DisplayList[] entries: "+displayList.size()+" - "+getThreadName());
- for(int j=0; i.hasNext(); j++) {
- Display d = i.next();
- System.err.println(" ["+j+"] : "+d);
+ final Iterator<WeakReference<Display>> ri = displayList.iterator();
+ for(int j=0; ri.hasNext(); j++) {
+ final Display d = ri.next().get();
+ System.err.println(" ["+j+"] : "+d+", GC'ed "+(null==d));
}
}
}
@@ -216,29 +216,62 @@ public abstract class Display {
return getDisplayOfImpl(type, name, fromIndex, -1, shared);
}
- private static Display getDisplayOfImpl(String type, String name, int fromIndex, int incr, boolean shared) {
+ private static Display getDisplayOfImpl(String type, String name, final int fromIndex, final int incr, boolean shared) {
synchronized(displayList) {
int i = fromIndex >= 0 ? fromIndex : displayList.size() - 1 ;
while( ( incr > 0 ) ? i < displayList.size() : i >= 0 ) {
- Display display = (Display) displayList.get(i);
- if( display.getType().equals(type) &&
- display.getName().equals(name) &&
- ( !shared || shared && !display.isExclusive() )
- ) {
- return display;
+ final Display display = (Display) displayList.get(i).get();
+ if( null == display ) {
+ // Clear GC'ed dead reference entry!
+ displayList.remove(i);
+ if( incr < 0 ) {
+ // decrease
+ i+=incr;
+ } // else nop - remove shifted subsequent elements to the left
+ } else {
+ if( display.getType().equals(type) &&
+ display.getName().equals(name) &&
+ ( !shared || shared && !display.isExclusive() )
+ ) {
+ return display;
+ }
+ i+=incr;
}
- i+=incr;
}
}
return null;
}
-
+
+ protected static void addDisplay2List(Display display) {
+ synchronized(displayList) {
+ // GC before add
+ int i=0;
+ while( i < displayList.size() ) {
+ if( null == displayList.get(i).get() ) {
+ displayList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ displayList.add(new WeakReference<Display>(display));
+ }
+ }
+
/** Returns the global display collection */
- @SuppressWarnings("unchecked")
public static Collection<Display> getAllDisplays() {
ArrayList<Display> list;
synchronized(displayList) {
- list = (ArrayList<Display>) displayList.clone();
+ list = new ArrayList<Display>();
+ int i = 0;
+ while( i < displayList.size() ) {
+ final Display d = displayList.get(i).get();
+ if( null == d ) {
+ displayList.remove(i);
+ } else {
+ list.add( displayList.get(i).get() );
+ i++;
+ }
+ }
}
return list;
}
diff --git a/src/newt/classes/com/jogamp/newt/MonitorDevice.java b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
index 4b0a760a4..8bc7f40e3 100644
--- a/src/newt/classes/com/jogamp/newt/MonitorDevice.java
+++ b/src/newt/classes/com/jogamp/newt/MonitorDevice.java
@@ -129,6 +129,10 @@ public abstract class MonitorDevice {
/**
* Returns a list of immutable {@link MonitorMode}s supported by this monitor.
* <p>
+ * The list is ordered in descending order,
+ * see {@link MonitorMode#compareTo(MonitorMode)}.
+ * </p>
+ * <p>
* Use w/ care, it's not a copy!
* </p>
*/
diff --git a/src/newt/classes/com/jogamp/newt/MonitorMode.java b/src/newt/classes/com/jogamp/newt/MonitorMode.java
index 914aa880f..218cd8bd5 100644
--- a/src/newt/classes/com/jogamp/newt/MonitorMode.java
+++ b/src/newt/classes/com/jogamp/newt/MonitorMode.java
@@ -28,6 +28,8 @@
package com.jogamp.newt;
+import java.util.Comparator;
+
import javax.media.nativewindow.util.DimensionImmutable;
import javax.media.nativewindow.util.RectangleImmutable;
import javax.media.nativewindow.util.SurfaceSize;
@@ -108,22 +110,36 @@ import com.jogamp.newt.util.MonitorModeUtil;
monitor.setCurrentMode(mm);
* </pre>
*/
-public class MonitorMode {
+public class MonitorMode implements Comparable<MonitorMode> {
+
+ /** Comparator for 2 {@link MonitorMode}s, following comparison order as described in {@link MonitorMode#compareTo(MonitorMode)}, returning the ascending order. */
+ public static final Comparator<MonitorMode> monitorModeComparator = new Comparator<MonitorMode>() {
+ public int compare(MonitorMode mm1, MonitorMode mm2) {
+ return mm1.compareTo(mm2);
+ } };
+
+ /** Comparator for 2 {@link MonitorMode}s, following comparison order as described in {@link MonitorMode#compareTo(MonitorMode)}, returning the descending order. */
+ public static final Comparator<MonitorMode> monitorModeComparatorInv = new Comparator<MonitorMode>() {
+ public int compare(MonitorMode mm1, MonitorMode mm2) {
+ return mm2.compareTo(mm1);
+ } };
+
/**
- * Immutable <i>surfaceSize and refreshRate</i> Class, consisting of it's read only components:<br>
+ * Immutable <i>surfaceSize, flags and refreshRate</i> Class, consisting of it's read only components:<br>
* <ul>
* <li>nativeId</li>
* <li>{@link SurfaceSize} surface memory size</li>
+ * <li><code>flags</code></li>
* <li><code>refresh rate</code></li>
* </ul>
*/
- public static class SizeAndRRate {
+ public static class SizeAndRRate implements Comparable<SizeAndRRate> {
/** Non rotated surface size */
public final SurfaceSize surfaceSize;
- /** Vertical refresh rate */
- public final float refreshRate;
/** Mode bitfield flags, i.e. {@link #FLAG_DOUBLESCAN}, {@link #FLAG_INTERLACE}, .. */
public final int flags;
+ /** Vertical refresh rate */
+ public final float refreshRate;
public final int hashCode;
public SizeAndRRate(SurfaceSize surfaceSize, float refreshRate, int flags) {
@@ -131,8 +147,8 @@ public class MonitorMode {
throw new IllegalArgumentException("surfaceSize must be set ("+surfaceSize+")");
}
this.surfaceSize=surfaceSize;
- this.refreshRate=refreshRate;
this.flags = flags;
+ this.refreshRate=refreshRate;
this.hashCode = getHashCode();
}
@@ -140,8 +156,8 @@ public class MonitorMode {
private final static String STR_DOUBLESCAN = "DoubleScan";
private final static String STR_SEP = ", ";
- public static final StringBuffer flags2String(int flags) {
- final StringBuffer sb = new StringBuffer();
+ public static final StringBuilder flags2String(int flags) {
+ final StringBuilder sb = new StringBuilder();
boolean sp = false;
if( 0 != ( flags & FLAG_INTERLACE ) ) {
sb.append(STR_INTERLACE);
@@ -161,6 +177,49 @@ public class MonitorMode {
}
/**
+ * <p>
+ * Compares {@link SurfaceSize#compareTo(SurfaceSize) surfaceSize} 1st, then {@link #flags}, then {@link #refreshRate}.
+ * </p>
+ * <p>
+ * Flags are compared as follows:
+ * <pre>
+ * NONE > DOUBLESCAN > INTERLACE
+ * </pre>
+ * </p>
+ * <p>
+ * Refresh rate differences of &lt; 0.01 are considered equal (epsilon).
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final SizeAndRRate sszr) {
+ final int rssz = surfaceSize.compareTo(sszr.surfaceSize);
+ if( 0 != rssz ) {
+ return rssz;
+ }
+ final int tflags = 0 == flags ? Integer.MAX_VALUE : flags; // normalize NONE
+ final int xflags = 0 == sszr.flags ? Integer.MAX_VALUE : sszr.flags; // normalize NONE
+ if( tflags == xflags ) {
+ final float refreshEpsilon = 0.01f; // reasonable sorting granularity of refresh rate
+ final float drate = refreshRate - sszr.refreshRate;
+ if( Math.abs(drate) < refreshEpsilon ) {
+ return 0;
+ } else if( drate > refreshEpsilon ) {
+ return 1;
+ } else {
+ return -1;
+ }
+ } else {
+ if(tflags > xflags) {
+ return 1;
+ } else if(tflags < xflags) {
+ return -1;
+ }
+ return 0;
+ }
+ }
+
+ /**
* Tests equality of two {@link SizeAndRRate} objects
* by evaluating equality of it's components:<br/>
* <ul>
@@ -174,8 +233,8 @@ public class MonitorMode {
if (obj instanceof SizeAndRRate) {
final SizeAndRRate p = (SizeAndRRate)obj;
return surfaceSize.equals(p.surfaceSize) &&
- refreshRate == p.refreshRate &&
- flags == p.flags ;
+ flags == p.flags &&
+ refreshRate == p.refreshRate ;
}
return false;
}
@@ -184,8 +243,8 @@ public class MonitorMode {
* Returns a combined hash code of it's elements:<br/>
* <ul>
* <li><code>surfaceSize</code></li>
- * <li><code>refreshRate</code></li>
* <li><code>flags</code></li>
+ * <li><code>refreshRate</code></li>
* </ul>
*/
public final int hashCode() {
@@ -194,8 +253,8 @@ public class MonitorMode {
private final int getHashCode() {
// 31 * x == (x << 5) - x
int hash = 31 + surfaceSize.hashCode();
- hash = ((hash << 5) - hash) + (int)(refreshRate*100.0f);
hash = ((hash << 5) - hash) + flags;
+ hash = ((hash << 5) - hash) + (int)(refreshRate*100.0f);
return hash;
}
}
@@ -306,6 +365,42 @@ public class MonitorMode {
}
/**
+ * <p>
+ * Compares {@link SizeAndRRate#compareTo(SizeAndRRate) sizeAndRRate} 1st, then {@link #rotation}.
+ * </p>
+ * <p>
+ * Rotation is compared inverted, i.e. <code>360 - rotation</code>,
+ * so the lowest rotation reflects a higher value.
+ * </p>
+ * <p>
+ * Order of comparing MonitorMode:
+ * <ul>
+ * <li>resolution</li>
+ * <li>bits per pixel</li>
+ * <li>flags</li>
+ * <li>refresh rate</li>
+ * <li>rotation</li>
+ * </ul>
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ public int compareTo(final MonitorMode mm) {
+ final int c = sizeAndRRate.compareTo(mm.sizeAndRRate);
+ if( 0 != c ) {
+ return c;
+ }
+ final int trot = 360 - rotation; // normalize rotation
+ final int xrot = 360 - mm.rotation; // normalize rotation
+ if(trot > xrot) {
+ return 1;
+ } else if(trot < xrot) {
+ return -1;
+ }
+ return 0;
+ }
+
+ /**
* Tests equality of two {@link MonitorMode} objects
* by evaluating equality of it's components:<br/>
* <ul>
diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java
index f56aff964..f56ee344b 100644
--- a/src/newt/classes/com/jogamp/newt/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/Screen.java
@@ -29,6 +29,8 @@ package com.jogamp.newt;
import com.jogamp.newt.event.MonitorModeListener;
import jogamp.newt.Debug;
+
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -64,7 +66,7 @@ public abstract class Screen {
}
/**
- * Manual trigger the native creation, if it is not done yet..<br>
+ * Manual trigger the native creation, if not done yet..<br>
* This is useful to be able to request the {@link javax.media.nativewindow.AbstractGraphicsScreen}, via
* {@link #getGraphicsScreen()}.<br>
* Otherwise the abstract device won't be available before the dependent component (Window) is realized.
@@ -164,6 +166,10 @@ public abstract class Screen {
/**
* Return a list of all {@link MonitorMode}s for all {@link MonitorDevice}s.
+ * <p>
+ * The list is ordered in descending order,
+ * see {@link MonitorMode#compareTo(MonitorMode)}.
+ * </p>
*/
public abstract List<MonitorMode> getMonitorModes();
@@ -220,7 +226,7 @@ public abstract class Screen {
public abstract void removeMonitorModeListener(MonitorModeListener sml);
// Global Screens
- protected static ArrayList<Screen> screenList = new ArrayList<Screen>();
+ protected static final ArrayList<WeakReference<Screen>> screenList = new ArrayList<WeakReference<Screen>>();
protected static int screensActive = 0;
/**
@@ -249,26 +255,60 @@ public abstract class Screen {
synchronized(screenList) {
int i = fromIndex >= 0 ? fromIndex : screenList.size() - 1 ;
while( ( incr > 0 ) ? i < screenList.size() : i >= 0 ) {
- Screen screen = (Screen) screenList.get(i);
- if( screen.getDisplay().equals(display) &&
- screen.getIndex() == idx ) {
- return screen;
+ final Screen screen = (Screen) screenList.get(i).get();
+ if( null == screen ) {
+ // Clear GC'ed dead reference entry!
+ screenList.remove(i);
+ if( incr < 0 ) {
+ // decrease
+ i+=incr;
+ } // else nop - remove shifted subsequent elements to the left
+ } else {
+ if( screen.getDisplay().equals(display) &&
+ screen.getIndex() == idx ) {
+ return screen;
+ }
+ i+=incr;
}
- i+=incr;
}
}
return null;
}
- /** Returns the global display collection */
- @SuppressWarnings("unchecked")
+
+ protected static void addScreen2List(Screen screen) {
+ synchronized(screenList) {
+ // GC before add
+ int i=0;
+ while( i < screenList.size() ) {
+ if( null == screenList.get(i).get() ) {
+ screenList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ screenList.add(new WeakReference<Screen>(screen));
+ }
+ }
+
+ /** Returns the global screen collection */
public static Collection<Screen> getAllScreens() {
ArrayList<Screen> list;
synchronized(screenList) {
- list = (ArrayList<Screen>) screenList.clone();
+ list = new ArrayList<Screen>();
+ int i = 0;
+ while( i < screenList.size() ) {
+ final Screen s = screenList.get(i).get();
+ if( null == s ) {
+ screenList.remove(i);
+ } else {
+ list.add( screenList.get(i).get() );
+ i++;
+ }
+ }
}
return list;
}
-
+
public static int getActiveScreenNumber() {
synchronized(screenList) {
return screensActive;
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index 0bebf330a..f63c03738 100644
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -406,7 +406,11 @@ public interface Window extends NativeWindow, WindowClosingProtocol {
* Sets a {@link KeyListener} allowing focus traversal with a covered window toolkit like AWT.
* <p>
* The {@link KeyListener} methods are invoked prior to all other {@link KeyListener}'s
- * allowing to suppress the {@link KeyEvent} via the {@link InputEvent#consumedTag}.
+ * allowing to suppress the {@link KeyEvent} via the {@link InputEvent#consumedTag}
+ * and to perform focus traversal with a 3rd party toolkit.
+ * </p>
+ * <p>
+ * The {@link KeyListener} methods are not invoked for {@link KeyEvent#isAutoRepeat() auto-repeat} events.
* </p>
* @param l
*/
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index d0a4b7e98..e4b5a25c4 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -31,6 +31,7 @@ package com.jogamp.newt.awt;
import java.awt.AWTKeyStroke;
import java.awt.Canvas;
+import java.awt.Component;
import java.awt.Graphics;
import java.awt.GraphicsConfiguration;
import java.awt.KeyboardFocusManager;
@@ -201,8 +202,6 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
};
class FocusTraversalKeyListener implements KeyListener {
- boolean suppress = false;
-
public void keyPressed(KeyEvent e) {
if( isParent() && !isFullscreen() ) {
handleKey(e, false);
@@ -213,34 +212,31 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
handleKey(e, true);
}
}
- public void keyTyped(KeyEvent e) {
- if(suppress) {
- e.setConsumed(true);
- suppress = false; // reset
- }
- }
void handleKey(KeyEvent evt, boolean onRelease) {
if(null == keyboardFocusManager) {
throw new InternalError("XXX");
}
final AWTKeyStroke ks = AWTKeyStroke.getAWTKeyStroke(evt.getKeyCode(), evt.getModifiers(), onRelease);
+ boolean suppress = false;
if(null != ks) {
final Set<AWTKeyStroke> fwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
- final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
+ final Set<AWTKeyStroke> bwdKeys = keyboardFocusManager.getDefaultFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS);
if(fwdKeys.contains(ks)) {
+ final Component nextFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, true /* forward */);
if(DEBUG) {
- System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner());
+ System.err.println("NewtCanvasAWT.focusKey (fwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", nextFocus "+nextFocus);
}
// Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
- NewtCanvasAWT.this.transferFocus();
+ nextFocus.requestFocus();
suppress = true;
} else if(bwdKeys.contains(ks)) {
+ final Component prevFocus = AWTMisc.getNextFocus(NewtCanvasAWT.this, false /* forward */);
if(DEBUG) {
- System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner());
+ System.err.println("NewtCanvasAWT.focusKey (bwd): "+ks+", current focusOwner "+keyboardFocusManager.getFocusOwner()+", hasFocus: "+hasFocus()+", prevFocus "+prevFocus);
}
// Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus.
- NewtCanvasAWT.this.transferFocusBackward();
+ prevFocus.requestFocus();
suppress = true;
}
}
@@ -355,8 +351,8 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
// after native peer is valid: Windows
disableBackgroundErase();
-
- jawtWindow = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities());
+
+ jawtWindow = NewtFactoryAWT.getNativeWindow(this, null != newtChild ? newtChild.getRequestedCapabilities() : null);
jawtWindow.setShallUseOffscreenLayer(shallUseOffscreenLayer);
if(DEBUG) {
@@ -540,6 +536,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingMode.DO_NOTHING_ON_CLOSE);
keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
keyboardFocusManager.addPropertyChangeListener("focusOwner", focusPropertyChangeListener);
+ // force this AWT Canvas to be focus-able,
+ // since this it is completely covered by the newtChild (z-order).
+ setFocusable(true);
if(isOnscreen) {
// onscreen newt child needs to fwd AWT focus
newtChild.setKeyboardFocusHandler(newtFocusTraversalKeyListener);
@@ -552,6 +551,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
newtChild.removeWindowListener(clearAWTMenusOnNewtFocus);
newtChild.setFocusAction(null);
newtChild.setDefaultCloseOperation(newtChildCloseOp);
+ setFocusable(false);
}
}
}
@@ -576,7 +576,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
}
final int w = getWidth();
final int h = getHeight();
- System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h);
+ if(DEBUG) {
+ System.err.println("NewtCanvasAWT.attachNewtChild.2: size "+w+"x"+h);
+ }
newtChild.setVisible(false);
newtChild.setSize(w, h);
newtChild.reparentWindow(jawtWindow);
@@ -588,9 +590,6 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto
configureNewtChild(true);
newtChild.sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout to listener
- // force this AWT Canvas to be focus-able,
- // since this it is completely covered by the newtChild (z-order).
- setFocusable(true);
if(DEBUG) {
System.err.println("NewtCanvasAWT.attachNewtChild.X: win "+newtWinHandleToHexString(newtChild)+", EDTUtil: cur "+newtChild.getScreen().getDisplay().getEDTUtil()+", comp "+this);
}
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 d06aca039..e8cd71514 100644
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtApplet1Run.java
@@ -42,6 +42,7 @@ import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLProfile;
+import com.jogamp.common.os.Platform;
import com.jogamp.newt.awt.NewtCanvasAWT;
import com.jogamp.newt.opengl.GLWindow;
@@ -94,12 +95,11 @@ import com.jogamp.newt.opengl.GLWindow;
public class JOGLNewtApplet1Run extends Applet {
public static final boolean DEBUG = JOGLNewtAppletBase.DEBUG;
- GLWindow glWindow;
- NewtCanvasAWT newtCanvasAWT;
- JOGLNewtAppletBase base;
+ GLWindow glWindow = null;
+ NewtCanvasAWT newtCanvasAWT = null;
+ JOGLNewtAppletBase base = null;
/** if valid glStandalone:=true (own window) ! */
int glXd=Integer.MAX_VALUE, glYd=Integer.MAX_VALUE, glWidth=Integer.MAX_VALUE, glHeight=Integer.MAX_VALUE;
- boolean glStandalone = false;
public void init() {
if(DEBUG) {
@@ -108,7 +108,7 @@ public class JOGLNewtApplet1Run extends Applet {
if(!(this instanceof Container)) {
throw new RuntimeException("This Applet is not a AWT Container");
}
- Container container = (Container) this;
+ final Container container = (Container) this;
String glEventListenerClazzName=null;
String glProfileName=null;
@@ -147,7 +147,7 @@ public class JOGLNewtApplet1Run extends Applet {
if(null==glEventListenerClazzName) {
throw new RuntimeException("No applet parameter 'gl_event_listener_class'");
}
- glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
+ final boolean glStandalone = Integer.MAX_VALUE>glXd && Integer.MAX_VALUE>glYd && Integer.MAX_VALUE>glWidth && Integer.MAX_VALUE>glHeight;
if(DEBUG) {
System.err.println("JOGLNewtApplet1Run Configuration:");
System.err.println("glStandalone: "+glStandalone);
@@ -209,9 +209,7 @@ public class JOGLNewtApplet1Run extends Applet {
addKeyListener((KeyListener)glEventListener);
}
}
- if(glStandalone) {
- newtCanvasAWT = null;
- } else {
+ if( !glStandalone ) {
newtCanvasAWT = new NewtCanvasAWT(glWindow);
container.add(newtCanvasAWT, BorderLayout.CENTER);
container.validate();
@@ -226,13 +224,15 @@ public class JOGLNewtApplet1Run extends Applet {
public void start() {
if(DEBUG) {
- System.err.println("JOGLNewtApplet1Run.start() START");
+ System.err.println("JOGLNewtApplet1Run.start() START (isVisible "+isVisible()+", isDisplayable "+isDisplayable()+")");
}
- this.validate();
this.setVisible(true);
-
final java.awt.Point p0 = this.getLocationOnScreen();
- if(glStandalone) {
+ if( null != newtCanvasAWT ) {
+ newtCanvasAWT.setFocusable(true);
+ newtCanvasAWT.requestFocus();
+ } else {
+ glWindow.requestFocus();
glWindow.setSize(glWidth, glHeight);
glWindow.setPosition(p0.x+glXd, p0.y+glYd);
}
@@ -251,6 +251,13 @@ public class JOGLNewtApplet1Run extends Applet {
System.err.println("GLWindow: "+glWindow);
}
base.start();
+ if( null != newtCanvasAWT && Platform.OSType.MACOS == Platform.getOSType() && newtCanvasAWT.isOffscreenLayerSurfaceEnabled() ) {
+ // force relayout
+ final int cW = newtCanvasAWT.getWidth();
+ final int cH = newtCanvasAWT.getHeight();
+ newtCanvasAWT.setSize(cW+1, cH+1);
+ newtCanvasAWT.setSize(cW, cH);
+ }
if(DEBUG) {
System.err.println("JOGLNewtApplet1Run.start() END");
}
@@ -271,12 +278,14 @@ public class JOGLNewtApplet1Run extends Applet {
System.err.println("JOGLNewtApplet1Run.destroy() START");
}
glWindow.setVisible(false); // hide 1st
- if(!glStandalone) {
+ if( null != newtCanvasAWT ) {
glWindow.reparentWindow(null); // get out of newtCanvasAWT
this.remove(newtCanvasAWT); // remove newtCanvasAWT
}
base.destroy(); // destroy glWindow unrecoverable
base=null;
+ glWindow=null;
+ newtCanvasAWT=null;
if(DEBUG) {
System.err.println("JOGLNewtApplet1Run.destroy() END");
}
diff --git a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
index c3ad51c96..25ddfad48 100644
--- a/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
+++ b/src/newt/classes/com/jogamp/newt/awt/applet/JOGLNewtAppletBase.java
@@ -164,12 +164,14 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
// Closing action: back to parent!
@Override
public void windowDestroyNotify(WindowEvent e) {
- if( WindowClosingMode.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation() ) {
+ if( isValid() && WindowClosingMode.DO_NOTHING_ON_CLOSE == glWindow.getDefaultCloseOperation() ) {
if(null == glWindow.getParent()) {
// we may be called directly by the native EDT
new Thread(new Runnable() {
public void run() {
- glWindow.reparentWindow(awtParent);
+ if( glWindow.isNativeValid() ) {
+ glWindow.reparentWindow(awtParent);
+ }
}
}).start();
}
@@ -284,11 +286,11 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
// ***********************************************************************************
// ***********************************************************************************
- public void keyPressed(KeyEvent e) {
- }
- public void keyReleased(KeyEvent e) {
- }
- public void keyTyped(KeyEvent e) {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
if(e.getKeyChar()=='d') {
glWindow.setUndecorated(!glWindow.isUndecorated());
} if(e.getKeyChar()=='f') {
@@ -304,5 +306,9 @@ public class JOGLNewtAppletBase implements KeyListener, GLEventListener {
}
}
}
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
index 93c8409b1..42ebea722 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyAdapter.java
@@ -35,7 +35,5 @@ public abstract class KeyAdapter implements KeyListener
}
public void keyReleased(KeyEvent e) {
}
- public void keyTyped(KeyEvent e) {
- }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
index 6e63ad3a3..085f598dc 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyEvent.java
@@ -43,9 +43,8 @@ import com.jogamp.common.util.IntBitfield;
* <p>
* <table border="0">
* <tr><th>#</th><th>Event Type</th> <th>Constraints</th> <th>Notes</th></tr>
- * <tr><td>1</td><td>{@link #EVENT_KEY_PRESSED} </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys</i></td><td></td></tr>
- * <tr><td>2</td><td>{@link #EVENT_KEY_RELEASED} </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys</i></td><td></td></tr>
- * <tr><td>3</td><td>{@link #EVENT_KEY_TYPED} </td><td> <i>only for {@link #isPrintableKey() printable} and non {@link #isAutoRepeat() auto-repeat} keys</i></td><td><b>Deprecated</b>: Use {@link #EVENT_KEY_RELEASED} and apply constraints.</td></tr>
+ * <tr><td>1</td><td>{@link #EVENT_KEY_PRESSED} </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys</i></td><td></td></tr>
+ * <tr><td>2</td><td>{@link #EVENT_KEY_RELEASED} </td><td> <i> excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys</i></td><td></td></tr>
* </table>
* </p>
* In case the native platform does not
@@ -58,27 +57,24 @@ import com.jogamp.common.util.IntBitfield;
* <p>
* Auto-Repeat shall behave as follow:
* <pre>
- P = pressed, R = released, T = typed
+ P = pressed, R = released
0 = normal, 1 = auto-repeat
- P(0), [ R(1), P(1), R(1), ..], R(0) T(0)
+ P(0), [ R(1), P(1), R(1), ..], R(0)
* </pre>
* The idea is if you mask out auto-repeat in your event listener
- * or catch {@link #EVENT_KEY_TYPED typed} events only,
- * you just get one long pressed P/R/T triple for {@link #isPrintableKey() printable} keys.
- * {@link #isActionKey() Action} keys would produce one long pressed P/R tuple in case you mask out auto-repeat .
+ * you just get one long pressed P/R tuple for {@link #isPrintableKey() printable} and {@link #isActionKey() Action} keys.
* </p>
* <p>
* {@link #isActionKey() Action} keys will produce {@link #EVENT_KEY_PRESSED pressed}
* and {@link #EVENT_KEY_RELEASED released} events including {@link #isAutoRepeat() auto-repeat}.
* </p>
* <p>
- * {@link #isPrintableKey() Printable} keys will produce {@link #EVENT_KEY_PRESSED pressed},
- * {@link #EVENT_KEY_RELEASED released} and {@link #EVENT_KEY_TYPED typed} events, the latter is excluded for {@link #isAutoRepeat() auto-repeat} events.
+ * {@link #isPrintableKey() Printable} keys will produce {@link #EVENT_KEY_PRESSED pressed} and {@link #EVENT_KEY_RELEASED released} events.
* </p>
* <p>
- * {@link #isModifierKey() Modifier} keys will produce {@link #EVENT_KEY_PRESSED pressed}
- * and {@link #EVENT_KEY_RELEASED released} events excluding {@link #isAutoRepeat() auto-repeat}.
+ * {@link #isModifierKey() Modifier} keys will produce {@link #EVENT_KEY_PRESSED pressed} and {@link #EVENT_KEY_RELEASED released} events
+ * excluding {@link #isAutoRepeat() auto-repeat}.
* They will also influence subsequent event's {@link #getModifiers() modifier} bits while pressed.
* </p>
*
@@ -217,7 +213,6 @@ public class KeyEvent extends InputEvent
switch(type) {
case EVENT_KEY_PRESSED: return "EVENT_KEY_PRESSED";
case EVENT_KEY_RELEASED: return "EVENT_KEY_RELEASED";
- case EVENT_KEY_TYPED: return "EVENT_KEY_TYPED";
default: return "unknown (" + type + ")";
}
}
@@ -317,13 +312,13 @@ public class KeyEvent extends InputEvent
* @param isKeyChar true if <code>uniChar</code> is a key character, otherwise a virtual key code
*/
public static boolean isPrintableKey(final short uniChar, final boolean isKeyChar) {
- if( VK_UNDEFINED == uniChar ) {
- return false;
+ if ( VK_BACK_SPACE == uniChar || VK_TAB == uniChar || VK_ENTER == uniChar ) {
+ return true;
}
if( !isKeyChar ) {
if( ( nonPrintableKeys[0].min <= uniChar && uniChar <= nonPrintableKeys[0].max ) ||
( nonPrintableKeys[1].min <= uniChar && uniChar <= nonPrintableKeys[1].max ) ||
- ( nonPrintableKeys[2].min <= uniChar && uniChar <= nonPrintableKeys[2].max ) ||
+ ( nonPrintableKeys[2].min <= uniChar && uniChar <= nonPrintableKeys[2].max ) ||
( nonPrintableKeys[3].min <= uniChar && uniChar <= nonPrintableKeys[3].max ) ) {
return false;
}
@@ -335,7 +330,7 @@ public class KeyEvent extends InputEvent
return false;
}
}
- return true;
+ return VK_UNDEFINED != uniChar;
}
/**
@@ -361,15 +356,10 @@ public class KeyEvent extends InputEvent
private static final byte F_ACTION_MASK = 1 << 1;
private static final byte F_PRINTABLE_MASK = 1 << 2;
- /** A key has been pressed, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. */
+ /** A key has been pressed, excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys. */
public static final short EVENT_KEY_PRESSED = 300;
- /** A key has been released, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. */
+ /** A key has been released, excluding {@link #isAutoRepeat() auto-repeat}-{@link #isModifierKey() modifier} keys. */
public static final short EVENT_KEY_RELEASED= 301;
- /**
- * A {@link #isPrintableKey() printable} key has been typed (pressed and released), excluding {@link #isAutoRepeat() auto-repeat}.
- * @deprecated Redundant, will be removed soon. Use {@link #EVENT_KEY_RELEASED} and exclude non {@link #isPrintableKey() printable} keys and {@link #isAutoRepeat() auto-repeat}.
- */
- public static final short EVENT_KEY_TYPED = 302;
/**
* This value, {@code '\0'}, is used to indicate that the keyChar is unknown or not printable.
@@ -391,9 +381,19 @@ public class KeyEvent extends InputEvent
this.inclKeyChar = inclKeyChar;
}
};
- /** Non printable key ranges, currently fixed to an array of size 4. */
+ /**
+ * Non printable key ranges, currently fixed to an array of size 4.
+ * <p>
+ * Not included, queried upfront:
+ * <ul>
+ * <li>{@link #VK_BACK_SPACE}</li>
+ * <li>{@link #VK_TAB}</li>
+ * <li>{@link #VK_ENTER}</li>
+ * </ul>
+ * </p>
+ */
public final static NonPrintableRange[] nonPrintableKeys = {
- new NonPrintableRange( (short)0x0000, (short)0x001F, true ), // Unicode: Non printable controls: [0x00 - 0x1F]
+ new NonPrintableRange( (short)0x0000, (short)0x001F, true ), // Unicode: Non printable controls: [0x00 - 0x1F], see exclusion above
new NonPrintableRange( (short)0x0061, (short)0x0078, false), // Small 'a' thru 'z' (0x61 - 0x7a) - Not used for keyCode / keySym - Re-used for Fn (collision)
new NonPrintableRange( (short)0x008F, (short)0x009F, true ), // Unicode: Non printable controls: [0x7F - 0x9F], Numpad keys [0x7F - 0x8E] are printable!
new NonPrintableRange( (short)0xE000, (short)0xF8FF, true ) // Unicode: Private 0xE000 - 0xF8FF (Marked Non-Printable)
@@ -425,14 +425,14 @@ public class KeyEvent extends InputEvent
static final short VK_FREE06 = (short) 0x06;
static final short VK_FREE07 = (short) 0x07;
- /** Constant for the BACK SPACE key "\b", matching ASCII. */
+ /** Constant for the BACK SPACE key "\b", matching ASCII. Printable! */
public static final short VK_BACK_SPACE = (short) 0x08;
- /** Constant for the HORIZ TAB key "\t", matching ASCII. */
+ /** Constant for the HORIZ TAB key "\t", matching ASCII. Printable! */
public static final short VK_TAB = (short) 0x09;
- /** Constant for the ENTER key, i.e. LINE FEED "\n", matching ASCII. */
- public static final short VK_ENTER = (short) 0x0A;
+ /** LINE_FEED "\n", matching ASCII, n/a on keyboard. */
+ static final short VK_FREE0A = (short) 0x0A;
/** Constant for the PAGE DOWN function key. ASCII: Vertical Tabulation. */
public static final short VK_PAGE_DOWN = (short) 0x0B;
@@ -440,7 +440,9 @@ public class KeyEvent extends InputEvent
/** Constant for the CLEAR key, i.e. FORM FEED, matching ASCII. */
public static final short VK_CLEAR = (short) 0x0C;
- static final short VK_FREE0D = (short) 0x0D;
+ /** Constant for the ENTER key, i.e. CARRIAGE RETURN, matching ASCII. Printable! */
+ public static final short VK_ENTER = (short) 0x0D;
+
static final short VK_FREE0E = (short) 0x0E;
/** Constant for the CTRL function key. ASCII: shift-in. */
diff --git a/src/newt/classes/com/jogamp/newt/event/KeyListener.java b/src/newt/classes/com/jogamp/newt/event/KeyListener.java
index 5bca733d3..b3927d81a 100644
--- a/src/newt/classes/com/jogamp/newt/event/KeyListener.java
+++ b/src/newt/classes/com/jogamp/newt/event/KeyListener.java
@@ -43,13 +43,19 @@ public interface KeyListener extends NEWTEventListener
{
/** A key has been {@link KeyEvent#EVENT_KEY_PRESSED pressed}, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. See {@link KeyEvent}. */
public void keyPressed(KeyEvent e);
- /** A key has been {@link KeyEvent#EVENT_KEY_RELEASED released}, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. See {@link KeyEvent}. */
- public void keyReleased(KeyEvent e);
/**
- * A {@link #isPrintableKey() printable} key has been {@link KeyEvent#EVENT_KEY_TYPED typed} (pressed and released), excluding {@link #isAutoRepeat() auto-repeat}. See {@link KeyEvent}.
- * @deprecated Redundant, will be removed soon. Use {@link #keyReleased(KeyEvent)} and exclude non {@link #isPrintableKey() printable} keys and {@link #isAutoRepeat() auto-repeat}.
- */
- public void keyTyped(KeyEvent e) ;
+ * A key has been {@link KeyEvent#EVENT_KEY_RELEASED released}, excluding {@link #isAutoRepeat() auto-repeat} {@link #isModifierKey() modifier} keys. See {@link KeyEvent}.
+ * <p>
+ * To simulated the removed <code>keyTyped(KeyEvent e)</code> semantics,
+ * simply apply the following constraints upfront and bail out if not matched, i.e.:
+ * <pre>
+ if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+ return;
+ }
+ * </pre>
+ * </p>
+ */
+ public void keyReleased(KeyEvent e);
}
diff --git a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
index 18c8285f7..93bbcc0b9 100644
--- a/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
+++ b/src/newt/classes/com/jogamp/newt/event/MouseEvent.java
@@ -252,33 +252,6 @@ public class MouseEvent extends InputEvent
}
/**
- * <i>Usually</i> a wheel rotation of <b>&gt; 0.0f is up</b>,
- * and <b>&lt; 0.0f is down</b>.
- * <p>
- * Usually a wheel rotations is considered a vertical scroll.<br/>
- * If {@link #isShiftDown()}, a wheel rotations is
- * considered a horizontal scroll, where <b>shift-up = left = &gt; 0.0f</b>,
- * and <b>shift-down = right = &lt; 0.0f</b>.
- * </p>
- * <p>
- * <i>However</i>, on some OS this might be flipped due to the OS <i>default</i> behavior.
- * The latter is true for OS X 10.7 (Lion) for example.
- * </p>
- * <p>
- * The events will be send usually in steps of one, ie. <i>-1.0f</i> and <i>1.0f</i>.
- * Higher values may result due to fast scrolling.
- * Fractional values may result due to slow scrolling with high resolution devices.
- * </p>
- * <p>
- * The button number refers to the wheel number.
- * </p>
- * @deprecated Use {@link #getRotation()}
- */
- public float getWheelRotation() {
- return isShiftDown() ? rotationXYZ[0] : rotationXYZ[1] ;
- }
-
- /**
* Returns a 3-component float array filled with the values of the rotational axis
* in the following order: horizontal-, vertical- and z-axis.
* <p>
diff --git a/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
index 98ba5a24d..629dc50d7 100644
--- a/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/TraceKeyAdapter.java
@@ -48,9 +48,5 @@ public class TraceKeyAdapter implements KeyListener {
System.err.println(e);
if(null!=downstream) { downstream.keyReleased(e); }
}
- public void keyTyped(KeyEvent e) {
- System.err.println(e);
- if(null!=downstream) { downstream.keyTyped(e); }
- }
}
diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
index 1edef347b..bef2e5d0f 100644
--- a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
+++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java
@@ -71,12 +71,11 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe
@Override
public void keyReleased(java.awt.event.KeyEvent e) {
- com.jogamp.newt.event.KeyEvent keyReleaseEvt = AWTNewtEventFactory.createKeyEvent(com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, e, newtWindow);
+ final com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED, e, newtWindow);
if(null!=newtListener) {
- final com.jogamp.newt.event.KeyListener newtKeyListener = (com.jogamp.newt.event.KeyListener)newtListener;
- newtKeyListener.keyReleased(keyReleaseEvt);
+ ((com.jogamp.newt.event.KeyListener)newtListener).keyReleased(event);
} else {
- enqueueEvent(false, keyReleaseEvt);
+ enqueueEvent(false, event);
}
}
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index 1500d48e6..e85d67dea 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -34,6 +34,8 @@
package com.jogamp.newt.opengl;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.List;
import javax.media.nativewindow.AbstractGraphicsConfiguration;
@@ -47,6 +49,8 @@ import javax.media.nativewindow.util.InsetsImmutable;
import javax.media.nativewindow.util.Point;
import javax.media.opengl.FPSCounter;
import javax.media.opengl.GL;
+import javax.media.opengl.GL3;
+import javax.media.opengl.GL4ES3;
import javax.media.opengl.GLAnimatorControl;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
@@ -54,6 +58,8 @@ import javax.media.opengl.GLCapabilitiesImmutable;
import javax.media.opengl.GLContext;
import javax.media.opengl.GLDrawable;
import javax.media.opengl.GLDrawableFactory;
+import javax.media.opengl.GLES2;
+import javax.media.opengl.GLES3;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLProfile;
@@ -79,11 +85,16 @@ import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.WindowUpdateEvent;
import com.jogamp.opengl.JoglVersion;
+import com.jogamp.opengl.GLStateKeeper;
/**
* An implementation of {@link GLAutoDrawable} and {@link Window} interface,
* using a delegated {@link Window} instance, which may be an aggregation (lifecycle: created and destroyed).
* <P>
+ * This implementation supports {@link GLStateKeeper GL state preservation},
+ * hence {@link #isGLStatePreservationSupported()} returns <code>true</code>.
+ * </P>
+ * <P>
* This implementation does not make the OpenGL context current<br>
* before calling the various input EventListener callbacks, ie {@link com.jogamp.newt.event.MouseListener} etc.<br>
* This design decision is made in favor of a more performant and simplified
@@ -433,8 +444,8 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
protected class GLLifecycleHook implements WindowImpl.LifecycleHook {
@Override
- public void preserveGLStateAtDestroy() {
- GLWindow.this.preserveGLStateAtDestroy(true);
+ public void preserveGLStateAtDestroy(boolean value) {
+ GLWindow.this.preserveGLStateAtDestroy(value);
}
@Override
@@ -524,6 +535,29 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
savedAnimator.resume();
}
}
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void shutdownRenderingAction() {
+ final GLAnimatorControl anim = GLWindow.this.getAnimator();
+ if ( null != anim && anim.isAnimating() ) {
+ final Thread animThread = anim.getThread();
+ if( animThread == Thread.currentThread() ) {
+ anim.stop(); // on anim thread, non-blocking
+ } else {
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ if( anim.isAnimating() && null != animThread ) {
+ try {
+ animThread.stop();
+ } catch(Throwable t) {
+ }
+ }
+ return null;
+ } } );
+ }
+ }
+ }
}
//----------------------------------------------------------------------
@@ -579,6 +613,12 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
}
}
+ /**
+ * {@inheritDoc}
+ * <p>
+ * GLWindow supports GL state preservation, hence returns <code>true</code>.
+ * </p>
+ */
@Override
public final boolean isGLStatePreservationSupported() { return true; }
@@ -794,14 +834,58 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
* A most simple JOGL AWT test entry
*/
public static void main(String args[]) {
+ final boolean forceES2;
+ final boolean forceES3;
+ final boolean forceGL3;
+ final boolean forceGL4ES3;
+ {
+ boolean _forceES2 = false;
+ boolean _forceES3 = false;
+ boolean _forceGL3 = false;
+ boolean _forceGL4ES3 = false;
+ if( null != args ) {
+ for(int i=0; i<args.length; i++) {
+ if(args[i].equals("-es2")) {
+ _forceES2 = true;
+ } else if(args[i].equals("-es3")) {
+ _forceES3 = true;
+ } else if(args[i].equals("-gl3")) {
+ _forceGL3 = true;
+ } else if(args[i].equals("-gl4es3")) {
+ _forceGL4ES3 = true;
+ }
+ }
+ }
+ forceES2 = _forceES2;
+ forceES3 = _forceES3;
+ forceGL3 = _forceGL3;
+ forceGL4ES3 = _forceGL4ES3;
+ }
+ System.err.println("forceES2 "+forceES2);
+ System.err.println("forceES3 "+forceES3);
+ System.err.println("forceGL3 "+forceGL3);
+ System.err.println("forceGL4ES3 "+forceGL4ES3);
+
System.err.println(VersionUtil.getPlatformInfo());
System.err.println(GlueGenVersion.getInstance());
System.err.println(JoglVersion.getInstance());
System.err.println(JoglVersion.getDefaultOpenGLInfo(null, null, true).toString());
- final GLProfile glp = GLProfile.getDefault();
+ final GLProfile glp;
+ if(forceGL4ES3) {
+ glp = GLProfile.get(GLProfile.GL4ES3);
+ } else if(forceGL3) {
+ glp = GLProfile.get(GLProfile.GL3);
+ } else if(forceES3) {
+ glp = GLProfile.get(GLProfile.GLES3);
+ } else if(forceES2) {
+ glp = GLProfile.get(GLProfile.GLES2);
+ } else {
+ glp = GLProfile.getDefault();
+ }
final GLCapabilitiesImmutable caps = new GLCapabilities( glp );
+ System.err.println("Requesting: "+caps);
GLWindow glWindow = GLWindow.create(caps);
glWindow.setSize(128, 128);
@@ -813,6 +897,23 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
System.err.println(JoglVersion.getGLInfo(gl, null));
System.err.println("Requested: "+drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities());
System.err.println("Chosen : "+drawable.getChosenGLCapabilities());
+ System.err.println("GL impl. class "+gl.getClass().getName());
+ if( gl.isGL4ES3() ) {
+ GL4ES3 _gl = gl.getGL4ES3();
+ System.err.println("GL4ES3 retrieved, impl. class "+_gl.getClass().getName());
+ }
+ if( gl.isGL3() ) {
+ GL3 _gl = gl.getGL3();
+ System.err.println("GL3 retrieved, impl. class "+_gl.getClass().getName());
+ }
+ if( gl.isGLES3() ) {
+ GLES3 _gl = gl.getGLES3();
+ System.err.println("GLES3 retrieved, impl. class "+_gl.getClass().getName());
+ }
+ if( gl.isGLES2() ) {
+ GLES2 _gl = gl.getGLES2();
+ System.err.println("GLES2 retrieved, impl. class "+_gl.getClass().getName());
+ }
}
@Override
diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
index dbe7c0d98..47dfca0f3 100644
--- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
+++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java
@@ -345,7 +345,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol {
// set SWT EDT and start it
{
final Display newtDisplay = newtChild.getScreen().getDisplay();
- newtDisplay.setEDTUtil( new SWTEDTUtil(newtDisplay, getDisplay()) );
+ final EDTUtil edtUtil = new SWTEDTUtil(newtDisplay, getDisplay());
+ edtUtil.restart();
+ newtDisplay.setEDTUtil( edtUtil );
}
newtChild.setSize(w, h);
diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
index 0183da592..e86df2084 100644
--- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
+++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java
@@ -65,14 +65,19 @@ public interface EDTUtil {
public void setPollPeriod(long ms);
/**
- * Create a new EDT. One should invoke <code>reset()</code><br>
- * after <code>invokeStop(..)</code> in case another start via <code>invoke(..)</code>
- * is expected.
- *
- * @see #invoke(boolean, java.lang.Runnable)
- * @see #invokeStop(java.lang.Runnable)
+ * Starts or restarts the EDT.
+ * <p>
+ * If the EDT is running, it must be stopped first via {@link #invokeStop(boolean, Runnable)}
+ * and the caller should wait until it's stopped via {@link #waitUntilStopped()}.
+ * </p>
+ *
+ * @return true if EDT has been successfully restarted, otherwise false
+ * @throws IllegalStateException if EDT is running and not subject to be stopped, i.e. {@link #isRunning()} returns true
+ *
+ * @see #invokeStop(boolean, java.lang.Runnable)
+ * @see #waitUntilStopped()
*/
- public void reset();
+ public boolean restart() throws IllegalStateException;
/**
* Returns true if the current thread is the event dispatch thread (EDT).
@@ -107,44 +112,57 @@ public interface EDTUtil {
public boolean isCurrentThreadEDTorNEDT();
/**
- * @return True if EDT is running
+ * @return True if EDT is running and not subject to be stopped.
*/
public boolean isRunning();
/**
* Append the final task to the EDT task queue,
- * signals EDT to stop and wait until stopped.<br/>
+ * signals EDT to stop.
+ * <p>
+ * If <code>wait</code> is <code>true</code> methods
+ * blocks until EDT is stopped.
+ * </p>
+ * <p>
* <code>task</code> maybe <code>null</code><br/>
* Due to the nature of this method:
* <ul>
* <li>All previous queued tasks will be finished.</li>
* <li>No new tasks are allowed, an Exception is thrown.</li>
* <li>Can be issued from within EDT, ie from within an enqueued task.</li>
- * <li>{@link #reset()} may follow immediately, ie creating a new EDT</li>
+ * <li>{@link #restart()} may follow immediately, ie creating a new EDT</li>
* </ul>
+ * </p>
+ * @return true if <code>task</code> has been executed or queued for later execution, otherwise false
*/
- public void invokeStop(Runnable finalTask);
+ public boolean invokeStop(boolean wait, Runnable finalTask);
/**
- * Shall start the thread if not running, <code>task</code> maybe null for this purpose.<br>
- * Append task to the EDT task queue.<br>
- * Wait until execution is finished if <code>wait == true</code>.<br>
+ * Appends task to the EDT task queue if current thread is not EDT,
+ * otherwise execute task immediately.
+ * <p>
+ * Wait until execution is finished if <code>wait == true</code>.
+ * </p>
* Can be issued from within EDT, ie from within an enqueued task.<br>
- *
- * @throws RuntimeException in case EDT is stopped and not {@link #reset()}
+ * @return true if <code>task</code> has been executed or queued for later execution, otherwise false
*/
- public void invoke(boolean wait, Runnable task);
+ public boolean invoke(boolean wait, Runnable task);
/**
* Wait until the EDT task queue is empty.<br>
* The last task may still be in execution when this method returns.
+ * @return true if waited for idle, otherwise false, i.e. in case of current thread is EDT or NEDT
*/
- public void waitUntilIdle();
+ public boolean waitUntilIdle();
/**
* Wait until EDT task is stopped.<br>
- * No <code>stop</code> action is performed, {@link #invokeStop(java.lang.Runnable)} should be used before.
+ * No <code>stop</code> action is performed, {@link #invokeStop(boolean, java.lang.Runnable)} should be used before.
+ * <p>
+ * If caller thread is EDT or NEDT, this call will not block.
+ * </p>
+ * @return true if stopped, otherwise false, i.e. in case of current thread is EDT or NEDT
*/
- public void waitUntilStopped();
+ public boolean waitUntilStopped();
}
diff --git a/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java
index 16ffe754f..c30b427d6 100644
--- a/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java
+++ b/src/newt/classes/com/jogamp/newt/util/MonitorModeUtil.java
@@ -31,7 +31,9 @@ package com.jogamp.newt.util;
import com.jogamp.newt.MonitorMode;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
+
import javax.media.nativewindow.util.DimensionImmutable;
import javax.media.nativewindow.util.SurfaceSize;
@@ -68,6 +70,15 @@ public class MonitorModeUtil {
return null;
}
+ /** Sort the given {@link MonitorMode} collection w/ {@link MonitorMode#compareTo(MonitorMode)} function. */
+ public static void sort(List<MonitorMode> monitorModes, boolean ascendingOrder) {
+ if( ascendingOrder ) {
+ Collections.sort(monitorModes);
+ } else {
+ Collections.sort(monitorModes, MonitorMode.monitorModeComparatorInv);
+ }
+ }
+
/**
*
* @param monitorModes