diff options
Diffstat (limited to 'src/newt')
23 files changed, 1464 insertions, 823 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Display.java b/src/newt/classes/com/jogamp/newt/Display.java index 674a45ded..113ec547e 100755 --- a/src/newt/classes/com/jogamp/newt/Display.java +++ b/src/newt/classes/com/jogamp/newt/Display.java @@ -146,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()) { @@ -253,7 +253,7 @@ public abstract class Display { 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() { @@ -277,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(); 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/awt/NewtFactoryAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.java index e0f86b1a9..6409ab7a8 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtFactoryAWT.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/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/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/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/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/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/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/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(); } } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 1956b6899..6e8599d92 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -60,15 +60,28 @@ void setFrameTopLeftPoint(NSWindow* pwin, NSWindow* win, jint x, jint y) NSRect visibleRect; // either screen or parent-window NSPoint pt; int d_pty=0; // parent titlebar height + int d_ptx=0; if(NULL==pwin) { visibleRect = [screen frame]; } else { visibleRect = [pwin frame]; - NSView* pview = [pwin contentView]; NSRect viewRect = [pview frame]; d_pty = visibleRect.size.height - viewRect.size.height; + //d_pty = visibleRect.origin.y - viewRect.size.height; + //d_ptx = visibleRect.size.height - viewRect.size.height; + fprintf(stderr, "pwin %lf/%lf %lfx%lf, pview %lf/%lf %lfx%lf -> %d/%d\n", + visibleRect.origin.x, + visibleRect.origin.y, + visibleRect.size.width, + visibleRect.size.height, + viewRect.origin.x, + viewRect.origin.y, + viewRect.size.width, + viewRect.size.height, + x, y); + } pt = NSMakePoint(visibleRect.origin.x + x, visibleRect.origin.y + visibleRect.size.height - y - d_pty); @@ -167,8 +180,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_macosx_MacDisplay_dispatchMessa NS_DURING - NSWindow* win = NULL; - NewtView* view = NULL; int num_events = 0; // Periodically take a break @@ -287,7 +298,17 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_macosx_MacWindow_createWindow0 backing: (NSBackingStoreType) bufferingType screen: screen] retain]; - NSWindow* parentWindow = (NSWindow*) ((intptr_t) parent); + NSObject *nsParentObj = (NSObject*) ((intptr_t) parent); + NSWindow* parentWindow = NULL; + if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSWindow class]] ) { + parentWindow = (NSWindow*) nsParentObj; + } else if( nsParentObj != NULL && [nsParentObj isKindOfClass:[NSView class]] ) { + NSView* view = (NSView*) nsParentObj; + parentWindow = [view window]; + fprintf(stderr, "createWindow0 - Parent is NSView : %p -> %p (win) \n", nsParentObj, parentWindow); + } else { + fprintf(stderr, "createWindow0 - Parent is neither NSWindow nor NSView : %p\n", nsParentObj); + } if(NULL!=parentWindow) { [parentWindow addChildWindow: window ordered: NSWindowAbove]; [window setParentWindow: parentWindow]; @@ -448,7 +469,7 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_macosx_MacWindow_changeContent [pool release]; - return oldView; + return (jlong) ((intptr_t) oldView); } /* diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index fabcab1c7..37fd9c621 100755 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -1034,7 +1034,7 @@ JNIEXPORT jint JNICALL Java_com_jogamp_newt_impl_windows_WindowsScreen_getHeight /* * Class: com_jogamp_newt_impl_windows_WindowsWindow - * Method: initIDs + * Method: initIDs0 * Signature: ()Z */ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_initIDs0 @@ -1282,10 +1282,10 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setPositi /* * Class: com_jogamp_newt_impl_windows_WindowsWindow * Method: setFullscreen - * Signature: (JIIIIZZ)V + * Signature: (JIIIIZ)V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullscreen0 - (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated, jboolean on) + (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated) { UINT flags; HWND hwndP = (HWND) (intptr_t) parent; @@ -1293,10 +1293,55 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc HWND hWndInsertAfter; DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; - if ( JNI_TRUE == on ) { - hwndP = NULL; // full-screen is top level + // order of call sequence: (MS documentation) + // SetParent(.., NULL), SetWindowLong ( WS_POPUP ) + // SetParent(.., PARENT), SetWindowLong ( WS_CHILD ) + if ( NULL == hwndP ) { + SetParent(hwnd, NULL); + } + + if(NULL!=hwndP) { + windowStyle |= WS_CHILD ; + } else if (bIsUndecorated) { + windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; + } else { + windowStyle |= WS_OVERLAPPEDWINDOW; + } + SetWindowLong(hwnd, GWL_STYLE, windowStyle); + + if ( NULL != hwndP ) { + SetParent(hwnd, hwndP ); + } + + if ( NULL == hwndP ) { + flags = SWP_SHOWWINDOW; + hWndInsertAfter = HWND_TOPMOST; + } else { + flags = SWP_NOACTIVATE | SWP_NOZORDER; + hWndInsertAfter = 0; } + SetWindowPos(hwnd, hWndInsertAfter, x, y, width, height, flags); + + NewtWindows_requestFocus ( hwnd ); + + (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); +} + +/* + * Class: com_jogamp_newt_impl_windows_WindowsWindow + * Method: reparentWindow0 + * Signature: (JIIIIZ)V + */ +JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_reparentWindow0 + (JNIEnv *env, jobject obj, jlong parent, jlong window, jint x, jint y, jint width, jint height, jboolean bIsUndecorated) +{ + UINT flags; + HWND hwndP = (HWND) (intptr_t) parent; + HWND hwnd = (HWND) (intptr_t) window; + HWND hWndInsertAfter; + DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; + // order of call sequence: (MS documentation) // SetParent(.., NULL), SetWindowLong ( WS_POPUP ) // SetParent(.., PARENT), SetWindowLong ( WS_CHILD ) @@ -1306,7 +1351,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc if(NULL!=hwndP) { windowStyle |= WS_CHILD ; - } else if (bIsUndecorated || on) { + } else if (bIsUndecorated) { windowStyle |= WS_POPUP | WS_SYSMENU | WS_MAXIMIZEBOX | WS_MINIMIZEBOX; } else { windowStyle |= WS_OVERLAPPEDWINDOW; @@ -1317,7 +1362,8 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc SetParent(hwnd, hwndP ); } - if(on==JNI_TRUE) { + /** + if ( NULL == hwndP ) { flags = SWP_SHOWWINDOW; hWndInsertAfter = HWND_TOPMOST; } else { @@ -1326,10 +1372,11 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc } SetWindowPos(hwnd, hWndInsertAfter, x, y, width, height, flags); + */ NewtWindows_requestFocus ( hwnd ); - (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); + // (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); } /* diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index abaa3594f..f77f54cd1 100755 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -69,6 +69,7 @@ #define DBG_PRINT6(str, arg1, arg2, arg3, arg4, arg5, arg6) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6); #define DBG_PRINT7(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6, arg7); #define DBG_PRINT8(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + #define DBG_PRINT9(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) fprintf(stderr, str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); #define DUMP_VISUAL_INFO(a,b) _dumpVisualInfo((a),(b)) @@ -105,6 +106,7 @@ #define DBG_PRINT6(str, arg1, arg2, arg3, arg4, arg5, arg6) #define DBG_PRINT7(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7) #define DBG_PRINT8(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + #define DBG_PRINT9(str, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) #define DUMP_VISUAL_INFO(a,b) @@ -173,6 +175,7 @@ static jclass newtWindowClz=NULL; static jmethodID windowChangedID = NULL; static jmethodID focusChangedID = NULL; +static jmethodID visibleChangedID = NULL; static jmethodID windowDestroyNotifyID = NULL; static jmethodID windowDestroyedID = NULL; static jmethodID windowCreatedID = NULL; @@ -312,6 +315,13 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_CompleteDisplay0 (*env)->CallVoidMethod(env, obj, displayCompletedID, javaObjectAtom, windowDeleteAtom); } +/** + * Window + */ + +// #define WINDOW_EVENT_MASK ( FocusChangeMask | StructureNotifyMask | ExposureMask | VisibilityNotify ) +#define WINDOW_EVENT_MASK ( FocusChangeMask | StructureNotifyMask | VisibilityNotify ) + static int putPtrIn32Long(unsigned long * dst, uintptr_t src) { int i=0; dst[i++] = (unsigned long) ( ( src >> 0 ) & 0xFFFFFFFF ) ; @@ -344,7 +354,7 @@ static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlon (unsigned char *)&jogl_java_object_data, nitems_32); } -static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom) { +static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) { Atom actual_type_return; int actual_format_return; int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ; @@ -362,14 +372,18 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j &nitems_return, &bytes_after_return, &jogl_java_object_data_pp); if ( Success != res ) { - fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, result 0!\n", res, nitems_return, bytes_after_return); + if(True==showWarning) { + fprintf(stderr, "Warning: NEWT X11Window: Could not fetch Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, result 0!\n", res, nitems_return, bytes_after_return); + } return NULL; } if(actual_type_return!=(Atom)javaObjectAtom || nitems_return<nitems_32 || NULL==jogl_java_object_data_pp) { XFree(jogl_java_object_data_pp); - fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, actual_type_return %ld, JOGL_JAVA_OBJECT %ld, result 0!\n", + if(True==showWarning) { + fprintf(stderr, "Warning: NEWT X11Window: Fetched invalid Atom JOGL_JAVA_OBJECT window property (res %d) nitems_return %ld, bytes_after_return %ld, actual_type_return %ld, JOGL_JAVA_OBJECT %ld, result 0!\n", res, nitems_return, bytes_after_return, (long)actual_type_return, javaObjectAtom); + } return NULL; } } @@ -385,29 +399,50 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j return jwindow; } -static void NewtWindows_requestFocus (Display *dpy, Window w) { - XWindowAttributes attributes; - - XLockDisplay(dpy) ; - +static void NewtWindows_requestFocus0 (Display *dpy, Window w, XWindowAttributes *xwa) { // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable - XGetWindowAttributes(dpy, w, &attributes); - if(attributes.map_state == IsViewable) { + if(xwa->map_state == IsViewable) { XSetInputFocus(dpy, w, RevertToParent, CurrentTime); - XSync(dpy, False); } +} + +static void NewtWindows_requestFocus1 (Display *dpy, Window w) { + XWindowAttributes xwa; + + XLockDisplay(dpy) ; + + XGetWindowAttributes(dpy, w, &xwa); + NewtWindows_requestFocus0 (dpy, w, &xwa); + XSync(dpy, False); XUnlockDisplay(dpy) ; } -/** changing this attribute while a window is established, - * didn't impact the decoration - only at window creation time. -static void NewtWindows_setOverrideRedirect (Display *dpy, Window w, Bool val) { +/** + * Changing this attribute while a window is established, + * returns the previous value. + */ +static Bool NewtWindows_setOverrideRedirect0 (Display *dpy, Window w, XWindowAttributes *xwa, Bool newVal) { + Bool oldVal = xwa->override_redirect; XSetWindowAttributes xswa; - memset(&xswa, 0, sizeof(XSetWindowAttributes)); - xswa.override_redirect = val; - XChangeWindowAttributes(dpy, w, CWOverrideRedirect, &xswa); -} */ + + if(oldVal != newVal) { + memset(&xswa, 0, sizeof(XSetWindowAttributes)); + xswa.override_redirect = newVal; + XChangeWindowAttributes(dpy, w, CWOverrideRedirect, &xswa); + } + return oldVal; +} + +static Bool NewtWindows_setOverrideRedirect1 (Display *dpy, Window w, Bool newVal) { + XWindowAttributes xwa; + Bool oldVal; + + XSync(dpy, False); + XGetWindowAttributes(dpy, w, &xwa); + + return NewtWindows_setOverrideRedirect0 (dpy, w, &xwa, newVal); +} #define MWM_HINTS_DECORATIONS (1L << 1) #define PROP_MWM_HINTS_ELEMENTS 5 @@ -469,18 +504,26 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages return ; } + DBG_PRINT3( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, evt.type); + displayDispatchErrorHandlerEnable(1, env); - jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom); + jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, + #ifdef VERBOSE_ON + True + #else + False + #endif + ); displayDispatchErrorHandlerEnable(0, env); if(NULL==jwindow) { - fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for invalid X11 window %p\n", + fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", (void*)dpy, evt.type, (void*)evt.xany.window); + XUnlockDisplay(dpy) ; - // DBG_PRINT1( "X11: DispatchMessages 0x%X - Leave 2\n", dpy); - return; + continue; } switch(evt.type) { @@ -497,11 +540,10 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages } XUnlockDisplay(dpy) ; - // DBG_PRINT3( "X11: DispatchMessages 0x%X - Window %p, Event %d\n", dpy, jwindow, evt.type); switch(evt.type) { case ButtonPress: - NewtWindows_requestFocus ( dpy, evt.xany.window ); + NewtWindows_requestFocus1 ( dpy, evt.xany.window ); (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, (jint) evt.xbutton.state, (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0 /*rotation*/); @@ -565,6 +607,16 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE); break; + case MapNotify: + DBG_PRINT1( "X11: event . MapNotify call 0x%X\n", (unsigned int)evt.xunmap.window); + // FIXME (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE); + break; + + case UnmapNotify: + DBG_PRINT1( "X11: event . UnmapNotify call 0x%X\n", (unsigned int)evt.xunmap.window); + // FIXME (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE); + break; + // unhandled events .. yet .. case VisibilityNotify: @@ -574,9 +626,6 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages DBG_PRINT1( "X11: event . Expose call 0x%X\n", (unsigned int)evt.xexpose.window); /* FIXME: Might want to send a repaint event .. */ break; - case UnmapNotify: - DBG_PRINT1( "X11: event . UnmapNotify call 0x%X\n", (unsigned int)evt.xunmap.window); - break; default: DBG_PRINT3("X11: event . unhandled %d 0x%X call 0x%X\n", evt.type, evt.type, (unsigned int)evt.xunmap.window); } @@ -644,6 +693,7 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 { windowChangedID = (*env)->GetMethodID(env, clazz, "windowChanged", "(IIII)V"); focusChangedID = (*env)->GetMethodID(env, clazz, "focusChanged", "(Z)V"); + visibleChangedID = (*env)->GetMethodID(env, clazz, "visibleChanged", "(Z)V"); windowDestroyNotifyID = (*env)->GetMethodID(env, clazz, "windowDestroyNotify", "()V"); windowDestroyedID = (*env)->GetMethodID(env, clazz, "windowDestroyed", "()V"); windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); @@ -652,6 +702,7 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 if (windowChangedID == NULL || focusChangedID == NULL || + visibleChangedID == NULL || windowDestroyNotifyID == NULL || windowDestroyedID == NULL || windowCreatedID == NULL || @@ -691,8 +742,6 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 Screen* scrn; Atom wm_delete_atom; - DBG_PRINT5( "X11: CreateWindow %x/%d %dx%d, undeco %d\n", x, y, width, height, undecorated); - if(dpy==NULL) { _FatalError(env, "invalid display connection.."); } @@ -707,6 +756,11 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 XSync(dpy, False); scrn = ScreenOfDisplay(dpy, scrn_idx); + if(0==windowParent) { + windowParent = XRootWindowOfScreen(scrn); + } + DBG_PRINT7( "X11: CreateWindow dpy %p, parent %p, %x/%d %dx%d, undeco %d\n", + (void*)dpy, (void*)windowParent, x, y, width, height, undecorated); // try given VisualID on screen memset(&visualTemplate, 0, sizeof(XVisualInfo)); @@ -721,8 +775,8 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 XFree(pVisualQuery); pVisualQuery=NULL; } - DBG_PRINT5( "X11: [CreateWindow] trying given (dpy %p, screen %d, visualID: %d, parent 0x%X) found: %p\n", - dpy, scrn_idx, (int)visualID, (unsigned int)windowParent, visual); + DBG_PRINT5( "X11: [CreateWindow] trying given (dpy %p, screen %d, visualID: %d, parent %p) found: %p\n", + dpy, scrn_idx, (int)visualID, (void*)windowParent, visual); if (visual==NULL) { @@ -735,17 +789,12 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 pVisualQuery=NULL; } - if(0==windowParent) { - windowParent = XRootWindowOfScreen(scrn); - } - - attrMask = ( CWBackPixel | CWBorderPixel | CWColormap | CWEventMask | CWOverrideRedirect ) ; + attrMask = ( CWBackPixel | CWBorderPixel | CWColormap | CWOverrideRedirect ) ; memset(&xswa, 0, sizeof(xswa)); - xswa.override_redirect = ( JNI_TRUE == undecorated || 0 != parent ) ? True : False ; + xswa.override_redirect = ( 0 != parent ) ? True : False ; xswa.border_pixel = 0; xswa.background_pixel = 0; - xswa.event_mask = FocusChangeMask | ExposureMask | StructureNotifyMask | KeyPressMask | KeyReleaseMask; xswa.colormap = XCreateColormap(dpy, windowParent, // XRootWindow(dpy, scrn_idx), visual, @@ -778,10 +827,12 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CreateWindow0 long xevent_mask = 0; xevent_mask |= ButtonPressMask | ButtonReleaseMask | PointerMotionMask; xevent_mask |= KeyPressMask | KeyReleaseMask; - xevent_mask |= FocusChangeMask | ExposureMask | StructureNotifyMask | VisibilityNotify ; + xevent_mask |= WINDOW_EVENT_MASK ; XSelectInput(dpy, window, xevent_mask); } + NewtWindows_setDecorations (dpy, window, ( JNI_TRUE == undecorated ) ? False : True ); + XSync(dpy, False); XUnlockDisplay(dpy) ; @@ -808,7 +859,9 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CloseWindow0 } XLockDisplay(dpy) ; - jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom); + DBG_PRINT2( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)w); + + jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom, True); if(NULL==jwindow) { _throwNewRuntimeException(dpy, env, "could not fetch Java Window object, bail out!"); return; @@ -825,6 +878,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_CloseWindow0 XDestroyWindow(dpy, w); XSync(dpy, False); + DBG_PRINT0( "X11: CloseWindow END\n"); XUnlockDisplay(dpy) ; (*env)->CallVoidMethod(env, obj, windowDestroyedID); @@ -886,8 +940,63 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setSize0 /* * Class: com_jogamp_newt_impl_x11_X11Window + * Method: setPosition0 + * Signature: (JJII)V + */ +JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosition0 + (JNIEnv *env, jobject obj, jlong parent, jlong display, jlong window, jint x, jint y) +{ + Display * dpy = (Display *) (intptr_t) display; + Window w = (Window)window; + XWindowChanges xwc; + + DBG_PRINT2( "X11: setPos0 . XConfigureWindow %d/%d\n", x, y); + if(dpy==NULL) { + _FatalError(env, "invalid display connection.."); + } + XLockDisplay(dpy) ; + + memset(&xwc, 0, sizeof(XWindowChanges)); + xwc.x=x; + xwc.y=y; + XConfigureWindow(dpy, w, CWX|CWY, &xwc); + XSync(dpy, False); + + XUnlockDisplay(dpy) ; +} + +static void NewtWindows_reparentWindow + (Display * dpy, Screen * scrn, Window w, XWindowAttributes *xwa, jlong jparent, jint x, jint y, jboolean undecorated) +{ + Window parent = (0!=jparent)?(Window)jparent:XRootWindowOfScreen(scrn); + + DBG_PRINT7( "X11: reparentWindow dpy %p, parent %p/%p, win %p, %d/%d undec %d\n", + (void*)dpy, (void*) jparent, (void*)parent, (void*)w, x, y, undecorated); + + // let parent ignore reparent request + NewtWindows_setOverrideRedirect0 (dpy, w, xwa, True); + if(JNI_TRUE == undecorated) { + NewtWindows_setDecorations (dpy, w, False); + } + XSync(dpy, False); + + XReparentWindow( dpy, w, parent, x, y ); + XRaiseWindow(dpy, w); + XSync(dpy, False); + + NewtWindows_setOverrideRedirect0 (dpy, w, xwa, ( 0 != jparent ) ? True : False ); + if(JNI_FALSE == undecorated) { + NewtWindows_setDecorations (dpy, w, True); + } + XSync(dpy, False); + + DBG_PRINT0( "X11: reparentWindow X\n"); +} + +/* + * Class: com_jogamp_newt_impl_x11_X11Window * Method: setPosSizeDecor0 - * Signature: (JIJIIIIIZ)V + * Signature: (JJIJIIIIZ)V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosSizeDecor0 (JNIEnv *env, jobject obj, jlong jparent, jlong display, jint screen_index, jlong window, @@ -896,23 +1005,22 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosSizeDecor0 Display * dpy = (Display *) (intptr_t) display; Window w = (Window)window; Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index); - Window parent = (0!=jparent)?(Window)jparent:XRootWindowOfScreen(scrn); XWindowChanges xwc; + XWindowAttributes xwa; - DBG_PRINT5( "X11: setPosSizeDecor0 %d/%d %dx%d, undec %d\n", x, y, width, height, undecorated); + DBG_PRINT8( "X11: setPosSizeDecor0 dpy %p, parent %p, win %p, %d/%d %dx%d undec %d\n", + (void*)dpy, (void*) jparent, (void*)w, x, y, width, height, undecorated); if(dpy==NULL) { _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; - // we need to reparent the window, - // to allow a child window to go fullscreen and back. - XReparentWindow( dpy, w, parent, x, y ); - XRaiseWindow(dpy, w); + XSync(dpy, False); + XGetWindowAttributes(dpy, w, &xwa); - NewtWindows_setDecorations (dpy, w, ( JNI_TRUE == undecorated ) ? False : True ); + NewtWindows_reparentWindow(dpy, scrn, w, &xwa, jparent, x, y, undecorated); memset(&xwc, 0, sizeof(XWindowChanges)); xwc.x=x; @@ -922,35 +1030,39 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosSizeDecor0 XConfigureWindow(dpy, w, CWX|CWY|CWWidth|CWHeight, &xwc); XSync(dpy, False); - NewtWindows_requestFocus ( dpy, w ); + NewtWindows_requestFocus0 ( dpy, w, &xwa ); + XSync(dpy, False); XUnlockDisplay(dpy) ; } /* * Class: com_jogamp_newt_impl_x11_X11Window - * Method: setPosition0 - * Signature: (JJII)V + * Method: reparentWindow0 + * Signature: (JJIJIIZ)V */ -JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosition0 - (JNIEnv *env, jobject obj, jlong parent, jlong display, jlong window, jint x, jint y) +JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reparentWindow0 + (JNIEnv *env, jobject obj, jlong jparent, jlong display, jint screen_index, jlong window, jint x, jint y, jboolean undecorated) { Display * dpy = (Display *) (intptr_t) display; Window w = (Window)window; - XWindowChanges xwc; + Screen * scrn = ScreenOfDisplay(dpy, (int)screen_index); + XWindowAttributes xwa; + + DBG_PRINT6( "X11: reparentWindow0 dpy %p, parent %p, win %p, %d/%d undec %d\n", + (void*)dpy, (void*) jparent, (void*)w, x, y, undecorated); - DBG_PRINT2( "X11: setPos0 . XConfigureWindow %d/%d\n", x, y); if(dpy==NULL) { _FatalError(env, "invalid display connection.."); } XLockDisplay(dpy) ; - memset(&xwc, 0, sizeof(XWindowChanges)); - xwc.x=x; - xwc.y=y; - XConfigureWindow(dpy, w, CWX|CWY, &xwc); XSync(dpy, False); + XGetWindowAttributes(dpy, w, &xwa); + + NewtWindows_reparentWindow(dpy, scrn, w, &xwa, jparent, x, y, undecorated); XUnlockDisplay(dpy) ; + DBG_PRINT0( "X11: reparentWindow0 X\n"); } /* |