diff options
Diffstat (limited to 'src/newt/classes')
27 files changed, 1277 insertions, 802 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 6705db970..113ec547e 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -127,17 +127,18 @@ public abstract class Display { /** Make sure to reuse a Display with the same name */ protected static Display create(String type, String name, final long handle) { try { - if(null==name && 0!=handle) { - name="wrapping-0x"+Long.toHexString(handle); // may change within implementation .. - } + Class displayClass = getDisplayClass(type); + Display tmpDisplay = (Display) displayClass.newInstance(); + name = tmpDisplay.validateDisplayName(name, handle); + if(DEBUG) { dumpDisplayMap("Display.create("+getFQName(type, name)+") BEGIN"); } Display display = getCurrentDisplay(type, name); if(null==display) { - Class displayClass = getDisplayClass(type); - display = (Display) displayClass.newInstance(); - display.name=name; + display = tmpDisplay; + tmpDisplay = null; + display.name = name; display.type=type; display.refCount=1; @@ -145,7 +146,7 @@ public abstract class Display { final Display f_dpy = display; Thread current = Thread.currentThread(); display.edtUtil = new EDTUtil(current.getThreadGroup(), - "Display_"+display.getFQName()+"-"+current.getName(), + "Display_"+display.getFQName(), new Runnable() { public void run() { if(null!=f_dpy.getGraphicsDevice()) { @@ -155,11 +156,11 @@ public abstract class Display { display.edt = display.edtUtil.start(); display.edtUtil.invokeAndWait(new Runnable() { public void run() { - f_dpy.createNative(handle); + f_dpy.createNative(); } } ); } else { - display.createNative(handle); + display.createNative(); } if(null==display.aDevice) { throw new RuntimeException("Display.createNative() failed to instanciate an AbstractGraphicsDevice"); @@ -169,6 +170,7 @@ public abstract class Display { System.err.println("Display.create("+getFQName(type, name)+") NEW: "+display+" "+Thread.currentThread()); } } else { + tmpDisplay = null; synchronized(display) { display.refCount++; if(DEBUG) { @@ -224,7 +226,7 @@ public abstract class Display { } } - protected abstract void createNative(long handle); + protected abstract void createNative(); protected abstract void closeNative(); public final String getType() { @@ -241,10 +243,17 @@ public abstract class Display { static final String nilString = "nil" ; + protected String validateDisplayName(String name, long handle) { + if(null==name && 0!=handle) { + name="wrapping-0x"+Long.toHexString(handle); + } + return ( null == name ) ? nilString : name ; + } + public static final String getFQName(String type, String name) { if(null==type) type=nilString; if(null==name) name=nilString; - return type+":"+name; + return type+"_"+name; } public long getHandle() { @@ -268,7 +277,7 @@ public abstract class Display { } public String toString() { - return "NEWT-Display["+getFQName()+", refCount "+refCount+", "+aDevice+"]"; + return "NEWT-Display["+getFQName()+", refCount "+refCount+", hasEDT "+(null!=edtUtil)+", "+aDevice+"]"; } protected abstract void dispatchMessagesNative(); @@ -276,32 +285,49 @@ public abstract class Display { private LinkedList/*<NEWTEvent>*/ events = new LinkedList(); protected void dispatchMessages() { - NEWTEvent e; - do { + if(!events.isEmpty()) { synchronized(events) { - if (!events.isEmpty()) { - e = (NEWTEvent) events.removeFirst(); - } else { - e = null; - } - } - if (e != null) { - Object source = e.getSource(); - if(source instanceof Window) { - ((Window)source).sendEvent(e); - } else { - throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); + while (!events.isEmpty()) { + NEWTEvent e = (NEWTEvent) events.removeFirst(); + Object source = e.getSource(); + if(source instanceof Window) { + ((Window)source).sendEvent(e); + } else { + throw new RuntimeException("Event source not a NEWT Window: "+source.getClass().getName()+", "+source); + } } + events.notifyAll(); } - } while (e != null); + } dispatchMessagesNative(); } public void enqueueEvent(NEWTEvent e) { + enqueueEvent(false, e); + } + + public void enqueueEvent(boolean wait, NEWTEvent e) { synchronized(events) { + if(DEBUG) { + System.out.println("Display.enqueueEvent: START - wait "+wait+", "+e); + } events.addLast(e); } + if(wait && !events.isEmpty()) { + synchronized(events) { + while(!events.isEmpty()) { + try { + events.wait(); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + } + } + if(DEBUG) { + System.out.println("Display.enqueueEvent: END - wait "+wait+", "+e); + } } diff --git a/src/newt/classes/com/jogamp/newt/NewtFactory.java b/src/newt/classes/com/jogamp/newt/NewtFactory.java index 7860197ef..3959c6a8d 100755 --- a/src/newt/classes/com/jogamp/newt/NewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/NewtFactory.java @@ -106,101 +106,80 @@ public abstract class NewtFactory { * Create a top level Window entity, incl native creation */ public static Window createWindow(Screen screen, Capabilities caps) { - return Window.create(NativeWindowFactory.getNativeWindowType(true), null, 0, screen, caps, false); + return createWindowImpl(NativeWindowFactory.getNativeWindowType(true), screen, caps, false); } /** * Create a top level Window entity, incl native creation */ public static Window createWindow(Screen screen, Capabilities caps, boolean undecorated) { - return Window.create(NativeWindowFactory.getNativeWindowType(true), null, 0, screen, caps, undecorated); + return createWindowImpl(NativeWindowFactory.getNativeWindowType(true), screen, caps, undecorated); } /** * Create a child Window entity attached to the given parent, incl native creation.<br> - * The Screen and Display information is regenrated utilizing the parents information.<br> + * The Screen and Display information is regenerated utilizing the parents information.<br> * <p> - * In case <code>parentWindowObject</code> is a {@link javax.media.nativewindow.NativeWindow},<br> - * we create a child {@link com.jogamp.newt.Window}, - * utilizing {@link com.jogamp.newt.NewtFactory#createWindowImpl(java.lang.String, javax.media.nativewindow.NativeWindow, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean)}<br></p>. - * <p> - * In case <code>parentWindowObject</code> is even a {@link com.jogamp.newt.Window}, the following applies:<br> - * {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_RESIZED} is not propagated to the child window for e.g. layout<br>, + * In case <code>parentWindowObject</code> is a {@link com.jogamp.newt.Window} instance,<br> + * the new window is added to it's list of children.<br> + * This assures proper handling of visibility, creation and destruction.<br> + * {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_RESIZED} is not propagated to the child window for layout<br>, * you have to add an appropriate {@link com.jogamp.newt.event.WindowListener} for this use case.<br> - * However, {@link com.jogamp.newt.event.WindowEvent#EVENT_WINDOW_DESTROY_NOTIFY} is propagated to the child window, so it will be closed properly.<br> * The parents visibility is passed to the new Window<br></p> * <p> * In case <code>parentWindowObject</code> is a different {@link javax.media.nativewindow.NativeWindow} implementation,<br> * you have to handle all events appropriatly.<br></p> * <p> - * In case <code>parentWindowObject</code> is a {@link java.awt.Component},<br> - * we utilize the {@link com.jogamp.newt.impl.awt.AWTNewtFactory#createNativeChildWindow(Object, com.jogamp.newt.Capabilities, boolean)} - * factory method.<br> - * The factory adds a {@link com.jogamp.newt.event.WindowListener} to propagate {@link com.jogamp.newt.event.WindowEvent}'s so - * your NEWT Window integrates into the AWT layout.<br> - * The parents visibility is passed to the new Window<br></p> * - * @param parentWindowObject either a NativeWindow or java.awt.Component + * @param parentWindowObject either a NativeWindow instance * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always - * - * @see com.jogamp.newt.NewtFactory#createWindow(long, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean) - * @see com.jogamp.newt.impl.awt.AWTNewtFactory#createNativeChildWindow(java.lang.Object, javax.media.nativewindow.Capabilities, boolean) */ - public static Window createWindow(Object parentWindowObject, Capabilities caps, boolean undecorated) { + public static Window createWindow(NativeWindow nParentWindow, Capabilities caps, boolean undecorated) { final String type = NativeWindowFactory.getNativeWindowType(true); - if(null==parentWindowObject) { - return createWindowImpl(type, null, null, caps, undecorated); + if(null==nParentWindow) { + return createWindowImpl(type, caps, undecorated); } - if(parentWindowObject instanceof NativeWindow) { - NativeWindow nParentWindow = (NativeWindow) parentWindowObject; - - Display display=null; - Screen screen=null; - Window parentWindow=null; - - if ( nParentWindow instanceof Window ) { - parentWindow = (Window) nParentWindow ; - Screen nParentScreen = parentWindow.getScreen(); - Display nParentDisplay = nParentScreen.getDisplay(); - display = NewtFactory.wrapDisplay(type, nParentDisplay.getHandle()); - screen = NewtFactory.createScreen(type, display, nParentScreen.getIndex()); - } else { - AbstractGraphicsConfiguration nParentConfig = nParentWindow.getGraphicsConfiguration(); - AbstractGraphicsScreen nParentScreen = nParentConfig.getScreen(); - AbstractGraphicsDevice nParentDevice = nParentScreen.getDevice(); - display = NewtFactory.wrapDisplay(type, nParentDevice.getHandle()); - screen = NewtFactory.createScreen(type, display, nParentScreen.getIndex()); - } - final Window win = createWindowImpl(type, nParentWindow, screen, caps, undecorated); - win.setSize(nParentWindow.getWidth(), nParentWindow.getHeight()); - if ( null != parentWindow ) { - parentWindow.addWindowListener(new WindowAdapter() { - public void windowDestroyNotify(WindowEvent e) { - win.sendEvent(e); - } - }); - win.setVisible(parentWindow.isVisible()); - } - return win; + Screen screen = null; + AbstractGraphicsConfiguration nParentConfig = nParentWindow.getGraphicsConfiguration(); + if(null!=nParentConfig) { + AbstractGraphicsScreen nParentScreen = nParentConfig.getScreen(); + AbstractGraphicsDevice nParentDevice = nParentScreen.getDevice(); + Display display = NewtFactory.wrapDisplay(type, nParentDevice.getHandle()); + screen = NewtFactory.createScreen(type, display, nParentScreen.getIndex()); } else { - if(ReflectionUtil.instanceOf(parentWindowObject, "java.awt.Component")) { - if(ReflectionUtil.isClassAvailable("com.jogamp.newt.impl.awt.AWTNewtFactory")) { - return (Window) ReflectionUtil.callStaticMethod( - "com.jogamp.newt.impl.awt.AWTNewtFactory", - "createNativeChildWindow", - new Class[] { Object.class, Capabilities.class, java.lang.Boolean.TYPE}, - new Object[] { parentWindowObject, caps, new Boolean(undecorated) } ); - } - } + Display display = NewtFactory.createDisplay(type, null); // local display + screen = NewtFactory.createScreen(type, display, 0); // screen 0 + } + final Window win = createWindowImpl(type, nParentWindow, screen, caps, undecorated); + + win.setSize(nParentWindow.getWidth(), nParentWindow.getHeight()); + if ( nParentWindow instanceof Window ) { + Window parentWindow = (Window) nParentWindow ; + parentWindow.getInnerWindow().addChild(win); + win.setVisible(parentWindow.isVisible()); } - throw new RuntimeException("No NEWT child Window factory method for parent object: "+parentWindowObject); + return win; } protected static Window createWindowImpl(String type, NativeWindow parentNativeWindow, Screen screen, Capabilities caps, boolean undecorated) { return Window.create(type, parentNativeWindow, 0, screen, caps, undecorated); } + protected static Window createWindowImpl(String type, long parentWindowHandle, Screen screen, Capabilities caps, boolean undecorated) { + return Window.create(type, null, parentWindowHandle, screen, caps, undecorated); + } + + protected static Window createWindowImpl(String type, Screen screen, Capabilities caps, boolean undecorated) { + return Window.create(type, null, 0, screen, caps, undecorated); + } + + protected static Window createWindowImpl(String type, Capabilities caps, boolean undecorated) { + Display display = NewtFactory.createDisplay(type, null); // local display + Screen screen = NewtFactory.createScreen(type, display, 0); // screen 0 + return Window.create(type, null, 0, screen, caps, undecorated); + } + /** * Create a child Window entity attached to the given parent, incl native creation<br> * @@ -208,7 +187,7 @@ public abstract class NewtFactory { * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always */ public static Window createWindow(long parentWindowHandle, Screen screen, Capabilities caps, boolean undecorated) { - return Window.create(NativeWindowFactory.getNativeWindowType(true), null, parentWindowHandle, screen, caps, undecorated); + return createWindowImpl(NativeWindowFactory.getNativeWindowType(true), parentWindowHandle, screen, caps, undecorated); } /** @@ -228,7 +207,7 @@ public abstract class NewtFactory { * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always */ public static Window createWindow(String type, Screen screen, Capabilities caps, boolean undecorated) { - return Window.create(type, null, 0, screen, caps, undecorated); + return createWindowImpl(type, null, screen, caps, undecorated); } public static Window createWindow(String type, Object[] cstrArguments, Screen screen, Capabilities caps, boolean undecorated) { diff --git a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java index 5b957afa5..0f75fbfa9 100644 --- a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java @@ -71,7 +71,7 @@ public class OffscreenWindow extends Window implements SurfaceChangeable { surfaceHandle = 0; } - public synchronized void destroy() { + public synchronized void destroy(boolean deep) { surfaceHandle = 0; } @@ -83,7 +83,7 @@ public class OffscreenWindow extends Window implements SurfaceChangeable { return surfaceHandle; } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { } public void setSize(int width, int height) { @@ -92,14 +92,24 @@ public class OffscreenWindow extends Window implements SurfaceChangeable { this.height = height; } } + protected void setSizeImpl(int width, int height) { + shouldNotCallThis(); + } public void setPosition(int x, int y) { // nop } + protected void setPositionImpl(int x, int y) { + shouldNotCallThis(); + } public boolean setFullscreen(boolean fullscreen) { // nop return false; } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + shouldNotCallThis(); + return false; + } } diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 978b7f068..bb3fa8982 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -90,10 +90,6 @@ public abstract class Window implements NativeWindow protected static Window create(String type, NativeWindow parentNativeWindow, long parentWindowHandle, Screen screen, Capabilities caps, boolean undecorated) { try { - if(null==screen) { - Display display = NewtFactory.createDisplay(type, null); // local display - screen = NewtFactory.createScreen(type, display, 0); // screen 0 - } Class windowClass; if(caps.isOnscreen()) { windowClass = getWindowClass(type); @@ -101,7 +97,7 @@ public abstract class Window implements NativeWindow windowClass = OffscreenWindow.class; } Window window = (Window) windowClass.newInstance(); - window.invalidate(); + window.invalidate(true); window.parentNativeWindow = parentNativeWindow; window.parentWindowHandle = parentWindowHandle; window.screen = screen; @@ -126,7 +122,7 @@ public abstract class Window implements NativeWindow throw new NativeWindowException("WindowClass "+windowClass+" constructor mismatch at argument #"+argsChecked+"; Constructor: "+getTypeStrList(cstrArgumentTypes)+", arguments: "+getArgsStrList(cstrArguments)); } Window window = (Window) ReflectionUtil.createInstance( windowClass, cstrArgumentTypes, cstrArguments ) ; - window.invalidate(); + window.invalidate(true); window.screen = screen; window.caps = (Capabilities)caps.clone(); window.setUndecorated(undecorated); @@ -146,7 +142,7 @@ public abstract class Window implements NativeWindow protected Screen screen; - private NativeWindow parentNativeWindow; + protected NativeWindow parentNativeWindow; protected long parentWindowHandle; protected Capabilities caps; @@ -154,52 +150,81 @@ public abstract class Window implements NativeWindow protected long windowHandle; protected boolean fullscreen, visible; protected int width, height, x, y; - protected int eventMask; + + // non fullscreen dimensions .. + protected int nfs_width, nfs_height, nfs_x, nfs_y; protected String title = "Newt Window"; protected boolean undecorated = false; - private synchronized boolean createNative() { + private boolean createNative() { if( null==screen || 0!=windowHandle || !visible ) { - // NOP .. or already done return 0 != windowHandle ; } EDTUtil edtUtil = screen.getDisplay().getEDTUtil(); - if( null != edtUtil && !edtUtil.isCurrentThreadEDT() ) { + if( null != edtUtil && edtUtil.isRunning() && !edtUtil.isCurrentThreadEDT() ) { throw new NativeWindowException("EDT enabled but not on EDT"); } - if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.createNative() START ("+Thread.currentThread()+", "+this+")"); + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.createNative() START ("+Thread.currentThread()+", "+this+")"); } if(validateParentWindowHandle()) { createNativeImpl(); - setVisibleImpl(); + setVisibleImpl(true); } - if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.createNative() END ("+Thread.currentThread()+", "+this+")"); + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.createNative() END ("+Thread.currentThread()+", "+this+")"); } return 0 != windowHandle ; } private boolean validateParentWindowHandle() { - boolean ok = true; if(null!=parentNativeWindow) { + parentWindowHandle = getNativeWindowHandle(parentNativeWindow); + return 0 != parentWindowHandle ; + } + return true; + } + + private static long getNativeWindowHandle(NativeWindow nativeWindow) { + long handle = 0; + if(null!=nativeWindow) { + boolean ok = true; try { - parentNativeWindow.lockSurface(); + nativeWindow.lockSurface(); } catch (NativeWindowException nwe) { // parent native window not ready .. just skip action for now ok = false; + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.getNativeWindowHandle: not successful yet: "+nwe); + } } if(ok) { - parentWindowHandle = parentNativeWindow.getWindowHandle(); - parentNativeWindow.unlockSurface(); - if(0==parentWindowHandle) { - throw new NativeWindowException("Parent native window handle is NULL, after succesful locking: "+parentNativeWindow); + handle = nativeWindow.getWindowHandle(); + nativeWindow.unlockSurface(); + if(0==handle) { + throw new NativeWindowException("Parent native window handle is NULL, after succesful locking: "+nativeWindow); + } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.getNativeWindowHandle: "+nativeWindow); } } } - return ok; + return handle; + } + + public void runOnEDTIfAvail(boolean wait, final Runnable task) { + Screen screen = getInnerWindow().getScreen(); + if(null==screen) { + throw new RuntimeException("Null screen of inner class: "+this); + } + EDTUtil edtUtil = screen.getDisplay().getEDTUtil(); + if(null!=edtUtil) { + edtUtil.invoke(wait, task); + } else { + task.run(); + } } /** @@ -209,6 +234,14 @@ public abstract class Window implements NativeWindow protected abstract void closeNative(); + public Capabilities getRequestedCapabilities() { + return (Capabilities)caps.clone(); + } + + public NativeWindow getParentNativeWindow() { + return parentNativeWindow; + } + public Screen getScreen() { return screen; } @@ -218,6 +251,8 @@ public abstract class Window implements NativeWindow sb.append(getClass().getName()+"[Config "+config+ "\n, "+screen+ + "\n, ParentWindow "+parentNativeWindow+ + "\n, ParentWindowHandle "+toHexString(parentWindowHandle)+ "\n, WindowHandle "+toHexString(getWindowHandle())+ "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ "\n, Pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+ @@ -261,8 +296,12 @@ public abstract class Window implements NativeWindow undecorated = value; } + public boolean isUndecorated(boolean fullscreen) { + return 0 != parentWindowHandle || undecorated || fullscreen ; + } + public boolean isUndecorated() { - return undecorated; + return 0 != parentWindowHandle || undecorated || fullscreen ; } public void requestFocus() { @@ -273,16 +312,19 @@ public abstract class Window implements NativeWindow // /** Recursive and blocking lockSurface() implementation */ - public synchronized int lockSurface() { + public int lockSurface() { // We leave the ToolkitLock lock to the specializtion's discretion, // ie the implicit JAWTWindow in case of AWTWindow + if(isDestroyed() || !isNativeWindowValid()) { + return LOCK_SURFACE_NOT_READY; + } surfaceLock.lock(); screen.getDisplay().lockDisplay(); return LOCK_SUCCESS; } /** Recursive and unblocking unlockSurface() implementation */ - public synchronized void unlockSurface() throws NativeWindowException { + public void unlockSurface() throws NativeWindowException { surfaceLock.unlock( new Runnable() { public void run() { screen.getDisplay().unlockDisplay(); @@ -292,59 +334,84 @@ public abstract class Window implements NativeWindow // ie the implicit JAWTWindow in case of AWTWindow } - public synchronized boolean isSurfaceLocked() { + public boolean isSurfaceLocked() { return surfaceLock.isLocked(); } - public synchronized Thread getSurfaceLockOwner() { + public Thread getSurfaceLockOwner() { return surfaceLock.getOwner(); } - public synchronized Exception getLockedStack() { + public Exception getLockedStack() { return surfaceLock.getLockedStack(); } - public void destroy() { + /** + * <p> + * destroys the window and children and releases + * windowing related resources.<br></p> + * <p> + * all other resources and states are kept intact, + * ie listeners, parent handles and size, position etc.<br></p> + * + * @see #destroy(boolean) + * @see #invalidate() + */ + public final void destroy() { destroy(false); } - /** @param deep If true, the linked Screen and Display will be destroyed as well. */ - public void destroy(boolean deep) { - if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.destroy() start (deep "+deep+" - "+Thread.currentThread()+", "+this+")"); - } - synchronized(surfaceUpdatedListeners) { - surfaceUpdatedListeners = new ArrayList(); - } - synchronized(windowListeners) { - windowListeners = new ArrayList(); + class DestroyAction implements Runnable { + boolean deep; + public DestroyAction(boolean deep) { + this.deep = deep; } - synchronized(mouseListeners) { - mouseListeners = new ArrayList(); - } - synchronized(keyListeners) { - keyListeners = new ArrayList(); - } - synchronized(this) { - destructionLock.lock(); + public void run() { + windowLock(); try { + if(DEBUG_WINDOW_EVENT) { + System.err.println("Window.destroy(deep: "+deep+") START "+Thread.currentThread()+", "+this); + } + + // Childs first .. + ArrayList listeners = null; + synchronized(childWindows) { + listeners = childWindows; + } + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + NativeWindow nw = (NativeWindow) i.next(); + if(nw instanceof Window) { + ((Window)nw).destroy(deep); + } else { + nw.destroy(); + } + } + + // Now us .. + if(deep) { + synchronized(childWindows) { + childWindows = new ArrayList(); + } + synchronized(surfaceUpdatedListeners) { + surfaceUpdatedListeners = new ArrayList(); + } + synchronized(windowListeners) { + windowListeners = new ArrayList(); + } + synchronized(mouseListeners) { + mouseListeners = new ArrayList(); + } + synchronized(keyListeners) { + keyListeners = new ArrayList(); + } + } Display dpy = null; if( null != screen && 0 != windowHandle ) { Screen scr = screen; dpy = (null!=screen) ? screen.getDisplay() : null; - EDTUtil edtUtil = (null!=dpy) ? dpy.getEDTUtil() : null; - if(null!=edtUtil) { - final Window f_win = this; - edtUtil.invokeAndWait(new Runnable() { - public void run() { - f_win.closeNative(); - } - } ); - } else { - closeNative(); - } + closeNative(); } - invalidate(); + invalidate(deep); if(deep) { if(null!=screen) { screen.destroy(); @@ -353,34 +420,85 @@ public abstract class Window implements NativeWindow dpy.destroy(); } } + if(DEBUG_WINDOW_EVENT) { + System.err.println("Window.destroy(deep: "+deep+") END "+Thread.currentThread()+", "+this); + } } finally { - destructionLock.unlock(); + windowUnlock(); } } - if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.destroy() end "+Thread.currentThread()); + } + + /** + * @param deep If true, all resources, ie listeners, parent handles, size, position + * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call + * this method with deep = true, you will not be able to regenerate the Window. + * @see #destroy() + * @see #invalidate(boolean) + */ + public void destroy(boolean deep) { + if(!isDestroyed()) { + runOnEDTIfAvail(true, new DestroyAction(deep)); } } + /** + * <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 void invalidate() { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - Exception e = new Exception("!!! Window Invalidate "+Thread.currentThread()); - e.printStackTrace(); + invalidate(false); + } + + /** + * @param deep if false only the native window handle is invalidated, otherwise all + * states (references and properties) are reset. Be aware that if you call + * this method with deep = true, you will not be able to regenerate the Window. + * @see #invalidate() + * @see #destroy() + * @see #destroy(boolean) + */ + public void invalidate(boolean deep) { + windowLock(); + try{ + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + String msg = new String("!!! Window Invalidate(deep: "+deep+") "+Thread.currentThread()); + System.err.println(msg); + //Exception e = new Exception(msg); + //e.printStackTrace(); + } + windowHandle = 0; + visible=false; + fullscreen=false; + + if(deep) { + screen = null; + parentWindowHandle = 0; + parentNativeWindow = null; + caps = null; + + // Default position and dimension will be re-set immediately by user + width = 128; + height = 128; + x=0; + y=0; + } + } finally { + windowUnlock(); } - screen = null; - parentNativeWindow = null; - parentWindowHandle = 0; - caps = null; - windowHandle = 0; - fullscreen=false; - visible=false; - eventMask = 0; + } - // Default position and dimension will be re-set immediately by user - width = 128; - height = 128; - x=0; - y=0; + /** @return true if the native window handle is valid and ready to operate */ + public boolean isNativeWindowValid() { + return 0 != windowHandle ; } public boolean isDestroyed() { @@ -391,10 +509,6 @@ public abstract class Window implements NativeWindow return false; } - protected void clearEventMask() { - eventMask=0; - } - public long getDisplayHandle() { return screen.getDisplay().getHandle(); } @@ -442,6 +556,14 @@ public abstract class Window implements NativeWindow return new Insets(0,0,0,0); } + /** Returns the most inner Window instance.<br> + Currently only {@link com.jogamp.newt.opengl.GLWindow} + has an aggregation to an inner Window instance. + */ + public Window getInnerWindow() { + return this; + } + /** If this Window actually wraps one from another toolkit such as the AWT, this will return a non-null value. */ public Object getWrappedWindow() { @@ -468,7 +590,7 @@ public abstract class Window implements NativeWindow return fullscreen; } - private boolean autoDrawableMember = false; + private boolean handleDestroyNotify = true; /** If the implementation is capable of detecting a device change return true and clear the status/reason of the change. */ @@ -477,107 +599,258 @@ public abstract class Window implements NativeWindow } /** - * If set to true, - * certain action will be performed by the owning - * AutoDrawable, ie the destroy() call within windowDestroyNotify() + * If set to true, the default value, this NEWT Window implementation will + * handle the destruction (ie {@link #destroy()} call) within {@link #windowDestroyNotify()} implementation.<br> + * If set to false, it's up to the caller/owner to handle destruction within {@link #windowDestroyNotify()}. */ - public void setAutoDrawableClient(boolean b) { - autoDrawableMember = b; + public void setHandleDestroyNotify(boolean b) { + handleDestroyNotify = b; } protected void windowDestroyNotify() { if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.windowDestroyNotify start "+Thread.currentThread()); + System.err.println("Window.windowDestroyNotify START "+Thread.currentThread()); } sendWindowEvent(WindowEvent.EVENT_WINDOW_DESTROY_NOTIFY); - if(!autoDrawableMember && !destructionLock.isLocked()) { + if(handleDestroyNotify && !isDestroyed()) { destroy(); } if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.windowDestroyeNotify end "+Thread.currentThread()); + System.err.println("Window.windowDestroyeNotify END "+Thread.currentThread()); } } protected void windowDestroyed() { if(DEBUG_WINDOW_EVENT) { - System.out.println("Window.windowDestroyed "+Thread.currentThread()); + System.err.println("Window.windowDestroyed "+Thread.currentThread()); } - if(!destructionLock.isLocked()) { - invalidate(); + invalidate(); + } + + protected boolean reparentWindowImpl() { + // default implementation, no native reparenting support + return false; + } + + /** + * Change this window's parent window.<br> + * <P> + * In case the old parent is not null and a Window, + * this window is removed from it's list of children.<br> + * In case the new parent is not null and a Window, + * this window is added to it's list of children.<br></P> + * + * @param newParent the new parent NativeWindow. If null, this Window becomes a top level window. + * @param newScreen if not null and this window handle is not yet set + * this Screen is being used. + */ + public void reparentWindow(NativeWindow newParent, Screen newScreen) { + windowLock(); + try{ + if ( 0 == windowHandle && null != newScreen ) { + screen = newScreen; + } + long newParentHandle = 0 ; + if(null!=newParent) { + newParentHandle = getNativeWindowHandle(newParent); + if ( 0 == newParentHandle ) { + return; // bail out .. not ready yet + } + } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("reparent: START ("+Thread.currentThread()+") windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+" -> "+toHexString(newParentHandle)+", visible "+visible+", parentNativeWindow "+(null!=parentNativeWindow)); + } + + if(null!=parentNativeWindow && parentNativeWindow instanceof Window) { + ((Window)parentNativeWindow).getInnerWindow().removeChild(this); + } + parentNativeWindow = newParent; + if(parentNativeWindow instanceof Window) { + ((Window)parentNativeWindow).getInnerWindow().addChild(this); + } + + if(newParentHandle != parentWindowHandle) { + parentWindowHandle = newParentHandle; + if(0!=parentWindowHandle) { + // reset position to 0/0 within parent space + // FIXME .. cache position ? + x = 0; + y = 0; + } + if(!reparentWindowImpl()) { + parentWindowHandle = 0; + + // do it the hard way .. reconstruction with setVisible(true) + if( 0 != windowHandle ) { + destroy(false); + } + } + } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("reparentWindow: END ("+Thread.currentThread()+") windowHandle "+toHexString(windowHandle)+", visible: "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); + } + } finally { + windowUnlock(); + } + } + + class VisibleAction implements Runnable { + boolean visible; + public VisibleAction(boolean visible) { + this.visible = visible; + } + public void run() { + windowLock(); + try{ + if( !isDestroyed() ) { + ArrayList listeners = null; + synchronized(childWindows) { + listeners = childWindows; + } + if(!visible && listeners.size()>0) { + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + NativeWindow nw = (NativeWindow) i.next(); + if(nw instanceof Window) { + ((Window)nw).setVisible(false); + } + } + } + if(0==windowHandle && visible) { + Window.this.visible = visible; + if( 0<width*height ) { + createNative(); + } + } else if(Window.this.visible != visible) { + Window.this.visible = visible; + if(0 != windowHandle) { + setVisibleImpl(visible); + } + } + if(0!=windowHandle && visible && listeners.size()>0) { + for(Iterator i = listeners.iterator(); i.hasNext(); ) { + NativeWindow nw = (NativeWindow) i.next(); + if(nw instanceof Window) { + ((Window)nw).setVisible(true); + } + } + } + } + + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setVisible: END ("+Thread.currentThread()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+Window.this.visible); + } + } finally { + windowUnlock(); + } } } /** * <p> - * <code>setVisible</code> makes the window visible if <code>visible</code> is true, - * otherwise the window becomes invisible.<br></p> + * <code>setVisible</code> makes the window and children visible if <code>visible</code> is true, + * otherwise the window and children becomes invisible.<br></p> * <p> * The <code>setVisible(true)</code> is responsible to actual create the native window.<br></p> * <p> + * Zero size semantics are respected, see {@link #setSize(int,int)}:<br> + * <pre> + * if ( 0 == windowHandle && visible ) { + * this.visible = visible; + * if( 0<width*height ) { + * createNative(); + * } + * } else if ( this.visible != visible ) { + * this.visible = visible; + * setNativeSizeImpl(); + * } + * </pre></p> + * <p> * In case this window is a child window and a parent {@link javax.media.nativewindow.NativeWindow} is being used,<br> * the parent's {@link javax.media.nativewindow.NativeWindow} handle is retrieved via {@link javax.media.nativewindow.NativeWindow#getWindowHandle()}.<br> * If this action fails, ie if the parent {@link javax.media.nativewindow.NativeWindow} is not valid yet,<br> * no native window is created yet and <code>setVisible(true)</code> shall be repeated when it is.<br></p> */ - public void setVisible(final boolean visible) { - setVisible(visible, false); - } - - public void setVisible(final boolean visible, boolean deferred) { - if(!isDestroyed()) { - EDTUtil edtUtil = screen.getDisplay().getEDTUtil(); - if(null!=edtUtil) { - edtUtil.invoke(deferred, new Runnable() { - public void run() { - setVisibleTask(visible); - } - }); - } else { - setVisibleTask(visible); - } - } - } - - private synchronized void setVisibleTask(final boolean visible) { + public void setVisible(boolean visible) { if(DEBUG_IMPLEMENTATION) { - System.err.println("setVisibleTask: START ("+Thread.currentThread()+") "+this.x+"/"+this.y+" "+this.width+"x"+this.height+", fs "+fullscreen+", windowHandle "+windowHandle+", visible: "+this.visible+" -> "+visible); - } - int didit = 0; - if(0==windowHandle && visible) { - this.visible = visible; - didit = 01; - if( createNative() ) { - didit = 11; - } - } else if(this.visible != visible) { - this.visible = visible; - didit = 2; - if(0 != windowHandle) { - setVisibleImpl(); - didit = 22; - } + String msg = new String("Window setVisible: START ("+Thread.currentThread()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentNativeWindow "+(null!=parentNativeWindow)); + //System.err.println(msg); + Exception ee = new Exception(msg); + ee.printStackTrace(); } - if(DEBUG_IMPLEMENTATION) { - System.err.println("setVisibleTask: END ("+Thread.currentThread()+") didit "+didit+", "+this.x+"/"+this.y+" "+this.width+"x"+this.height+", fs "+fullscreen+", windowHandle "+windowHandle+", visible: "+visible); + if(!isDestroyed()) { + runOnEDTIfAvail(true, new VisibleAction(visible)); } } - - protected abstract void setVisibleImpl(); + protected abstract void setVisibleImpl(boolean visible); /** * Sets the size of the client area of the window, excluding decorations * Total size of the window will be * {@code width+insets.left+insets.right, height+insets.top+insets.bottom}<br> - * - * This call is ignored if in fullscreen mode.<br> + * <p> + * Zero size semantics are respected, see {@link #setVisible(boolean)}:<br> + * <pre> + * if ( 0 != windowHandle && 0>=width*height && visible ) { + * setVisible(false); + * } else if ( 0 == windowHandle && 0<width*height && visible ) { + * setVisible(true); + * } else { + * // as expected .. + * } + * </pre></p> + * <p> + * This call is ignored if in fullscreen mode.<br></p> * * @param width of the client area of the window * @param height of the client area of the window */ - public abstract void setSize(int width, int height); + public void setSize(int width, int height) { + int visibleAction = 0; // 1 invisible, 2 visible + windowLock(); + try{ + if(DEBUG_IMPLEMENTATION) { + String msg = new String("Window setSize: START "+this.width+"x"+this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible); + //System.err.println(msg); + Exception e = new Exception(msg); + e.printStackTrace(); + } + if (width != this.width || this.height != height) { + if(!fullscreen) { + nfs_width=width; + nfs_height=height; + if ( 0 != windowHandle && 0>=width*height && visible ) { + visibleAction=1; // invisible + this.width = 0; + this.height = 0; + } else if ( 0 == windowHandle && 0<width*height && visible ) { + visibleAction = 2; // visible + this.width = width; + this.height = height; + } else if ( 0 != windowHandle ) { + // this width/height will be set by windowChanged, called by X11 + setSizeImpl(width, height); + } else { + this.width = width; + this.height = height; + } + } + } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setSize: END "+this.width+"x"+this.height+", visibleAction "+visibleAction); + } + } finally { + windowUnlock(); + } + if(visibleAction>0) { + setVisible( ( 1 == visibleAction ) ? false : true ); + } + } + protected abstract void setSizeImpl(int width, int height); /** * Sets the location of the top left corner of the window, including @@ -589,13 +862,103 @@ public abstract class Window implements NativeWindow * @param x coord of the top left corner * @param y coord of the top left corner */ - public abstract void setPosition(int x, int y); + public void setPosition(int x, int y) { + windowLock(); + try{ + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)); + } + if ( this.x != x || this.y != y ) { + if(!fullscreen) { + nfs_x=x; + nfs_y=y; + if(0!=windowHandle) { + // this x/y will be set by windowChanged, called by X11 + setPositionImpl(x, y); + } else { + this.x = x; + this.y = y; + } + } + } + } finally { + windowUnlock(); + } + } + protected abstract void setPositionImpl(int x, int y); + + public boolean setFullscreen(boolean fullscreen) { + windowLock(); + try{ + if(0!=windowHandle && this.fullscreen!=fullscreen) { + int x,y,w,h; + if(fullscreen) { + x = 0; y = 0; + w = screen.getWidth(); + h = screen.getHeight(); + } else { + x = nfs_x; + y = nfs_y; + w = nfs_width; + h = nfs_height; + } + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()); + } + this.fullscreen = setFullscreenImpl(fullscreen, x, y, w, h); + } + return this.fullscreen; + } finally { + windowUnlock(); + } + } + protected abstract boolean setFullscreenImpl(boolean fullscreen, int x, int y, int widht, int height); - public abstract boolean setFullscreen(boolean fullscreen); + // + // Child Window Management + // + + private ArrayList childWindows = new ArrayList(); + + protected void removeChild(NativeWindow win) { + synchronized(childWindows) { + ArrayList newChildWindows = (ArrayList) childWindows.clone(); + newChildWindows.remove(win); + childWindows = newChildWindows; + } + } + + protected void addChild(NativeWindow win) { + if (win == null) { + return; + } + synchronized(childWindows) { + ArrayList newChildWindows = (ArrayList) childWindows.clone(); + newChildWindows.add(win); + childWindows = newChildWindows; + } + } + + // + // Generic Event Support + // + + public void sendEvent(NEWTEvent e) { + if(e instanceof WindowEvent) { + sendWindowEvent((WindowEvent)e); + } else if(e instanceof KeyEvent) { + sendKeyEvent((KeyEvent)e); + } else if(e instanceof MouseEvent) { + sendMouseEvent((MouseEvent)e); + } else if(e instanceof PaintEvent) { + sendPaintEvent((PaintEvent)e); + } + } // // SurfaceUpdatedListener Support // + private ArrayList surfaceUpdatedListeners = new ArrayList(); public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { @@ -643,22 +1006,6 @@ public abstract class Window implements NativeWindow } } - // - // Generic Event Support - // - - public void sendEvent(NEWTEvent e) { - if(e instanceof WindowEvent) { - sendWindowEvent((WindowEvent)e); - } else if(e instanceof KeyEvent) { - sendKeyEvent((KeyEvent)e); - } else if(e instanceof MouseEvent) { - sendMouseEvent((MouseEvent)e); - } else if(e instanceof PaintEvent) { - sendPaintEvent((PaintEvent)e); - } - } - // // MouseListener/Event Support // @@ -704,7 +1051,7 @@ public abstract class Window implements NativeWindow return; // .. invalid .. } if(DEBUG_MOUSE_EVENT) { - System.out.println("sendMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ + System.err.println("sendMouseEvent: "+MouseEvent.getEventTypeString(eventType)+ ", mod "+modifiers+", pos "+x+"/"+y+", button "+button); } if(button<0||button>MouseEvent.BUTTON_NUMBER) { @@ -751,7 +1098,7 @@ public abstract class Window implements NativeWindow sendMouseEvent(e); if(null!=eClicked) { if(DEBUG_MOUSE_EVENT) { - System.out.println("sendMouseEvent: synthesized MOUSE_CLICKED event"); + System.err.println("sendMouseEvent: synthesized MOUSE_CLICKED event"); } sendMouseEvent(eClicked); } @@ -759,7 +1106,7 @@ public abstract class Window implements NativeWindow protected void sendMouseEvent(MouseEvent e) { if(DEBUG_MOUSE_EVENT) { - System.out.println("sendMouseEvent: event: "+e); + System.err.println("sendMouseEvent: event: "+e); } ArrayList listeners = null; @@ -840,7 +1187,7 @@ public abstract class Window implements NativeWindow protected void sendKeyEvent(KeyEvent e) { if(DEBUG_KEY_EVENT) { - System.out.println("sendKeyEvent: "+e); + System.err.println("sendKeyEvent: "+e); } ArrayList listeners = null; synchronized(keyListeners) { @@ -904,7 +1251,7 @@ public abstract class Window implements NativeWindow protected void sendWindowEvent(WindowEvent e) { if(DEBUG_WINDOW_EVENT) { - System.out.println("sendWindowEvent: "+e); + System.err.println("sendWindowEvent: "+e); } ArrayList listeners = null; synchronized(windowListeners) { @@ -1027,7 +1374,30 @@ public abstract class Window implements NativeWindow return sb.toString(); } - private RecursiveToolkitLock destructionLock = new RecursiveToolkitLock(); private RecursiveToolkitLock surfaceLock = new RecursiveToolkitLock(); + private RecursiveToolkitLock windowLock = new RecursiveToolkitLock(); + + private static final boolean TRACE_LOCK = false; + + protected final void windowLock() { + getInnerWindow().windowLock.lock(); + if(TRACE_LOCK) { + Exception e = new Exception("WINDOW LOCK SET: R "+getInnerWindow().windowLock.getRecursionCount()+", "+getInnerWindow().windowLock); + e.printStackTrace(); + } + } + protected final void windowUnlock() { + getInnerWindow().windowLock.unlock(); + if(TRACE_LOCK) { + Exception e = new Exception("WINDOW LOCK FREE: R "+getInnerWindow().windowLock.getRecursionCount()+", "+getInnerWindow().windowLock); + e.printStackTrace(); + } + } + protected final boolean windowIsLocked() { + return getInnerWindow().windowLock.isLocked(); + } + protected final void shouldNotCallThis() { + throw new NativeWindowException("Should not call this"); + } } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java new file mode 100644 index 000000000..23269a93b --- /dev/null +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2010 Sven Gothel. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * - Redistribution of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistribution in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name Sven Gothel or the names of + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * This software is provided "AS IS," without a warranty of any kind. ALL + * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, + * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A + * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN + * MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR + * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR + * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR + * ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR + * DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE + * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, + * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF + * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +package com.jogamp.newt.awt; + +import java.lang.reflect.*; +import java.security.*; + +import java.awt.Canvas; + +import javax.media.nativewindow.*; +// import javax.media.nativewindow.awt.*; + +import com.jogamp.newt.event.awt.AWTAdapter; +import com.jogamp.newt.event.awt.AWTParentWindowAdapter; +import com.jogamp.newt.Screen; +import com.jogamp.newt.Window; +import com.jogamp.newt.impl.Debug; + +public class NewtCanvasAWT extends java.awt.Canvas { + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + + NativeWindow parent = null; + Window newtChild = null; + AWTAdapter awtAdapter = null; + + /** + * Instantiates a NewtCanvas without a NEWT child.<br> + * @see #setNEWTChild(Window) + */ + public NewtCanvasAWT() { + super(); + } + + /** + * Instantiates a NewtCanvas with a NEWT child. + */ + public NewtCanvasAWT(Window child) { + super(); + setNEWTChild(child); + } + + /** sets a new NEWT child, provoking reparenting on the NEWT level. */ + public NewtCanvasAWT setNEWTChild(Window child) { + if(newtChild!=child) { + newtChild = child; + if(null!=parent) { + // reparent right away, addNotify has been called already + reparentWindow( (null!=newtChild) ? true : false ); + } + } + return this; + } + + /** @return the current NEWT child */ + public Window getNEWTChild() { + return newtChild; + } + + /** @return this AWT Canvas NativeWindow represention, may be null in case {@link #removeNotify()} has been called, + * or {@link #addNotify()} hasn't been called yet.*/ + public NativeWindow getNativeWindow() { return parent; } + + void setWindowAdapter(boolean attach) { + if(null!=awtAdapter) { + awtAdapter.removeFrom(this); + awtAdapter=null; + } + if(attach && null!=newtChild) { + awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this); + } + } + + public void addNotify() { + super.addNotify(); + disableBackgroundErase(); + if(DEBUG_IMPLEMENTATION) { + // if ( isShowing() == false ) -> Container was not visible yet. + // if ( isShowing() == true ) -> Container is already visible. + System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+", displayable "+isDisplayable()); + } + reparentWindow(true); + } + + public void removeNotify() { + if(DEBUG_IMPLEMENTATION) { + System.err.println("NewtCanvasAWT.removeNotify: "+newtChild); + } + reparentWindow(false); + super.removeNotify(); + } + + void reparentWindow(boolean add) { + if(null==newtChild) { + return; // nop + } + + if(add) { + if(null!=newtChild) { + parent = NewtFactoryAWT.getNativeWindow(this, newtChild.getRequestedCapabilities()); + } + if(null!=parent) { + // 1st choice - NEWT size := AWT size + // 2nd choice - AWT size := NEWT size + if(0>=getWidth()*getHeight()) { + setSize(newtChild.getWidth(), newtChild.getHeight()); // #2 + } + Screen screen = null; + if( !newtChild.isNativeWindowValid() ) { + screen = NewtFactoryAWT.createCompatibleScreen(parent); + } + newtChild.reparentWindow(parent, screen); + if ( 0 < getWidth() * getHeight() ) { + newtChild.setSize(getWidth(), getHeight()); // #1 + newtChild.setVisible(true); + } + setWindowAdapter(true); + } + } else { + setWindowAdapter(false); + parent = null; + newtChild.setVisible(false); + newtChild.reparentWindow(null, null); + } + } + + // Disables the AWT's erasing of this Canvas's background on Windows + // in Java SE 6. This internal API is not available in previous + // releases, but the system property + // -Dsun.awt.noerasebackground=true can be specified to get similar + // results globally in previous releases. + private static boolean disableBackgroundEraseInitialized; + private static Method disableBackgroundEraseMethod; + private void disableBackgroundErase() { + if (!disableBackgroundEraseInitialized) { + try { + AccessController.doPrivileged(new PrivilegedAction() { + public Object run() { + try { + Class clazz = getToolkit().getClass(); + while (clazz != null && disableBackgroundEraseMethod == null) { + try { + disableBackgroundEraseMethod = + clazz.getDeclaredMethod("disableBackgroundErase", + new Class[] { Canvas.class }); + disableBackgroundEraseMethod.setAccessible(true); + } catch (Exception e) { + clazz = clazz.getSuperclass(); + } + } + } catch (Exception e) { + } + return null; + } + }); + } catch (Exception e) { + } + disableBackgroundEraseInitialized = true; + } + if (disableBackgroundEraseMethod != null) { + try { + disableBackgroundEraseMethod.invoke(getToolkit(), new Object[] { this }); + } catch (Exception e) { + // FIXME: workaround for 6504460 (incorrect backport of 6333613 in 5.0u10) + // throw new GLException(e); + } + } + } +} + diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTNewtFactory.java b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java index e0f86b1a9..6409ab7a8 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTNewtFactory.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java @@ -30,7 +30,7 @@ * SVEN GOTHEL HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. */ -package com.jogamp.newt.impl.awt; +package com.jogamp.newt.awt; import java.awt.GraphicsConfiguration; import java.awt.GraphicsDevice; @@ -46,9 +46,12 @@ import com.jogamp.newt.Display; import com.jogamp.newt.Screen; import com.jogamp.newt.Window; import com.jogamp.newt.NewtFactory; +import com.jogamp.newt.util.EDTUtil; +import com.jogamp.newt.impl.Debug; import com.jogamp.common.util.ReflectionUtil; -public class AWTNewtFactory extends NewtFactory { +public class NewtFactoryAWT extends NewtFactory { + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); /** * Wraps an AWT component into a {@link javax.media.nativewindow.NativeWindow} utilizing the {@link javax.media.nativewindow.NativeWindowFactory},<br> @@ -76,46 +79,13 @@ public class AWTNewtFactory extends NewtFactory { DefaultGraphicsConfiguration config = AWTGraphicsConfiguration.create(awtComp, (Capabilities) capsRequested.clone(), capsRequested); NativeWindow awtNative = NativeWindowFactory.getNativeWindow(awtComp, config); // a JAWTWindow + if(DEBUG_IMPLEMENTATION) { + System.out.println("NewtFactoryAWT.getNativeWindow: "+awtComp+" -> "+awtNative); + } return awtNative; } - /** - * Creates a native NEWT child window to a AWT parent window.<br> - * <p> - * First we create a {@link javax.media.nativewindow.NativeWindow} presentation of the given {@link java.awt.Component}, - * utilizing {@link #getNativeWindow(java.awt.Component)}.<br> - * The actual wrapping implementation is {@link com.jogamp.nativewindow.impl.jawt.JAWTWindow}.<br></p> - * <p> - * Second we create a child {@link com.jogamp.newt.Window}, - * utilizing {@link com.jogamp.newt.NewtFactory#createWindowImpl(java.lang.String, javax.media.nativewindow.NativeWindow, com.jogamp.newt.Screen, javax.media.nativewindow.Capabilities, boolean)}, - * passing the created {@link javax.media.nativewindow.NativeWindow}.<br></p> - - * <p> - * Third we attach a {@link com.jogamp.newt.event.awt.AWTParentWindowAdapter} to the given AWT component.<br> - * The adapter passes window related events to our new child window, look at the implementation<br></p> - * - * <p> - * Forth we pass the parents visibility to the new Window<br></p> - * - * @param awtParentObject must be of type java.awt.Component - * @param undecorated only impacts if the window is in top-level state, while attached to a parent window it's rendered undecorated always - * @return The successful created child window, or null if the AWT parent is not ready yet (no valid peers) - */ - public static Window createNativeChildWindow(Object awtParentObject, Capabilities newtCaps, boolean undecorated) { - if( null == awtParentObject ) { - throw new NativeWindowException("Null AWT Parent Component"); - } - if( ! (awtParentObject instanceof java.awt.Component) ) { - throw new NativeWindowException("AWT Parent Component not a java.awt.Component"); - } - java.awt.Component awtParent = (java.awt.Component) awtParentObject; - - // Generate a complete JAWT NativeWindow from the AWT Component - NativeWindow parent = getNativeWindow(awtParent, newtCaps); - if(null==parent) { - throw new NativeWindowException("Null NativeWindow from parent: "+awtParent); - } - + public static Screen createCompatibleScreen(NativeWindow parent) { // Get parent's NativeWindow details AWTGraphicsConfiguration parentConfig = (AWTGraphicsConfiguration) parent.getGraphicsConfiguration(); AWTGraphicsScreen parentScreen = (AWTGraphicsScreen) parentConfig.getScreen(); @@ -124,16 +94,7 @@ public class AWTNewtFactory extends NewtFactory { // Prep NEWT's Display and Screen according to the parent final String type = NativeWindowFactory.getNativeWindowType(true); Display display = NewtFactory.wrapDisplay(type, parentDevice.getHandle()); - Screen screen = NewtFactory.createScreen(type, display, parentScreen.getIndex()); - - // NEWT Window creation and add event handler for proper propagation AWT -> NEWT - // and copy size/visible state - Window window = NewtFactory.createWindowImpl(type, parent, screen, newtCaps, undecorated); - new AWTParentWindowAdapter(window).addTo(awtParent); - window.setSize(awtParent.getWidth(), awtParent.getHeight()); - window.setVisible(awtParent.isVisible()); - - return window; + return NewtFactory.createScreen(type, display, parentScreen.getIndex()); } } diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java index 3abe6531a..e8497a741 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTAdapter.java @@ -31,6 +31,9 @@ */ package com.jogamp.newt.event.awt; +import com.jogamp.newt.util.EDTUtil; +import com.jogamp.newt.impl.Debug; + /** * Convenient adapter forwarding AWT events to NEWT via the event listener model.<br> * <p> @@ -102,6 +105,8 @@ package com.jogamp.newt.event.awt; */ public abstract class AWTAdapter implements java.util.EventListener { + public static final boolean DEBUG_IMPLEMENTATION = Debug.debug("Window"); + com.jogamp.newt.event.NEWTEventListener newtListener; com.jogamp.newt.Window newtWindow; @@ -157,9 +162,16 @@ public abstract class AWTAdapter implements java.util.EventListener */ public abstract AWTAdapter addTo(java.awt.Component awtComponent); + /** @see #addTo(java.awt.Component) */ + public abstract AWTAdapter removeFrom(java.awt.Component awtComponent); + void enqueueEvent(com.jogamp.newt.event.NEWTEvent event) { + enqueueEvent(false, event); + } + + void enqueueEvent(boolean wait, com.jogamp.newt.event.NEWTEvent event) { try { - newtWindow.getScreen().getDisplay().enqueueEvent(event); + newtWindow.getScreen().getDisplay().enqueueEvent(wait, event); } catch (NullPointerException npe) { /* that's ok .. window might be down already */ } diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java index 64d4d8d86..d2b733f98 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTKeyAdapter.java @@ -50,6 +50,11 @@ public class AWTKeyAdapter extends AWTAdapter implements java.awt.event.KeyListe return this; } + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeKeyListener(this); + return this; + } + public void keyPressed(java.awt.event.KeyEvent e) { com.jogamp.newt.event.KeyEvent event = AWTNewtEventFactory.createKeyEvent(e, newtWindow); if(null!=newtListener) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java index 7efcd123e..058a5f250 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTMouseAdapter.java @@ -51,6 +51,12 @@ public class AWTMouseAdapter extends AWTAdapter implements java.awt.event.MouseL return this; } + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeMouseListener(this); + awtComponent.removeMouseMotionListener(this); + return this; + } + public void mouseClicked(java.awt.event.MouseEvent e) { com.jogamp.newt.event.MouseEvent event = AWTNewtEventFactory.createMouseEvent(e, newtWindow); if(null!=newtListener) { diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java index 01f0457e3..d94a32a9c 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -42,9 +42,18 @@ public class AWTParentWindowAdapter extends AWTWindowAdapter } public void componentResized(java.awt.event.ComponentEvent e) { - // need to really resize the NEWT child window - java.awt.Component comp = e.getComponent(); - newtWindow.setSize(comp.getWidth(), comp.getHeight()); + // Need to resize the NEWT child window + // the resized event will be send via the native window feedback. + final java.awt.Component comp = e.getComponent(); + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + if( 0 < comp.getWidth() * comp.getHeight() ) { + newtWindow.setSize(comp.getWidth(), comp.getHeight()); + newtWindow.setVisible(comp.isVisible()); + } else { + newtWindow.setVisible(false); + } + }}); } public void componentMoved(java.awt.event.ComponentEvent e) { 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 fd6ceddae..53ce03299 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTWindowAdapter.java @@ -33,9 +33,9 @@ package com.jogamp.newt.event.awt; public class AWTWindowAdapter extends AWTAdapter - implements java.awt.event.ComponentListener, java.awt.event.WindowListener, java.awt.event.HierarchyListener + implements java.awt.event.ComponentListener, java.awt.event.WindowListener, + java.awt.event.HierarchyListener, java.awt.event.HierarchyBoundsListener { - java.awt.Component awtComponent; WindowClosingListener windowClosingListener; public AWTWindowAdapter(com.jogamp.newt.event.WindowListener newtListener) { @@ -51,16 +51,36 @@ public class AWTWindowAdapter } public AWTAdapter addTo(java.awt.Component awtComponent) { - this.awtComponent = awtComponent; + java.awt.Window win = getWindow(awtComponent); awtComponent.addComponentListener(this); awtComponent.addHierarchyListener(this); - addWindowClosingListenerTo(getWindow(awtComponent)); + awtComponent.addHierarchyBoundsListener(this); + if( null == windowClosingListener ) { + windowClosingListener = new WindowClosingListener(); + } + if( null != win ) { + win.addWindowListener(windowClosingListener); + } if(awtComponent instanceof java.awt.Window) { ((java.awt.Window)awtComponent).addWindowListener(this); } return this; } + public AWTAdapter removeFrom(java.awt.Component awtComponent) { + awtComponent.removeComponentListener(this); + awtComponent.removeHierarchyListener(this); + awtComponent.removeHierarchyBoundsListener(this); + java.awt.Window win = getWindow(awtComponent); + if( null != win && null != windowClosingListener ) { + win.removeWindowListener(windowClosingListener); + } + if(awtComponent instanceof java.awt.Window) { + ((java.awt.Window)awtComponent).removeWindowListener(this); + } + return this; + } + static java.awt.Window getWindow(java.awt.Component comp) { while( null != comp && !(comp instanceof java.awt.Window) ) { comp = comp.getParent(); @@ -71,15 +91,6 @@ public class AWTWindowAdapter return null; } - void addWindowClosingListenerTo(java.awt.Window win) { - if( null == windowClosingListener ) { - windowClosingListener = new WindowClosingListener(); - } - if( null != win ) { - win.addWindowListener(windowClosingListener); - } - } - public void componentResized(java.awt.event.ComponentEvent e) { com.jogamp.newt.event.WindowEvent event = AWTNewtEventFactory.createWindowEvent(e, newtWindow); if(null!=newtListener) { @@ -101,7 +112,11 @@ public class AWTWindowAdapter public void componentShown(java.awt.event.ComponentEvent e) { if(null==newtListener) { if(!newtWindow.isDestroyed()) { - newtWindow.setVisible(true, true /* deferred */); + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + newtWindow.setVisible(true); + } + }); } } } @@ -109,7 +124,11 @@ public class AWTWindowAdapter public void componentHidden(java.awt.event.ComponentEvent e) { if(null==newtListener) { if(!newtWindow.isDestroyed()) { - newtWindow.setVisible(false, true /* deferred */); + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + newtWindow.setVisible(false); + } + }); } } } @@ -145,27 +164,45 @@ public class AWTWindowAdapter public void hierarchyChanged(java.awt.event.HierarchyEvent e) { if( null == newtListener ) { long bits = e.getChangeFlags(); - java.awt.Component changed = e.getChanged(); + final java.awt.Component changed = e.getChanged(); if( 0 != ( java.awt.event.HierarchyEvent.SHOWING_CHANGED & bits ) ) { - final boolean visible = changed.isVisible(); - if(!newtWindow.isDestroyed()) { - newtWindow.setVisible(visible, true /* deferred */); + final boolean showing = changed.isShowing(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("hierarchyChanged SHOWING_CHANGED: showing "+showing+", "+changed); } - } else if( 0 != ( java.awt.event.HierarchyEvent.PARENT_CHANGED & bits ) ) { - if(awtComponent == changed) { - java.awt.Window win = getWindow(changed); - if(null != win) { - addWindowClosingListenerTo(win); - } else { - java.awt.Component parent = e.getChangedParent(); - if(parent instanceof java.awt.Window) { - ((java.awt.Window)parent).removeWindowListener(this); - if( null != windowClosingListener ) { - ((java.awt.Window)parent).removeWindowListener(windowClosingListener); - } + if(!newtWindow.isDestroyed()) { + newtWindow.runOnEDTIfAvail(false, new Runnable() { + public void run() { + newtWindow.setVisible(showing); } - } + }); } + } + if( 0 != ( java.awt.event.HierarchyEvent.DISPLAYABILITY_CHANGED & bits ) ) { + final boolean displayability = changed.isDisplayable(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("hierarchyChanged DISPLAYABILITY_CHANGED: displayability "+displayability+", "+changed); + } + } + } + } + + public void ancestorMoved(java.awt.event.HierarchyEvent e) { + if( null == newtListener ) { + final java.awt.Component changed = e.getChanged(); + final boolean showing = changed.isShowing(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("ancestorMoved: showing "+showing+", "+changed); + } + } + } + + public void ancestorResized(java.awt.event.HierarchyEvent e) { + if( null == newtListener ) { + final java.awt.Component changed = e.getChanged(); + final boolean showing = changed.isShowing(); + if(DEBUG_IMPLEMENTATION) { + System.out.println("ancestorResized: showing "+showing+", "+changed); } } } @@ -176,7 +213,7 @@ public class AWTWindowAdapter if(null!=newtListener) { ((com.jogamp.newt.event.WindowListener)newtListener).windowDestroyNotify(event); } else { - enqueueEvent(event); + enqueueEvent(true, event); } } diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java index b0b518c59..f54e66f07 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTDisplay.java @@ -44,7 +44,7 @@ public class AWTDisplay extends Display { public AWTDisplay() { } - protected void createNative(long handle) { + protected void createNative() { aDevice = (AWTGraphicsDevice) AWTGraphicsDevice.createDevice(null); // default } diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java index b98a6fa20..f97625320 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -176,7 +176,7 @@ public class AWTWindow extends Window { return res; } - protected void setVisibleImpl() { + protected void setVisibleImpl(final boolean visible) { runOnEDT(true, new Runnable() { public void run() { container.setVisible(visible); @@ -203,13 +203,7 @@ public class AWTWindow extends Window { ((AWTScreen)screen).setScreenSize(w, h); } - public void setSize(final int width, final int height) { - this.width = width; - this.height = height; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } + protected void setSizeImpl(final int width, final int height) { if(null!=container) { /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ runOnEDT(false, new Runnable() { @@ -237,55 +231,34 @@ public class AWTWindow extends Window { Insets(insets[0],insets[1],insets[2],insets[3]); } - public void setPosition(final int x, final int y) { - this.x = x; - this.y = y; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; + protected void setPositionImpl(final int x, final int y) { + if(null!=container) { + runOnEDT(true, new Runnable() { + public void run() { + container.setLocation(x, y); + } + }); } - runOnEDT(true, new Runnable() { - public void run() { - container.setLocation(x, y); - } - }); } - public boolean setFullscreen(final boolean fullscreen) { - if(this.fullscreen!=fullscreen) { - final int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("AWTWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); - } - /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ - runOnEDT(false, new Runnable() { - public void run() { - if(null!=frame) { - if(!container.isDisplayable()) { - frame.setUndecorated(undecorated||fullscreen); - } else { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("AWTWindow can't undecorate already created frame"); - } + protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ + runOnEDT(false, new Runnable() { + public void run() { + if(null!=frame) { + if(!container.isDisplayable()) { + frame.setUndecorated(isUndecorated(fullscreen)); + } else { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("AWTWindow can't undecorate already created frame"); } } - container.setLocation(x, y); - container.setSize(w, h); } - }); - } - return true; + container.setLocation(x, y); + container.setSize(w, h); + } + }); + return fullscreen; } public Object getWrappedWindow() { diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java index ac27da9ef..d19aaf796 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Display.java @@ -58,10 +58,10 @@ public class Display extends com.jogamp.newt.Display { public Display() { } - protected void createNative(long handle) { + protected void createNative() { synchronized(Display.class) { if(0==initCounter) { - displayHandle = (0 == handle) ? CreateDisplay() : handle; + displayHandle = CreateDisplay(); if(0==displayHandle) { throw new NativeWindowException("Couldn't initialize GDL Display"); } diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java index 7b867db21..74cb53f7e 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java @@ -77,13 +77,13 @@ public class Window extends com.jogamp.newt.Window { } } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { if(visible) { ((Display)screen.getDisplay()).setFocus(this); } } - public void setSize(int width, int height) { + protected void setSizeImpl(int width, int height) { Screen screen = (Screen) getScreen(); if((x+width)>screen.getWidth()) { width=screen.getWidth()-x; @@ -91,18 +91,12 @@ public class Window extends com.jogamp.newt.Window { if((y+height)>screen.getHeight()) { height=screen.getHeight()-y; } - this.width = width; - this.height = height; - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - } if(0!=surfaceHandle) { SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, width, height); } } - public void setPosition(int x, int y) { + protected void setPositionImpl(int x, int y) { Screen screen = (Screen) getScreen(); if((x+width)>screen.getWidth()) { x=screen.getWidth()-width; @@ -110,37 +104,14 @@ public class Window extends com.jogamp.newt.Window { if((y+height)>screen.getHeight()) { y=screen.getHeight()-height; } - this.x = x; - this.y = y; - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - } if(0!=surfaceHandle) { SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, width, height); } } - public boolean setFullscreen(boolean fullscreen) { - if(this.fullscreen!=fullscreen) { - int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("IntelGDL Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); - } - if(0!=surfaceHandle) { - SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, w, h); - } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + if(0!=surfaceHandle) { + SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, w, h); } return fullscreen; } diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java index 6e1119a9d..0c4362a9e 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java @@ -70,7 +70,7 @@ public class MacDisplay extends Display { MainThread.invoke(false, dispatchAction); } - protected void createNative(long handle) { + protected void createNative() { aDevice = new MacOSXGraphicsDevice(); } diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java index 93c2b14bb..20a181096 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -153,12 +153,17 @@ public class MacWindow extends Window { public void run() { nsViewLock.lock(); try { - if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); + if(DEBUG_IMPLEMENTATION) { System.out.println("MacWindow.CloseAction "+Thread.currentThread().getName()); } if (windowHandle != 0) { close0(windowHandle); - windowHandle = 0; + } + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); } } finally { + windowHandle = 0; nsViewLock.unlock(); } } @@ -191,7 +196,7 @@ public class MacWindow extends Window { public void run() { nsViewLock.lock(); try { - createWindow(false); + createWindow(false, getX(), getY(), getWidth(), getHeight(), isFullscreen()); } finally { nsViewLock.unlock(); } @@ -229,30 +234,26 @@ public class MacWindow extends Window { nsViewLock.unlock(); } - class VisibleAction implements Runnable { - public void run() { - nsViewLock.lock(); - try { - if(DEBUG_IMPLEMENTATION) System.out.println("MacWindow.VisibleAction "+visible+" "+Thread.currentThread().getName()); - if (visible) { - createWindow(false); - if (windowHandle != 0) { - makeKeyAndOrderFront0(windowHandle); - } - } else { - if (windowHandle != 0) { - orderOut0(windowHandle); + protected void setVisibleImpl(final boolean visible) { + MainThread.invoke(true, new Runnable() { + public void run() { + nsViewLock.lock(); + try { + if (visible) { + createWindow(false, getX(), getY(), getWidth(), getHeight(), isFullscreen()); + if (windowHandle != 0) { + makeKeyAndOrderFront0(windowHandle); + } + } else { + if (windowHandle != 0) { + orderOut0(windowHandle); + } } + } finally { + nsViewLock.unlock(); } - } finally { - nsViewLock.unlock(); } - } - } - private VisibleAction visibleAction = new VisibleAction(); - - protected void setVisibleImpl() { - MainThread.invoke(true, visibleAction); + }); } class TitleAction implements Runnable { @@ -307,20 +308,9 @@ public class MacWindow extends Window { } private SizeAction sizeAction = new SizeAction(); - public void setSize(int width, int height) { - if (width != this.width || this.height != height) { - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - if (0 != windowHandle) { - // this width/height will be set by sizeChanged, called by OSX - MainThread.invoke(true, sizeAction); - } else { - this.width=width; - this.height=height; - } - } - } + protected void setSizeImpl(int width, int height) { + // this width/height will be set by sizeChanged, called by OSX + MainThread.invoke(true, sizeAction); } class PositionAction implements Runnable { @@ -337,56 +327,28 @@ public class MacWindow extends Window { } private PositionAction positionAction = new PositionAction(); - public void setPosition(int x, int y) { - if ( this.x != x || this.y != y ) { - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - if (0 != windowHandle) { - // this x/y will be set by positionChanged, called by OSX - MainThread.invoke(true, positionAction); - } else { - this.x=x; - this.y=y; - } - } - } + protected void setPositionImpl(int x, int y) { + // this x/y will be set by positionChanged, called by OSX + MainThread.invoke(true, positionAction); } - class FullscreenAction implements Runnable { - public void run() { - nsViewLock.lock(); - try { - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("MacWindow fs: "+fullscreen+" "+x+"/"+y+" "+width+"x"+height); - } - createWindow(true); - if (windowHandle != 0) { - makeKeyAndOrderFront0(windowHandle); + protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + MainThread.invoke(true, new Runnable() { + public void run() { + nsViewLock.lock(); + try { + if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { + System.err.println("MacWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); + } + createWindow(true, x, y, w, h, fullscreen); + if (windowHandle != 0) { + makeKeyAndOrderFront0(windowHandle); + } + } finally { + nsViewLock.unlock(); } - } finally { - nsViewLock.unlock(); } - } - } - private FullscreenAction fullscreenAction = new FullscreenAction(); - - public boolean setFullscreen(boolean fullscreen) { - if(this.fullscreen!=fullscreen) { - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; - y = 0; - width = screen.getWidth(); - height = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - width = nfs_width; - height = nfs_height; - } - MainThread.invoke(true, fullscreenAction); - } + }); return fullscreen; } @@ -538,7 +500,7 @@ public class MacWindow extends Window { super.sendKeyEvent(eventType, modifiers, key, keyChar); } - private void createWindow(boolean recreate) { + private void createWindow(boolean recreate, int x, int y, int width, int height, boolean fullscreen) { if(0!=windowHandle && !recreate) { return; } @@ -554,8 +516,8 @@ public class MacWindow extends Window { surfaceHandle = 0; } windowHandle = createWindow0(parentWindowHandle, - getX(), getY(), getWidth(), getHeight(), fullscreen, - (isUndecorated() ? + x, y, width, height, fullscreen, + (isUndecorated(fullscreen) ? NSBorderlessWindowMask : NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask), NSBackingStoreBuffered, diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java index c08499359..c2d323e56 100644 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Display.java @@ -56,10 +56,8 @@ public class Display extends com.jogamp.newt.Display { public Display() { } - protected void createNative(long handle) { - if( 0 == handle ) { - handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight); - } + protected void createNative() { + long handle = CreateDisplay(Screen.fixedWidth, Screen.fixedHeight); if (handle == EGL.EGL_NO_DISPLAY) { throw new NativeWindowException("BC EGL CreateDisplay failed"); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java index b25ed4ee8..7d3a0ac8c 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java @@ -70,32 +70,24 @@ public class Window extends com.jogamp.newt.Window { } } - protected void setVisibleImpl() { } + protected void setVisibleImpl(boolean visible) { } - public void setSize(int width, int height) { - System.err.println("setSize "+width+"x"+height+" n/a in BroadcomEGL"); - } - - void setSizeImpl(int width, int height) { + protected void setSizeImpl(int width, int height) { if(0!=windowHandle) { // n/a in BroadcomEGL System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); } else { - if(DEBUG_IMPLEMENTATION) { - Exception e = new Exception("BCEGL Window.setSizeImpl() "+this.width+"x"+this.height+" -> "+width+"x"+height); - e.printStackTrace(); - } this.width = width; this.height = height; } } - public void setPosition(int x, int y) { + protected void setPositionImpl(int x, int y) { // n/a in BroadcomEGL - System.err.println("setPosition n/a in BroadcomEGL"); + System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL"); } - public boolean setFullscreen(boolean fullscreen) { + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { // n/a in BroadcomEGL System.err.println("setFullscreen n/a in BroadcomEGL"); return false; diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java index bb5f1cc7a..2ab30773f 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDDisplay.java @@ -57,12 +57,9 @@ public class KDDisplay extends Display { public KDDisplay() { } - protected void createNative(long handle) { + protected void createNative() { // FIXME: map name to EGL_*_DISPLAY - // FIXME: what do to with external handle ? - if(0==handle) { - handle = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); - } + long handle = EGL.eglGetDisplay(EGL.EGL_DEFAULT_DISPLAY); if (handle == EGL.EGL_NO_DISPLAY) { throw new NativeWindowException("eglGetDisplay failed"); } diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java index f60abb7cd..54623996c 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java @@ -85,30 +85,26 @@ public class KDWindow extends Window { } } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { setVisible0(eglWindowHandle, visible); - clearEventMask(); } - public void setSize(int width, int height) { + protected void setSizeImpl(int width, int height) { if(0!=eglWindowHandle) { setSize0(eglWindowHandle, width, height); } } - public void setPosition(int x, int y) { + protected void setPositionImpl(int x, int y) { // n/a in KD System.err.println("setPosition n/a in KD"); } - public boolean setFullscreen(boolean fullscreen) { - if(0!=eglWindowHandle && this.fullscreen!=fullscreen) { - this.fullscreen=fullscreen; - if(this.fullscreen) { - setFullScreen0(eglWindowHandle, true); - } else { - setFullScreen0(eglWindowHandle, false); - setSize0(eglWindowHandle, nfs_width, nfs_height); + protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + if(0!=eglWindowHandle) { + setFullScreen0(eglWindowHandle, fullscreen); + if(!fullscreen) { + setSize0(eglWindowHandle, w, h); } } return true; diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java index f75c11cfb..ef033d1c8 100755 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsDisplay.java @@ -60,7 +60,7 @@ public class WindowsDisplay extends Display { public WindowsDisplay() { } - protected void createNative(long handle) { + protected void createNative() { aDevice = new WindowsGraphicsDevice(); } diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java index dad3456d7..5e1b5a43c 100755 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -131,13 +131,28 @@ public class WindowsWindow extends Window { protected void closeNative() { if (hdc != 0) { if(windowHandleClose != 0) { - ReleaseDC0(windowHandleClose, hdc); + try { + ReleaseDC0(windowHandleClose, hdc); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } } hdc = 0; } if(windowHandleClose != 0) { - DestroyWindow0(windowHandleClose); - windowHandleClose = 0; + try { + DestroyWindow0(windowHandleClose); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } finally { + windowHandleClose = 0; + } } } @@ -146,66 +161,32 @@ public class WindowsWindow extends Window { super.windowDestroyed(); } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { setVisible0(windowHandle, visible); } - // @Override - public void setSize(int width, int height) { - if (width != this.width || this.height != height) { - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - if(0!=windowHandle) { - // this width/height will be set by sizeChanged, called by Windows - setSize0(parentWindowHandle, windowHandle, x, y, width, height); - } else { - this.width=width; - this.height=height; - } - } - } + protected void setSizeImpl(int width, int height) { + // this width/height will be set by sizeChanged, called by Windows + setSize0(parentWindowHandle, windowHandle, x, y, width, height); } - //@Override - public void setPosition(int x, int y) { - if ( this.x != x || this.y != y ) { - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - if(0!=windowHandle) { - // this x/y will be set by positionChanged, called by Windows - setPosition0(parentWindowHandle, windowHandle, x , y /*, width, height*/); - } else { - this.x=x; - this.y=y; - } - } - } + protected void setPositionImpl(int x, int y) { + // this x/y will be set by positionChanged, called by Windows + setPosition0(parentWindowHandle, windowHandle, x , y /*, width, height*/); } - public boolean setFullscreen(boolean fullscreen) { - if(0!=windowHandle && (this.fullscreen!=fullscreen)) { - int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("WindowsWindow fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h); - } - setFullscreen0(parentWindowHandle, windowHandle, x, y, w, h, undecorated, fullscreen); - } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + setFullscreen0(fullscreen?0:parentWindowHandle, windowHandle, x, y, w, h, isUndecorated(fullscreen)); return fullscreen; } + protected boolean reparentWindowImpl() { + if(0!=windowHandle) { + reparentWindow0(fullscreen?0:parentWindowHandle, windowHandle, x, y, width, height, isUndecorated()); + } + return true; + } + // @Override public void requestFocus() { super.requestFocus(); @@ -245,7 +226,8 @@ public class WindowsWindow extends Window { private static native void setVisible0(long windowHandle, boolean visible); private native void setSize0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height); private static native void setPosition0(long parentWindowHandle, long windowHandle, int x, int y /*, int width, int height*/); - private native void setFullscreen0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated, boolean on); + private native void setFullscreen0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated); + private native void reparentWindow0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated); private static native void setTitle0(long windowHandle, String title); private static native void requestFocus0(long windowHandle); diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java index 3b0868620..54fe0542b 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Display.java @@ -60,19 +60,12 @@ public class X11Display extends Display { public X11Display() { } - protected void createNative(long handle) { - if(0 != handle) { - // Can't use that Display handle directly, - // but we open up a new connection to the same Display by it's name - String newName = X11Util.getNameOfDisplay(handle); - if(DEBUG) { - System.out.println("Changing Display Name (provided handle): "+name+" -> 0x"+ - Long.toHexString(handle)+" : "+newName); - } - handle = 0; - name = newName; - } - handle= X11Util.createThreadLocalDisplay(name); + protected String validateDisplayName(String name, long handle) { + return X11Util.validateDisplayName(name, handle); + } + + protected void createNative() { + long handle= X11Util.createThreadLocalDisplay(name); if( 0 == handle ) { throw new RuntimeException("Error creating display: "+name); } diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java index 085d1cab7..a51eee241 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -55,13 +55,12 @@ public class X11Window extends Window { if (config == null) { throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } - attachedToParent = 0 != parentWindowHandle ; X11GraphicsConfiguration x11config = (X11GraphicsConfiguration) config; long visualID = x11config.getVisualID(); long w = CreateWindow0(parentWindowHandle, display.getHandle(), screen.getIndex(), visualID, display.getJavaObjectAtom(), display.getWindowDeleteAtom(), - x, y, width, height, undecorated()); + x, y, width, height, isUndecorated()); if (w == 0 || w!=windowHandle) { throw new NativeWindowException("Error creating window: "+w); } @@ -72,9 +71,17 @@ public class X11Window extends Window { protected void closeNative() { if(0!=displayHandleClose && 0!=windowHandleClose && null!=getScreen() ) { X11Display display = (X11Display) getScreen().getDisplay(); - CloseWindow0(displayHandleClose, windowHandleClose, display.getJavaObjectAtom()); - windowHandleClose = 0; - displayHandleClose = 0; + try { + CloseWindow0(displayHandleClose, windowHandleClose, display.getJavaObjectAtom()); + } catch (Throwable t) { + if(DEBUG_IMPLEMENTATION) { + Exception e = new Exception("closeNative failed - "+Thread.currentThread().getName(), t); + e.printStackTrace(); + } + } finally { + windowHandleClose = 0; + displayHandleClose = 0; + } } } @@ -84,72 +91,33 @@ public class X11Window extends Window { super.windowDestroyed(); } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { setVisible0(getDisplayHandle(), windowHandle, visible); - clearEventMask(); } - public void setSize(int width, int height) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window setSize: "+this.width+"x"+this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+windowHandle); - } - if (width != this.width || this.height != height) { - if(!fullscreen) { - nfs_width=width; - nfs_height=height; - if(0!=windowHandle) { - // this width/height will be set by windowChanged, called by X11 - setSize0(getDisplayHandle(), windowHandle, width, height); - } else { - this.width = width; - this.height = height; - } - } - } + protected void setSizeImpl(int width, int height) { + // this width/height will be set by windowChanged, called by X11 + setSize0(getDisplayHandle(), windowHandle, width, height); } - public void setPosition(int x, int y) { - if(DEBUG_IMPLEMENTATION) { - System.err.println("X11Window setPosition: "+this.x+"/"+this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+windowHandle); - } - if ( this.x != x || this.y != y ) { - if(!fullscreen) { - nfs_x=x; - nfs_y=y; - if(0!=windowHandle) { - // this x/y will be set by windowChanged, called by X11 - setPosition0(parentWindowHandle, getDisplayHandle(), windowHandle, x, y); - } else { - this.x = x; - this.y = y; - } - } - } + protected void setPositionImpl(int x, int y) { + // this x/y will be set by windowChanged, called by X11 + setPosition0(parentWindowHandle, getDisplayHandle(), windowHandle, x, y); } - public boolean setFullscreen(boolean fullscreen) { - if(0!=windowHandle && this.fullscreen!=fullscreen) { - int x,y,w,h; - this.fullscreen=fullscreen; - if(fullscreen) { - x = 0; y = 0; - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - } - if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { - System.err.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+undecorated()); - } - setPosSizeDecor0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, w, h, undecorated()); - } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + setPosSizeDecor0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, w, h, isUndecorated(fullscreen)); return fullscreen; } - final boolean undecorated() { return attachedToParent || undecorated || fullscreen ; } + protected boolean reparentWindowImpl() { + if(0!=windowHandle) { + reparentWindow0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, isUndecorated()); + // X11 reparent unmaps the window + setVisibleImpl(visible); + } + return true; + } // @Override public void requestFocus() { @@ -187,6 +155,8 @@ public class X11Window extends Window { private native void setTitle0(long display, long windowHandle, String title); private native void requestFocus0(long display, long windowHandle); private native void setPosition0(long parentWindowHandle, long display, long windowHandle, int x, int y); + private native void reparentWindow0(long parentWindowHandle, long display, int screen_index, long windowHandle, + int x, int y, boolean undecorated); private void windowChanged(int newX, int newY, int newWidth, int newHeight) { if(width != newWidth || height != newHeight) { @@ -226,14 +196,17 @@ public class X11Window extends Window { } } + /** + * @param focusGained + */ + private void visibleChanged(boolean visible) { + // FIXME .. this.visible = visible ; + } + private void windowCreated(long windowHandle) { this.windowHandle = windowHandle; } private long windowHandleClose; private long displayHandleClose; - private boolean attachedToParent; - - // non fullscreen dimensions .. - private int nfs_width, nfs_height, nfs_x, nfs_y; } diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index b5d55aebd..2bb28466c 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -35,6 +35,7 @@ package com.jogamp.newt.opengl; import com.jogamp.newt.*; import com.jogamp.newt.event.*; +import com.jogamp.nativewindow.impl.RecursiveToolkitLock; import javax.media.nativewindow.*; import javax.media.opengl.*; import com.jogamp.opengl.impl.GLDrawableHelper; @@ -53,19 +54,15 @@ import java.util.*; * <p> */ public class GLWindow extends Window implements GLAutoDrawable { - private static List/*GLWindow*/ glwindows = new ArrayList(); - - private boolean ownerOfWinScrDpy; private Window window; private boolean runPumpMessages; /** * Constructor. Do not call this directly -- use {@link #create()} instead. */ - protected GLWindow(Window window, boolean ownerOfWinScrDpy) { - this.ownerOfWinScrDpy = ownerOfWinScrDpy; + protected GLWindow(Window window) { this.window = window; - this.window.setAutoDrawableClient(true); + this.window.setHandleDestroyNotify(false); this.runPumpMessages = ( null == getScreen().getDisplay().getEDTUtil() ) ; window.addWindowListener(new WindowAdapter() { public void windowResized(WindowEvent e) { @@ -76,10 +73,6 @@ public class GLWindow extends Window implements GLAutoDrawable { sendDestroy = true; } }); - - List newglw = (List) ((ArrayList) glwindows).clone(); - newglw.add(this); - glwindows=newglw; } /** Creates a new GLWindow attaching the given window - not owning the Window. */ @@ -87,10 +80,10 @@ public class GLWindow extends Window implements GLAutoDrawable { return create(null, window, null, false); } - /** Creates a new GLWindow attaching a new native child Window of the given <code>parentWindowObject</code> + /** Creates a new GLWindow attaching a new native child Window of the given <code>parentNativeWindow</code> with the given GLCapabilities - owning the Window */ - public static GLWindow create(Object parentWindowObject, GLCapabilities caps) { - return create(parentWindowObject, null, caps, true); + public static GLWindow create(NativeWindow parentNativeWindow, GLCapabilities caps) { + return create(parentNativeWindow, null, caps, false); } /** Creates a new GLWindow attaching a new decorated Window on the local display, screen 0, with a @@ -106,27 +99,29 @@ public class GLWindow extends Window implements GLAutoDrawable { } /** Either or: window (prio), or caps and undecorated (2nd choice) */ - private static GLWindow create(Object parentWindowObject, Window window, + private static GLWindow create(NativeWindow parentNativeWindow, Window window, GLCapabilities caps, boolean undecorated) { - boolean ownerOfWinScrDpy=false; if (window == null) { if (caps == null) { caps = new GLCapabilities(null); // default .. } - ownerOfWinScrDpy = true; - window = NewtFactory.createWindow(parentWindowObject, caps, undecorated); + window = NewtFactory.createWindow(parentNativeWindow, caps, undecorated); } - return new GLWindow(window, ownerOfWinScrDpy); + return new GLWindow(window); } + public boolean isNativeWindowValid() { + return (null!=window)?window.isNativeWindowValid():false; + } + public boolean isDestroyed() { - return null == window ; + return (null!=window)?window.isDestroyed():true; } - public Window getWindow() { - return window; + public Window getInnerWindow() { + return window.getInnerWindow(); } /** @@ -162,67 +157,66 @@ public class GLWindow extends Window implements GLAutoDrawable { shouldNotCallThis(); } - protected void dispose(boolean regenerate, boolean sendEvent) { + protected void dispose() { if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - Exception e1 = new Exception("GLWindow.dispose("+regenerate+") "+Thread.currentThread()+", 1"); + Exception e1 = new Exception("GLWindow.dispose() "+Thread.currentThread()+", start: "+this); e1.printStackTrace(); } - if(sendEvent) { - sendDisposeEvent(); + if ( null != context && null != drawable && drawable.isRealized() ) { + helper.invokeGL(drawable, context, disposeAction, null); } if (context != null) { context.destroy(); + context = null; } if (drawable != null) { drawable.setRealized(false); - } - - if(regenerate) { - if(null==window) { - throw new GLException("GLWindow.dispose(true): null window"); - } - - // recreate GLDrawable, to reflect the new graphics configurations - NativeWindow nw; - if (window.getWrappedWindow() != null) { - nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); - } else { - nw = window; - } - drawable = factory.createGLDrawable(nw); - drawable.setRealized(true); - context = drawable.createContext(null); - sendReshape = true; // ensure a reshape event is send .. + drawable = null; } if(Window.DEBUG_WINDOW_EVENT || window.DEBUG_IMPLEMENTATION) { - System.out.println("GLWindow.dispose("+regenerate+") "+Thread.currentThread()+", fin: "+this); + System.out.println("GLWindow.dispose() "+Thread.currentThread()+", fin: "+this); } } - public synchronized void destroy() { - destroy(true); - } - - /** @param sendDisposeEvent should be false in a [time,reliable] critical shutdown */ - public synchronized void destroy(boolean sendDisposeEvent) { - List newglw = (List) ((ArrayList) glwindows).clone(); - newglw.remove(this); - glwindows=newglw; + class DestroyAction implements Runnable { + boolean deep; + public DestroyAction(boolean deep) { + this.deep = deep; + } + public void run() { + windowLock(); + try { + if(null==window || window.isDestroyed()) { + return; // nop + } + dispose(); - dispose(false, sendDisposeEvent); + if(null!=window) { + window.destroy(deep); + } - if(null!=window) { - if(ownerOfWinScrDpy) { - window.destroy(true); + if(deep) { + helper=null; + } + } finally { + windowUnlock(); } } + } - drawable = null; - context = null; - window = null; + /** + * @param deep If true, all resources, ie listeners, parent handles, size, position + * and the referenced NEWT screen and display, will be destroyed as well. Be aware that if you call + * this method with deep = true, you will not be able to regenerate the Window. + * @see #destroy() + */ + public void destroy(boolean deep) { + if(!isDestroyed()) { + runOnEDTIfAvail(true, new DestroyAction(deep)); + } } public boolean getPerfLogEnabled() { return perfLog; } @@ -231,28 +225,61 @@ public class GLWindow extends Window implements GLAutoDrawable { perfLog = v; } - protected void setVisibleImpl() { + protected void setVisibleImpl(boolean visible) { shouldNotCallThis(); } - public void setVisible(final boolean visible) { - window.setVisible(visible); - if (visible && null == context && 0 != window.getWindowHandle()) { - NativeWindow nw; - if (window.getWrappedWindow() != null) { - nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); - } else { - nw = window; + public void reparentWindow(NativeWindow newParent, Screen newScreen) { + window.reparentWindow(newParent, newScreen); + } + + class VisibleAction implements Runnable { + boolean visible; + public VisibleAction(boolean visible) { + this.visible = visible; + } + public void run() { + windowLock(); + try{ + window.setVisible(visible); + if (null == context && visible && 0 != window.getWindowHandle() && 0<getWidth()*getHeight()) { + NativeWindow nw; + if (window.getWrappedWindow() != null) { + nw = NativeWindowFactory.getNativeWindow(window.getWrappedWindow(), window.getGraphicsConfiguration()); + } else { + nw = window; + } + GLCapabilities glCaps = (GLCapabilities) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); + if(null==factory) { + factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); + } + if(null==drawable) { + drawable = factory.createGLDrawable(nw); + } + drawable.setRealized(true); + context = drawable.createContext(null); + sendReshape = true; // ensure a reshape event is send .. + } + } finally { + windowUnlock(); } - GLCapabilities glCaps = (GLCapabilities) nw.getGraphicsConfiguration().getNativeGraphicsConfiguration().getChosenCapabilities(); - factory = GLDrawableFactory.getFactory(glCaps.getGLProfile()); - drawable = factory.createGLDrawable(nw); - drawable.setRealized(true); - context = drawable.createContext(null); - sendReshape = true; // ensure a reshape event is send .. } } + public void setVisible(boolean visible) { + if(!isDestroyed()) { + runOnEDTIfAvail(true, new VisibleAction(visible)); + } + } + + public Capabilities getRequestedCapabilities() { + return window.getRequestedCapabilities(); + } + + public NativeWindow getParentNativeWindow() { + return window.getParentNativeWindow(); + } + public Screen getScreen() { return window.getScreen(); } @@ -277,21 +304,31 @@ public class GLWindow extends Window implements GLAutoDrawable { window.requestFocus(); } + public Insets getInsets() { + return window.getInsets(); + } + public void setSize(int width, int height) { window.setSize(width, height); } + protected void setSizeImpl(int width, int height) { + shouldNotCallThis(); + } public void setPosition(int x, int y) { window.setPosition(x, y); } - - public Insets getInsets() { - return window.getInsets(); + protected void setPositionImpl(int x, int y) { + shouldNotCallThis(); } public boolean setFullscreen(boolean fullscreen) { return window.setFullscreen(fullscreen); } + protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + shouldNotCallThis(); + return false; + } public boolean isVisible() { return window.isVisible(); @@ -317,6 +354,10 @@ public class GLWindow extends Window implements GLAutoDrawable { return window.isFullscreen(); } + public void sendEvent(NEWTEvent e) { + window.sendEvent(e); + } + public void addSurfaceUpdatedListener(SurfaceUpdatedListener l) { window.addSurfaceUpdatedListener(l); } @@ -333,10 +374,6 @@ public class GLWindow extends Window implements GLAutoDrawable { window.surfaceUpdated(updater, window, when); } - public void sendEvent(NEWTEvent e) { - window.sendEvent(e); - } - public void addMouseListener(MouseListener l) { window.addMouseListener(l); } @@ -437,14 +474,11 @@ public class GLWindow extends Window implements GLAutoDrawable { setVisible(true); } - if( null != context ) { + if( window.isNativeWindowValid() && null != context ) { if(runPumpMessages) { window.getScreen().getDisplay().pumpMessages(); } - if(window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) { - dispose(true, true); - } - if (sendDestroy) { + if(sendDestroy || window.hasDeviceChanged() && GLAutoDrawable.SCREEN_CHANGE_ACTION_ENABLED) { destroy(); sendDestroy=false; } else if ( window.isVisible() ) { @@ -456,12 +490,6 @@ public class GLWindow extends Window implements GLAutoDrawable { } } - private void sendDisposeEvent() { - if(drawable!=null && context != null) { - helper.invokeGL(drawable, context, disposeAction, null); - } - } - /** This implementation uses a static value */ public void setAutoSwapBufferMode(boolean onOrOff) { helper.setAutoSwapBufferMode(onOrOff); @@ -555,24 +583,24 @@ public class GLWindow extends Window implements GLAutoDrawable { // NativeWindow/Window methods // - public synchronized int lockSurface() throws NativeWindowException { + public int lockSurface() throws NativeWindowException { if(null!=drawable) return drawable.getNativeWindow().lockSurface(); - return NativeWindow.LOCK_SURFACE_NOT_READY; + return window.lockSurface(); } - public synchronized void unlockSurface() { + public void unlockSurface() { if(null!=drawable) drawable.getNativeWindow().unlockSurface(); - else throw new NativeWindowException("NEWT-GLWindow not locked"); + else window.unlockSurface(); } - public synchronized boolean isSurfaceLocked() { + public boolean isSurfaceLocked() { if(null!=drawable) return drawable.getNativeWindow().isSurfaceLocked(); - return false; + return window.isSurfaceLocked(); } - public synchronized Exception getLockedStack() { + public Exception getLockedStack() { if(null!=drawable) return drawable.getNativeWindow().getLockedStack(); - return null; + return window.getLockedStack(); } public boolean surfaceSwap() { @@ -614,6 +642,10 @@ public class GLWindow extends Window implements GLAutoDrawable { public void setRealized(boolean realized) { } + public boolean isRealized() { + return ( null != drawable ) ? drawable.isRealized() : false; + } + public GLCapabilities getChosenGLCapabilities() { if (drawable == null) { throw new GLException("No drawable yet"); @@ -629,12 +661,4 @@ public class GLWindow extends Window implements GLAutoDrawable { return drawable.getGLProfile(); } - - //---------------------------------------------------------------------- - // Internals only below this point - // - - private void shouldNotCallThis() { - throw new NativeWindowException("Should not call this"); - } } diff --git a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java index e6af747c8..235132460 100644 --- a/src/newt/classes/com/jogamp/newt/util/EDTUtil.java +++ b/src/newt/classes/com/jogamp/newt/util/EDTUtil.java @@ -54,7 +54,7 @@ public class EDTUtil { public EDTUtil(ThreadGroup tg, String name, Runnable pumpMessages) { this.threadGroup = tg; - this.name=new String("EDT-"+name); + this.name=new String(Thread.currentThread().getName()+"-"+"EDT-"+name); this.pumpMessages=pumpMessages; } @@ -123,15 +123,15 @@ public class EDTUtil { } public void invokeAndWait(Runnable task) { - invoke(false, task); + invoke(true, task); } - public void invoke(boolean deferred, Runnable task) { + public void invoke(boolean wait, Runnable task) { if(task == null) { return; } invokeLater(task); - if(!deferred) { + if(wait) { waitOnWorker(); } } |