summaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2010-11-16 10:36:28 +0100
committerSven Gothel <[email protected]>2010-11-16 10:36:28 +0100
commitdb4d7d198cc826bba871fea39461c3c8a2a3b1c6 (patch)
tree723c5d4958df50a2ca7443171873e6f854c745a5 /src/newt
parentb3420aeb07f9bef1e4fe5f436524d0b3d66cfaa2 (diff)
NEWT Lifecycle remodel: Window destroy() !
NEWT's removed: Window: destoy(boolean unrecoverable) Display/Screen: get/set DestroyWhenUnused(boolean) We behave as follows: - Window.destroy() always decr Screen's reference counter, which issues destruction when reached zero. Then Screen does the same for Display .. - Window.destroy() keeps alive all references, hence it can be always recreated via setVisible(true). - Window.destroy() ensures Display's EDT is stopped if display is destroyed. - Window.invalidate() actually removes all Object reference, hence it cannot be recreated or used after it. This method exist to support a way to cleanup memory, GC. All test passed on Linux/X11 and Windows
Diffstat (limited to 'src/newt')
-rw-r--r--src/newt/classes/com/jogamp/newt/Display.java42
-rw-r--r--src/newt/classes/com/jogamp/newt/NewtFactory.java2
-rw-r--r--src/newt/classes/com/jogamp/newt/Screen.java42
-rw-r--r--src/newt/classes/com/jogamp/newt/Window.java28
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java22
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java2
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java32
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java6
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java32
-rw-r--r--src/newt/classes/com/jogamp/newt/impl/WindowImpl.java319
-rw-r--r--src/newt/classes/com/jogamp/newt/opengl/GLWindow.java46
11 files changed, 299 insertions, 274 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java
index 19733723e..3e5c0c25e 100644
--- a/src/newt/classes/com/jogamp/newt/Display.java
+++ b/src/newt/classes/com/jogamp/newt/Display.java
@@ -54,43 +54,39 @@ public abstract class Display {
}
/**
- * Manual trigger the native creation.<br>
+ * Manual trigger the native creation, if it is not done yet.<br>
* This is useful to be able to request the {@link javax.media.nativewindow.AbstractGraphicsDevice}, via
- * {@link #getGraphicsDevice()}. Otherwise the abstract device won't be available before the dependent components (Screen and Window)
- * are realized.
+ * {@link #getGraphicsDevice()}.<br>
+ * Otherwise the abstract device won't be available before the dependent components (Screen and Window) are realized.
+ * <p>
+ * This method is usually invoke by {@link #addReference()}
+ * </p>
* @throws NativeWindowException if the native creation failed.
*/
public abstract void createNative() throws NativeWindowException;
- public abstract void destroy();
-
/**
- * @return true if the native display handle is valid and ready to operate,
- * otherwise false.
- *
- * @see #destroy()
+ * Manually trigger the destruction, incl. native destruction.<br>
+ * <p>
+ * This method is usually invoke by {@link #removeReference()}
+ * </p>
*/
- public abstract boolean isNativeValid();
+ public abstract void destroy();
/**
- * @return the value set by {@link #setDestroyWhenUnused(boolean)}
- * or the default <code>false</code>.
- *
- * @see #addReference()
- * @see #removeReference()
+ * Validate EDT running state.<br>
+ * Stop the running EDT in case this display is destroyed already.<br>
+ * @return true if EDT has been stopped (destroyed but running), otherwise false.
*/
- public abstract boolean getDestroyWhenUnused();
+ public abstract boolean validateEDT();
/**
- * Handles the lifecycle of the native Display instance.<br>
- * If set to <code>true</code>, the last {@link #removeReference()} call
- * will destroy this instance, otherwise it will stay alive.<br>
- * Default is <code>false</code>.
+ * @return true if the native display handle is valid and ready to operate,
+ * otherwise false.
*
- * @see #addReference()
- * @see #removeReference()
+ * @see #destroy()
*/
- public abstract void setDestroyWhenUnused(boolean v);
+ public abstract boolean isNativeValid();
/**
* @return number of references by Screen
diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java
index e1b15da69..892a2426e 100644
--- a/src/newt/classes/com/jogamp/newt/NewtFactory.java
+++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java
@@ -162,7 +162,6 @@ public class NewtFactory {
Display display = NewtFactory.createDisplay(type, null, true); // local display
screen = NewtFactory.createScreen(display, 0); // screen 0
}
- screen.setDestroyWhenUnused(true);
}
final Window win = createWindowImpl(nParentWindow, screen, caps);
@@ -189,7 +188,6 @@ public class NewtFactory {
protected static Window createWindowImpl(String type, Capabilities caps) {
Display display = NewtFactory.createDisplay(type, null, true); // local display
Screen screen = NewtFactory.createScreen(display, 0); // screen 0
- screen.setDestroyWhenUnused(true);
return WindowImpl.create(null, 0, screen, caps);
}
diff --git a/src/newt/classes/com/jogamp/newt/Screen.java b/src/newt/classes/com/jogamp/newt/Screen.java
index a6d45d789..bf8c6f0eb 100644
--- a/src/newt/classes/com/jogamp/newt/Screen.java
+++ b/src/newt/classes/com/jogamp/newt/Screen.java
@@ -59,38 +59,36 @@ public abstract class Screen {
}
/**
- * Manual trigger the native creation.<br>
+ * Manual trigger the native creation, if it is not done yet..<br>
* This is useful to be able to request the {@link javax.media.nativewindow.AbstractGraphicsScreen}, via
- * {@link #getGraphicsScreen()}. Otherwise the abstract device won't be available before the dependent component (Window)
- * is realized.
+ * {@link #getGraphicsScreen()}.<br>
+ * Otherwise the abstract device won't be available before the dependent component (Window) is realized.
+ * <p>
+ * This method is usually invoke by {@link #addReference()}
+ * </p>
+ * <p>
+ * This method invokes {@link Display#addReference()} after creating the native peer,<br>
+ * which will issue {@link Display#createNative()} if the reference count was 0.
+ * </p>
* @throws NativeWindowException if the native creation failed.
*/
public abstract void createNative() throws NativeWindowException;
- public abstract void destroy();
-
- public abstract boolean isNativeValid();
-
/**
- * @return {@link Display#getDestroyWhenUnused()}
- *
- * @see #addReference()
- * @see #removeReference()
- * @see Display#setDestroyWhenUnused(boolean)
+ * Manually trigger the destruction, incl. native destruction.<br>
+ * <p>
+ * This method is usually invoke by {@link #removeReference()}
+ * </p>
+ * <p>
+ * This method invokes {@link Display#removeReference()} after it's own destruction,<br>
+ * which will issue {@link Display#destroy()} if the reference count becomes 0.
+ * </p>
*/
- public abstract boolean getDestroyWhenUnused();
+ public abstract void destroy();
- /**
- * calls {@link Display#setDestroyWhenUnused(boolean)}.
- *
- * @see #addReference()
- * @see #removeReference()
- * @see Display#setDestroyWhenUnused(boolean)
- */
- public abstract void setDestroyWhenUnused(boolean v);
+ public abstract boolean isNativeValid();
/**
- *
* @return number of references by Window
*/
public abstract int getReferenceCount();
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java
index ba7d51e67..9307ea7f7 100644
--- a/src/newt/classes/com/jogamp/newt/Window.java
+++ b/src/newt/classes/com/jogamp/newt/Window.java
@@ -87,30 +87,24 @@ public interface Window extends NativeWindow, ScreenModeListener {
Capabilities getChosenCapabilities();
/**
- *
- * <p>
- * destroys the window and children and releases
- * windowing related resources.<br></p>
+ * Destroy the Window and it's children, incl. native destruction.<br>
+ * The Window can be recreate via {@link #setVisible(boolean) setVisible(true)}.
* <p>
- * all other resources and states are kept intact,
- * ie listeners, parent handles, size, position and Screen reference.<br></p>
- *
- * @see #destroy(boolean)
+ * This method invokes {@link Screen#removeReference()} after it's own destruction,<br>
+ * which will issue {@link Screen#destroy()} if the reference count becomes 0.<br>
+ * This destruction sequence shall end up in {@link Display#destroy()}, if all reference counts become 0.
+ * </p>
* @see #invalidate()
+ * @see #setVisible(boolean)
*/
void destroy();
/**
- *
- * Destroys the Window and it's children.
- * @param unrecoverable If true, all resources, ie listeners, parent handles,
- * size, position and reference to it's Screen will be destroyed as well.
- * Otherwise you can recreate the window, via <code>setVisible(true)</code>.
- * @see #destroy()
- * @see #invalidate(boolean)
- * @see #setVisible(boolean)
+ * Destroys the Window via {@link #destroy()} and clears all Object references,
+ * eg. all states, size, position, parent handles, list of child Windows and reference to it's Screen.<br>
+ * This Window cannot be recreated after calling this method anymore.<br>
*/
- void destroy(boolean unrecoverable);
+ void invalidate();
/**
* <p>
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
index 3ba721855..a0ab5f9f6 100644
--- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
+++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java
@@ -193,37 +193,27 @@ public class NewtCanvasAWT extends java.awt.Canvas {
}
/**
- * @see #destroy(boolean)
- */
- public final void destroy() {
- destroy(false);
- }
-
- /**
* Destroys this resource:
* <ul>
* <li> Make the NEWT Child invisible </li>
* <li> Disconnects the NEWT Child from this Canvas NativeWindow, reparent to NULL </li>
- * <li> Issues <code>destroy(unrecoverable)</code> on the NEWT Child</li>
- * <li> Remove reference to the NEWT Child, if unrecoverable</li>
+ * <li> Issues <code>destroy()</code> on the NEWT Child</li>
+ * <li> Remove reference to the NEWT Child</li>
* <li> Remove this Canvas from it's parent.</li>
* </ul>
* @see Window#destroy()
- * @see Window#destroy(boolean)
*/
- public final void destroy(boolean unrecoverable) {
+ public final void destroy() {
if(null!=newtChild) {
java.awt.Container cont = getContainer(this);
if(DEBUG) {
- System.err.println("NewtCanvasAWT.destroy("+unrecoverable+"): "+newtChild+", from "+cont);
+ System.err.println("NewtCanvasAWT.destroy(): "+newtChild+", from "+cont);
}
nativeWindow = null;
newtChild.setVisible(false);
newtChild.reparentWindow(null);
- newtChild.destroy(unrecoverable);
- if(unrecoverable) {
- newtChild = null;
- }
+ newtChild.destroy();
+ newtChild=null;
if(null!=cont) {
cont.remove(this);
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java b/src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java
index e2b3b81ef..7a2a0c9bd 100644
--- a/src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java
+++ b/src/newt/classes/com/jogamp/newt/impl/DefaultEDTUtil.java
@@ -57,6 +57,7 @@ public class DefaultEDTUtil implements EDTUtil {
this.name=new String(Thread.currentThread().getName()+"-"+name+"-EDT-");
this.dispatchMessages=dispatchMessages;
this.edt = new EventDispatchThread(threadGroup, name);
+ this.edt.setDaemon(true); // don't stop JVM from shutdown ..
}
public final void reset() {
@@ -72,6 +73,7 @@ public class DefaultEDTUtil implements EDTUtil {
System.err.println(Thread.currentThread()+": EDT reset - edt: "+edt);
}
this.edt = new EventDispatchThread(threadGroup, name);
+ this.edt.setDaemon(true); // don't stop JVM from shutdown ..
}
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java b/src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java
index 7983a1118..2af01c217 100644
--- a/src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java
+++ b/src/newt/classes/com/jogamp/newt/impl/DisplayImpl.java
@@ -181,13 +181,29 @@ public abstract class DisplayImpl extends Display {
}
}
+ public boolean validateEDT() {
+ if(0==refCount && null==aDevice && null != edtUtil && edtUtil.isRunning()) {
+ stopEDT( new Runnable() {
+ public void run() {
+ // nop
+ }
+ } );
+ edtUtil.waitUntilStopped();
+ edtUtil.reset();
+ return true;
+ }
+ return false;
+ }
+
public synchronized final void destroy() {
if(DEBUG) {
dumpDisplayList("Display.destroy("+getFQName()+") BEGIN");
}
synchronized(displayList) {
displayList.remove(this);
- displaysActive--;
+ if(0 < displaysActive) {
+ displaysActive--;
+ }
}
if(DEBUG) {
System.err.println("Display.destroy(): "+this+" "+getThreadName());
@@ -225,7 +241,7 @@ public abstract class DisplayImpl extends Display {
if(null == aDevice) {
throw new NativeWindowException ("Display.addReference() (refCount "+refCount+") null AbstractGraphicsDevice");
}
- return ++refCount;
+ return refCount++;
}
@@ -233,9 +249,10 @@ public abstract class DisplayImpl extends Display {
if(DEBUG) {
System.err.println("Display.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
}
- refCount--; // could become < 0, in case of forced destruction without actual creation/addReference
- if(0>=refCount && getDestroyWhenUnused()) {
+ refCount--; // could become < 0, in case of manual destruction without actual creation/addReference
+ if(0>=refCount) {
destroy();
+ refCount=0; // fix < 0
}
return refCount;
}
@@ -244,9 +261,6 @@ public abstract class DisplayImpl extends Display {
return refCount;
}
- public final boolean getDestroyWhenUnused() { return destroyWhenUnused; }
- public final void setDestroyWhenUnused(boolean v) { destroyWhenUnused=v; }
-
protected abstract void createNativeImpl();
protected abstract void closeNativeImpl();
@@ -275,7 +289,7 @@ public abstract class DisplayImpl extends Display {
return ( null == name ) ? nilString : name ;
}
- protected static final String getFQName(String type, String name, int id) {
+ private static final String getFQName(String type, String name, int id) {
if(null==type) type=nilString;
if(null==name) name=nilString;
StringBuffer sb = new StringBuffer();
@@ -284,7 +298,7 @@ public abstract class DisplayImpl extends Display {
sb.append(name);
sb.append("-");
sb.append(id);
- return sb.toString();
+ return sb.toString().intern();
}
public final long getHandle() {
diff --git a/src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java b/src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java
index f3c7b8415..30dc945db 100644
--- a/src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java
+++ b/src/newt/classes/com/jogamp/newt/impl/OffscreenWindow.java
@@ -68,13 +68,13 @@ public class OffscreenWindow extends WindowImpl implements SurfaceChangeable {
// nop
}
- public void invalidate(boolean unrecoverable) {
+ protected void invalidate(boolean unrecoverable) {
super.invalidate(unrecoverable);
surfaceHandle = 0;
}
- public synchronized void destroy(boolean unrecoverable) {
- super.destroy(unrecoverable);
+ public synchronized void destroy() {
+ super.destroy();
surfaceHandle = 0;
}
diff --git a/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java b/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java
index c9d1a9c32..071122a68 100644
--- a/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java
+++ b/src/newt/classes/com/jogamp/newt/impl/ScreenImpl.java
@@ -50,7 +50,8 @@ import java.util.ArrayList;
import java.util.List;
public abstract class ScreenImpl extends Screen implements ScreenModeListener {
- protected static final boolean DisableScreenModeImpl = Debug.debug("Screen.DisableScreenModeImpl");
+ protected static final boolean DEBUG_TEST_SCREENMODE_DISABLED = Debug.isPropertyDefined("newt.test.Screen.disableScreenMode", true);
+
protected DisplayImpl display;
protected int screen_idx;
protected String fqname;
@@ -112,7 +113,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
ScreenImpl screen = (ScreenImpl) screenClass.newInstance();
screen.display = (DisplayImpl) display;
screen.screen_idx = idx;
- screen.fqname = display.getFQName()+idx;
+ screen.fqname = (display.getFQName()+idx).intern();
screen.hashCode = screen.fqname.hashCode();
screenList.add(screen);
if(DEBUG) {
@@ -157,7 +158,9 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
synchronized(screenList) {
screenList.remove(this);
- screensActive--;
+ if(0 < screensActive) {
+ screensActive--;
+ }
}
if ( null != aScreen ) {
@@ -183,11 +186,15 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
public synchronized final int removeReference() {
if(DEBUG) {
- System.err.println("Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1));
+ String msg = "Screen.removeReference() ("+DisplayImpl.getThreadName()+"): "+refCount+" -> "+(refCount-1);
+ // Throwable t = new Throwable(msg);
+ // t.printStackTrace();
+ System.err.println(msg);
}
- refCount--; // could become < 0, in case of forced destruction without actual creation/addReference
- if(0>=refCount && getDestroyWhenUnused()) {
+ refCount--; // could become < 0, in case of manual destruction without actual creation/addReference
+ if(0>=refCount) {
destroy();
+ refCount=0; // fix < 0
}
return refCount;
}
@@ -196,13 +203,6 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
return refCount;
}
- public final boolean getDestroyWhenUnused() {
- return display.getDestroyWhenUnused();
- }
- public final void setDestroyWhenUnused(boolean v) {
- display.setDestroyWhenUnused(v);
- }
-
protected abstract void createNativeImpl();
protected abstract void closeNativeImpl();
@@ -260,7 +260,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
ScreenMode smU = null;
ScreenModeStatus sms = ScreenModeStatus.getScreenModeStatus(this.getFQName());
if(null != sms) {
- ScreenMode sm0 = ( DisableScreenModeImpl ) ? null : getCurrentScreenModeImpl();
+ ScreenMode sm0 = ( DEBUG_TEST_SCREENMODE_DISABLED ) ? null : getCurrentScreenModeImpl();
if(null == sm0) {
return null;
}
@@ -415,7 +415,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
ArrayHashSet screenModes = collectNativeScreenModes(screenModesIdx2NativeIdx);
sms = new ScreenModeStatus(screenModes, screenModesIdx2NativeIdx);
if(null!=screenModes && screenModes.size()>0) {
- ScreenMode originalScreenMode = ( DisableScreenModeImpl ) ? null : getCurrentScreenModeImpl();
+ ScreenMode originalScreenMode = ( DEBUG_TEST_SCREENMODE_DISABLED ) ? null : getCurrentScreenModeImpl();
if(null != originalScreenMode) {
ScreenMode originalScreenMode0 = (ScreenMode) screenModes.get(originalScreenMode); // unify via value hash
if(null == originalScreenMode0) {
@@ -450,7 +450,7 @@ public abstract class ScreenImpl extends Screen implements ScreenModeListener {
+ ScreenModeUtil.NUM_SURFACE_SIZE_PROPERTIES
- 1 ; // index 0 based
do {
- if(DisableScreenModeImpl) {
+ if(DEBUG_TEST_SCREENMODE_DISABLED) {
smProps = null;
} else if(0 == num) {
smProps = getScreenModeFirstImpl();
diff --git a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java
index c34081ebf..9f744be82 100644
--- a/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java
+++ b/src/newt/classes/com/jogamp/newt/impl/WindowImpl.java
@@ -71,6 +71,59 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
{
public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true);
+ private RecursiveLock windowLock = new RecursiveLock();
+ private long windowHandle;
+ private ScreenImpl screen;
+ private boolean screenReferenceAdded = false;
+ private NativeWindow parentWindow;
+ private long parentWindowHandle;
+ protected AbstractGraphicsConfiguration config;
+ protected Capabilities caps;
+ protected boolean fullscreen, visible, hasFocus;
+ protected int width, height, x, y;
+ protected int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen dimensions ..
+ protected String title = "Newt Window";
+ protected boolean undecorated = false;
+ private LifecycleHook lifecycleHook = null;
+
+ private DestroyAction destroyAction = new DestroyAction();
+ private boolean handleDestroyNotify = true;
+
+ private ReparentActionRecreate reparentActionRecreate = new ReparentActionRecreate();
+
+ private RequestFocusAction requestFocusAction = new RequestFocusAction();
+ private FocusRunnable focusAction = null;
+
+ private Object surfaceUpdatedListenersLock = new Object();
+ private ArrayList surfaceUpdatedListeners;
+
+ private Object childWindowsLock = new Object();
+ private ArrayList childWindows;
+
+ private ArrayList mouseListeners;
+ private int mouseButtonPressed; // current pressed mouse button number
+ private long lastMousePressed; // last time when a mouse button was pressed
+ private int lastMouseClickCount; // last mouse button click count
+
+ private ArrayList keyListeners;
+
+ private ArrayList windowListeners;
+ private boolean repaintQueued = false;
+
+ private void initializeStates() {
+ invalidate(true);
+
+ childWindows = new ArrayList();
+ surfaceUpdatedListeners = new ArrayList();
+ windowListeners = new ArrayList();
+ mouseListeners = new ArrayList();
+
+ mouseButtonPressed = 0; // current pressed mouse button number
+ lastMousePressed = 0; // last time when a mouse button was pressed
+ lastMouseClickCount = 0; // last mouse button click count
+ keyListeners = new ArrayList();
+ }
+
// Workaround for initialization order problems on Mac OS X
// between native Newt and (apparently) Fmod -- if Fmod is
// initialized first then the connection to the window server
@@ -89,8 +142,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
// Construction Methods
//
- private static Class getWindowClass(String type)
- throws ClassNotFoundException
+ private static Class getWindowClass(String type)
+ throws ClassNotFoundException
{
Class windowClass = NewtFactory.getCustomClass(type, "Window");
if(null==windowClass) {
@@ -120,7 +173,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
windowClass = OffscreenWindow.class;
}
WindowImpl window = (WindowImpl) windowClass.newInstance();
- window.invalidate(true);
+ window.initializeStates();
window.parentWindow = parentWindow;
window.parentWindowHandle = parentWindowHandle;
window.screen = (ScreenImpl) screen;
@@ -145,7 +198,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
throw new NativeWindowException("WindowClass "+windowClass+" constructor mismatch at argument #"+argsChecked+"; Constructor: "+getTypeStrList(cstrArgumentTypes)+", arguments: "+getArgsStrList(cstrArguments));
}
WindowImpl window = (WindowImpl) ReflectionUtil.createInstance( windowClass, cstrArgumentTypes, cstrArguments ) ;
- window.invalidate(true);
+ window.initializeStates();
window.screen = (ScreenImpl) screen;
window.caps = (Capabilities)caps.clone();
return window;
@@ -174,7 +227,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
* Surface not locked yet.<br>
* Called not necessarily from EDT.
*/
- void destroyActionPreLock(boolean unrecoverable);
+ void destroyActionPreLock();
/**
* Invoked before Window destroy action,
@@ -182,7 +235,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
* Surface locked.<br>
* Called from EDT while window is locked.
*/
- void destroyActionInLock(boolean unrecoverable);
+ void destroyActionInLock();
+
+ /**
+ * Invoked after destruction from Window's invalidate method.<br>
+ * Called while window is locked.
+ * @param unrecoverable
+ */
+ void invalidate(boolean unrecoverable);
/**
* Invoked for expensive modifications, ie while reparenting and ScreenMode change.<br>
@@ -201,41 +261,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
void resumeRenderingAction();
}
- private LifecycleHook lifecycleHook = null;
- private RecursiveLock windowLock = new RecursiveLock();
- private long windowHandle;
- private ScreenImpl screen;
- private boolean screenReferenced = false;
- private NativeWindow parentWindow;
- private long parentWindowHandle;
-
- protected AbstractGraphicsConfiguration config;
- protected Capabilities caps;
- protected boolean fullscreen, visible, hasFocus;
- protected int width, height, x, y;
- protected int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen dimensions ..
-
- protected String title = "Newt Window";
- protected boolean undecorated = false;
- private boolean handleDestroyNotify = true;
-
- private final void destroyScreen() {
- if(null!=screen) {
- if(screenReferenced) {
- screen.removeReference();
- screenReferenced = false;
- }
- screen = null;
- }
- }
- private final void setScreen(ScreenImpl newScreen) {
- if(screenReferenced) {
- screenReferenced = false;
- screen.removeReference();
- }
- screen = newScreen;
- }
-
private boolean createNative() {
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.createNative() START ("+getThreadName()+", "+this+")");
@@ -246,10 +271,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
}
try {
if(validateParentWindowHandle()) {
- if(!screenReferenced) {
- screenReferenced = true;
- screen.addReference();
+ if(screenReferenceAdded) {
+ throw new InternalError("XXX");
}
+ screen.addReference();
+ screenReferenceAdded = true;
createNativeImpl();
setVisibleImpl(true, x, y, width, height);
screen.addScreenModeListener(this);
@@ -265,6 +291,36 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
return 0 != windowHandle ;
}
+ private void removeScreenReference() {
+ if(screenReferenceAdded) {
+ // be nice, probably already called recursive via
+ // closeAndInvalidate() -> closeNativeIml() -> .. -> windowDestroyed() -> closeAndInvalidate() !
+ // or via reparentWindow .. etc
+ screenReferenceAdded = false;
+ screen.removeReference();
+ }
+ }
+
+ private void closeAndInvalidate() {
+ windowLock.lock();
+ try {
+ if( null != screen ) {
+ if( 0 != windowHandle ) {
+ screen.removeScreenModeListener(WindowImpl.this);
+ closeNativeImpl();
+ removeScreenReference();
+ }
+ Display dpy = screen.getDisplay();
+ if(null != dpy) {
+ dpy.validateEDT();
+ }
+ }
+ invalidate(false);
+ } finally {
+ windowLock.unlock();
+ }
+ }
+
private boolean validateParentWindowHandle() {
if(null!=parentWindow) {
parentWindowHandle = getNativeWindowHandle(parentWindow);
@@ -446,9 +502,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
// NativeWindow
//
- public final void destroy() {
- destroy(false);
- }
+ // public final void destroy() - see below
public final NativeWindow getParent() {
return parentWindow;
@@ -649,11 +703,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
}
class DestroyAction implements Runnable {
- boolean unrecoverable;
-
- public DestroyAction(boolean unrecoverable) {
- this.unrecoverable = unrecoverable;
- }
public void run() {
windowLock.lock();
try {
@@ -663,47 +712,29 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
// Childs first ..
synchronized(childWindowsLock) {
- // avoid ConcurrentModificationException: parent -> child -> parent.removeChild(this)
- ArrayList clonedChildWindows = (ArrayList) childWindows.clone();
- while( clonedChildWindows.size() > 0 ) {
- NativeWindow nw = (NativeWindow) clonedChildWindows.remove(0);
- if(nw instanceof WindowImpl) {
- ((WindowImpl)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
- if(unrecoverable) {
- ((WindowImpl)nw).destroy(unrecoverable);
- }
- } else {
- nw.destroy();
+ if(childWindows.size()>0) {
+ // avoid ConcurrentModificationException: parent -> child -> parent.removeChild(this)
+ ArrayList clonedChildWindows = (ArrayList) childWindows.clone();
+ while( clonedChildWindows.size() > 0 ) {
+ NativeWindow nw = (NativeWindow) clonedChildWindows.remove(0);
+ if(nw instanceof WindowImpl) {
+ ((WindowImpl)nw).sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY);
+ ((WindowImpl)nw).destroy();
+ } else {
+ nw.destroy();
+ }
}
}
}
if(null!=lifecycleHook) {
- lifecycleHook.destroyActionInLock(unrecoverable);
+ lifecycleHook.destroyActionInLock();
}
- // Now us ..
- if(unrecoverable) {
- if(null!=parentWindow && parentWindow instanceof Window) {
- ((Window)parentWindow).removeChild(WindowImpl.this);
- }
- synchronized(childWindowsLock) {
- childWindows = new ArrayList();
- }
- synchronized(surfaceUpdatedListenersLock) {
- surfaceUpdatedListeners = new ArrayList();
- }
- windowListeners = new ArrayList();
- mouseListeners = new ArrayList();
- keyListeners = new ArrayList();
- }
- if( null != screen && 0 != windowHandle ) {
- screen.removeScreenModeListener(WindowImpl.this);
- closeNativeImpl();
- }
- invalidate(unrecoverable);
+ closeAndInvalidate();
+
if(DEBUG_IMPLEMENTATION) {
- System.err.println("Window.destroy(unrecoverable: "+unrecoverable+") END "+getThreadName()/*+", "+WindowImpl.this*/);
+ System.err.println("Window.destroy() END "+getThreadName()/*+", "+WindowImpl.this*/);
}
} finally {
windowLock.unlock();
@@ -711,36 +742,27 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
}
}
- public void destroy(boolean unrecoverable) {
+ public void destroy() {
if( isValid() ) {
if(DEBUG_IMPLEMENTATION) {
- String msg = new String("Window.destroy(unrecoverable: "+unrecoverable+") START "+getThreadName()/*+", "+this*/);
+ String msg = new String("Window.destroy() START "+getThreadName()/*+", "+this*/);
System.err.println(msg);
//Exception ee = new Exception(msg);
//ee.printStackTrace();
- }
+ }
if(null!=lifecycleHook) {
- lifecycleHook.destroyActionPreLock(unrecoverable);
+ lifecycleHook.pauseRenderingAction();
+ }
+ if(null!=lifecycleHook) {
+ lifecycleHook.destroyActionPreLock();
}
- DestroyAction destroyAction = new DestroyAction(unrecoverable);
runOnEDTIfAvail(true, destroyAction);
}
}
- /**
- * <p>
- * render all native window information invalid,
- * as if the native window was destroyed.<br></p>
- * <p>
- * all other resources and states are kept intact,
- * ie listeners, parent handles and size, position etc.<br></p>
- *
- * @see #destroy()
- * @see #destroy(boolean)
- * @see #invalidate(boolean)
- */
public final void invalidate() {
- invalidate(false);
+ destroy();
+ invalidate(true);
}
/**
@@ -757,16 +779,49 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) {
String msg = new String("!!! Window Invalidate(unrecoverable: "+unrecoverable+") "+getThreadName());
System.err.println(msg);
- // Exception e = new Exception(msg);
- // e.printStackTrace();
+ // Throwable t = new Throwable(msg);
+ // t.printStackTrace();
+ }
+
+ // Childs first ..
+ synchronized(childWindowsLock) {
+ // avoid ConcurrentModificationException: parent -> child -> parent.removeChild(this)
+ if(null!=childWindows && childWindows.size()>0) {
+ ArrayList clonedChildWindows = (ArrayList) childWindows.clone();
+ while( clonedChildWindows.size() > 0 ) {
+ NativeWindow nw = (NativeWindow) clonedChildWindows.remove(0);
+ if(nw instanceof WindowImpl) {
+ ((WindowImpl)nw).invalidate(unrecoverable);
+ }
+ }
+ }
}
+
+ if(null!=lifecycleHook) {
+ lifecycleHook.invalidate(unrecoverable);
+ }
+
windowHandle = 0;
visible = false;
fullscreen = false;
hasFocus = false;
if(unrecoverable) {
- destroyScreen();
+ if(null!=parentWindow && parentWindow instanceof Window) {
+ ((Window)parentWindow).removeChild(WindowImpl.this);
+ }
+ screen = null;
+
+ synchronized(childWindowsLock) {
+ childWindows = null;
+ }
+ synchronized(surfaceUpdatedListenersLock) {
+ surfaceUpdatedListeners = null;
+ }
+ windowListeners = null;
+ mouseListeners = null;
+ keyListeners = null;
+
parentWindowHandle = 0;
parentWindow = null;
caps = null;
@@ -794,10 +849,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
this.reparentAction = -1; // ensure it's set
}
- public int getStrategy() {
+ public final int getStrategy() {
return reparentAction;
}
+ private final void setScreen(ScreenImpl newScreen) {
+ WindowImpl.this.removeScreenReference();
+ screen = newScreen;
+ }
+
public void run() {
boolean wasVisible;
@@ -846,9 +906,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
if(null==newParentWindowNEWT) {
throw new NativeWindowException("Reparenting with non NEWT Window type only available after it's realized: "+newParentWindow);
}
- // Destroy this window (handle screen + native) and use parent's Screen.
+ // Destroy this window and use parent's Screen.
// It may be created properly when the parent is made visible.
- destroy(false);
+ destroy();
setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
reparentAction = ACTION_NATIVE_CREATION_PENDING;
} else if(newParentWindow != getParent()) {
@@ -862,7 +922,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
Screen newScreen = NewtFactory.createCompatibleScreen(newParentWindow, getScreen());
if( getScreen() != newScreen ) {
// auto destroy on-the-fly created Screen/Display
- newScreen.setDestroyWhenUnused(true);
setScreen( (ScreenImpl) newScreen );
}
}
@@ -873,15 +932,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
}
} else if ( DEBUG_TEST_REPARENT_INCOMPATIBLE || forceDestroyCreate ||
!NewtFactory.isScreenCompatible(newParentWindow, getScreen()) ) {
- // Destroy this window (handle screen + native) and
- // may create a new compatible Screen/Display and
- // mark it for creation.
- destroy(false);
+ // Destroy this window, may create a new compatible Screen/Display,
+ // and mark it for creation.
+ destroy();
if(null!=newParentWindowNEWT) {
setScreen( (ScreenImpl) newParentWindowNEWT.getScreen() );
} else {
setScreen( (ScreenImpl) NewtFactory.createCompatibleScreen(newParentWindow, getScreen()) );
- screen.setDestroyWhenUnused(true);
}
reparentAction = ACTION_NATIVE_CREATION;
} else {
@@ -906,9 +963,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
// Already Top Window
reparentAction = ACTION_UNCHANGED;
} else if( !isNativeValid() || DEBUG_TEST_REPARENT_INCOMPATIBLE || forceDestroyCreate ) {
- // Destroy this window (handle screen + native),
- // keep Screen/Display and mark it for creation.
- destroy(false);
+ // Destroy this window and mark it for [pending] creation.
+ destroy();
if( 0<width*height ) {
reparentAction = ACTION_NATIVE_CREATION;
} else {
@@ -1015,7 +1071,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.reparent: native reparenting failed ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentWindowHandle)+" - Trying recreation");
}
- destroy(false);
+ destroy();
reparentAction = ACTION_NATIVE_CREATION ;
}
}
@@ -1065,7 +1121,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
}
}
}
- private ReparentActionRecreate reparentActionRecreate = new ReparentActionRecreate();
public final int reparentWindow(NativeWindow newParent) {
return reparentWindow(newParent, false);
@@ -1075,7 +1130,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
int reparentActionStrategy = ReparentAction.ACTION_INVALID;
if(isValid()) {
if(null!=lifecycleHook) {
- // pause animation
lifecycleHook.pauseRenderingAction();
}
try {
@@ -1084,7 +1138,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
reparentActionStrategy = reparentAction.getStrategy();
} finally {
if(null!=lifecycleHook) {
- // resume animation
lifecycleHook.resumeRenderingAction();
}
}
@@ -1316,7 +1369,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
WindowImpl.this.requestFocusImpl(false);
}
}
- RequestFocusAction requestFocusAction = new RequestFocusAction();
protected void enqueueRequestFocus(boolean wait) {
runOnEDTIfAvail(wait, requestFocusAction);
@@ -1345,7 +1397,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
}
return res;
}
- protected FocusRunnable focusAction = null;
class SetPositionActionImpl implements Runnable {
int x, y;
@@ -1475,7 +1526,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
}
if(null!=lifecycleHook) {
- // pause animation
lifecycleHook.pauseRenderingAction();
}
}
@@ -1494,7 +1544,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
}
if(null!=lifecycleHook) {
- // resume animation
lifecycleHook.resumeRenderingAction();
sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
}
@@ -1504,9 +1553,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
// Child Window Management
//
- private ArrayList childWindows = new ArrayList();
- private Object childWindowsLock = new Object();
-
public final void removeChild(NativeWindow win) {
synchronized(childWindowsLock) {
childWindows.remove(win);
@@ -1591,15 +1637,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
}
return true;
}
- protected boolean repaintQueued = false;
//
// SurfaceUpdatedListener Support
//
- private ArrayList surfaceUpdatedListeners = new ArrayList();
- private Object surfaceUpdatedListenersLock = new Object();
-
public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) {
addSurfaceUpdatedListener(-1, l);
}
@@ -1660,11 +1702,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
//
// MouseListener/Event Support
//
- private ArrayList mouseListeners = new ArrayList();
- private int mouseButtonPressed = 0; // current pressed mouse button number
- private long lastMousePressed = 0; // last time when a mouse button was pressed
- private int lastMouseClickCount = 0; // last mouse button click count
-
public void sendMouseEvent(int eventType, int modifiers,
int x, int y, int button, int rotation) {
doMouseEvent(false, false, eventType, modifiers, x, y, button, rotation);
@@ -1857,8 +1894,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
return (KeyListener[]) keyListeners.toArray();
}
- private ArrayList keyListeners = new ArrayList();
-
protected void consumeKeyEvent(KeyEvent e) {
if(DEBUG_KEY_EVENT) {
System.err.println("consumeKeyEvent: "+e);
@@ -1892,8 +1927,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
enqueueEvent( wait, new WindowEvent(eventType, this, System.currentTimeMillis()) );
}
- private ArrayList windowListeners = new ArrayList();
-
public void addWindowListener(WindowListener l) {
addWindowListener(-1, l);
}
@@ -2055,7 +2088,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer, ScreenMod
if(DEBUG_IMPLEMENTATION) {
System.err.println("Window.windowDestroyed "+getThreadName());
}
- invalidate();
+ closeAndInvalidate();
}
public void windowRepaint(int x, int y, int width, int height) {
diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
index f84c65cb7..72963eaa3 100644
--- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
+++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
@@ -246,8 +246,8 @@ public class GLWindow implements GLAutoDrawable, Window {
// Window.LifecycleHook Implementation
//
- public final void destroy(boolean unrecoverable) {
- window.destroy(unrecoverable);
+ public final void destroy() {
+ window.destroy();
}
public final void setVisible(boolean visible) {
@@ -282,23 +282,14 @@ public class GLWindow implements GLAutoDrawable, Window {
DisposeAction disposeAction = new DisposeAction();
/** Window.LifecycleHook */
- public synchronized void destroyActionPreLock(boolean unrecoverable) {
- GLAnimatorControl animator = GLWindow.this.getAnimator();
- if(null!=animator) {
- if(unrecoverable) {
- if(animator.isStarted()) {
- animator.stop();
- }
- } else if(animator.isAnimating()) {
- animator.pause();
- }
- }
+ public synchronized void destroyActionPreLock() {
+ // nop
}
/** Window.LifecycleHook */
- public synchronized void destroyActionInLock(boolean unrecoverable) {
+ public synchronized void destroyActionInLock() {
if(Window.DEBUG_WINDOW_EVENT || Window.DEBUG_IMPLEMENTATION) {
- String msg = new String("GLWindow.destroy("+unrecoverable+") "+Thread.currentThread()+", start");
+ String msg = new String("GLWindow.destroy() "+Thread.currentThread()+", start");
System.err.println(msg);
//Exception e1 = new Exception(msg);
//e1.printStackTrace();
@@ -320,12 +311,25 @@ public class GLWindow implements GLAutoDrawable, Window {
context = null;
drawable = null;
- if(unrecoverable) {
- helper=null;
+ if(Window.DEBUG_WINDOW_EVENT || Window.DEBUG_IMPLEMENTATION) {
+ System.err.println("GLWindow.destroy() "+Thread.currentThread()+", fin");
}
+ }
+ /** Window.LifecycleHook */
+ public synchronized void invalidate(boolean unrecoverable) {
if(Window.DEBUG_WINDOW_EVENT || Window.DEBUG_IMPLEMENTATION) {
- System.err.println("GLWindow.destroy("+unrecoverable+") "+Thread.currentThread()+", fin");
+ String msg = new String("GLWindow.invalidate("+unrecoverable+") "+Thread.currentThread()+", start");
+ System.err.println(msg);
+ //Exception e1 = new Exception(msg);
+ //e1.printStackTrace();
+ }
+ if(unrecoverable) {
+ GLAnimatorControl ctrl = GLWindow.this.getAnimator();
+ if ( null!=ctrl && ctrl.isStarted() ) {
+ ctrl.stop();
+ }
+ helper=null;
}
}
@@ -635,10 +639,6 @@ public class GLWindow implements GLAutoDrawable, Window {
return null!=drawable ? drawable.getHandle() : 0;
}
- public final void destroy() {
- window.destroy();
- }
-
public final int getX() {
return window.getX();
}
@@ -878,7 +878,7 @@ public class GLWindow implements GLAutoDrawable, Window {
});
glWindow.setVisible(true);
- glWindow.destroy(true);
+ glWindow.invalidate();
}
}