summaryrefslogtreecommitdiffstats
path: root/src/newt/classes
diff options
context:
space:
mode:
authorPetr Skramovsky <[email protected]>2013-07-17 09:20:46 +0200
committerPetr Skramovsky <[email protected]>2013-07-17 09:20:46 +0200
commit9fce91044649c9f97bd94c5791a10270afad7570 (patch)
treea69fa244ddeb78e52248d4306a4ecc6b27e924da /src/newt/classes
parent5116d72f0150bdd6353ee664ef76e414bd61f87e (diff)
parentbfb10d309d97c19a33f9b6758f647186f8e0ddd6 (diff)
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src/newt/classes')
-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
-rw-r--r--src/newt/classes/jogamp/newt/Debug.java34
-rw-r--r--src/newt/classes/jogamp/newt/DefaultEDTUtil.java115
-rw-r--r--src/newt/classes/jogamp/newt/DisplayImpl.java199
-rw-r--r--src/newt/classes/jogamp/newt/MonitorDeviceImpl.java12
-rw-r--r--src/newt/classes/jogamp/newt/ScreenImpl.java99
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java269
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java135
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java4
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java4
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java2
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java13
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java10
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR.java12
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR11.java26
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/RandR13.java63
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java61
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java73
-rw-r--r--src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java170
-rw-r--r--src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java1
44 files changed, 1310 insertions, 676 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
diff --git a/src/newt/classes/jogamp/newt/Debug.java b/src/newt/classes/jogamp/newt/Debug.java
index 3c83da4d9..4b0a98216 100644
--- a/src/newt/classes/jogamp/newt/Debug.java
+++ b/src/newt/classes/jogamp/newt/Debug.java
@@ -1,5 +1,6 @@
/*
- * Copyright (c) 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright (c) 2010 JogAmp Community. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -39,6 +40,9 @@
package jogamp.newt;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
import com.jogamp.common.util.PropertyAccess;
/** Helper routines for logging and debugging. */
@@ -49,7 +53,12 @@ public class Debug extends PropertyAccess {
private static final boolean debugAll;
static {
- PropertyAccess.addTrustedPrefix("newt.", Debug.class);
+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
+ public Object run() {
+ PropertyAccess.addTrustedPrefix("newt.");
+ return null;
+ } } );
+
verbose = isPropertyDefined("newt.verbose", true);
debugAll = isPropertyDefined("newt.debug", true);
if (verbose) {
@@ -60,27 +69,18 @@ public class Debug extends PropertyAccess {
}
}
- public static final boolean isPropertyDefined(final String property, final boolean jnlpAlias) {
- return PropertyAccess.isPropertyDefined(property, jnlpAlias, null);
- }
-
- public static final int getIntProperty(final String property, final boolean jnlpAlias, int defaultValue) {
- return PropertyAccess.getIntProperty(property, jnlpAlias, null, defaultValue);
- }
-
- public static final boolean getBooleanProperty(final String property, final boolean jnlpAlias) {
- return PropertyAccess.getBooleanProperty(property, jnlpAlias, null);
- }
-
- public static boolean verbose() {
+ /** Ensures static init block has been issues, i.e. if calling through to {@link PropertyAccess#isPropertyDefined(String, boolean)}. */
+ public static final void initSingleton() {}
+
+ public static final boolean verbose() {
return verbose;
}
- public static boolean debugAll() {
+ public static final boolean debugAll() {
return debugAll;
}
- public static boolean debug(String subcomponent) {
+ public static final boolean debug(String subcomponent) {
return debugAll() || isPropertyDefined("newt.debug." + subcomponent, true);
}
}
diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
index 651522799..a229a0512 100644
--- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java
@@ -53,7 +53,7 @@ public class DefaultEDTUtil implements EDTUtil {
private final ThreadGroup threadGroup;
private final String name;
private final Runnable dispatchMessages;
- private EventDispatchThread edt = null;
+ private NEDT edt = null;
private int start_iter=0;
private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
@@ -61,7 +61,7 @@ public class DefaultEDTUtil implements EDTUtil {
this.threadGroup = tg;
this.name=Thread.currentThread().getName()+"-"+name+"-EDT-";
this.dispatchMessages=dispatchMessages;
- this.edt = new EventDispatchThread(threadGroup, name);
+ this.edt = new NEDT(threadGroup, name);
this.edt.setDaemon(true); // don't stop JVM from shutdown ..
}
@@ -76,31 +76,34 @@ public class DefaultEDTUtil implements EDTUtil {
}
@Override
- public final void reset() {
- synchronized(edtLock) {
- waitUntilStopped();
+ public final boolean restart() throws IllegalStateException {
+ synchronized(edtLock) {
+ if( edt.isRunning() ) {
+ throw new IllegalStateException("EDT still running and not subject to stop. Curr "+Thread.currentThread().getName()+", EDT "+edt.getName()+", isRunning "+edt.isRunning+", shouldStop "+edt.shouldStop);
+ }
if(DEBUG) {
if(edt.tasks.size()>0) {
System.err.println(Thread.currentThread()+": Default-EDT reset, remaining tasks: "+edt.tasks.size()+" - "+edt);
- // Thread.dumpStack();
}
System.err.println(Thread.currentThread()+": Default-EDT reset - edt: "+edt);
}
- this.edt = new EventDispatchThread(threadGroup, name);
- this.edt.setDaemon(true); // don't stop JVM from shutdown ..
+ if( edt.getState() != Thread.State.NEW ) {
+ edt = new NEDT(threadGroup, name);
+ edt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+ startImpl();
}
+ return invoke(true, nullTask);
}
private final void startImpl() {
if(edt.isAlive()) {
- throw new RuntimeException("Default-EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size());
+ throw new RuntimeException("Default-EDT Thread.isAlive(): true, isRunning: "+edt.isRunning+", shouldStop "+edt.shouldStop+", edt: "+edt+", tasks: "+edt.tasks.size());
}
start_iter++;
edt.setName(name+start_iter);
- edt.shouldStop = false;
if(DEBUG) {
System.err.println(Thread.currentThread()+": Default-EDT START - edt: "+edt);
- // Thread.dumpStack();
}
edt.start();
}
@@ -126,13 +129,13 @@ public class DefaultEDTUtil implements EDTUtil {
}
@Override
- public final void invokeStop(Runnable task) {
- invokeImpl(true, task, true);
+ public final boolean invokeStop(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, true);
}
@Override
- public final void invoke(boolean wait, Runnable task) {
- invokeImpl(wait, task, false);
+ public final boolean invoke(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, false);
}
private static Runnable nullTask = new Runnable() {
@@ -140,28 +143,26 @@ public class DefaultEDTUtil implements EDTUtil {
public void run() { }
};
- private void invokeImpl(boolean wait, Runnable task, boolean stop) {
+ private final boolean invokeImpl(boolean wait, Runnable task, boolean stop) {
Throwable throwable = null;
RunnableTask rTask = null;
- Object rTaskLock = new Object();
+ final Object rTaskLock = new Object();
synchronized(rTaskLock) { // lock the optional task execution
synchronized(edtLock) { // lock the EDT status
if( edt.shouldStop ) {
// drop task ..
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT about (1) to stop, won't enqueue new task: "+edt);
if(DEBUG) {
- System.err.println(Thread.currentThread()+": Warning: Default-EDT about (1) to stop, won't enqueue new task: "+edt);
Thread.dumpStack();
}
- return;
+ return false;
}
- // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
- // Thread.dumpStack();
if( isCurrentThreadEDT() ) {
if(null != task) {
task.run();
}
wait = false; // running in same thread (EDT) -> no wait
- if(stop) {
+ if( stop ) {
edt.shouldStop = true;
if( edt.tasks.size()>0 ) {
System.err.println(Thread.currentThread()+": Warning: Default-EDT about (2) to stop, task executed. Remaining tasks: "+edt.tasks.size()+" - "+edt);
@@ -171,19 +172,20 @@ public class DefaultEDTUtil implements EDTUtil {
}
}
} else {
- if( !edt.isRunning() ) {
- if( !stop ) {
- startImpl();
- } else {
- // drop task and don't wait
- task = null;
- System.err.println(Thread.currentThread()+": Warning: Default-EDT is about (3) to stop and stopped already, dropping task. Remaining tasks: "+edt.tasks.size()+" - "+edt);
+ if( !edt.isRunning ) {
+ if( null != task ) {
+ if( stop ) {
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT is about (3) to stop and stopped already, dropping task. Remaining tasks: "+edt.tasks.size()+" - "+edt);
+ } else {
+ System.err.println(Thread.currentThread()+": Warning: Default-EDT is not running, dropping task. NEDT "+edt);
+ }
if(DEBUG) {
Thread.dumpStack();
}
}
- } else if(stop && null == task) {
- task = nullTask;
+ return false;
+ } else if( stop && null == task ) {
+ task = nullTask; // ensures execution triggering stop
}
if(null != task) {
@@ -220,23 +222,26 @@ public class DefaultEDTUtil implements EDTUtil {
throw new RuntimeException(throwable);
}
}
- }
- if(DEBUG && stop) {
- System.err.println(Thread.currentThread()+": Default-EDT signal STOP X edt: "+edt);
+ if(DEBUG) {
+ if( stop) {
+ System.err.println(Thread.currentThread()+": Default-EDT signal STOP X edt: "+edt);
+ }
+ }
+ return true;
}
}
@Override
- final public void waitUntilIdle() {
- final EventDispatchThread _edt;
+ final public boolean waitUntilIdle() {
+ final NEDT _edt;
synchronized(edtLock) {
_edt = edt;
}
- if(!_edt.isRunning() || _edt == Thread.currentThread()) {
- return;
+ if(!_edt.isRunning || _edt == Thread.currentThread()) {
+ return false;
}
synchronized(_edt.tasks) {
- while(_edt.isRunning() && _edt.tasks.size()>0) {
+ while(_edt.isRunning && _edt.tasks.size()>0) {
try {
_edt.tasks.notifyAll();
_edt.tasks.wait();
@@ -244,35 +249,39 @@ public class DefaultEDTUtil implements EDTUtil {
e.printStackTrace();
}
}
+ return true;
}
}
@Override
- final public void waitUntilStopped() {
+ final public boolean waitUntilStopped() {
synchronized(edtLock) {
- if(edt.isRunning() && edt != Thread.currentThread() ) {
- while(edt.isRunning()) {
+ if(edt.isRunning && edt != Thread.currentThread() ) {
+ while( edt.isRunning ) {
try {
edtLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
+ return true;
+ } else {
+ return false;
}
}
}
- class EventDispatchThread extends Thread {
+ class NEDT extends Thread {
volatile boolean shouldStop = false;
volatile boolean isRunning = false;
ArrayList<RunnableTask> tasks = new ArrayList<RunnableTask>(); // one shot tasks
- public EventDispatchThread(ThreadGroup tg, String name) {
+ public NEDT(ThreadGroup tg, String name) {
super(tg, name);
}
final public boolean isRunning() {
- return isRunning;
+ return isRunning && !shouldStop;
}
@Override
@@ -282,11 +291,9 @@ public class DefaultEDTUtil implements EDTUtil {
}
private final void validateNoRecursiveLocksHold() {
- if(Lock.DEBUG) {
- if(LockDebugUtil.getRecursiveLockTrace().size()>0) {
- LockDebugUtil.dumpRecursiveLockTrace(System.err);
- throw new InternalError("XXX");
- }
+ if(LockDebugUtil.getRecursiveLockTrace().size()>0) {
+ LockDebugUtil.dumpRecursiveLockTrace(System.err);
+ throw new InternalError("XXX");
}
}
@@ -299,7 +306,9 @@ public class DefaultEDTUtil implements EDTUtil {
if(DEBUG) {
System.err.println(getName()+": Default-EDT run() START "+ getName());
}
- validateNoRecursiveLocksHold();
+ if(Lock.DEBUG) {
+ validateNoRecursiveLocksHold();
+ }
RuntimeException error = null;
try {
do {
@@ -329,7 +338,9 @@ public class DefaultEDTUtil implements EDTUtil {
}
if(null!=task) {
task.run();
- validateNoRecursiveLocksHold();
+ if(Lock.DEBUG) {
+ validateNoRecursiveLocksHold();
+ }
if(!task.hasWaiter() && null != task.getThrowable()) {
// at least dump stack-trace in case nobody waits for result
System.err.println("DefaultEDT.run(): Catched exception occured on thread "+Thread.currentThread().getName()+": "+task.toString());
diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java
index d4842ba2f..8f792b23c 100644
--- a/src/newt/classes/jogamp/newt/DisplayImpl.java
+++ b/src/newt/classes/jogamp/newt/DisplayImpl.java
@@ -41,14 +41,29 @@ import com.jogamp.newt.event.NEWTEventConsumer;
import jogamp.newt.event.NEWTEventTask;
import com.jogamp.newt.util.EDTUtil;
+
import java.util.ArrayList;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.NativeWindowException;
+import javax.media.nativewindow.NativeWindowFactory;
public abstract class DisplayImpl extends Display {
private static int serialno = 1;
+ static {
+ NativeWindowFactory.addCustomShutdownHook(true /* head */, new Runnable() {
+ public void run() {
+ WindowImpl.shutdownAll();
+ ScreenImpl.shutdownAll();
+ DisplayImpl.shutdownAll();
+ }
+ });
+ }
+
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
+
private static Class<?> getDisplayClass(String type)
throws ClassNotFoundException
{
@@ -62,12 +77,12 @@ public abstract class DisplayImpl extends Display {
/** Make sure to reuse a Display with the same name */
public static Display create(String type, String name, final long handle, boolean reuse) {
try {
- Class<?> displayClass = getDisplayClass(type);
- DisplayImpl display = (DisplayImpl) displayClass.newInstance();
+ final Class<?> displayClass = getDisplayClass(type);
+ final DisplayImpl display = (DisplayImpl) displayClass.newInstance();
name = display.validateDisplayName(name, handle);
synchronized(displayList) {
if(reuse) {
- Display display0 = Display.getLastDisplayOf(type, name, -1, true /* shared only */);
+ final Display display0 = Display.getLastDisplayOf(type, name, -1, true /* shared only */);
if(null != display0) {
if(DEBUG) {
System.err.println("Display.create() REUSE: "+display0+" "+getThreadName());
@@ -82,9 +97,9 @@ public abstract class DisplayImpl extends Display {
display.id = serialno++;
display.fqname = getFQName(display.type, display.name, display.id);
display.hashCode = display.fqname.hashCode();
- displayList.add(display);
+ display.setEDTUtil( display.edtUtil ); // device's default if EDT is used, or null
+ Display.addDisplay2List(display);
}
- display.setEDTUtil(display.edtUtil); // device's default if EDT is used, or null
if(DEBUG) {
System.err.println("Display.create() NEW: "+display+" "+getThreadName());
@@ -122,10 +137,10 @@ public abstract class DisplayImpl extends Display {
}
@Override
- public synchronized final void createNative()
+ public synchronized final void createNative()
throws NativeWindowException
{
- if(null==aDevice) {
+ if( null == aDevice ) {
if(DEBUG) {
System.err.println("Display.createNative() START ("+getThreadName()+", "+this+")");
}
@@ -138,14 +153,14 @@ public abstract class DisplayImpl extends Display {
} catch (Throwable t) {
throw new NativeWindowException(t);
}
- if(null==aDevice) {
+ if( null == aDevice ) {
throw new NativeWindowException("Display.createNative() failed to instanciate an AbstractGraphicsDevice");
}
- if(DEBUG) {
- System.err.println("Display.createNative() END ("+getThreadName()+", "+this+")");
- }
synchronized(displayList) {
displaysActive++;
+ if(DEBUG) {
+ System.err.println("Display.createNative() END ("+getThreadName()+", "+this+", active "+displaysActive+")");
+ }
}
}
}
@@ -164,25 +179,23 @@ public abstract class DisplayImpl extends Display {
}
@Override
- public EDTUtil setEDTUtil(EDTUtil newEDTUtil) {
+ public synchronized EDTUtil setEDTUtil(final EDTUtil usrEDTUtil) {
final EDTUtil oldEDTUtil = edtUtil;
- if(null == newEDTUtil) {
- if(DEBUG) {
- System.err.println("Display.setEDTUtil(default): "+oldEDTUtil+" -> "+newEDTUtil);
+ final EDTUtil newEDTUtil;
+ if( null != usrEDTUtil && usrEDTUtil == oldEDTUtil ) {
+ if( DEBUG ) {
+ System.err.println("Display.setEDTUtil: "+usrEDTUtil+" - keep!");
}
- edtUtil = createEDTUtil();
- } else if( newEDTUtil != edtUtil ) {
+ newEDTUtil = oldEDTUtil;
+ } else {
if(DEBUG) {
- System.err.println("Display.setEDTUtil(custom): "+oldEDTUtil+" -> "+newEDTUtil);
+ final String msg = ( null == usrEDTUtil ) ? "default" : "custom";
+ System.err.println("Display.setEDTUtil("+msg+"): "+oldEDTUtil+" -> "+usrEDTUtil);
}
- removeEDT( null );
- edtUtil = newEDTUtil;
- } else if( DEBUG ) {
- System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!");
- }
- if( !edtUtil.isRunning() ) { // start EDT if not running yet
- edtUtil.invoke(true, null);
+ stopEDT( oldEDTUtil, null );
+ newEDTUtil = ( null == usrEDTUtil ) ? createEDTUtil() : usrEDTUtil;
}
+ edtUtil = newEDTUtil;
return oldEDTUtil;
}
@@ -191,29 +204,61 @@ public abstract class DisplayImpl extends Display {
return edtUtil;
}
- private void removeEDT(final Runnable task) {
- if(null!=edtUtil) {
- edtUtil.invokeStop(task);
- // ready for restart ..
+ private static void stopEDT(final EDTUtil edtUtil, final Runnable task) {
+ if( null != edtUtil ) {
+ if( edtUtil.isRunning() ) {
+ final boolean res = edtUtil.invokeStop(true, task);
+ if( DEBUG ) {
+ if ( !res ) {
+ System.err.println("Warning: invokeStop() failed");
+ Thread.dumpStack();
+ }
+ }
+ }
edtUtil.waitUntilStopped();
- edtUtil.reset();
- } else {
+ // ready for restart ..
+ } else if( null != task ) {
task.run();
}
}
public void runOnEDTIfAvail(boolean wait, final Runnable task) {
- if( null!=edtUtil && !edtUtil.isCurrentThreadEDT()) {
- edtUtil.invoke(wait, task);
+ final EDTUtil _edtUtil = edtUtil;
+ if( null != _edtUtil && !_edtUtil.isCurrentThreadEDT() ) {
+ if( !_edtUtil.isRunning() ) { // start EDT if not running yet
+ synchronized( this ) {
+ if( !_edtUtil.isRunning() ) { // // volatile dbl-checked-locking OK
+ _edtUtil.restart();
+ if( DEBUG ) {
+ System.err.println("Info: EDT started "+Thread.currentThread().getName()+", "+this);
+ Thread.dumpStack();
+ }
+ }
+ }
+ }
+ if( !_edtUtil.invoke(wait, task) ) {
+ if( DEBUG ) {
+ System.err.println("Warning: invoke(wait "+wait+", ..) on EDT failed .. invoke on current thread "+Thread.currentThread().getName());
+ Thread.dumpStack();
+ }
+ task.run();
+ }
} else {
task.run();
}
}
public boolean validateEDT() {
- if(0==refCount && null==aDevice && null != edtUtil && edtUtil.isRunning()) {
- removeEDT( null );
- return true;
+ if( 0==refCount && null == aDevice ) {
+ final EDTUtil _edtUtil = edtUtil;
+ if( null != _edtUtil && _edtUtil.isRunning() ) {
+ synchronized( this ) {
+ if( null != edtUtil && edtUtil.isRunning() ) { // // volatile dbl-checked-locking OK
+ stopEDT( edtUtil, null );
+ return true;
+ }
+ }
+ }
}
return false;
}
@@ -224,29 +269,69 @@ public abstract class DisplayImpl extends Display {
dumpDisplayList("Display.destroy("+getFQName()+") BEGIN");
}
synchronized(displayList) {
- displayList.remove(this);
if(0 < displaysActive) {
displaysActive--;
}
- }
- if(DEBUG) {
- System.err.println("Display.destroy(): "+this+" "+getThreadName());
- }
- final AbstractGraphicsDevice f_aDevice = aDevice;
+ if(DEBUG) {
+ System.err.println("Display.destroy(): "+this+", active "+displaysActive+" "+getThreadName());
+ }
+ }
final DisplayImpl f_dpy = this;
- removeEDT( new Runnable() {
+ final AbstractGraphicsDevice f_aDevice = aDevice;
+ aDevice = null;
+ refCount=0;
+ stopEDT( edtUtil, new Runnable() { // blocks!
public void run() {
if ( null != f_aDevice ) {
- f_dpy.closeNativeImpl();
+ f_dpy.closeNativeImpl(f_aDevice);
}
}
} );
- aDevice = null;
- refCount=0;
if(DEBUG) {
dumpDisplayList("Display.destroy("+getFQName()+") END");
}
}
+
+ /** May be utilized at a shutdown hook, impl. does not block. */
+ /* pp */ static final void shutdownAll() {
+ final int dCount = displayList.size();
+ if(DEBUG) {
+ dumpDisplayList("Display.shutdownAll "+dCount+" instances, on thread "+getThreadName());
+ }
+ for(int i=0; i<dCount && displayList.size()>0; i++) { // be safe ..
+ final DisplayImpl d = (DisplayImpl) displayList.remove(0).get();
+ if(DEBUG) {
+ System.err.println("Display.shutdownAll["+(i+1)+"/"+dCount+"]: "+d+", GCed "+(null==d));
+ }
+ if( null != d ) { // GC'ed ?
+ if(0 < displaysActive) {
+ displaysActive--;
+ }
+ final EDTUtil edtUtil = d.getEDTUtil();
+ final AbstractGraphicsDevice f_aDevice = d.aDevice;
+ d.aDevice = null;
+ d.refCount=0;
+ final Runnable closeNativeTask = new Runnable() {
+ public void run() {
+ if ( null != d.getGraphicsDevice() ) {
+ d.closeNativeImpl(f_aDevice);
+ }
+ }
+ };
+ if(null != edtUtil) {
+ final long coopSleep = edtUtil.getPollPeriod() * 2;
+ if( edtUtil.isRunning() ) {
+ edtUtil.invokeStop(false, closeNativeTask); // don't block
+ }
+ try {
+ Thread.sleep( coopSleep < 50 ? coopSleep : 50 );
+ } catch (InterruptedException e) { }
+ } else {
+ closeNativeTask.run();
+ }
+ }
+ }
+ }
public synchronized final int addReference() {
if(DEBUG) {
@@ -279,7 +364,7 @@ public abstract class DisplayImpl extends Display {
}
protected abstract void createNativeImpl();
- protected abstract void closeNativeImpl();
+ protected abstract void closeNativeImpl(AbstractGraphicsDevice aDevice);
@Override
public final int getId() {
@@ -347,15 +432,18 @@ public abstract class DisplayImpl extends Display {
@Override
public boolean isEDTRunning() {
- if(null!=edtUtil) {
- return edtUtil.isRunning();
+ final EDTUtil _edtUtil = edtUtil;
+ if( null != _edtUtil ) {
+ return _edtUtil.isRunning();
}
return false;
}
@Override
public String toString() {
- return "NEWT-Display["+getFQName()+", excl "+exclusive+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", edtRunning "+isEDTRunning()+", "+aDevice+"]";
+ final EDTUtil _edtUtil = edtUtil;
+ final boolean _edtUtilRunning = ( null != _edtUtil ) ? _edtUtil.isRunning() : false;
+ return "NEWT-Display["+getFQName()+", excl "+exclusive+", refCount "+refCount+", hasEDT "+(null!=_edtUtil)+", edtRunning "+_edtUtilRunning+", "+aDevice+"]";
}
/** Dispatch native Toolkit messageges */
@@ -448,17 +536,18 @@ public abstract class DisplayImpl extends Display {
}
public void enqueueEvent(boolean wait, NEWTEvent e) {
- if(!isEDTRunning()) {
+ final EDTUtil _edtUtil = edtUtil;
+ if( !_edtUtil.isRunning() ) {
// oops .. we are already dead
if(DEBUG) {
- Throwable t = new Throwable("Warning: EDT already stopped: wait:="+wait+", "+e);
- t.printStackTrace();
+ System.err.println("Warning: EDT already stopped: wait:="+wait+", "+e);
+ Thread.dumpStack();
}
return;
}
// can't wait if we are on EDT or NEDT -> consume right away
- if(wait && edtUtil.isCurrentThreadEDTorNEDT() ) {
+ if(wait && _edtUtil.isCurrentThreadEDTorNEDT() ) {
dispatchMessage(e);
return;
}
@@ -505,7 +594,7 @@ public abstract class DisplayImpl extends Display {
return runWithLockedDevice(device, action);
}
- protected EDTUtil edtUtil = null;
+ protected volatile EDTUtil edtUtil = null;
protected int id;
protected String name;
protected String type;
diff --git a/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java
index db31cc83f..43d558515 100644
--- a/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java
+++ b/src/newt/classes/jogamp/newt/MonitorDeviceImpl.java
@@ -94,20 +94,20 @@ public class MonitorDeviceImpl extends MonitorDevice {
}
final long tStart;
if(Screen.DEBUG) {
- tStart = System.nanoTime();
+ tStart = System.currentTimeMillis();
} else {
tStart = 0;
}
sms.fireMonitorModeChangeNotify(this, mmU);
if(Screen.DEBUG) {
- System.err.println("Screen.setCurrentMode ("+(System.nanoTime()-tStart)/1e6+"ms): fireModeChangeNotify() "+mmU);
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): fireModeChangeNotify() "+mmU);
}
-
+
boolean success = screenImpl.setCurrentMonitorModeImpl(this, mmU);
if(success) {
if(Screen.DEBUG) {
- System.err.println("Screen.setCurrentMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentModeImpl() "+mmU+", success(1): "+success);
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): setCurrentModeImpl() "+mmU+", success(1): "+success);
}
} else {
// 2nd attempt validate!
@@ -115,7 +115,7 @@ public class MonitorDeviceImpl extends MonitorDevice {
success = queriedCurrent.hashCode() == mmU.hashCode() ;
if(Screen.DEBUG) {
System.err.println("Screen.setCurrentMode.2: queried "+queriedCurrent);
- System.err.println("Screen.setCurrentMode ("+(System.nanoTime()-tStart)/1e6+"ms): setCurrentModeImpl() "+mmU+", success(2): "+success);
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): setCurrentModeImpl() "+mmU+", success(2): "+success);
}
}
if( success ) {
@@ -124,7 +124,7 @@ public class MonitorDeviceImpl extends MonitorDevice {
}
sms.fireMonitorModeChanged(this, mmU, success);
if(Screen.DEBUG) {
- System.err.println("Screen.setCurrentMode ("+(System.nanoTime()-tStart)/1e6+"ms): X.X "+this+", success: "+success);
+ System.err.println("Screen.setCurrentMode ("+(System.currentTimeMillis()-tStart)+"ms): X.X: success "+success+": "+this);
}
return success;
} finally {
diff --git a/src/newt/classes/jogamp/newt/ScreenImpl.java b/src/newt/classes/jogamp/newt/ScreenImpl.java
index 7edf7b63a..5ffa2ebbf 100644
--- a/src/newt/classes/jogamp/newt/ScreenImpl.java
+++ b/src/newt/classes/jogamp/newt/ScreenImpl.java
@@ -34,8 +34,6 @@
package jogamp.newt;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@@ -54,9 +52,15 @@ import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.Screen;
import com.jogamp.newt.event.MonitorEvent;
import com.jogamp.newt.event.MonitorModeListener;
+import com.jogamp.newt.util.MonitorModeUtil;
public abstract class ScreenImpl extends Screen implements MonitorModeListener {
- protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableScreenMode", true);
+ protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_TEST_SCREENMODE_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableScreenMode", true);
+ }
public static final int default_sm_bpp = 32;
public static final int default_sm_widthmm = 519;
@@ -64,6 +68,13 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
public static final int default_sm_rate = 60;
public static final int default_sm_rotation = 0;
+ static {
+ DisplayImpl.initSingleton();
+ }
+
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
+
protected DisplayImpl display;
protected int screen_idx;
protected String fqname;
@@ -77,15 +88,6 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
private long tCreated; // creationTime
- static {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- registerShutdownHook();
- return null;
- }
- });
- }
-
private static Class<?> getScreenClass(String type) throws ClassNotFoundException
{
final Class<?> screenClass = NewtFactory.getCustomClass(type, "ScreenDriver");
@@ -128,7 +130,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
screen.screen_idx = idx;
screen.fqname = display.getFQName()+"-s"+idx;
screen.hashCode = screen.fqname.hashCode();
- screenList.add(screen);
+ Screen.addScreen2List(screen);
if(DEBUG) {
System.err.println("Screen.create() NEW: "+screen+" "+Display.getThreadName());
}
@@ -172,39 +174,39 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
System.err.println("Screen.createNative() START ("+DisplayImpl.getThreadName()+", "+this+")");
} else {
tCreated = 0;
- }
-
+ }
display.addReference();
createNativeImpl();
if(null == aScreen) {
throw new NativeWindowException("Screen.createNative() failed to instanciate an AbstractGraphicsScreen");
}
-
+
initMonitorState();
- if(DEBUG) {
- System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+"), total "+ (System.nanoTime()-tCreated)/1e6 +"ms");
- }
synchronized(screenList) {
screensActive++;
+ if(DEBUG) {
+ System.err.println("Screen.createNative() END ("+DisplayImpl.getThreadName()+", "+this+"), active "+screensActive+", total "+ (System.nanoTime()-tCreated)/1e6 +"ms");
+ }
}
+ ScreenMonitorState.getScreenMonitorState(this.getFQName()).addListener(this);
}
- ScreenMonitorState sms = ScreenMonitorState.getScreenMonitorState(this.getFQName());
- sms.addListener(this);
}
@Override
public synchronized final void destroy() {
- releaseMonitorState();
-
synchronized(screenList) {
- screenList.remove(this);
if(0 < screensActive) {
screensActive--;
}
+ if(DEBUG) {
+ System.err.println("Screen.destroy() ("+DisplayImpl.getThreadName()+"): active "+screensActive);
+ // Thread.dumpStack();
+ }
}
if ( null != aScreen ) {
+ releaseMonitorState();
closeNativeImpl();
aScreen = null;
}
@@ -220,8 +222,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
}
if ( 0 == refCount ) {
createNative();
- }
- if(null == aScreen) {
+ } else if(null == aScreen) {
throw new NativeWindowException("Screen.addReference() (refCount "+refCount+") null AbstractGraphicsScreen");
}
return ++refCount;
@@ -289,12 +290,12 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
vOriginSize.setWidth(usrSize.getWidth());
vOriginSize.setHeight(usrSize.getHeight());
if(DEBUG) {
- System.err.println("User virtual screen viewport "+vOriginSize);
+ System.err.println("Update user virtual screen viewport @ "+Thread.currentThread().getName()+": "+vOriginSize);
}
} else {
calcVirtualScreenOriginAndSize(vOriginSize);
if(DEBUG) {
- System.err.println("Detected virtual screen viewport "+vOriginSize);
+ System.err.println("Updated virtual screen viewport @ "+Thread.currentThread().getName()+": "+vOriginSize);
}
}
}
@@ -401,7 +402,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
@Override
public void monitorModeChangeNotify(MonitorEvent me) {
if(DEBUG) {
- System.err.println("monitorModeChangeNotify: "+me);
+ System.err.println("monitorModeChangeNotify @ "+Thread.currentThread().getName()+": "+me);
}
for(int i=0; i<refMonitorModeListener.size(); i++) {
((MonitorModeListener)refMonitorModeListener.get(i)).monitorModeChangeNotify(me);
@@ -414,7 +415,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
final MonitorDeviceImpl monitor = (MonitorDeviceImpl) monitors.get(i);
final Rectangle newViewport = getNativeMonitorDeviceViewportImpl(monitor);
if( DEBUG ) {
- System.err.println("Screen.updateMonitorViewport["+i+"]: "+monitor.getViewport()+" -> "+newViewport);
+ System.err.println("Screen.updateMonitorViewport["+i+"] @ "+Thread.currentThread().getName()+": "+monitor.getViewport()+" -> "+newViewport);
}
if( null != newViewport ) {
monitor.setViewportValue(newViewport);
@@ -429,7 +430,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
updateVirtualScreenOriginAndSize();
}
if(DEBUG) {
- System.err.println("monitorModeChanged: success "+success+", "+me);
+ System.err.println("monitorModeChangeNotify @ "+Thread.currentThread().getName()+": success "+success+", "+me);
}
for(int i=0; i<refMonitorModeListener.size(); i++) {
((MonitorModeListener)refMonitorModeListener.get(i)).monitorModeChanged(me, success);
@@ -540,6 +541,11 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
final MonitorDevice monitor = getVirtualMonitorDevice(cache, 0, mode);
cache.monitorDevices.getOrAdd(monitor);
}
+ // Sort MonitorModes (all and per device) in descending order - default!
+ MonitorModeUtil.sort(cache.monitorModes.getData(), false ); // descending order
+ for(Iterator<MonitorDevice> iMonitor=cache.monitorDevices.iterator(); iMonitor.hasNext(); ) {
+ MonitorModeUtil.sort(iMonitor.next().getSupportedModes(), false ); // descending order
+ }
if(DEBUG) {
int i=0;
for(Iterator<MonitorMode> iMode=cache.monitorModes.iterator(); iMode.hasNext(); i++) {
@@ -554,7 +560,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
System.err.println("["+i+"]["+j+"]: "+iMode.next());
}
}
- }
+ }
sms = new ScreenMonitorState(cache.monitorDevices, cache.monitorModes);
ScreenMonitorState.mapScreenMonitorState(this.getFQName(), sms);
}
@@ -609,7 +615,7 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
return cache.monitorDevices.size();
}
- private void releaseMonitorState() {
+ private final void releaseMonitorState() {
ScreenMonitorState sms;
ScreenMonitorState.lockScreenMonitorState();
try {
@@ -660,23 +666,20 @@ public abstract class ScreenImpl extends Screen implements MonitorModeListener {
ScreenMonitorState.unmapScreenMonitorStateUnlocked(getFQName());
}
}
- private static final void shutdownAll() {
- for(int i=0; i < screenList.size(); i++) {
- ((ScreenImpl)screenList.get(i)).shutdown();
- }
- }
- private static synchronized void registerShutdownHook() {
- final Thread shutdownHook = new Thread(new Runnable() {
- public void run() {
- ScreenImpl.shutdownAll();
+ /** pp */ static final void shutdownAll() {
+ final int sCount = screenList.size();
+ if(DEBUG) {
+ System.err.println("Screen.shutdownAll "+sCount+" instances, on thread "+Display.getThreadName());
+ }
+ for(int i=0; i<sCount && screenList.size()>0; i++) { // be safe ..
+ final ScreenImpl s = (ScreenImpl) screenList.remove(0).get();
+ if(DEBUG) {
+ System.err.println("Screen.shutdownAll["+(i+1)+"/"+sCount+"]: "+s+", GCed "+(null==s));
}
- });
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
- Runtime.getRuntime().addShutdownHook(shutdownHook);
- return null;
+ if( null != s ) {
+ s.shutdown();
}
- });
+ }
}
}
diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java
index 805ad08ad..caa461e41 100644
--- a/src/newt/classes/jogamp/newt/WindowImpl.java
+++ b/src/newt/classes/jogamp/newt/WindowImpl.java
@@ -36,6 +36,7 @@ package jogamp.newt;
import java.util.ArrayList;
import java.util.List;
+import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import com.jogamp.common.util.IntBitfield;
@@ -80,7 +81,52 @@ import jogamp.nativewindow.SurfaceUpdatedHelper;
public abstract class WindowImpl implements Window, NEWTEventConsumer
{
- public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true);
+ public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE;
+
+ static {
+ Debug.initSingleton();
+ DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true);
+
+ ScreenImpl.initSingleton();
+ }
+
+ protected static final ArrayList<WeakReference<WindowImpl>> windowList = new ArrayList<WeakReference<WindowImpl>>();
+
+ /** Maybe utilized at a shutdown hook, impl. does not block. */
+ public static final void shutdownAll() {
+ final int wCount = windowList.size();
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.shutdownAll "+wCount+" instances, on thread "+getThreadName());
+ }
+ for(int i=0; i<wCount && windowList.size()>0; i++) { // be safe ..
+ final WindowImpl w = windowList.remove(0).get();
+ if(DEBUG_IMPLEMENTATION) {
+ final long wh = null != w ? w.getWindowHandle() : 0;
+ System.err.println("Window.shutdownAll["+(i+1)+"/"+wCount+"]: "+toHexString(wh)+", GCed "+(null==w));
+ }
+ if( null != w ) {
+ w.shutdown();
+ }
+ }
+ }
+ private static void addWindow2List(WindowImpl window) {
+ synchronized(windowList) {
+ // GC before add
+ int i=0, gced=0;
+ while( i < windowList.size() ) {
+ if( null == windowList.get(i).get() ) {
+ gced++;
+ windowList.remove(i);
+ } else {
+ i++;
+ }
+ }
+ windowList.add(new WeakReference<WindowImpl>(window));
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.addWindow2List: GCed "+gced+", size "+windowList.size());
+ }
+ }
+ }
/** Timeout of queued events (repaint and resize) */
static final long QUEUED_EVENT_TO = 1200; // ms
@@ -108,6 +154,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private boolean fullscreen = false, brokenFocusChange = false;
private List<MonitorDevice> fullscreenMonitors = null;
private boolean fullscreenUseMainMonitor = true;
+ private boolean fullscreenUseSpanningMode = true; // spanning mode: fake full screen, only on certain platforms
private boolean autoPosition = true; // default: true (allow WM to choose top-level position, if not set by user)
private int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets
@@ -186,6 +233,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
window.screen = (ScreenImpl) screen;
window.capsRequested = (CapabilitiesImmutable) caps.cloneMutable();
window.instantiationFinished();
+ addWindow2List(window);
return window;
} catch (Throwable t) {
t.printStackTrace();
@@ -207,12 +255,29 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
WindowImpl window = (WindowImpl) ReflectionUtil.createInstance( windowClass, cstrArgumentTypes, cstrArguments ) ;
window.screen = (ScreenImpl) screen;
window.capsRequested = (CapabilitiesImmutable) caps.cloneMutable();
+ window.instantiationFinished();
+ addWindow2List(window);
return window;
} catch (Throwable t) {
throw new NativeWindowException(t);
}
}
+ /** Fast invalidation of instance w/o any blocking function call. */
+ private final void shutdown() {
+ if(null!=lifecycleHook) {
+ lifecycleHook.shutdownRenderingAction();
+ }
+ setWindowHandle(0);
+ visible = false;
+ fullscreen = false;
+ fullscreenMonitors = null;
+ fullscreenUseMainMonitor = true;
+ fullscreenUseSpanningMode = false;
+ hasFocus = false;
+ parentWindowHandle = 0;
+ }
+
protected final void setGraphicsConfiguration(AbstractGraphicsConfiguration cfg) {
config = cfg;
}
@@ -233,9 +298,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
/**
* Notifies the receiver to preserve resources (GL, ..)
- * for the next destroy*() calls (only).
+ * for the next destroy*() calls (only), if supported and if <code>value</code> is <code>true</code>, otherwise clears preservation flag.
+ * @param value <code>true</code> to set the one-shot preservation if supported, otherwise clears it.
*/
- void preserveGLStateAtDestroy();
+ void preserveGLStateAtDestroy(boolean value);
/**
* Invoked before Window destroy action,
@@ -270,6 +336,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
* @see #pauseRenderingAction()
*/
void resumeRenderingAction();
+
+ /**
+ * Shutdown rendering action (thread) abnormally.
+ * <p>
+ * Should be called only at shutdown, if necessary.
+ * </p>
+ */
+ void shutdownRenderingAction();
}
private boolean createNative() {
@@ -321,9 +395,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
if(isFullscreen()) {
synchronized(fullScreenAction) {
fullscreen = false; // trigger a state change
- fullScreenAction.init(true, fullscreenUseMainMonitor, fullscreenMonitors);
- fullscreenMonitors = null; // release references ASAP
- fullscreenUseMainMonitor = true;
+ fullScreenAction.init(true);
fullScreenAction.run();
}
} else {
@@ -511,6 +583,16 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
* @see #positionChanged(boolean,int, int)
*/
protected abstract boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags);
+
+ /**
+ * Tests whether a single reconfigure flag is supported by implementation.
+ * <p>
+ * Default is all but {@link #FLAG_IS_FULLSCREEN_SPAN}
+ * </p>
+ */
+ protected boolean isReconfigureFlagSupported(int changeFlags) {
+ return 0 == ( changeFlags & FLAG_IS_FULLSCREEN_SPAN );
+ }
protected int getReconfigureFlags(int changeFlags, boolean visible) {
return changeFlags |= ( ( 0 != getParentWindowHandle() ) ? FLAG_HAS_PARENT : 0 ) |
@@ -841,17 +923,19 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class SetSizeAction implements Runnable {
int width, height;
+ boolean disregardFS;
- private SetSizeAction(int w, int h) {
+ private SetSizeAction(int w, int h, boolean disregardFS) {
this.width = w;
this.height = h;
+ this.disregardFS = disregardFS;
}
public final void run() {
final RecursiveLock _lock = windowLock;
_lock.lock();
try {
- if ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) {
+ if ( ( disregardFS || !isFullscreen() ) && ( getWidth() != width || getHeight() != height ) ) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible);
}
@@ -886,9 +970,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
+ private void setFullscreenSize(int width, int height) {
+ runOnEDTIfAvail(true, new SetSizeAction(width, height, true));
+ }
@Override
public void setSize(int width, int height) {
- runOnEDTIfAvail(true, new SetSizeAction(width, height));
+ runOnEDTIfAvail(true, new SetSizeAction(width, height, false));
}
@Override
public void setTopLevelSize(int width, int height) {
@@ -964,6 +1051,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
fullscreen = false;
fullscreenMonitors = null;
fullscreenUseMainMonitor = true;
+ fullscreenUseSpanningMode = false;
hasFocus = false;
parentWindowHandle = 0;
@@ -1000,8 +1088,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
protected void destroy(boolean preserveResources) {
- if( preserveResources && null != WindowImpl.this.lifecycleHook ) {
- WindowImpl.this.lifecycleHook.preserveGLStateAtDestroy();
+ if( null != lifecycleHook ) {
+ lifecycleHook.preserveGLStateAtDestroy( preserveResources );
}
destroy();
}
@@ -1108,7 +1196,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
// Destroy this window and use parent's Screen.
// It may be created properly when the parent is made visible.
- destroy(false);
+ destroy( false );
setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
operation = ReparentOperation.ACTION_NATIVE_CREATION_PENDING;
} else if(newParentWindow != getParent()) {
@@ -1796,25 +1884,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class FullScreenAction implements Runnable {
boolean fullscreen;
- List<MonitorDevice> monitors;
- boolean useMainMonitor;
- private boolean init(boolean fullscreen, boolean useMainMonitor, List<MonitorDevice> monitors) {
+ private boolean init(boolean fullscreen) {
if(isNativeValid()) {
this.fullscreen = fullscreen;
- if( isFullscreen() != fullscreen ) {
- this.monitors = monitors;
- this.useMainMonitor = useMainMonitor;
- return true;
- } else {
- this.monitors = null;
- this.useMainMonitor = true;
- return false;
- }
+ return isFullscreen() != fullscreen;
} else {
WindowImpl.this.fullscreen = fullscreen; // set current state for createNative(..)
- WindowImpl.this.fullscreenMonitors = monitors;
- WindowImpl.this.fullscreenUseMainMonitor = useMainMonitor;
return false;
}
}
@@ -1829,19 +1905,27 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
int x,y,w,h;
- final RectangleImmutable viewport;
+ final RectangleImmutable sviewport = screen.getViewport();
+ final RectangleImmutable viewport;
final int fs_span_flag;
if(fullscreen) {
- if( null == monitors ) {
- if( useMainMonitor ) {
- monitors = new ArrayList<MonitorDevice>();
- monitors.add( getMainMonitor() );
+ if( null == fullscreenMonitors ) {
+ if( fullscreenUseMainMonitor ) {
+ fullscreenMonitors = new ArrayList<MonitorDevice>();
+ fullscreenMonitors.add( getMainMonitor() );
} else {
- monitors = getScreen().getMonitorDevices();
+ fullscreenMonitors = getScreen().getMonitorDevices();
}
}
- fs_span_flag = monitors.size() > 1 ? FLAG_IS_FULLSCREEN_SPAN : 0 ;
- viewport = MonitorDevice.unionOfViewports(new Rectangle(), monitors);
+ viewport = MonitorDevice.unionOfViewports(new Rectangle(), fullscreenMonitors);
+ if( isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN) &&
+ ( fullscreenMonitors.size() > 1 || sviewport.compareTo(viewport) > 0 ) ) {
+ fullscreenUseSpanningMode = true;
+ fs_span_flag = FLAG_IS_FULLSCREEN_SPAN;
+ } else {
+ fullscreenUseSpanningMode = false;
+ fs_span_flag = 0;
+ }
nfs_x = getX();
nfs_y = getY();
nfs_width = getWidth();
@@ -1851,6 +1935,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
w = viewport.getWidth();
h = viewport.getHeight();
} else {
+ fullscreenUseMainMonitor = true;
+ fullscreenUseSpanningMode = false;
+ fullscreenMonitors = null;
fs_span_flag = 0;
viewport = null;
x = nfs_x;
@@ -1872,16 +1959,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
}
}
}
- monitors = null; // clear references ASAP
- useMainMonitor = true;
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+
- ", virtl-size: "+screen.getWidth()+"x"+screen.getHeight()+", monitorsViewport "+viewport);
+ ", virtl-screenSize: "+sviewport+", monitorsViewport "+viewport+
+ ", spanning "+fullscreenUseSpanningMode+" @ "+Thread.currentThread().getName());
}
- DisplayImpl display = (DisplayImpl) screen.getDisplay();
+ final DisplayImpl display = (DisplayImpl) screen.getDisplay();
display.dispatchMessagesNative(); // status up2date
- boolean wasVisible = isVisible();
+ final boolean wasVisible = isVisible();
// Lock parentWindow only during reparenting (attempt)
final NativeWindow parentWindowLocked;
@@ -1909,8 +1995,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
WindowImpl.this.waitForVisible(true, false);
display.dispatchMessagesNative(); // status up2date
WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW);
- display.dispatchMessagesNative(); // status up2date
-
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window fs done: " + WindowImpl.this);
}
@@ -1921,7 +2005,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
}
- private final FullScreenAction fullScreenAction = new FullScreenAction();
+ private final FullScreenAction fullScreenAction = new FullScreenAction();
@Override
public boolean setFullscreen(boolean fullscreen) {
@@ -1935,7 +2019,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private boolean setFullscreenImpl(boolean fullscreen, boolean useMainMonitor, List<MonitorDevice> monitors) {
synchronized(fullScreenAction) {
- if( fullScreenAction.init(fullscreen, useMainMonitor, monitors) ) {
+ fullscreenMonitors = monitors;
+ fullscreenUseMainMonitor = useMainMonitor;
+ fullscreenUseSpanningMode = false;
+ if( fullScreenAction.init(fullscreen) ) {
if(fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow)) {
// enable fullscreen on offscreen instance
if(null != parentWindow) {
@@ -1954,8 +2041,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
nfs_parent = null;
}
- if(isVisible()) {
- requestFocus(true /* wait */, this.fullscreen /* skipFocusAction */, true /* force */);
+ if( fullscreen && isVisible() ) { // force focus on fullscreen
+ requestFocus(true /* wait */, true /* skipFocusAction */, true /* force */);
}
}
return this.fullscreen;
@@ -1964,20 +2051,34 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
private class MonitorModeListenerImpl implements MonitorModeListener {
boolean animatorPaused = false;
+ boolean hadFocus = false;
+ boolean fullscreenPaused = false;
+ List<MonitorDevice> _fullscreenMonitors = null;
+ boolean _fullscreenUseMainMonitor = true;
public void monitorModeChangeNotify(MonitorEvent me) {
+ hadFocus = hasFocus();
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.monitorModeChangeNotify: "+me);
+ System.err.println("Window.monitorModeChangeNotify: hadFocus "+hadFocus+", "+me+" @ "+Thread.currentThread().getName());
}
if(null!=lifecycleHook) {
animatorPaused = lifecycleHook.pauseRenderingAction();
}
+ if( fullscreen && isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN) ) {
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChangeNotify: FS Pause");
+ }
+ fullscreenPaused = true;
+ _fullscreenMonitors = fullscreenMonitors;
+ _fullscreenUseMainMonitor = fullscreenUseMainMonitor;
+ setFullscreenImpl(false, true, null);
+ }
}
public void monitorModeChanged(MonitorEvent me, boolean success) {
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.monitorModeChanged: "+me+", success: "+success);
+ System.err.println("Window.monitorModeChanged: hadFocus "+hadFocus+", "+me+", success: "+success+" @ "+Thread.currentThread().getName());
}
if(success) {
@@ -1985,7 +2086,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
// Didn't pass above notify method. probably detected screen change after it happened.
animatorPaused = lifecycleHook.pauseRenderingAction();
}
- if( !fullscreen ) {
+ if( !fullscreen && !fullscreenPaused ) {
// Simply move/resize window to fit in virtual screen if required
final RectangleImmutable viewport = screen.getViewport();
if( viewport.getWidth() > 0 && viewport.getHeight() > 0 ) { // failsafe
@@ -2001,13 +2102,35 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
setSize(viewport.getWidth(), viewport.getHeight());
}
}
+ } else if( fullscreenPaused ){
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("Window.monitorModeChanged: FS Restore");
+ }
+ setFullscreenImpl(true, _fullscreenUseMainMonitor, _fullscreenMonitors);
+ fullscreenPaused = false;
+ _fullscreenMonitors = null;
+ _fullscreenUseMainMonitor = true;
+ } else {
+ // If changed monitor is part of this fullscreen mode, reset size! (Bug 771)
+ final MonitorDevice md = me.getMonitor();
+ if( fullscreenMonitors.contains(md) ) {
+ final RectangleImmutable viewport = MonitorDevice.unionOfViewports(new Rectangle(), fullscreenMonitors);
+ if(DEBUG_IMPLEMENTATION) {
+ final RectangleImmutable rect = new Rectangle(getX(), getY(), getWidth(), getHeight());
+ System.err.println("Window.monitorModeChanged: FS Monitor Match: Fit window "+rect+" into new viewport union "+viewport+", provoked by "+md);
+ }
+ definePosition(viewport.getX(), viewport.getY()); // set pos for setVisible(..) or createNative(..) - reduce EDT roundtrip
+ setFullscreenSize(viewport.getWidth(), viewport.getHeight());
+ }
}
}
-
if(animatorPaused) {
lifecycleHook.resumeRenderingAction();
}
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
+ if( hadFocus ) {
+ requestFocus(true);
+ }
}
}
private final MonitorModeListenerImpl monitorModeListenerImpl = new MonitorModeListenerImpl();
@@ -2476,7 +2599,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
return keyListeners.toArray(new KeyListener[keyListeners.size()]);
}
- @SuppressWarnings("deprecation")
private final boolean propagateKeyEvent(KeyEvent e, KeyListener l) {
switch(e.getEventType()) {
case KeyEvent.EVENT_KEY_PRESSED:
@@ -2485,58 +2607,29 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
case KeyEvent.EVENT_KEY_RELEASED:
l.keyReleased(e);
break;
- case KeyEvent.EVENT_KEY_TYPED:
- l.keyTyped(e);
- break;
default:
throw new NativeWindowException("Unexpected key event type " + e.getEventType());
}
return e.isConsumed();
}
- @SuppressWarnings("deprecation")
protected void consumeKeyEvent(KeyEvent e) {
- boolean consumedE = false, consumedTyped = false;
- if( KeyEvent.EVENT_KEY_TYPED == e.getEventType() ) {
- throw new InternalError("Deprecated KeyEvent.EVENT_KEY_TYPED is synthesized - don't send/enqueue it!");
- }
-
- // Synthesize deprecated event KeyEvent.EVENT_KEY_TYPED
- final KeyEvent eTyped;
- if( KeyEvent.EVENT_KEY_RELEASED == e.getEventType() && e.isPrintableKey() && !e.isAutoRepeat() ) {
- eTyped = KeyEvent.create(KeyEvent.EVENT_KEY_TYPED, e.getSource(), e.getWhen(), e.getModifiers(), e.getKeyCode(), e.getKeySymbol(), e.getKeyChar());
- } else {
- eTyped = null;
- }
- if(null != keyboardFocusHandler) {
+ boolean consumedE = false;
+ if( null != keyboardFocusHandler && !e.isAutoRepeat() ) {
consumedE = propagateKeyEvent(e, keyboardFocusHandler);
if(DEBUG_KEY_EVENT) {
- System.err.println("consumeKeyEvent: "+e+", keyboardFocusHandler consumed: "+consumedE);
- }
- if( null != eTyped ) {
- consumedTyped = propagateKeyEvent(eTyped, keyboardFocusHandler);
- if(DEBUG_KEY_EVENT) {
- System.err.println("consumeKeyEvent: "+eTyped+", keyboardFocusHandler consumed: "+consumedTyped);
- }
+ if( consumedE ) {
+ System.err.println("consumeKeyEvent(kfh): "+e+", consumed: "+consumedE);
+ }
}
}
- if(DEBUG_KEY_EVENT) {
- if( !consumedE ) {
- System.err.println("consumeKeyEvent: "+e);
+ if( !consumedE ) {
+ for(int i = 0; !consumedE && i < keyListeners.size(); i++ ) {
+ consumedE = propagateKeyEvent(e, keyListeners.get(i));
}
- }
- for(int i = 0; !consumedE && i < keyListeners.size(); i++ ) {
- consumedE = propagateKeyEvent(e, keyListeners.get(i));
- }
- if( null != eTyped ) {
if(DEBUG_KEY_EVENT) {
- if( !consumedTyped ) {
- System.err.println("consumeKeyEvent: "+eTyped);
- }
+ System.err.println("consumeKeyEvent(usr): "+e+", consumed: "+consumedE);
}
- for(int i = 0; !consumedTyped && i < keyListeners.size(); i++ ) {
- consumedTyped = propagateKeyEvent(eTyped, keyListeners.get(i));
- }
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java
index a367462c4..a2877dba2 100644
--- a/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/android/DisplayDriver.java
@@ -55,7 +55,7 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl {
aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
}
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
aDevice.close();
}
diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
index de524d54c..9f6210269 100644
--- a/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
+++ b/src/newt/classes/jogamp/newt/driver/android/NewtVersionActivity.java
@@ -78,7 +78,7 @@ public class NewtVersionActivity extends NewtBaseActivity {
glWindow.addGLEventListener(new GLEventListener() {
public void init(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
- final StringBuffer sb = new StringBuffer();
+ final StringBuilder sb = new StringBuilder();
sb.append(JoglVersion.getGLInfo(gl, null, true)).append(Platform.NEWLINE);
sb.append("Requested: ").append(Platform.NEWLINE);
sb.append(drawable.getNativeSurface().getGraphicsConfiguration().getRequestedCapabilities()).append(Platform.NEWLINE).append(Platform.NEWLINE);
diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
index fc9bbb848..80c72c008 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java
@@ -45,7 +45,7 @@ public class AWTEDTUtil implements EDTUtil {
private final ThreadGroup threadGroup;
private final String name;
private final Runnable dispatchMessages;
- private NewtEventDispatchThread nedt = null;
+ private NEDT nedt = null;
private int start_iter=0;
private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
@@ -53,7 +53,7 @@ public class AWTEDTUtil implements EDTUtil {
this.threadGroup = tg;
this.name=Thread.currentThread().getName()+"-"+name+"-EDT-";
this.dispatchMessages=dispatchMessages;
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
+ this.nedt = new NEDT(threadGroup, name);
this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
}
@@ -68,24 +68,29 @@ public class AWTEDTUtil implements EDTUtil {
}
@Override
- final public void reset() {
- synchronized(edtLock) {
- waitUntilStopped();
+ public final boolean restart() throws IllegalStateException {
+ synchronized(edtLock) {
+ if( nedt.isRunning() ) {
+ throw new IllegalStateException("EDT still running and not subject to stop. Curr "+Thread.currentThread().getName()+", NEDT "+nedt.getName()+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", on AWT-EDT "+EventQueue.isDispatchThread());
+ }
if(DEBUG) {
System.err.println(Thread.currentThread()+": AWT-EDT reset - edt: "+nedt);
}
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
- this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ if( nedt.getState() != Thread.State.NEW ) {
+ nedt = new NEDT(threadGroup, name);
+ nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+ startImpl();
}
+ return invoke(true, nullTask);
}
private final void startImpl() {
if(nedt.isAlive()) {
- throw new RuntimeException("AWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
+ throw new RuntimeException("AWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", edt: "+nedt);
}
start_iter++;
nedt.setName(name+start_iter);
- nedt.shouldStop = false;
if(DEBUG) {
System.err.println(Thread.currentThread()+": AWT-EDT START - edt: "+nedt);
// Thread.dumpStack();
@@ -110,59 +115,76 @@ public class AWTEDTUtil implements EDTUtil {
@Override
final public boolean isRunning() {
- return nedt.isRunning() ; // AWT is always running
+ return nedt.isRunning() ;
}
@Override
- public final void invokeStop(Runnable task) {
- invokeImpl(true, task, true);
+ public final boolean invokeStop(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, true);
}
@Override
- public final void invoke(boolean wait, Runnable task) {
- invokeImpl(wait, task, false);
+ public final boolean invoke(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, false);
}
- private void invokeImpl(boolean wait, Runnable task, boolean stop) {
+ private static Runnable nullTask = new Runnable() {
+ @Override
+ public void run() { }
+ };
+
+ private final boolean invokeImpl(boolean wait, Runnable task, boolean stop) {
Throwable throwable = null;
RunnableTask rTask = null;
- Object rTaskLock = new Object();
+ final Object rTaskLock = new Object();
synchronized(rTaskLock) { // lock the optional task execution
synchronized(edtLock) { // lock the EDT status
if( nedt.shouldStop ) {
// drop task ..
+ System.err.println(Thread.currentThread()+": Warning: AWT-EDT about (1) to stop, won't enqueue new task: "+nedt);
if(DEBUG) {
- System.err.println(Thread.currentThread()+": Warning: AWT-EDT about (1) to stop, won't enqueue new task: "+nedt);
Thread.dumpStack();
}
- return;
+ return false;
}
- // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
- // Thread.dumpStack();
- if(stop) {
- synchronized(nedt.sync) {
+ if( isCurrentThreadEDT() ) {
+ if(null != task) {
+ task.run();
+ }
+ wait = false; // running in same thread (EDT) -> no wait
+ if(stop) {
nedt.shouldStop = true;
- nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
}
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": AWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
- // Thread.dumpStack();
+ } else {
+ if( !nedt.isRunning ) {
+ if( null != task ) {
+ if( stop ) {
+ System.err.println(Thread.currentThread()+": Warning: AWT-EDT is about (3) to stop and stopped already, dropping task. NEDT "+nedt);
+ } else {
+ System.err.println(Thread.currentThread()+": Warning: AWT-EDT is not running, dropping task. NEDT "+nedt);
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
+ return false;
+ } else if( stop ) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": AWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop);
+ }
+ synchronized(nedt.sync) {
+ nedt.shouldStop = true;
+ nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
+ }
+ }
+
+ if(null != task) {
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ true /* always catch and report Exceptions, don't disturb EDT */,
+ wait ? null : System.err);
+ AWTEDTExecutor.singleton.invoke(false, rTask);
}
- } else if( !nedt.isRunning() ) {
- // start if should not stop && not started yet
- startImpl();
- }
- if( null == task ) {
- wait = false;
- } else if( isCurrentThreadEDT() ) {
- task.run();
- wait = false; // running in same thread (EDT) -> no wait
- } else {
- rTask = new RunnableTask(task,
- wait ? rTaskLock : null,
- true /* always catch and report Exceptions, don't disturb EDT */,
- wait ? null : System.err);
- AWTEDTExecutor.singleton.invoke(false, rTask);
}
}
if( wait ) {
@@ -181,51 +203,56 @@ public class AWTEDTUtil implements EDTUtil {
throw new RuntimeException(throwable);
}
}
+ return true;
}
}
@Override
- final public void waitUntilIdle() {
- final NewtEventDispatchThread _edt;
+ final public boolean waitUntilIdle() {
+ final NEDT _edt;
synchronized(edtLock) {
_edt = nedt;
}
- if(!_edt.isRunning() || _edt == Thread.currentThread() || EventQueue.isDispatchThread()) {
- return;
+ if(!_edt.isRunning || _edt == Thread.currentThread() || EventQueue.isDispatchThread()) {
+ return false;
}
try {
AWTEDTExecutor.singleton.invoke(true, new Runnable() {
public void run() { }
});
} catch (Exception e) { }
+ return true;
}
@Override
- final public void waitUntilStopped() {
+ final public boolean waitUntilStopped() {
synchronized(edtLock) {
- if(nedt.isRunning() && nedt != Thread.currentThread() && !EventQueue.isDispatchThread()) {
- while(nedt.isRunning()) {
+ if( nedt.isRunning && nedt != Thread.currentThread() && !EventQueue.isDispatchThread() ) {
+ while( nedt.isRunning ) {
try {
edtLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
+ return true;
+ } else {
+ return false;
}
}
}
- class NewtEventDispatchThread extends Thread {
+ class NEDT extends Thread {
volatile boolean shouldStop = false;
volatile boolean isRunning = false;
Object sync = new Object();
- public NewtEventDispatchThread(ThreadGroup tg, String name) {
+ public NEDT(ThreadGroup tg, String name) {
super(tg, name);
}
final public boolean isRunning() {
- return isRunning;
+ return isRunning && !shouldStop;
}
@Override
@@ -278,10 +305,8 @@ public class AWTEDTUtil implements EDTUtil {
System.err.println(getName()+": AWT-EDT run() END "+ getName()+", "+error);
}
synchronized(edtLock) {
- isRunning = !shouldStop;
- if(!isRunning) {
- edtLock.notifyAll();
- }
+ isRunning = false;
+ edtLock.notifyAll();
}
if(DEBUG) {
System.err.println(getName()+": AWT-EDT run() EXIT "+ getName()+", exception: "+error);
diff --git a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
index 4139951aa..30449f9bc 100644
--- a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java
@@ -34,6 +34,8 @@
package jogamp.newt.driver.awt;
+import javax.media.nativewindow.AbstractGraphicsDevice;
+
import com.jogamp.nativewindow.awt.AWTGraphicsDevice;
import com.jogamp.newt.NewtFactory;
import com.jogamp.newt.util.EDTUtil;
@@ -65,7 +67,7 @@ public class DisplayDriver extends DisplayImpl {
return def;
}
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
aDevice.close();
}
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java
index cc55c336e..112be2b04 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/DisplayDriver.java
@@ -69,7 +69,7 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl {
aDevice = new EGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, handle, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, null);
}
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
if (aDevice.getHandle() != EGL.EGL_NO_DISPLAY) {
DestroyDisplay(aDevice.getHandle());
}
diff --git a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java
index 08c5c573c..4872a9071 100644
--- a/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/bcm/vc/iv/DisplayDriver.java
@@ -64,7 +64,7 @@ public class DisplayDriver extends DisplayImpl {
aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
}
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
aDevice.close();
}
diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java
index e370038d9..ee93eb932 100644
--- a/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/DisplayDriver.java
@@ -72,7 +72,7 @@ public class DisplayDriver extends jogamp.newt.DisplayImpl {
aDevice = new DefaultGraphicsDevice(NativeWindowFactory.TYPE_DEFAULT, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT, displayHandle);
}
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
if(0==displayHandle) {
throw new NativeWindowException("displayHandle null; initCnt "+initCounter);
}
diff --git a/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java
index 745be5dae..3cd72e971 100644
--- a/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/kd/DisplayDriver.java
@@ -64,7 +64,7 @@ public class DisplayDriver extends DisplayImpl {
aDevice = EGLDisplayUtil.eglCreateEGLGraphicsDevice(EGL.EGL_DEFAULT_DISPLAY, AbstractGraphicsDevice.DEFAULT_CONNECTION, AbstractGraphicsDevice.DEFAULT_UNIT);
}
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
aDevice.close();
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
index b49c6b6e0..a99bc4f23 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/DisplayDriver.java
@@ -72,7 +72,7 @@ public class DisplayDriver extends DisplayImpl {
aDevice = new MacOSXGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
}
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
aDevice.close();
}
diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
index 6370782df..6aebf0410 100644
--- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
@@ -423,8 +423,8 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
", was: pressed "+isKeyPressed(keyCode)+", isModifierKeyCode "+isModifierKeyCode);
} */
- // 1:1 Order: OSX and NEWT delivery order is PRESSED, RELEASED and TYPED
- // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE and TYPED keys _before_ PRESSED
+ // OSX delivery order is PRESSED (t0), RELEASED (t1) and TYPED (t2) -> NEWT order: PRESSED (t0) and RELEASED (t1)
+ // Auto-Repeat: OSX delivers only PRESSED, inject auto-repeat RELEASE key _before_ PRESSED
switch(eventType) {
case KeyEvent.EVENT_KEY_RELEASED:
if( isKeyCodeTracked(keyCode) ) {
diff --git a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
index 1b9ec0f25..595d5e952 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/DisplayDriver.java
@@ -76,7 +76,7 @@ public class DisplayDriver extends DisplayImpl {
aDevice = new WindowsGraphicsDevice(AbstractGraphicsDevice.DEFAULT_UNIT);
}
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
sharedClassFactory.releaseSharedClass();
aDevice.close();
}
diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
index ad7e1e8f3..393445db0 100644
--- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
@@ -79,6 +79,11 @@ public class WindowDriver extends WindowImpl {
}
hmon = MonitorFromWindow0(hWnd);
+ // Let's not trigger on HDC change, GLDrawableImpl.'s destroy/create is a nop here anyways.
+ // FIXME: Validate against EGL surface creation: ANGLE uses HWND -> fine!
+ return LOCK_SUCCESS;
+
+ /**
if( hdc_old == hdc ) {
return LOCK_SUCCESS;
}
@@ -86,7 +91,7 @@ public class WindowDriver extends WindowImpl {
System.err.println("WindowsWindow: surface change "+toHexString(hdc_old)+" -> "+toHexString(hdc));
// Thread.dumpStack();
}
- return LOCK_SURFACE_CHANGED;
+ return LOCK_SURFACE_CHANGED; */
}
@Override
@@ -286,9 +291,9 @@ public class WindowDriver extends WindowImpl {
public final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar) {
final boolean isModifierKey = KeyEvent.isModifierKey(keySym);
// System.err.println("*** sendKeyEvent: event "+KeyEvent.getEventTypeString(eventType)+", keyCode "+toHexString(keyCode)+", keyChar <"+keyChar+">, mods "+toHexString(modifiers)+
- // ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", repeat "+isKeyInAutoRepeat(keyCode)+", printableKey "+KeyEvent.isPrintableKey(keyCode)+" [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis());
+ // ", isKeyCodeTracked "+isKeyCodeTracked(keyCode)+", was: pressed "+isKeyPressed(keyCode)+", printableKey "+KeyEvent.isPrintableKey(keyCode, false)+" [modifierKey "+isModifierKey+"] - "+System.currentTimeMillis());
- // Reorder: WINDOWS delivery order is PRESSED (t0), TYPED (t0) and RELEASED (t1) -> NEWT order: PRESSED (t0), RELEASED (t1) and TYPED (t1)
+ // Reorder: WINDOWS delivery order is PRESSED (t0), TYPED (t0) and RELEASED (t1) -> NEWT order: PRESSED (t0) and RELEASED (t1)
// Auto-Repeat: WINDOWS delivers only PRESSED (t0) and TYPED (t0).
switch(eventType) {
case KeyEvent.EVENT_KEY_RELEASED:
@@ -307,8 +312,6 @@ public class WindowDriver extends WindowImpl {
super.sendKeyEvent(KeyEvent.EVENT_KEY_PRESSED, modifiers, keyCode, keySym, keyChar);
}
break;
- // case KeyEvent.EVENT_KEY_TYPED:
- // break;
}
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
index 4fe025ec4..d911483b0 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/DisplayDriver.java
@@ -57,10 +57,8 @@ public class DisplayDriver extends DisplayImpl {
}
}
- public static void initSingleton() {
- // just exist to ensure static init has been run
- }
-
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
public DisplayDriver() {
}
@@ -84,13 +82,13 @@ public class DisplayDriver extends DisplayImpl {
try {
CompleteDisplay0(aDevice.getHandle());
} catch(RuntimeException e) {
- closeNativeImpl();
+ closeNativeImpl(aDevice);
throw e;
}
}
@Override
- protected void closeNativeImpl() {
+ protected void closeNativeImpl(AbstractGraphicsDevice aDevice) {
DisplayRelease0(aDevice.getHandle(), javaObjectAtom, windowDeleteAtom /*, kbdHandle */); // XKB disabled for now
javaObjectAtom = 0;
windowDeleteAtom = 0;
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR.java b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
index c569e5fd8..e39a6c63a 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/RandR.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR.java
@@ -29,13 +29,21 @@ package jogamp.newt.driver.x11;
import java.util.List;
+import javax.media.nativewindow.util.RectangleImmutable;
+
import jogamp.newt.MonitorModeProps;
+import com.jogamp.common.util.VersionNumber;
import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.MonitorMode;
public interface RandR {
+ public static final VersionNumber version110 = new VersionNumber(1, 1, 0);
+ public static final VersionNumber version130 = new VersionNumber(1, 3, 0);
+ public static final VersionNumber version140 = new VersionNumber(1, 4, 0);
+ VersionNumber getVersion();
+
void dumpInfo(final long dpy, final int screen_idx);
/**
@@ -72,5 +80,7 @@ public interface RandR {
int[] getMonitorDeviceProps(final long dpy, final ScreenDriver screen, MonitorModeProps.Cache cache, final int crt_idx);
int[] getMonitorDeviceViewport(final long dpy, final ScreenDriver screen, final int crt_idx);
int[] getCurrentMonitorModeProps(final long dpy, final ScreenDriver screen, final int crt_idx);
- boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode);
+ boolean setCurrentMonitorMode(final long dpy, final ScreenDriver screen, MonitorDevice monitor, final MonitorMode mode);
+
+ public void updateScreenViewport(final long dpy, final ScreenDriver screen, RectangleImmutable viewport);
}
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
index a938b4064..877607f72 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR11.java
@@ -27,6 +27,8 @@
*/
package jogamp.newt.driver.x11;
+import javax.media.nativewindow.util.RectangleImmutable;
+
import jogamp.newt.MonitorModeProps;
import jogamp.newt.ScreenImpl;
@@ -34,20 +36,17 @@ import com.jogamp.common.util.VersionNumber;
import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.MonitorMode;
-public class RandR11 implements RandR {
+class RandR11 implements RandR {
private static final boolean DEBUG = ScreenDriver.DEBUG;
- public static VersionNumber version = new VersionNumber(1, 1, 0);
-
- public static RandR11 createInstance(VersionNumber rAndRVersion) {
- if( rAndRVersion.compareTo(version) >= 0 ) {
- return new RandR11();
- }
- return null;
- }
- private RandR11() {
+ RandR11() {
}
-
+
+ @Override
+ public final VersionNumber getVersion() {
+ return version110;
+ }
+
@Override
public void dumpInfo(final long dpy, final int screen_idx) {
// NOP
@@ -336,6 +335,11 @@ public class RandR11 implements RandR {
}
return done;
}
+
+ @Override
+ public final void updateScreenViewport(final long dpy, final ScreenDriver screen, RectangleImmutable viewport) {
+ // nop
+ }
/** @return int[] { rot1, .. } */
private static native int[] getAvailableScreenRotations0(long display, int screen_index);
diff --git a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
index d10591381..ac83fc5f2 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/RandR13.java
@@ -29,6 +29,8 @@ package jogamp.newt.driver.x11;
import java.util.Iterator;
+import javax.media.nativewindow.util.RectangleImmutable;
+
import jogamp.newt.MonitorModeProps;
import com.jogamp.common.util.IntLongHashMap;
@@ -43,18 +45,15 @@ import com.jogamp.newt.MonitorMode;
* MonitorDevice.id == XRR monitor-idx (not id)
* </pre>
*/
-public class RandR13 implements RandR {
+class RandR13 implements RandR {
private static final boolean DEBUG = ScreenDriver.DEBUG;
- public static VersionNumber version = new VersionNumber(1, 3, 0);
-
- public static RandR13 createInstance(VersionNumber rAndRVersion) {
- if( rAndRVersion.compareTo(version) >= 0 ) {
- return new RandR13();
- }
- return null;
- }
- private RandR13() {
+ RandR13() {
+ }
+
+ @Override
+ public final VersionNumber getVersion() {
+ return version130;
}
@Override
@@ -238,54 +237,20 @@ public class RandR13 implements RandR {
} finally {
releaseScreenResourceHandle(screenResources);
}
- /***
- * TODO: Would need a complete re-layout of crt positions,
- * which is _not_ implicit by XRandR .. sadly.
- *
- if( res ) {
- updateScreenViewport(dpy, screen, monitor);
- } */
return res;
}
- /** See above ..
- private final void updateScreenViewport(final long dpy, final ScreenDriver screen, MonitorDevice monitor) {
+ @Override
+ public final void updateScreenViewport(final long dpy, final ScreenDriver screen, final RectangleImmutable viewport) {
final int screen_idx = screen.getIndex();
final long screenResources = getScreenResourceHandle(dpy, screen_idx);
try {
- RectangleImmutable newViewp = null;
- final long monitorInfo = getMonitorInfoHandle(dpy, screen_idx, screenResources, monitor.getId());
- try {
- final int[] vprops = getMonitorViewport0(monitorInfo);
- if( null != vprops ) {
- newViewp = new Rectangle(vprops[0], vprops[1], vprops[2], vprops[3]);
- }
- System.err.println("XXX setScreenViewport: newVp "+newViewp);
- } finally {
- releaseMonitorInfoHandle(monitorInfo);
- }
- if( null != newViewp ) {
- final List<MonitorDevice> monitors = screen.getMonitorDevices();
- final ArrayList<RectangleImmutable> viewports = new ArrayList<RectangleImmutable>();
- for(int i=0; i<monitors.size(); i++) {
- final MonitorDevice crt = monitors.get(i);
- if( crt.getId() != monitor.getId() ) {
- System.err.println("XXX setScreenViewport: add.pre["+i+"]: "+crt.getViewport());
- viewports.add( crt.getViewport() ) ;
- } else {
- System.err.println("XXX setScreenViewport: add.new["+i+"]: "+newViewp);
- viewports.add( newViewp );
- }
- }
- final RectangleImmutable newScrnViewp = new Rectangle().union(viewports);
- System.err.println("XXX setScreenViewport: "+screen.getViewport()+" -> "+newScrnViewp);
- setScreenViewport0(dpy, screen_idx, screenResources, newScrnViewp.getX(), newScrnViewp.getY(), newScrnViewp.getWidth(), newScrnViewp.getHeight());
- }
+ setScreenViewport0(dpy, screen_idx, screenResources, viewport.getX(), viewport.getY(), viewport.getWidth(), viewport.getHeight());
} finally {
dumpInfo0(dpy, screen_idx, screenResources);
releaseScreenResourceHandle(screenResources);
- }
- } */
+ }
+ }
private static native long getScreenResources0(long display, int screen_index);
private static native void freeScreenResources0(long screenResources);
diff --git a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
index b8b13939b..f37556dd7 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/ScreenDriver.java
@@ -38,6 +38,7 @@ import java.util.List;
import javax.media.nativewindow.AbstractGraphicsDevice;
import javax.media.nativewindow.util.Rectangle;
+import javax.media.nativewindow.util.RectangleImmutable;
import jogamp.nativewindow.x11.X11Util;
import jogamp.newt.Debug;
@@ -54,12 +55,18 @@ import com.jogamp.newt.MonitorDevice;
import com.jogamp.newt.MonitorMode;
public class ScreenDriver extends ScreenImpl {
- protected static final boolean DEBUG_TEST_RANDR13_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableRandR13", true);
+ protected static final boolean DEBUG_TEST_RANDR13_DISABLED;
static {
+ Debug.initSingleton();
+ DEBUG_TEST_RANDR13_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableRandR13", true);
+
DisplayDriver.initSingleton();
}
+ /** Ensure static init has been run. */
+ /* pp */static void initSingleton() { }
+
public ScreenDriver() {
}
@@ -81,11 +88,12 @@ public class ScreenDriver extends ScreenImpl {
randrVersion = new VersionNumber(v[0], v[1], 0);
}
{
- final RandR13 rAndR13 = DEBUG_TEST_RANDR13_DISABLED ? null : RandR13.createInstance(randrVersion);
- if( null != rAndR13 ) {
- rAndR = rAndR13;
+ if( !DEBUG_TEST_RANDR13_DISABLED && randrVersion.compareTo(RandR.version130) >= 0 ) {
+ rAndR = new RandR13();
+ } else if( randrVersion.compareTo(RandR.version110) >= 0 ) {
+ rAndR = new RandR11();
} else {
- rAndR = RandR11.createInstance(randrVersion);
+ rAndR = null;
}
}
if( DEBUG ) {
@@ -183,7 +191,7 @@ public class ScreenDriver extends ScreenImpl {
if( null == rAndR ) { return false; }
final long t0 = System.currentTimeMillis();
- boolean done = runWithTempDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
+ boolean done = runWithOptTempDisplayHandle( new DisplayImpl.DisplayRunnable<Boolean>() {
public Boolean run(long dpy) {
return Boolean.valueOf( rAndR.setCurrentMonitorMode(dpy, ScreenDriver.this, monitor, mode) );
}
@@ -214,14 +222,31 @@ public class ScreenDriver extends ScreenImpl {
@Override
protected void calcVirtualScreenOriginAndSize(final Rectangle vOriginSize) {
- runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
- public Object run(long dpy) {
- vOriginSize.setX(0);
- vOriginSize.setY(0);
- vOriginSize.setWidth(getWidth0(dpy, screen_idx));
- vOriginSize.setHeight(getHeight0(dpy, screen_idx));
- return null;
- } } );
+ final RectangleImmutable ov = (RectangleImmutable) getViewport().cloneMutable();
+ /**
+ if( null != rAndR && rAndR.getVersion().compareTo(RandR.version130) >= 0 && getMonitorDevices().size()>0 ) {
+ super.calcVirtualScreenOriginAndSize(vOriginSize);
+ if( DEBUG ) {
+ System.err.println("X11Screen.calcVirtualScreenOriginAndSize: UpdatingViewport "+ov+" -> "+vOriginSize);
+ }
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ public Object run(long dpy) {
+ rAndR.updateScreenViewport(dpy, ScreenDriver.this, vOriginSize);
+ return null;
+ } } );
+ } else */ {
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ public Object run(long dpy) {
+ vOriginSize.setX(0);
+ vOriginSize.setY(0);
+ vOriginSize.setWidth(getWidth0(dpy, screen_idx));
+ vOriginSize.setHeight(getHeight0(dpy, screen_idx));
+ return null;
+ } } );
+ if( DEBUG ) {
+ System.err.println("X11Screen.calcVirtualScreenOriginAndSize: Querying X11: "+ov+" -> "+vOriginSize);
+ }
+ }
}
//----------------------------------------------------------------------
@@ -245,6 +270,14 @@ public class ScreenDriver extends ScreenImpl {
return res;
}
+ private final <T> T runWithOptTempDisplayHandle(DisplayRunnable<T> action) {
+ if( null != rAndR && rAndR.getVersion().compareTo(RandR.version130) >= 0 ) {
+ return display.runWithLockedDisplayDevice(action);
+ } else {
+ return runWithTempDisplayHandle(action);
+ }
+ }
+
private static native long GetScreen0(long dpy, int scrn_idx);
private static native int getWidth0(long display, int scrn_idx);
diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
index 69a09c1f9..4786ea04f 100644
--- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
+++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
@@ -59,12 +59,13 @@ public class WindowDriver extends WindowImpl {
private static final int X11_WHEEL_TWO_DOWN_BUTTON = 7;
static {
- DisplayDriver.initSingleton();
+ ScreenDriver.initSingleton();
}
public WindowDriver() {
}
+ @Override
protected void createNativeImpl() {
final ScreenDriver screen = (ScreenDriver) getScreen();
final DisplayDriver display = (DisplayDriver) screen.getDisplay();
@@ -109,6 +110,7 @@ public class WindowDriver extends WindowImpl {
}
}
+ @Override
protected void closeNativeImpl() {
if(0!=windowHandleClose && null!=getScreen() ) {
DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
@@ -133,7 +135,19 @@ public class WindowDriver extends WindowImpl {
}
}
- protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
+ /**
+ * <p>
+ * X11 Window supports {@link #FLAG_IS_FULLSCREEN_SPAN}
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean isReconfigureFlagSupported(int changeFlags) {
+ return true; // all flags!
+ }
+
+ @Override
+ protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, int flags) {
if(DEBUG_IMPLEMENTATION) {
System.err.println("X11Window reconfig: "+x+"/"+y+" "+width+"x"+height+", "+ getReconfigureFlagsAsString(null, flags));
}
@@ -148,18 +162,57 @@ public class WindowDriver extends WindowImpl {
_x = x;
_y = y;
}
+ if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags ) ) {
+ if( 0 != ( FLAG_IS_FULLSCREEN & flags) && 0 != ( FLAG_IS_FULLSCREEN_SPAN & flags) && 0 == ( FLAG_IS_ALWAYSONTOP & flags) ) {
+ tempFSAlwaysOnTop = true;
+ flags |= FLAG_IS_ALWAYSONTOP;
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("X11Window reconfig.2: temporary "+getReconfigureFlagsAsString(null, flags));
+ }
+ } else {
+ tempFSAlwaysOnTop = false;
+ }
+ }
+ final int fflags = flags;
final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
public Object run(long dpy) {
reconfigureWindow0( dpy, getScreenIndex(),
getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
- _x, _y, width, height, flags);
+ _x, _y, width, height, fflags);
return null;
}
});
return true;
}
+ volatile boolean tempFSAlwaysOnTop = false;
+ /**
+ * <p>
+ * Deal w/ tempAlwaysOnTop.
+ * </p>
+ * {@inheritDoc}
+ */
+ @Override
+ protected void focusChanged(boolean defer, boolean focusGained) {
+ if( tempFSAlwaysOnTop && hasFocus() != focusGained && isNativeValid() ) {
+ final int flags = getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()) | ( focusGained ? FLAG_IS_ALWAYSONTOP : 0 );
+ if(DEBUG_IMPLEMENTATION) {
+ System.err.println("X11Window reconfig.3 (focus): temporary "+getReconfigureFlagsAsString(null, flags));
+ }
+ final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
+ runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
+ public Object run(long dpy) {
+ reconfigureWindow0( dpy, getScreenIndex(),
+ getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
+ getX(), getY(), getWidth(), getHeight(), flags);
+ return null;
+ }
+ });
+ }
+ super.focusChanged(defer, focusGained);
+ }
+
protected void reparentNotify(long newParentWindowHandle) {
if(DEBUG_IMPLEMENTATION) {
final long p0 = getParentWindowHandle();
@@ -167,6 +220,7 @@ public class WindowDriver extends WindowImpl {
}
}
+ @Override
protected void requestFocusImpl(final boolean force) {
runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
public Object run(long dpy) {
@@ -214,6 +268,7 @@ public class WindowDriver extends WindowImpl {
});
}
+ @Override
protected Point getLocationOnScreenImpl(final int x, final int y) {
return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Point>() {
public Point run(long dpy) {
@@ -222,6 +277,7 @@ public class WindowDriver extends WindowImpl {
} );
}
+ @Override
protected void updateInsetsImpl(Insets insets) {
// nop - using event driven insetsChange(..)
}
@@ -241,16 +297,17 @@ public class WindowDriver extends WindowImpl {
}
break;
case MouseEvent.EVENT_MOUSE_RELEASED:
+ final boolean shiftPressed = 0 != ( modifiers & InputEvent.SHIFT_MASK );
switch(button) {
case X11_WHEEL_ONE_UP_BUTTON: // vertical scroll up
eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
button = 1;
- rotationXYZ[1] = 1;
+ rotationXYZ[shiftPressed ? 0 : 1] = 1;
break;
case X11_WHEEL_ONE_DOWN_BUTTON: // vertical scroll down
eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
button = 1;
- rotationXYZ[1] = -1;
+ rotationXYZ[shiftPressed ? 0 : 1] = -1;
break;
case X11_WHEEL_TWO_UP_BUTTON: // horizontal scroll left
eventType = MouseEvent.EVENT_MOUSE_WHEEL_MOVED;
@@ -269,7 +326,8 @@ public class WindowDriver extends WindowImpl {
}
super.doMouseEvent(enqueue, wait, eventType, modifiers, x, y, button, rotationXYZ, rotationScale);
}
-
+
+ /** Called by native TK */
protected final void sendKeyEvent(short eventType, int modifiers, short keyCode, short keySym, char keyChar0, String keyString) {
// handleKeyEvent(true, false, eventType, modifiers, keyCode, keyChar);
final boolean isModifierKey = KeyEvent.isModifierKey(keyCode);
@@ -287,9 +345,6 @@ public class WindowDriver extends WindowImpl {
case KeyEvent.EVENT_KEY_RELEASED:
super.sendKeyEvent(KeyEvent.EVENT_KEY_RELEASED, modifiers, keyCode, keySym, keyChar);
break;
-
- // case KeyEvent.EVENT_KEY_TYPED:
- // break;
}
}
}
diff --git a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
index 2008b5ea4..d46562050 100644
--- a/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
+++ b/src/newt/classes/jogamp/newt/swt/SWTEDTUtil.java
@@ -46,7 +46,7 @@ public class SWTEDTUtil implements EDTUtil {
private final String name;
private final Runnable dispatchMessages;
private final org.eclipse.swt.widgets.Display swtDisplay;
- private NewtEventDispatchThread nedt = null;
+ private NEDT nedt = null;
private int start_iter=0;
private static long pollPeriod = EDTUtil.defaultEDTPollPeriod;
@@ -58,7 +58,7 @@ public class SWTEDTUtil implements EDTUtil {
((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages();
} };
this.swtDisplay = swtDisplay;
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
+ this.nedt = new NEDT(threadGroup, name);
this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
}
@@ -77,24 +77,39 @@ public class SWTEDTUtil implements EDTUtil {
}
@Override
- public void reset() {
- synchronized(edtLock) {
- waitUntilStopped();
+ public final boolean restart() throws IllegalStateException {
+ final boolean swtDisposed = swtDisplay.isDisposed();
+ synchronized(edtLock) {
+ if( nedt.isRunning() ) {
+ final Thread curT = Thread.currentThread();
+ final Thread swtT = !swtDisposed ? swtDisplay.getThread() : null;
+ final boolean onSWTEDT = swtT == curT;
+ throw new IllegalStateException("EDT still running and not subject to stop. Curr "+curT.getName()+", NEDT "+nedt.getName()+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", SWT-EDT "+swtT.getName()+", on SWT-EDT "+onSWTEDT);
+ }
if(DEBUG) {
- System.err.println(Thread.currentThread()+": SWT-EDT reset - edt: "+nedt);
+ System.err.println(Thread.currentThread()+": SWT-EDT reset - edt: "+nedt+", swtDisposed (skipping) "+swtDisposed);
+ }
+ if( !swtDisposed ) {
+ if( nedt.getState() != Thread.State.NEW ) {
+ nedt = new NEDT(threadGroup, name);
+ nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+ startImpl();
}
- this.nedt = new NewtEventDispatchThread(threadGroup, name);
- this.nedt.setDaemon(true); // don't stop JVM from shutdown ..
+ }
+ if( !swtDisposed ) {
+ return invoke(true, nullTask);
+ } else {
+ return false;
}
}
private final void startImpl() {
if(nedt.isAlive()) {
- throw new RuntimeException("SWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt);
+ throw new RuntimeException("SWT-EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning+", shouldStop "+nedt.shouldStop+", edt: "+nedt);
}
start_iter++;
nedt.setName(name+start_iter);
- nedt.shouldStop = false;
if(DEBUG) {
System.err.println(Thread.currentThread()+": SWT-EDT START - edt: "+nedt);
// Thread.dumpStack();
@@ -104,7 +119,7 @@ public class SWTEDTUtil implements EDTUtil {
@Override
public boolean isCurrentThreadEDT() {
- return swtDisplay.getThread() == Thread.currentThread();
+ return !swtDisplay.isDisposed() && swtDisplay.getThread() == Thread.currentThread();
}
@Override
@@ -115,66 +130,94 @@ public class SWTEDTUtil implements EDTUtil {
@Override
public final boolean isCurrentThreadEDTorNEDT() {
final Thread ct = Thread.currentThread();
- return ct == swtDisplay.getThread() || ct == nedt ;
+ return ( !swtDisplay.isDisposed() && ct == swtDisplay.getThread() ) || ct == nedt ;
}
@Override
public boolean isRunning() {
- return nedt.isRunning() ; // SWT is always running
+ return nedt.isRunning();
}
@Override
- public final void invokeStop(Runnable task) {
- invokeImpl(true, task, true);
+ public final boolean invokeStop(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, true);
}
@Override
- public final void invoke(boolean wait, Runnable task) {
- invokeImpl(wait, task, false);
+ public final boolean invoke(boolean wait, Runnable task) {
+ return invokeImpl(wait, task, false);
}
- private void invokeImpl(boolean wait, Runnable task, boolean stop) {
+ private static Runnable nullTask = new Runnable() {
+ @Override
+ public void run() { }
+ };
+
+ private final boolean invokeImpl(boolean wait, Runnable task, boolean stop) {
Throwable throwable = null;
RunnableTask rTask = null;
- Object rTaskLock = new Object();
+ final Object rTaskLock = new Object();
synchronized(rTaskLock) { // lock the optional task execution
synchronized(edtLock) { // lock the EDT status
if( nedt.shouldStop ) {
// drop task ..
if(DEBUG) {
- System.err.println(Thread.currentThread()+": Warning: SWT-EDT about (1) to stop, won't enqueue new task: "+nedt);
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT about (1) to stop, won't enqueue new task: "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop);
Thread.dumpStack();
}
- return;
+ return false;
+ }
+ if( swtDisplay.isDisposed() ) {
+ stop = true;
}
- // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task);
- // Thread.dumpStack();
- if(stop) {
- synchronized(nedt.sync) {
+
+ if( isCurrentThreadEDT() ) {
+ if(null != task) {
+ task.run();
+ }
+ wait = false; // running in same thread (EDT) -> no wait
+ if( stop ) {
nedt.shouldStop = true;
- nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
}
- if(DEBUG) {
- System.err.println(Thread.currentThread()+": SWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt);
- // Thread.dumpStack();
+ } else {
+ if( !nedt.isRunning && !swtDisplay.isDisposed() ) {
+ if( null != task ) {
+ if( stop ) {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT is about (3) to stop and stopped already, dropping task. NEDT "+nedt);
+ } else {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT is not running, dropping task. NEDT "+nedt);
+ }
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ }
+ return false;
+ } else if( stop ) {
+ if( nedt.isRunning ) {
+ if(DEBUG) {
+ System.err.println(Thread.currentThread()+": SWT-EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt+", isRunning "+nedt.isRunning+", shouldStop "+nedt.shouldStop);
+ }
+ synchronized(nedt.sync) {
+ nedt.shouldStop = true;
+ nedt.sync.notifyAll(); // stop immediate if waiting (poll freq)
+ }
+ }
+ if( swtDisplay.isDisposed() ) {
+ System.err.println(Thread.currentThread()+": Warning: SWT-EDT is about (3) to stop and stopped already, dropping task. "+nedt);
+ if(DEBUG) {
+ Thread.dumpStack();
+ }
+ return false;
+ }
+ }
+
+ if( null != task ) {
+ rTask = new RunnableTask(task,
+ wait ? rTaskLock : null,
+ true /* always catch and report Exceptions, don't disturb EDT */,
+ wait ? null : System.err);
+ swtDisplay.asyncExec(rTask);
}
- } else if( !nedt.isRunning() ) {
- // start if should not stop && not started yet
- startImpl();
- }
- if( null == task ) {
- wait = false;
- } else if( isCurrentThreadEDT() ) {
- task.run();
- wait = false; // running in same thread (EDT) -> no wait
- } else if( swtDisplay.isDisposed() ) {
- wait = false; // drop task, SWT disposed
- } else {
- rTask = new RunnableTask(task,
- wait ? rTaskLock : null,
- true /* always catch and report Exceptions, don't disturb EDT */,
- wait ? null : System.err);
- swtDisplay.asyncExec(rTask);
}
}
if( wait ) {
@@ -193,53 +236,60 @@ public class SWTEDTUtil implements EDTUtil {
throw new RuntimeException(throwable);
}
}
+ return true;
}
}
@Override
- final public void waitUntilIdle() {
- final NewtEventDispatchThread _nedt;
+ final public boolean waitUntilIdle() {
+ final NEDT _nedt;
synchronized(edtLock) {
_nedt = nedt;
}
final Thread ct = Thread.currentThread();
- if(!_nedt.isRunning() || _nedt == ct || swtDisplay.getThread() == ct) {
- return;
+ if( !_nedt.isRunning || _nedt == ct || swtDisplay.isDisposed() || swtDisplay.getThread() == ct ) {
+ return false;
}
try {
swtDisplay.syncExec(new Runnable() {
public void run() { }
});
} catch (Exception e) { }
+ return true;
}
@Override
- final public void waitUntilStopped() {
+ final public boolean waitUntilStopped() {
synchronized(edtLock) {
- final Thread ct = Thread.currentThread();
- if(nedt.isRunning() && nedt != ct && swtDisplay.getThread() != ct) {
- while(nedt.isRunning()) {
+ final Thread curT = Thread.currentThread();
+ final Thread swtT = !swtDisplay.isDisposed() ? swtDisplay.getThread() : null;
+ final boolean onSWTEDT = swtT == curT;
+ if( nedt.isRunning && nedt != curT && !onSWTEDT ) {
+ while( nedt.isRunning ) {
try {
edtLock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
+ return true;
+ } else {
+ return false;
}
}
}
- class NewtEventDispatchThread extends Thread {
+ class NEDT extends Thread {
volatile boolean shouldStop = false;
volatile boolean isRunning = false;
Object sync = new Object();
- public NewtEventDispatchThread(ThreadGroup tg, String name) {
+ public NEDT(ThreadGroup tg, String name) {
super(tg, name);
}
final public boolean isRunning() {
- return isRunning;
+ return isRunning && !shouldStop;
}
@Override
@@ -296,10 +346,8 @@ public class SWTEDTUtil implements EDTUtil {
System.err.println(getName()+": SWT-EDT run() END "+ getName()+", "+error);
}
synchronized(edtLock) {
- isRunning = !shouldStop;
- if(!isRunning) {
- edtLock.notifyAll();
- }
+ isRunning = false;
+ edtLock.notifyAll();
}
if(DEBUG) {
System.err.println(getName()+": SWT-EDT run() EXIT "+ getName()+", exception: "+error);
diff --git a/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
index 1e99d1ef7..3782a1186 100644
--- a/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
+++ b/src/newt/classes/jogamp/newt/swt/event/SWTNewtEventFactory.java
@@ -56,7 +56,6 @@ public class SWTNewtEventFactory {
case SWT.KeyDown: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_PRESSED;
case SWT.KeyUp: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_RELEASED;
- // case SWT.KeyXXX: return com.jogamp.newt.event.KeyEvent.EVENT_KEY_TYPED;
}
return (short)0;
}