aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt/classes/com/jogamp/newt/Window.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt/classes/com/jogamp/newt/Window.java')
-rwxr-xr-xsrc/newt/classes/com/jogamp/newt/Window.java698
1 files changed, 534 insertions, 164 deletions
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");
+ }
}