diff options
Diffstat (limited to 'src/newt')
18 files changed, 727 insertions, 204 deletions
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index 6f0028a77..89a749c51 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -68,6 +68,15 @@ import com.jogamp.newt.event.awt.AWTAdapter; import com.jogamp.newt.event.awt.AWTKeyAdapter; import com.jogamp.newt.event.awt.AWTMouseAdapter; +/** + * AWT {@link java.awt.Canvas Canvas} containing a NEWT {@link Window} using native parenting. + * + * <h5><A NAME="java2dgl">Offscreen Layer Remarks</A></h5> + * + * {@link OffscreenLayerOption#setShallUseOffscreenLayer(boolean) setShallUseOffscreenLayer(true)} + * maybe called to use an offscreen drawable (FBO or PBuffer) allowing + * the underlying JAWT mechanism to composite the image, if supported. + */ @SuppressWarnings("serial") public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProtocol, OffscreenLayerOption { public static final boolean DEBUG = Debug.debug("Window"); diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java index 69b0d0482..2d63ca455 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -28,6 +28,8 @@ package com.jogamp.newt.event.awt; +import java.awt.Dimension; + import jogamp.newt.awt.event.AWTNewtEventFactory; public class AWTWindowAdapter @@ -61,9 +63,9 @@ public class AWTWindowAdapter if(awtComponent instanceof java.awt.Window) { ((java.awt.Window)awtComponent).addWindowListener(this); } - return this; + return this; } - + public AWTAdapter removeFrom(java.awt.Component awtComponent) { awtComponent.removeFocusListener(this); awtComponent.removeComponentListener(this); @@ -89,6 +91,9 @@ public class AWTWindowAdapter public void focusGained(java.awt.event.FocusEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); + if(DEBUG_IMPLEMENTATION) { + System.err.println("AWT: focusGained: "+e+" -> "+event); + } if(null!=newtListener) { ((com.jogamp.newt.event.WindowListener)newtListener).windowGainedFocus(event); } else { @@ -98,6 +103,9 @@ public class AWTWindowAdapter public void focusLost(java.awt.event.FocusEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); + if(DEBUG_IMPLEMENTATION) { + System.err.println("AWT: focusLost: "+e+" -> "+event); + } if(null!=newtListener) { ((com.jogamp.newt.event.WindowListener)newtListener).windowLostFocus(event); } else { @@ -108,7 +116,19 @@ public class AWTWindowAdapter public void componentResized(java.awt.event.ComponentEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); if(DEBUG_IMPLEMENTATION) { - System.err.println("AWT: componentResized: "+event); + final java.awt.Component c = e.getComponent(); + final java.awt.Dimension sz = c.getSize(); + final java.awt.Insets insets; + final java.awt.Dimension sz2; + if(c instanceof java.awt.Container) { + insets = ((java.awt.Container)c).getInsets(); + sz2 = new Dimension(sz.width - insets.left - insets.right, + sz.height - insets.top - insets.bottom); + } else { + insets = null; + sz2 = sz; + } + System.err.println("AWT: componentResized: "+sz+" ( "+insets+", "+sz2+" ), "+e+" -> "+event); } if(null!=newtListener) { ((com.jogamp.newt.event.WindowListener)newtListener).windowResized(event); @@ -120,7 +140,7 @@ public class AWTWindowAdapter public void componentMoved(java.awt.event.ComponentEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); if(DEBUG_IMPLEMENTATION) { - System.err.println("AWT: componentMoved: "+event); + System.err.println("AWT: componentMoved: "+e+" -> "+event); } if(null!=newtListener) { ((com.jogamp.newt.event.WindowListener)newtListener).windowMoved(event); diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 0fc1b4e89..a89ccaedb 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -51,6 +51,7 @@ import javax.media.opengl.GLAutoDrawable; import javax.media.opengl.GLCapabilities; import javax.media.opengl.GLCapabilitiesImmutable; import javax.media.opengl.GLContext; +import javax.media.opengl.GLDrawable; import javax.media.opengl.GLDrawableFactory; import javax.media.opengl.GLEventListener; import javax.media.opengl.GLException; @@ -97,7 +98,7 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind * Constructor. Do not call this directly -- use {@link #create()} instead. */ protected GLWindow(Window window) { - super(null, null, false); + super(null, null, false /* always handle device lifecycle ourselves */); this.window = (WindowImpl) window; this.window.setHandleDestroyNotify(false); window.addWindowListener(new WindowAdapter() { @@ -107,8 +108,8 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind } @Override - public void windowResized(WindowEvent e) { - defaultWindowResizedOp(); + public void windowResized(WindowEvent e) { + defaultWindowResizedOp(getWidth(), getHeight()); } @Override @@ -201,11 +202,8 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind @Override public final CapabilitiesImmutable getChosenCapabilities() { - if (drawable == null) { - return window.getChosenCapabilities(); - } - - return drawable.getChosenGLCapabilities(); + final GLDrawable _drawable = drawable; + return null != _drawable ? _drawable.getChosenGLCapabilities() : window.getChosenCapabilities(); } @Override @@ -536,19 +534,24 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind return; } + final boolean done; final RecursiveLock lock = window.getLock(); lock.lock(); // sync: context/drawable could have been recreated/destroyed while animating try { if( null != context ) { // surface is locked/unlocked implicit by context's makeCurrent/release helper.invokeGL(drawable, context, defaultDisplayAction, defaultInitAction); - } else if( 0<getWidth()*getHeight() ) { - // retry drawable and context creation, will itself issue resize -> display - setVisible(true); + done = true; + } else { + done = false; } } finally { lock.unlock(); } + if( !done && 0<getWidth()*getHeight() ) { + // retry drawable and context creation, will itself issue resize -> display + setVisible(true); + } } //---------------------------------------------------------------------- diff --git a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java index f45b864fa..36bc3f28f 100644 --- a/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java +++ b/src/newt/classes/com/jogamp/newt/swt/NewtCanvasSWT.java @@ -63,13 +63,13 @@ import com.jogamp.newt.Window; import com.jogamp.newt.event.WindowEvent; import com.jogamp.newt.util.EDTUtil; +/** + * SWT {@link Canvas} containing a NEWT {@link Window} using native parenting. + */ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { private static final boolean DEBUG = Debug.debug("Window"); private static final boolean isOSX = NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(false); - /** SWT EDTUtil associated w/ parent's SWT Display */ - private final EDTUtil swtEDTUtil; - private final AbstractGraphicsScreen screen; private WindowClosingMode newtChildCloseOp = WindowClosingMode.DISPOSE_ON_CLOSE; @@ -117,8 +117,6 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { public NewtCanvasSWT(final Composite parent, final int style, Window child) { super(parent, style | SWT.NO_BACKGROUND); - swtEDTUtil = new SWTEDTUtil(parent.getDisplay()); - SWTAccessor.setRealized(this, true); clientArea = getClientArea(); @@ -326,8 +324,9 @@ public class NewtCanvasSWT extends Canvas implements WindowClosingProtocol { updateSizeCheck(); final int w = clientArea.width; final int h = clientArea.height; - - newtChild.getScreen().getDisplay().setEDTUtil(swtEDTUtil); + + final Display newtDisplay = newtChild.getScreen().getDisplay(); + newtDisplay.setEDTUtil(new SWTEDTUtil(newtDisplay, getDisplay())); newtChild.setSize(w, h); newtChild.reparentWindow(nativeWindow); diff --git a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java index 3538caad2..d4b83d891 100644 --- a/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/swt/SWTEDTUtil.java @@ -27,7 +27,9 @@ */ package com.jogamp.newt.swt; -import org.eclipse.swt.widgets.Display; +import java.awt.EventQueue; + +import jogamp.newt.Debug; import com.jogamp.newt.util.EDTUtil; @@ -36,64 +38,243 @@ import com.jogamp.newt.util.EDTUtil; * of the given {@link Display}. */ public class SWTEDTUtil implements EDTUtil { - private final Display swtDisplay; + public static final boolean DEBUG = Debug.debug("EDT"); + + private final Object edtLock = new Object(); // locking the EDT start/stop state + private final ThreadGroup threadGroup; + private final String name; + private final Runnable dispatchMessages; + private final org.eclipse.swt.widgets.Display swtDisplay; + private NewtEventDispatchThread nedt = null; + private int start_iter=0; + private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; - public SWTEDTUtil(Display swtDisplay) { + public SWTEDTUtil(final com.jogamp.newt.Display newtDisplay, org.eclipse.swt.widgets.Display swtDisplay) { + this.threadGroup = Thread.currentThread().getThreadGroup(); + this.name=Thread.currentThread().getName()+"-SWTDisplay-"+newtDisplay.getFQName()+"-EDT-"; + this.dispatchMessages = new Runnable() { + public void run() { + ((jogamp.newt.DisplayImpl) newtDisplay).dispatchMessages(); + } }; this.swtDisplay = swtDisplay; + this.nedt = new NewtEventDispatchThread(threadGroup, name); + this.nedt.setDaemon(true); // don't stop JVM from shutdown .. } - public final Display getDisplay() { + public final org.eclipse.swt.widgets.Display getDisplay() { return swtDisplay; } @Override public long getPollPeriod() { - return 0; + return pollPeriod; } @Override public void setPollPeriod(long ms) { + pollPeriod = ms; } @Override public void reset() { + synchronized(edtLock) { + waitUntilStopped(); + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT reset - edt: "+nedt); + } + this.nedt = new NewtEventDispatchThread(threadGroup, name); + this.nedt.setDaemon(true); // don't stop JVM from shutdown .. + } } - @Override - public void start() { + private final void startImpl() { + if(nedt.isAlive()) { + throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt); + } + start_iter++; + nedt.setName(name+start_iter); + nedt.shouldStop = false; + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT START - edt: "+nedt); + // Thread.dumpStack(); + } + nedt.start(); } - + @Override public boolean isCurrentThreadEDT() { return swtDisplay.getThread() == Thread.currentThread(); } @Override + public final boolean isCurrentThreadNEDT() { + return nedt == Thread.currentThread(); + } + + @Override + public final boolean isCurrentThreadEDTorNEDT() { + final Thread ct = Thread.currentThread(); + return ct == swtDisplay.getThread() || ct == nedt ; + } + + @Override public boolean isRunning() { - return true; + return nedt.isRunning() ; // SWT is always running } - + @Override - public void invokeStop(Runnable finalTask) { - swtDisplay.syncExec(finalTask); + public final void invokeStop(Runnable task) { + invokeImpl(true, task, true); } @Override - public void invoke(boolean wait, Runnable task) { + public final void invoke(boolean wait, Runnable task) { + invokeImpl(wait, task, false); + } + + private void invokeImpl(boolean wait, Runnable task, boolean stop) { + if(task == null) { + throw new RuntimeException("Null Runnable"); + } + synchronized(edtLock) { // lock the EDT status + if( nedt.shouldStop ) { + // drop task .. + if(DEBUG) { + System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt); + Thread.dumpStack(); + } + return; + } + // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task); + // Thread.dumpStack(); + if(stop) { + nedt.shouldStop = true; + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt); + // Thread.dumpStack(); + } + } + + // start if should not stop && not started yet + if( !stop && !nedt.isRunning() ) { + startImpl(); + } + } if(wait) { swtDisplay.syncExec(task); } else { swtDisplay.asyncExec(task); } - } + } @Override - public void waitUntilIdle() { - // all sync .. + final public void waitUntilIdle() { + final NewtEventDispatchThread _edt; + synchronized(edtLock) { + _edt = nedt; + } + if(!_edt.isRunning() || EventQueue.isDispatchThread() || _edt == Thread.currentThread()) { + return; + } + try { + swtDisplay.syncExec(new Runnable() { + public void run() { } + }); + } catch (Exception e) { } } @Override - public void waitUntilStopped() { - // all sync .. + final public void waitUntilStopped() { + synchronized(edtLock) { + if(nedt.isRunning() && nedt != Thread.currentThread() ) { + while(nedt.isRunning()) { + try { + edtLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } } + + class NewtEventDispatchThread extends Thread { + volatile boolean shouldStop = false; + volatile boolean isRunning = false; + Object sync = new Object(); + + public NewtEventDispatchThread(ThreadGroup tg, String name) { + super(tg, name); + } + + final public boolean isRunning() { + return isRunning; + } + + @Override + final public void start() throws IllegalThreadStateException { + isRunning = true; + super.start(); + } + + /** + * Utilizing locking only on tasks and its execution, + * not for event dispatching. + */ + @Override + final public void run() { + if(DEBUG) { + System.err.println(getName()+": EDT run() START "+ getName()); + } + RuntimeException error = null; + try { + do { + // event dispatch + if(!shouldStop) { + // FIXME: Determine whether we require to run the + // delivery of events (dispatch) on AWT-EDT. + // Since the WindowDriver itself delivers all Window related events, + // this shall not be required. + // AWTEDTExecutor.singleton.invoke(true, dispatchMessages); + dispatchMessages.run(); + } + // wait + synchronized(sync) { + if(!shouldStop) { + try { + sync.wait(pollPeriod); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } while(!shouldStop) ; + } catch (Throwable t) { + // handle errors .. + shouldStop = true; + if(t instanceof RuntimeException) { + error = (RuntimeException) t; + } else { + error = new RuntimeException("Within EDT", t); + } + } finally { + if(DEBUG) { + System.err.println(getName()+": EDT run() END "+ getName()+", "+error); + } + synchronized(edtLock) { + isRunning = !shouldStop; + if(!isRunning) { + edtLock.notifyAll(); + } + } + if(DEBUG) { + System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error); + } + if(null!=error) { + throw error; + } + } // finally + } // run() + } // EventDispatchThread + } diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index 4493e2781..7e19d9de5 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -28,6 +28,9 @@ package com.jogamp.newt.util; +import jogamp.newt.DisplayImpl; +import com.jogamp.newt.event.NEWTEvent; + /** * EDT stands for Event Dispatch Thread. * <p> @@ -63,25 +66,46 @@ public interface EDTUtil { /** * Create a new EDT. One should invoke <code>reset()</code><br> - * after <code>invokeStop(..)</code> in case another <code>start()</code> or <code>invoke(..)</code> + * after <code>invokeStop(..)</code> in case another start via <code>invoke(..)</code> * is expected. * - * @see #start() * @see #invoke(boolean, java.lang.Runnable) * @see #invokeStop(java.lang.Runnable) */ public void reset(); /** - * Start the EDT + * Returns true if the current thread is the event dispatch thread (EDT). + * <p> + * The EDT is the platform specific thread dispatching toolkit-events + * and executing toolkit-tasks enqueued via {@link #invoke(boolean, Runnable)}. + * </p> + * <p> + * Usually it is the same thread as used to dequeue informal {@link NEWTEvent}s (NEDT), see {@link #isCurrentThreadNEDT()}, + * however, this may differ, e.g. SWT and AWT implementation. + * </p> */ - public void start(); + public boolean isCurrentThreadEDT(); /** - * @return True if the current thread is the EDT thread + * Returns true if the current thread is the internal NEWT event dequeue thread (NEDT). + * <p> + * The NEDT is the NEWT thread used to dequeue informal {@link NEWTEvent}s enqueued internally + * via {@link DisplayImpl#enqueueEvent(boolean, NEWTEvent)}. + * </p> + * <p> + * Usually it is the same thread as the EDT, see {@link #isCurrentThreadEDT()}, + * however, this may differ, e.g. SWT and AWT implementation. + * </p> */ - public boolean isCurrentThreadEDT(); - + public boolean isCurrentThreadNEDT(); + + /** + * Returns <code>true</code> if either {@link #isCurrentThreadEDT()} or {@link #isCurrentThreadNEDT()} is <code>true</code>, + * otherwise <code>false</code>. + */ + public boolean isCurrentThreadEDTorNEDT(); + /** * @return True if EDT is running */ @@ -101,9 +125,9 @@ public interface EDTUtil { public void invokeStop(Runnable finalTask); /** + * Shall start the thread if not running.<br> * Append task to the EDT task queue.<br> * Wait until execution is finished if <code>wait == true</code>.<br> - * Shall start the thread if not running.<br> * Can be issued from within EDT, ie from within an enqueued task.<br> * * @throws RuntimeException in case EDT is stopped and not {@link #reset()} diff --git a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java index bdbe96070..18418a8dc 100644 --- a/src/newt/classes/jogamp/newt/DefaultEDTUtil.java +++ b/src/newt/classes/jogamp/newt/DefaultEDTUtil.java @@ -49,12 +49,12 @@ import com.jogamp.newt.util.EDTUtil; public class DefaultEDTUtil implements EDTUtil { public static final boolean DEBUG = Debug.debug("EDT"); - private ThreadGroup threadGroup; + private final Object edtLock = new Object(); // locking the EDT start/stop state + private final ThreadGroup threadGroup; + private final String name; + private final Runnable dispatchMessages; private EventDispatchThread edt = null; - private Object edtLock = new Object(); // locking the EDT start/stop state - private String name; - int start_iter=0; - private Runnable dispatchMessages; + private int start_iter=0; private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; public DefaultEDTUtil(ThreadGroup tg, String name, Runnable dispatchMessages) { @@ -65,14 +65,17 @@ public class DefaultEDTUtil implements EDTUtil { this.edt.setDaemon(true); // don't stop JVM from shutdown .. } + @Override final public long getPollPeriod() { return pollPeriod; } + @Override final public void setPollPeriod(long ms) { pollPeriod = ms; } + @Override public final void reset() { synchronized(edtLock) { waitUntilStopped(); @@ -88,36 +91,46 @@ public class DefaultEDTUtil implements EDTUtil { } } - public final void start() { - synchronized(edtLock) { - if(!edt.isRunning() && !edt.shouldStop) { - if(edt.isAlive()) { - throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size()); - } - start_iter++; - edt.setName(name+start_iter); - edt.shouldStop = false; - if(DEBUG) { - System.err.println(Thread.currentThread()+": EDT START - edt: "+edt); - // Thread.dumpStack(); - } - edt.start(); - } + private final void startImpl() { + if(edt.isAlive()) { + throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+edt.isRunning()+", edt: "+edt+", tasks: "+edt.tasks.size()); } + start_iter++; + edt.setName(name+start_iter); + edt.shouldStop = false; + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT START - edt: "+edt); + // Thread.dumpStack(); + } + edt.start(); } + @Override public final boolean isCurrentThreadEDT() { - return edt == Thread.currentThread(); + return edt == Thread.currentThread(); // EDT == NEDT + } + + @Override + public final boolean isCurrentThreadNEDT() { + return edt == Thread.currentThread(); // EDT == NEDT } + @Override + public final boolean isCurrentThreadEDTorNEDT() { + return edt == Thread.currentThread(); // EDT == NEDT + } + + @Override public final boolean isRunning() { return edt.isRunning() ; } + @Override public final void invokeStop(Runnable task) { invokeImpl(true, task, true); } + @Override public final void invoke(boolean wait, Runnable task) { invokeImpl(wait, task, false); } @@ -158,8 +171,11 @@ public class DefaultEDTUtil implements EDTUtil { } } } else { + // start if should not stop && not started yet + if( !stop && !edt.isRunning() ) { + startImpl(); + } synchronized(edt.tasks) { - start(); // start if not started yet and !shouldStop wait = wait && edt.isRunning(); rTask = new RunnableTask(task, wait ? rTaskLock : null, @@ -195,6 +211,7 @@ public class DefaultEDTUtil implements EDTUtil { } } + @Override final public void waitUntilIdle() { final EventDispatchThread _edt; synchronized(edtLock) { @@ -215,6 +232,7 @@ public class DefaultEDTUtil implements EDTUtil { } } + @Override final public void waitUntilStopped() { synchronized(edtLock) { if(edt.isRunning() && edt != Thread.currentThread() ) { diff --git a/src/newt/classes/jogamp/newt/DisplayImpl.java b/src/newt/classes/jogamp/newt/DisplayImpl.java index bac4031f0..bca7f6e5b 100644 --- a/src/newt/classes/jogamp/newt/DisplayImpl.java +++ b/src/newt/classes/jogamp/newt/DisplayImpl.java @@ -169,8 +169,7 @@ public abstract class DisplayImpl extends Display { public EDTUtil setEDTUtil(EDTUtil newEDTUtil) { if(null == newEDTUtil) { newEDTUtil = createEDTUtil(); - } - if( newEDTUtil == edtUtil ) { + } else if( newEDTUtil == edtUtil ) { if(DEBUG) { System.err.println("Display.setEDTUtil: "+newEDTUtil+" - keep!"); } @@ -366,7 +365,7 @@ public abstract class DisplayImpl extends Display { DisplayImpl.this.dispatchMessages(); } } - DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable(); + protected DispatchMessagesRunnable dispatchMessagesRunnable = new DispatchMessagesRunnable(); final void dispatchMessage(final NEWTEventTask eventTask) { final NEWTEvent event = eventTask.get(); @@ -446,8 +445,8 @@ public abstract class DisplayImpl extends Display { return; } - // can't wait if we are on EDT -> consume right away - if(wait && edtUtil.isCurrentThreadEDT()) { + // can't wait if we are on EDT or NEDT -> consume right away + if(wait && edtUtil.isCurrentThreadEDTorNEDT() ) { dispatchMessage(new NEWTEventTask(e, null)); return; } diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index ba98ca3af..c6c1814f6 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -39,20 +39,16 @@ import javax.media.nativewindow.AbstractGraphicsScreen; import javax.media.nativewindow.GraphicsConfigurationFactory; import javax.media.nativewindow.MutableSurface; import javax.media.nativewindow.NativeWindowException; -import javax.media.nativewindow.ProxySurface; import javax.media.nativewindow.VisualIDHolder; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; public class OffscreenWindow extends WindowImpl implements MutableSurface { - long surfaceHandle = 0; - ProxySurface.UpstreamSurfaceHook upstreamHook; - ProxySurface dummySurface; + long surfaceHandle; public OffscreenWindow() { - upstreamHook = null; - dummySurface = null; + surfaceHandle = 0; } static long nextWindowHandle = 0x100; // start here - a marker @@ -62,17 +58,6 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { throw new NativeWindowException("Capabilities is onscreen"); } final AbstractGraphicsScreen aScreen = getScreen().getGraphicsScreen(); - /** Cannot use OpenGL here .. - if(capsRequested instanceof GLCapabilitiesImmutable) { - final GLCapabilitiesImmutable caps = (GLCapabilitiesImmutable) capsRequested; - if(caps.isFBO() && GLContext.isFBOAvailable(aScreen.getDevice(), caps.getGLProfile()) ) { - final GLDrawableFactoryImpl factory = (GLDrawableFactoryImpl) GLDrawableFactory.getFactory(caps.getGLProfile()); - final GLCapabilitiesImmutable dummyCaps = GLGraphicsConfigurationUtil.fixOnscreenGLCapabilities(caps); - final ProxySurface dummySurface = factory.createDummySurfaceImpl(aScreen.getDevice(), false, dummyCaps, null, 64, 64); - upstreamHook = dummySurface.getUpstreamSurfaceHook(); - dummySurface.createNotify(); - } - } */ final AbstractGraphicsConfiguration cfg = GraphicsConfigurationFactory.getFactory(aScreen.getDevice(), capsRequested).chooseGraphicsConfiguration( capsRequested, capsRequested, capabilitiesChooser, aScreen, VisualIDHolder.VID_UNDEFINED); if (null == cfg) { @@ -83,6 +68,7 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { synchronized(OffscreenWindow.class) { setWindowHandle(nextWindowHandle++); } + visibleChanged(false, true); } protected void closeNativeImpl() { @@ -92,11 +78,6 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { @Override public synchronized void destroy() { super.destroy(); - if(null != dummySurface) { - dummySurface.destroyNotify(); - dummySurface = null; - upstreamHook = null; - } surfaceHandle = 0; } @@ -106,10 +87,6 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { @Override public long getSurfaceHandle() { - if(null != dummySurface) { - return dummySurface.getSurfaceHandle(); - // return upstreamHook.getWidth(); - } return surfaceHandle; } @@ -128,8 +105,8 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface { } protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + sizeChanged(false, width, height, false); if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { - sizeChanged(false, width, height, false); visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); } else { /** diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index ad7195944..c1ac87d38 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -767,11 +767,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } - public void setVisible(boolean visible) { + protected void setVisible(boolean wait, boolean visible) { if(DEBUG_IMPLEMENTATION) { System.err.println("Window setVisible: START ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow)); } - runOnEDTIfAvail(true, new VisibleAction(visible)); + runOnEDTIfAvail(wait, new VisibleAction(visible)); + } + + public void setVisible(boolean visible) { + setVisible(true, visible); } private class SetSizeAction implements Runnable { @@ -783,21 +787,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public final void run() { - boolean recreate = false; final RecursiveLock _lock = windowLock; _lock.lock(); try { if ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) { - recreate = isNativeValid() && !getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible+", recreate "+recreate); - } - if(recreate) { - // will trigger visibleAction:=2 -> create if wasVisible - final boolean wasVisible = WindowImpl.this.visible; - screen.addReference(); // retain screen - destroyAction.run(); - WindowImpl.this.visible = wasVisible; + System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible); } int visibleAction; // 0 nop, 1 invisible, 2 visible (create) if ( isNativeValid() && 0>=width*height && visible ) { @@ -823,9 +818,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } } finally { - if(recreate) { - screen.removeReference(); // bring back ref-count - } _lock.unlock(); } } @@ -940,11 +932,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer */ protected static boolean isOffscreenInstance(NativeWindow cWin, NativeWindow pWin) { boolean ofs = false; - if( null != cWin.getGraphicsConfiguration() ) { - ofs = !cWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + final AbstractGraphicsConfiguration cWinCfg = cWin.getGraphicsConfiguration(); + if( null != cWinCfg ) { + ofs = !cWinCfg.getChosenCapabilities().isOnscreen(); } - if( !ofs && null != pWin && null != pWin.getGraphicsConfiguration() ) { - ofs |= !pWin.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + if( !ofs && null != pWin ) { + final AbstractGraphicsConfiguration pWinCfg = pWin.getGraphicsConfiguration(); + if( null != pWinCfg ) { + ofs = !pWinCfg.getChosenCapabilities().isOnscreen(); + } } return ofs; } diff --git a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java index 91c589beb..28c4da72f 100644 --- a/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java +++ b/src/newt/classes/jogamp/newt/driver/android/NewtBaseActivity.java @@ -265,16 +265,17 @@ public class NewtBaseActivity extends Activity { if(!isDelegatedActivity()) { super.onResume(); } - if(null != animator) { - animator.resume(); - animator.resetFPSCounter(); - } - for(int i=newtWindows.size()-1; i>=0; i--) { + for(int i=0; i<newtWindows.size(); i++) { final Window win = newtWindows.get(i); + win.setVisible(true); if(win instanceof FPSCounter) { ((FPSCounter)win).resetFPSCounter(); } } + if(null != animator) { + animator.resume(); + animator.resetFPSCounter(); + } } @Override @@ -283,6 +284,10 @@ public class NewtBaseActivity extends Activity { if(null != animator) { animator.pause(); } + for(int i=0; i<newtWindows.size(); i++) { + final Window win = newtWindows.get(i); + win.setVisible(false); + } if(!isDelegatedActivity()) { super.onPause(); } diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java index 8ad11b35f..f18520630 100644 --- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java @@ -39,6 +39,7 @@ import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import javax.media.opengl.GLCapabilitiesChooser; import javax.media.opengl.GLCapabilitiesImmutable; +import javax.media.opengl.GLException; import com.jogamp.nativewindow.egl.EGLGraphicsDevice; @@ -263,15 +264,24 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { setGraphicsConfiguration(eglConfig); setWindowHandle(surfaceHandle); focusChanged(false, true); - Log.d(MD.TAG, "createNativeImpl X"); + Log.d(MD.TAG, "createNativeImpl X: eglSurfaceHandle 0x"+Long.toHexString(eglSurface)); } @Override protected void closeNativeImpl() { + Log.d(MD.TAG, "closeNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ + ", eglSurfaceHandle 0x"+Long.toHexString(eglSurface)+ + ", format [a "+androidFormat+", n "+nativeFormat+"], "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName()); + if(0 != eglSurface) { + final EGLGraphicsDevice eglDevice = (EGLGraphicsDevice) getScreen().getDisplay().getGraphicsDevice(); + if (!EGL.eglDestroySurface(eglDevice.getHandle(), eglSurface)) { + throw new GLException("Error destroying window surface (eglDestroySurface)"); + } + eglSurface = 0; + } release0(surfaceHandle); surface = null; surfaceHandle = 0; - eglSurface = 0; } @Override @@ -291,25 +301,33 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { } } - protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { + boolean res = true; + if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { Log.d(MD.TAG, "reconfigureWindowImpl.setFullscreen post creation (setContentView()) n/a"); return false; } - if(width>0 || height>0) { + if(getWidth() != width || getHeight() != height) { if(0!=getWindowHandle()) { Log.d(MD.TAG, "reconfigureWindowImpl.setSize n/a"); - return false; + res = false; + } else { + defineSize(width, height); } } - if(x>=0 || y>=0) { - Log.d(MD.TAG, "reconfigureWindowImpl.setPos n/a"); - return false; + if(getX() != x || getY() != y) { + if(0!=getWindowHandle()) { + Log.d(MD.TAG, "reconfigureWindowImpl.setPos n/a"); + res = false; + } else { + definePosition(x, y); + } } if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); } - return true; + return res; } protected Point getLocationOnScreenImpl(int x, int y) { @@ -410,7 +428,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 { getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible()); if(isVisible()) { - setVisible(true); + setVisible(false, true); } } sizeChanged(false, aWidth, aHeight, false); diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java index b3fdcad41..17eb6a2fb 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTCanvas.java @@ -35,6 +35,7 @@ package jogamp.newt.driver.awt; import java.awt.Canvas; +import java.awt.Graphics; import java.awt.GraphicsDevice; import java.awt.GraphicsConfiguration; import java.lang.reflect.Method; @@ -61,14 +62,16 @@ public class AWTCanvas extends Canvas { private GraphicsConfiguration chosen; private AWTGraphicsConfiguration awtConfig; + private WindowDriver newtWindowImpl; private CapabilitiesChooser chooser=null; private CapabilitiesImmutable capabilities; private boolean displayConfigChanged=false; - public AWTCanvas(CapabilitiesImmutable capabilities, CapabilitiesChooser chooser) { + public AWTCanvas(WindowDriver newtWindowImpl, CapabilitiesImmutable capabilities, CapabilitiesChooser chooser) { super(); + this.newtWindowImpl = newtWindowImpl; if(null==capabilities) { throw new NativeWindowException("Capabilities null"); } @@ -80,6 +83,25 @@ public class AWTCanvas extends Canvas { return awtConfig; } + /** + * Overridden from Canvas to prevent the AWT's clearing of the + * canvas from interfering with the OpenGL rendering. + */ + @Override + public void update(Graphics g) { + paint(g); + } + + /** Overridden to cause OpenGL rendering to be performed during + repaint cycles. Subclasses which override this method must call + super.paint() in their paint() method in order to function + properly. + */ + @Override + public void paint(Graphics g) { + newtWindowImpl.windowRepaint(0, 0, getWidth(), getHeight()); + } + public boolean hasDeviceChanged() { boolean res = displayConfigChanged; displayConfigChanged=false; @@ -275,10 +297,10 @@ public class AWTCanvas extends Canvas { private void disableBackgroundErase() { if (!disableBackgroundEraseInitialized) { try { - AccessController.doPrivileged(new PrivilegedAction() { + AccessController.doPrivileged(new PrivilegedAction<Object>() { public Object run() { try { - Class clazz = getToolkit().getClass(); + Class<?> clazz = getToolkit().getClass(); while (clazz != null && disableBackgroundEraseMethod == null) { try { disableBackgroundEraseMethod = diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java index 942651187..8771f5c74 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTEDTUtil.java @@ -28,72 +28,239 @@ package jogamp.newt.driver.awt; -import javax.media.opengl.Threading; +import java.awt.EventQueue; import com.jogamp.newt.util.EDTUtil; + +import jogamp.common.awt.AWTEDTExecutor; import jogamp.newt.Debug; public class AWTEDTUtil implements EDTUtil { public static final boolean DEBUG = Debug.debug("EDT"); - - private static AWTEDTUtil singletonMainThread = new AWTEDTUtil(); // one singleton MainThread - public static AWTEDTUtil getSingleton() { - return singletonMainThread; - } + private final Object edtLock = new Object(); // locking the EDT start/stop state + private final ThreadGroup threadGroup; + private final String name; + private final Runnable dispatchMessages; + private NewtEventDispatchThread nedt = null; + private int start_iter=0; + private static long pollPeriod = EDTUtil.defaultEDTPollPeriod; - AWTEDTUtil() { - // package private access .. + public AWTEDTUtil(ThreadGroup tg, String name, Runnable dispatchMessages) { + this.threadGroup = tg; + this.name=Thread.currentThread().getName()+"-"+name+"-EDT-"; + this.dispatchMessages=dispatchMessages; + this.nedt = new NewtEventDispatchThread(threadGroup, name); + this.nedt.setDaemon(true); // don't stop JVM from shutdown .. } + @Override final public long getPollPeriod() { - return 0; + return pollPeriod; } + @Override final public void setPollPeriod(long ms) { - // nop + pollPeriod = ms; } + @Override final public void reset() { - // nop AWT is always running + synchronized(edtLock) { + waitUntilStopped(); + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT reset - edt: "+nedt); + } + this.nedt = new NewtEventDispatchThread(threadGroup, name); + this.nedt.setDaemon(true); // don't stop JVM from shutdown .. + } } - final public void start() { - // nop AWT is always running + private final void startImpl() { + if(nedt.isAlive()) { + throw new RuntimeException("EDT Thread.isAlive(): true, isRunning: "+nedt.isRunning()+", edt: "+nedt); + } + start_iter++; + nedt.setName(name+start_iter); + nedt.shouldStop = false; + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT START - edt: "+nedt); + // Thread.dumpStack(); + } + nedt.start(); } + @Override final public boolean isCurrentThreadEDT() { - return Threading.isToolkitThread(); + return EventQueue.isDispatchThread(); } + @Override + public final boolean isCurrentThreadNEDT() { + return nedt == Thread.currentThread(); + } + + @Override + public final boolean isCurrentThreadEDTorNEDT() { + return EventQueue.isDispatchThread() || nedt == Thread.currentThread(); + } + + @Override final public boolean isRunning() { - return true; // AWT is always running + return nedt.isRunning() ; // AWT is always running } - final public void invokeStop(Runnable r) { - invoke(true, r); // AWT is always running + @Override + public final void invokeStop(Runnable task) { + invokeImpl(true, task, true); } - final public void invoke(boolean wait, Runnable r) { - if(r == null) { - return; - } - - Threading.invoke(wait, r, null); + @Override + public final void invoke(boolean wait, Runnable task) { + invokeImpl(wait, task, false); } + + private void invokeImpl(boolean wait, Runnable task, boolean stop) { + if(task == null) { + throw new RuntimeException("Null Runnable"); + } + synchronized(edtLock) { // lock the EDT status + if( nedt.shouldStop ) { + // drop task .. + if(DEBUG) { + System.err.println("Warning: EDT about (1) to stop, won't enqueue new task: "+nedt); + Thread.dumpStack(); + } + return; + } + // System.err.println(Thread.currentThread()+" XXX stop: "+stop+", tasks: "+edt.tasks.size()+", task: "+task); + // Thread.dumpStack(); + if(stop) { + nedt.shouldStop = true; + if(DEBUG) { + System.err.println(Thread.currentThread()+": EDT signal STOP (on edt: "+isCurrentThreadEDT()+") - "+nedt); + // Thread.dumpStack(); + } + } + + // start if should not stop && not started yet + if( !stop && !nedt.isRunning() ) { + startImpl(); + } + } + AWTEDTExecutor.singleton.invoke(wait, task); + } + @Override final public void waitUntilIdle() { - // wait until previous events are processed, at least .. + final NewtEventDispatchThread _edt; + synchronized(edtLock) { + _edt = nedt; + } + if(!_edt.isRunning() || EventQueue.isDispatchThread() || _edt == Thread.currentThread()) { + return; + } try { - Threading.invoke(true, new Runnable() { + AWTEDTExecutor.singleton.invoke(true, new Runnable() { public void run() { } - }, null); + }); } catch (Exception e) { } } + @Override final public void waitUntilStopped() { - // nop: AWT is always running + synchronized(edtLock) { + if(nedt.isRunning() && nedt != Thread.currentThread() ) { + while(nedt.isRunning()) { + try { + edtLock.wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } } + + class NewtEventDispatchThread extends Thread { + volatile boolean shouldStop = false; + volatile boolean isRunning = false; + Object sync = new Object(); + + public NewtEventDispatchThread(ThreadGroup tg, String name) { + super(tg, name); + } + + final public boolean isRunning() { + return isRunning; + } + + @Override + final public void start() throws IllegalThreadStateException { + isRunning = true; + super.start(); + } + + /** + * Utilizing locking only on tasks and its execution, + * not for event dispatching. + */ + @Override + final public void run() { + if(DEBUG) { + System.err.println(getName()+": EDT run() START "+ getName()); + } + RuntimeException error = null; + try { + do { + // event dispatch + if(!shouldStop) { + // FIXME: Determine whether we require to run the + // delivery of events (dispatch) on AWT-EDT. + // Since the WindowDriver itself delivers all Window related events, + // this shall not be required. + // AWTEDTExecutor.singleton.invoke(true, dispatchMessages); + dispatchMessages.run(); + } + // wait + synchronized(sync) { + if(!shouldStop) { + try { + sync.wait(pollPeriod); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + } while(!shouldStop) ; + } catch (Throwable t) { + // handle errors .. + shouldStop = true; + if(t instanceof RuntimeException) { + error = (RuntimeException) t; + } else { + error = new RuntimeException("Within EDT", t); + } + } finally { + if(DEBUG) { + System.err.println(getName()+": EDT run() END "+ getName()+", "+error); + } + synchronized(edtLock) { + isRunning = !shouldStop; + if(!isRunning) { + edtLock.notifyAll(); + } + } + if(DEBUG) { + System.err.println(getName()+": EDT run() EXIT "+ getName()+", exception: "+error); + } + if(null!=error) { + throw error; + } + } // finally + } // run() + } // EventDispatchThread + } diff --git a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java index 39d96585b..70e9ba570 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/DisplayDriver.java @@ -38,6 +38,7 @@ import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.newt.NewtFactory; import com.jogamp.newt.util.EDTUtil; +import jogamp.newt.DefaultEDTUtil; import jogamp.newt.DisplayImpl; public class DisplayDriver extends DisplayImpl { @@ -52,15 +53,12 @@ public class DisplayDriver extends DisplayImpl { aDevice = d; } - protected void closeNativeImpl() { } - - @Override protected EDTUtil createEDTUtil() { final EDTUtil def; if(NewtFactory.useEDT()) { - def = AWTEDTUtil.getSingleton(); + def = new AWTEDTUtil(Thread.currentThread().getThreadGroup(), "AWTDisplay-"+getFQName(), dispatchMessagesRunnable); if(DEBUG) { - System.err.println("AWTDisplay.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); + System.err.println("Display.createNative("+getFQName()+") Create EDTUtil: "+def.getClass().getName()); } } else { def = null; @@ -68,6 +66,8 @@ public class DisplayDriver extends DisplayImpl { return def; } + protected void closeNativeImpl() { } + protected void dispatchMessagesNative() { /* nop */ } } diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java index 1723ffee5..bee43a95e 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java @@ -36,6 +36,7 @@ package jogamp.newt.driver.awt; import java.awt.BorderLayout; import java.awt.Container; +import java.awt.Dimension; import java.awt.Frame; import java.awt.Insets; @@ -47,6 +48,8 @@ import jogamp.newt.WindowImpl; import com.jogamp.nativewindow.awt.AWTGraphicsConfiguration; import com.jogamp.nativewindow.awt.AWTGraphicsDevice; import com.jogamp.nativewindow.awt.AWTGraphicsScreen; +import com.jogamp.newt.event.WindowEvent; +import com.jogamp.newt.event.WindowUpdateEvent; import com.jogamp.newt.event.awt.AWTKeyAdapter; import com.jogamp.newt.event.awt.AWTMouseAdapter; import com.jogamp.newt.event.awt.AWTWindowAdapter; @@ -107,18 +110,18 @@ public class WindowDriver extends WindowImpl { frame.setTitle(getTitle()); } container.setLayout(new BorderLayout()); - canvas = new AWTCanvas(capsRequested, WindowDriver.this.capabilitiesChooser); - - addWindowListener(new LocalWindowListener()); - - new AWTMouseAdapter(this).addTo(canvas); // fwd all AWT Mouse events to here - new AWTKeyAdapter(this).addTo(canvas); // fwd all AWT Key events to here + + canvas = new AWTCanvas(this, capsRequested, WindowDriver.this.capabilitiesChooser); // canvas.addComponentListener(listener); container.add(canvas, BorderLayout.CENTER); - container.setSize(getWidth(), getHeight()); - container.setLocation(getX(), getY()); - new AWTWindowAdapter(this).addTo(container); // fwd all AWT Window events to here + + // via EDT .. + new AWTMouseAdapter(this).addTo(canvas); // fwd all AWT Mouse events to here + new AWTKeyAdapter(this).addTo(canvas); // fwd all AWT Key events to here + + // direct w/o EDT + new AWTWindowAdapter(new LocalWindowListener(), this).addTo(canvas); // fwd all AWT Window events to here reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true)); // throws exception if failed .. @@ -174,20 +177,32 @@ public class WindowDriver extends WindowImpl { frame.setUndecorated(isUndecorated()); } else { if(DEBUG_IMPLEMENTATION) { - System.err.println("AWTWindow can't undecorate already created frame"); + System.err.println(getThreadName()+": AWTWindow can't undecorate already created frame"); } } } + final Dimension szClient = new Dimension(width, height); + canvas.setMinimumSize(szClient); + canvas.setPreferredSize(szClient); + canvas.setSize(szClient); + if(DEBUG_IMPLEMENTATION) { + final Insets insets = container.getInsets(); + final Dimension szContainer = new Dimension(width + insets.left + insets.right, + height + insets.top + insets.bottom); + System.err.println(getThreadName()+": AWTWindow new size: szClient "+szClient+", szCont "+szContainer+", insets "+insets); + } + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { + if(null != frame) { + frame.pack(); + } + container.validate(); container.setVisible(0 != ( FLAG_IS_VISIBLE & flags)); } container.setLocation(x, y); - Insets insets = container.getInsets(); - container.setSize(width + insets.left + insets.right, - height + insets.top + insets.bottom); - + if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) { if( 0 != ( FLAG_IS_VISIBLE & flags ) ) { if( !hasDeviceChanged() ) { @@ -200,6 +215,12 @@ public class WindowDriver extends WindowImpl { } } visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags)); + } else { + container.invalidate(); + if(null != frame) { + frame.pack(); + } + container.validate(); } return true; @@ -216,18 +237,41 @@ public class WindowDriver extends WindowImpl { return canvas; } - class LocalWindowListener extends com.jogamp.newt.event.WindowAdapter { + class LocalWindowListener implements com.jogamp.newt.event.WindowListener { @Override public void windowMoved(com.jogamp.newt.event.WindowEvent e) { if(null!=container) { - definePosition(container.getX(), container.getY()); + WindowDriver.this.positionChanged(false, container.getX(), container.getY()); } } @Override public void windowResized(com.jogamp.newt.event.WindowEvent e) { if(null!=canvas) { - defineSize(canvas.getWidth(), canvas.getHeight()); + WindowDriver.this.sizeChanged(false, canvas.getWidth(), canvas.getHeight(), false); + } + } + @Override + public void windowDestroyNotify(WindowEvent e) { + WindowDriver.this.windowDestroyNotify(false); + } + @Override + public void windowDestroyed(WindowEvent e) { + if(isNativeValid()) { + WindowDriver.this.windowDestroyNotify(true); } + + } + @Override + public void windowGainedFocus(WindowEvent e) { + WindowDriver.this.focusChanged(false, true); + } + @Override + public void windowLostFocus(WindowEvent e) { + WindowDriver.this.focusChanged(false, false); + } + @Override + public void windowRepaint(WindowUpdateEvent e) { + WindowDriver.this.windowRepaint(false, 0, 0, getWidth(), getHeight()); } } } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index ea48569bf..d0c0b8b20 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -117,6 +117,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl return 0 != sscSurfaceHandle ? sscSurfaceHandle : surfaceHandle; } + @Override public void setSurfaceHandle(long surfaceHandle) { if(DEBUG_IMPLEMENTATION) { System.err.println("MacWindow.setSurfaceHandle(): 0x"+Long.toHexString(surfaceHandle)); @@ -170,13 +171,22 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl protected boolean reconfigureWindowImpl(int x, int y, int width, int height, int flags) { - final Point pS = getTopLevelLocationOnScreen(x, y); - isOffscreenInstance = 0 != sscSurfaceHandle || isOffscreenInstance(this, this.getParent()); + final boolean _isOffscreenInstance = isOffscreenInstance(this, this.getParent()); + isOffscreenInstance = 0 != sscSurfaceHandle || _isOffscreenInstance; + final PointImmutable pS = isOffscreenInstance ? new Point(0, 0) : getTopLevelLocationOnScreen(x, y); if(DEBUG_IMPLEMENTATION) { + final AbstractGraphicsConfiguration cWinCfg = this.getGraphicsConfiguration(); + final NativeWindow pWin = getParent(); + final AbstractGraphicsConfiguration pWinCfg = null != pWin ? pWin.getGraphicsConfiguration() : null; System.err.println("MacWindow reconfig: "+x+"/"+y+" -> "+pS+" - "+width+"x"+height+ - ", offscreenInstance "+isOffscreenInstance+ - ", "+getReconfigureFlagsAsString(null, flags)); + ",\n\t parent type "+(null != pWin ? pWin.getClass().getName() : null)+ + ",\n\t this-chosenCaps "+(null != cWinCfg ? cWinCfg.getChosenCapabilities() : null)+ + ",\n\t parent-chosenCaps "+(null != pWinCfg ? pWinCfg.getChosenCapabilities() : null)+ + ", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+ + ", ioi: "+_isOffscreenInstance+ + ") -> "+isOffscreenInstance+ + "\n\t, "+getReconfigureFlagsAsString(null, flags)); } if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && 0 == ( FLAG_IS_VISIBLE & flags) ) { @@ -190,7 +200,11 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl 0 != ( FLAG_CHANGE_DECORATION & flags) || 0 != ( FLAG_CHANGE_PARENTING & flags) || 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) { - createWindow(isOffscreenInstance, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + if(isOffscreenInstance) { + createWindow(true, 0 != getWindowHandle(), pS, 64, 64, false); + } else { + createWindow(false, 0 != getWindowHandle(), pS, width, height, 0 != ( FLAG_IS_FULLSCREEN & flags)); + } if(isVisible()) { flags |= FLAG_CHANGE_VISIBILITY; } } if(x>=0 && y>=0) { diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index e0330a563..b9c339285 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -94,7 +94,13 @@ static void changeContentView(JNIEnv *env, jobject javaWindowObject, NSView *pvi if(NULL!=oldNSView) { NS_DURING // Available >= 10.5 - Makes the menubar disapear - if([oldNSView isInFullScreenMode]) { + BOOL iifs; + if ( [oldNSView respondsToSelector:@selector(isInFullScreenMode)] ) { + iifs = [oldNSView isInFullScreenMode]; + } else { + iifs = NO; + } + if(iifs && [oldNSView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) { [oldNSView exitFullScreenModeWithOptions: NULL]; } NS_HANDLER @@ -430,6 +436,8 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree if( -1 < mode_idx ) { prop[propIndex++] = mode_idx; } + int refreshRate = CGDDGetModeRefreshRate(mode); + int fRefreshRate = ( 0 < refreshRate ) ? refreshRate : 60; // default .. (experienced on OSX 10.6.8) prop[propIndex++] = 0; // set later for verification of iterator propIndexRes = propIndex; prop[propIndex++] = mWidth; @@ -437,14 +445,14 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_ScreenDriver_getScree prop[propIndex++] = CGDDGetModeBitsPerPixel(mode); prop[propIndex++] = widthMM; prop[propIndex++] = heightMM; - prop[propIndex++] = CGDDGetModeRefreshRate(mode); + prop[propIndex++] = fRefreshRate; prop[propIndex++] = ccwRot; prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL - DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d Hz, rot %d ccw\n", + DBG_PRINT( "getScreenMode0: Mode %d/%d (%d): %dx%d, %d bpp, %dx%d mm, %d / %d Hz, rot %d ccw\n", (int)mode_idx, (int)numberOfAvailableModesRots, (int)numberOfAvailableModes, (int)prop[propIndexRes+0], (int)prop[propIndexRes+1], (int)prop[propIndexRes+2], - (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], (int)prop[propIndexRes+6]); + (int)prop[propIndexRes+3], (int)prop[propIndexRes+4], (int)prop[propIndexRes+5], refreshRate, (int)prop[propIndexRes+6]); jintArray properties = (*env)->NewIntArray(env, prop_num); if (properties == NULL) { @@ -516,6 +524,8 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 if(initialized) return JNI_TRUE; initialized = 1; + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + jclass c; c = (*env)->FindClass(env, ClazzNamePoint); if(NULL==c) { @@ -537,7 +547,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_initIDs0 // printf("Going to sleep for 10 seconds\n"); // sleep(10); - return (jboolean) [NewtMacWindow initNatives: env forClass: clazz]; + BOOL res = [NewtMacWindow initNatives: env forClass: clazz]; + [pool release]; + + return (jboolean) res; } /* @@ -602,8 +615,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_createWindow // Remove animations for child windows if(NULL != parentWindow) { NS_DURING - // Available >= 10.7 - Removes default animations - [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; + if ( [myWindow respondsToSelector:@selector(setAnimationBehavior:)] ) { + // Available >= 10.7 - Removes default animations + [myWindow setAnimationBehavior: NSWindowAnimationBehaviorNone]; + } NS_HANDLER NS_ENDHANDLER } @@ -658,8 +673,12 @@ NS_ENDHANDLER NS_DURING // concurrent view rendering // Available >= 10.6 - Makes the menubar disapear - [myWindow setAllowsConcurrentViewDrawing: YES]; - [myView setCanDrawConcurrently: YES]; + if ( [myWindow respondsToSelector:@selector(setAllowsConcurrentViewDrawing:)] ) { + [myWindow setAllowsConcurrentViewDrawing: YES]; + } + if ( [myView respondsToSelector:@selector(setCanDrawConcurrently:)] ) { + [myView setCanDrawConcurrently: YES]; + } NS_HANDLER NS_ENDHANDLER @@ -669,7 +688,9 @@ NS_ENDHANDLER NS_DURING // Available >= 10.5 - Makes the menubar disapear if(fullscreen) { - [myView enterFullScreenMode: myScreen withOptions:NULL]; + if ( [myView respondsToSelector:@selector(enterFullScreenMode:withOptions:)] ) { + [myView enterFullScreenMode: myScreen withOptions:NULL]; + } } NS_HANDLER NS_ENDHANDLER @@ -730,7 +751,13 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_close0 NS_DURING if(NULL!=mView) { // Available >= 10.5 - Makes the menubar disapear - if([mView isInFullScreenMode]) { + BOOL iifs; + if ( [mView respondsToSelector:@selector(isInFullScreenMode)] ) { + iifs = [mView isInFullScreenMode]; + } else { + iifs = NO; + } + if(iifs && [mView respondsToSelector:@selector(exitFullScreenModeWithOptions:)] ) { [mView exitFullScreenModeWithOptions: NULL]; } // Note: mWin's release will also release it's mView! |