Jogamp
Bug 1188, Bug 1186: NEWT Window: Support non-resizable, minimize, maximize, alwaysOnB...
authorSven Gothel <sgothel@jausoft.com>
Mon, 10 Aug 2015 14:16:13 +0000 (16:16 +0200)
committerSven Gothel <sgothel@jausoft.com>
Mon, 10 Aug 2015 14:16:13 +0000 (16:16 +0200)
Change also implements Bug 1186: 'NEWT Window: Use a Bitfield holding all state flags and expose it accordingly',
since it is essential for an efficient implementation.

Part 1:

- Bug 1186
  - Using Bitfield, holding public (Window) and private state bits/mask

- Bug 1188
  - Window adds:
       - [is|set]AlwaysOnBottom(..),
       - [is|set]Resizable(..),
       - [is|set]Sticky(..),
       - [is|set]Maximized(..),
       - isChildWindow(),

  - Full implementation for X11

  - TODO: Implement for OSX and Windows

- Manual tests:
  - TestGearsES2NEWT, TestGearsES2NEWTSimple and TestGearsES2NewtCanvasAWT
    utilize new NewtDemoListener, which has a key-listener to perform
    all [new] actions. See source code of NewtDemoListener.

29 files changed:
make/scripts/tests.sh
src/nativewindow/classes/com/jogamp/nativewindow/util/Rectangle.java
src/newt/classes/com/jogamp/newt/Window.java
src/newt/classes/com/jogamp/newt/opengl/GLWindow.java
src/newt/classes/jogamp/newt/OffscreenWindow.java
src/newt/classes/jogamp/newt/WindowImpl.java
src/newt/classes/jogamp/newt/driver/android/WindowDriver.java
src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java
src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java
src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java
src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java
src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java
src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java
src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java
src/newt/native/MacWindow.m
src/newt/native/Window.h
src/newt/native/WindowsWindow.c
src/newt/native/X11AllowedWMActions.c [new file with mode: 0644]
src/newt/native/X11Common.h
src/newt/native/X11Display.c
src/newt/native/X11Event.c
src/newt/native/X11Window.c
src/newt/native/XCBEvent.c
src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/GearsES2.java
src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NEWT.java
src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2NewtCanvasAWT.java
src/test/com/jogamp/opengl/test/junit/jogl/demos/es2/newt/TestGearsES2SimpleNEWT.java
src/test/com/jogamp/opengl/test/junit/newt/parenting/NewtAWTReparentingKeyAdapter.java
src/test/com/jogamp/opengl/test/junit/util/NEWTDemoListener.java [new file with mode: 0644]

index 3e37837..bfa518d 100644 (file)
@@ -108,6 +108,7 @@ function jrun() {
 
     #D_ARGS="-Djogamp.debug.NativeLibrary=true -Djogamp.debug.JNILibLoader=true"
     #D_ARGS="-Djogl.debug.GLContext -Djogamp.debug.NativeLibrary -Djogamp.debug.JNILibLoader -Djogl.debug.DebugGL -Djogl.debug.GLDebugMessageHandler"
+    #D_ARGS="-Djogamp.debug.ProcAddressHelper -Djogamp.debug.NativeLibrary -Djogamp.debug.NativeLibrary.Lookup -Djogamp.debug.JNILibLoader -Djogl.debug.GLContext"
     #D_ARGS="-Djogamp.debug.ProcAddressHelper -Djogamp.debug.NativeLibrary -Djogamp.debug.NativeLibrary.Lookup -Djogamp.debug.JNILibLoader -Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil"
     #D_ARGS="-Djogamp.debug.ProcAddressHelper -Djogamp.debug.NativeLibrary -Djogamp.debug.NativeLibrary.Lookup -Djogamp.debug.JNILibLoader -Djogamp.debug.TempJarCache -Djogamp.debug.JarUtil -Djogl.glu.nojava=true"
 
@@ -137,7 +138,7 @@ function jrun() {
     #D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.TraceGL"
     #D_ARGS="-Djogl.debug.GLSLCode -Djogl.debug.DebugGL"
     #D_ARGS="-Djogl.debug.GLContext -Dnativewindow.debug.JAWT -Dnewt.debug.Window"
-    D_ARGS="-Dnativewindow.debug.JAWT -Djogl.debug.GLCanvas"
+    #D_ARGS="-Dnativewindow.debug.JAWT -Djogl.debug.GLCanvas"
     #D_ARGS="-Dnativewindow.debug.JAWT -Djogamp.debug.TaskBase.TraceSource"
     #D_ARGS="-Dnativewindow.debug.JAWT"
     #D_ARGS="-Djogl.debug.GLContext.TraceSwitch"
@@ -181,7 +182,7 @@ function jrun() {
     #D_ARGS="-Djogl.debug.DebugGL -Djogl.debug.TraceGL -Djogl.debug.GLContext.TraceSwitch -Djogl.debug=all"
     #D_ARGS="-Djogl.debug.GLArrayData"
     #D_ARGS="-Dnewt.debug.Screen -Dnewt.debug.Window"
-    #D_ARGS="-Dnewt.debug.Window"
+    D_ARGS="-Dnewt.debug.Window"
     #D_ARGS="-Dnewt.debug.Screen"
     #D_ARGS="-Dnewt.test.Screen.disableRandR13"
     #D_ARGS="-Dnewt.test.Screen.disableScreenMode -Dnewt.debug.Screen"
@@ -420,10 +421,10 @@ function testawtswt() {
 # HiDPI
 #
 #testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NEWT $*
-testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2SimpleNEWT $*
+#testnoawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2SimpleNEWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2GLJPanelAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.demos.es2.awt.TestGearsES2AWT $*
-#testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $*
+testawt com.jogamp.opengl.test.junit.jogl.demos.es2.newt.TestGearsES2NewtCanvasAWT $*
 #testawt com.jogamp.opengl.test.junit.jogl.demos.gl2.awt.TestGearsAWT $*
 #testnoawt com.jogamp.opengl.test.junit.jogl.glsl.TestRulerNEWT01 $*
 #testnoawt com.jogamp.opengl.test.junit.graph.demos.GPUUISceneNewtDemo $*
index 33a1955..9b4d7ec 100644 (file)
@@ -46,6 +46,9 @@ public class Rectangle implements Cloneable, RectangleImmutable {
         this.width=width;
         this.height=height;
     }
+    public Rectangle(final RectangleImmutable s) {
+        set(s);
+    }
 
     @Override
     public Object cloneMutable() {
@@ -82,6 +85,12 @@ public class Rectangle implements Cloneable, RectangleImmutable {
         this.width = s.width;
         this.height = s.height;
     }
+    public final void set(final RectangleImmutable s) {
+        this.x = s.getX();
+        this.y = s.getY();
+        this.width = s.getWidth();
+        this.height = s.getHeight();
+    }
     public final void setX(final int x) { this.x = x; }
     public final void setY(final int y) { this.y = y; }
     public final void setWidth(final int width) { this.width = width; }
@@ -196,6 +205,7 @@ public class Rectangle implements Cloneable, RectangleImmutable {
             }
         }
         {
+            // FIXME: Invalid, position needs to be compared differently
             final int sq = x*y;
             final int xsq = d.getX()*d.getY();
 
index 2afa464..37147d1 100644 (file)
@@ -116,6 +116,185 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
     public static final long TIMEOUT_NATIVEWINDOW = 1000;
 
     //
+    // States (keep in sync w/ src/newt/native/Window.h)
+    //
+    /**
+     * Visibility of this instance.
+     * <p>Native instance gets created at first visibility, following NEWT's lazy creation pattern.</p>
+     * <p>Changing this state is <a href="#lifecycleHeavy">lifecycle heavy</a>.</p>
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_VISIBLE = 0; // reconfig-flag
+    /**
+     * Hinting that no custom position has been set before first {@link #STATE_BIT_VISIBLE visibility} of this instance.
+     * <p>If kept {@code false} at creation, this allows the WM to choose the top-level window position,
+     * otherwise the custom position is being enforced.</p>
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code true}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_AUTOPOSITION = 1;
+    /**
+     * Set if window is a <i>child window</i>, i.e. has been {@link #reparentWindow(NativeWindow, int, int, int) reparented}.
+     * <p>
+     * Otherwise bit is cleared, i.e. window is <i>top-level</i>.
+     * </p>
+     * <p>Changing this state is <a href="#lifecycleHeavy">lifecycle heavy</a>.</p>
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_CHILDWIN = 2;       // reconfig-flag
+    /**
+     * Set if window has <i>the input focus</i>, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_FOCUSED = 3;
+    /**
+     * Set if window has <i>window decorations</i>, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_UNDECORATED = 4;    // reconfig-flag
+    /**
+     * Set if window is <i>always on top</i>, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_ALWAYSONTOP = 5;    // reconfig-flag
+    /**
+     * Set if window is <i>always on bottom</i>, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_ALWAYSONBOTTOM = 6; // reconfig-flag
+    /**
+     * Set if window is <i>sticky</i>, i.e. visible <i>on all virtual desktop</i>, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_STICKY = 7;    // reconfig-flag
+    /**
+     * Set if window is <i>resizable</i>, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code true}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_RESIZABLE = 8; // reconfig-flag
+    /**
+     * Set if window is <i>maximized vertically</i>, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_MAXIMIZED_VERT = 9; // reconfig-flag
+    /**
+     * Set if window is <i>maximized horizontally</i>, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_MAXIMIZED_HORZ = 10; // reconfig-flag
+    /**
+     * Set if window is in <i>fullscreen mode</i>, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_FULLSCREEN = 11;    // reconfig-flag
+
+    // Hidden in WindowImpl:
+    //   static final int STATE_BIT_FULLSCREEN_SPAN = 12;
+
+    /**
+     * Set if the <i>pointer is visible</i> when inside the window, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code true}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_POINTERVISIBLE = 13;
+    /**
+     * Set if the <i>pointer is confined</i> to the window, otherwise cleared.
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    public static final int STATE_BIT_POINTERCONFINED = 14;
+
+    /** Bitmask for {@link #STATE_BIT_VISIBLE}, {@value}. */
+    public static final int STATE_MASK_VISIBLE = 1 << STATE_BIT_VISIBLE;
+    /** Bitmask for {@link #STATE_BIT_AUTOPOSITION}, {@value}. */
+    public static final int STATE_MASK_AUTOPOSITION = 1 << STATE_BIT_AUTOPOSITION;
+    /** Bitmask for {@link #STATE_BIT_CHILDWIN}, {@value}. */
+    public static final int STATE_MASK_CHILDWIN = 1 << STATE_BIT_CHILDWIN;
+    /** Bitmask for {@link #STATE_BIT_FOCUSED}, {@value}. */
+    public static final int STATE_MASK_FOCUSED = 1 << STATE_BIT_FOCUSED;
+    /** Bitmask for {@link #STATE_BIT_UNDECORATED}, {@value}. */
+    public static final int STATE_MASK_UNDECORATED = 1 << STATE_BIT_UNDECORATED;
+    /** Bitmask for {@link #STATE_BIT_ALWAYSONTOP}, {@value}. */
+    public static final int STATE_MASK_ALWAYSONTOP = 1 << STATE_BIT_ALWAYSONTOP;
+    /** Bitmask for {@link #STATE_BIT_ALWAYSONBOTTOM}, {@value}. */
+    public static final int STATE_MASK_ALWAYSONBOTTOM = 1 << STATE_BIT_ALWAYSONBOTTOM;
+    /** Bitmask for {@link #STATE_BIT_STICKY}, {@value}. */
+    public static final int STATE_MASK_STICKY = 1 << STATE_BIT_STICKY;
+    /** Bitmask for {@link #STATE_BIT_RESIZABLE}, {@value}. */
+    public static final int STATE_MASK_RESIZABLE = 1 << STATE_BIT_RESIZABLE;
+    /** Bitmask for {@link #STATE_BIT_MAXIMIZED_VERT}, {@value}. */
+    public static final int STATE_MASK_MAXIMIZED_VERT = 1 << STATE_BIT_MAXIMIZED_VERT;
+    /** Bitmask for {@link #STATE_BIT_MAXIMIZED_HORZ}, {@value}. */
+    public static final int STATE_MASK_MAXIMIZED_HORZ = 1 << STATE_BIT_MAXIMIZED_HORZ;
+    /** Bitmask for {@link #STATE_BIT_FULLSCREEN}, {@value}. */
+    public static final int STATE_MASK_FULLSCREEN = 1 << STATE_BIT_FULLSCREEN;
+    /** Bitmask for {@link #STATE_BIT_POINTERVISIBLE}, {@value}. */
+    public static final int STATE_MASK_POINTERVISIBLE = 1 << STATE_BIT_POINTERVISIBLE;
+    /** Bitmask for {@link #STATE_BIT_POINTERCONFINED}, {@value}. */
+    public static final int STATE_MASK_POINTERCONFINED = 1 << STATE_BIT_POINTERCONFINED;
+
+    /**
+     * Number of all public state bits.
+     * @see #getStateMask()
+     */
+    public int getStatePublicBitCount();
+
+    /**
+     * Bitmask covering all public state bits.
+     * @see #getStateMask()
+     */
+    public int getStatePublicBitmask();
+
+    /**
+     * Returns the current status mask of this instance.
+     * @see #STATE_MASK_VISIBLE
+     * @see #STATE_MASK_AUTOPOSITION
+     * @see #STATE_MASK_CHILDWIN
+     * @see #STATE_MASK_FOCUSED
+     * @see #STATE_MASK_UNDECORATED
+     * @see #STATE_MASK_ALWAYSONTOP
+     * @see #STATE_MASK_ALWAYSONBOTTOM
+     * @see #STATE_MASK_STICKY
+     * @see #STATE_MASK_RESIZABLE
+     * @see #STATE_MASK_MAXIMIZED_VERT
+     * @see #STATE_MASK_MAXIMIZED_HORZ
+     * @see #STATE_MASK_FULLSCREEN
+     * @see #STATE_MASK_POINTERVISIBLE
+     * @see #STATE_MASK_POINTERCONFINED
+     */
+    int getStateMask();
+
+    /**
+     * Returns a string representation of the {@link #getStateMask() current state mask}.
+     */
+    String getStateMaskString();
+
+    //
     // Lifecycle
     //
 
@@ -207,15 +386,14 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
      * i.e. blocks until the window becomes visible.
      * <p>This method is <a href="#lifecycleHeavy">lifecycle heavy</a>.</p>
      * @see #setVisible(boolean, boolean)
+     * @see #STATE_BIT_VISIBLE
      */
     void setVisible(boolean visible);
 
     /**
      * <code>setVisible(..)</code> makes the window and children visible if <code>visible</code> is true,
      * otherwise the window and children becomes invisible.
-     * <p>
-     * <code>setVisible(wait, true)</code> is responsible to actual create the native window.
-     * </p>
+     * <p>Native instance gets created at first visibility, following NEWT's lazy creation pattern.</p>
      * <p>
      * If <code>wait</code> is true, method blocks until window is {@link #isVisible() visible} and {@link #isNativeValid() valid},
      * otherwise method returns immediately.
@@ -234,15 +412,20 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
      * }
      * </pre></p>
      * <p>
-     * In case this window is a child window and has a {@link com.jogamp.nativewindow.NativeWindow} parent,<br>
+     * In case this window is {@link #isChildWindow() a child window} and has a {@link com.jogamp.nativewindow.NativeWindow} parent,<br>
      * <code>setVisible(wait, true)</code> has no effect as long the parent's is not valid yet,
      * i.e. {@link com.jogamp.nativewindow.NativeWindow#getWindowHandle()} returns <code>null</code>.<br>
      * <code>setVisible(wait, true)</code> shall be repeated when the parent becomes valid.
      * </p>
      * <p>This method is <a href="#lifecycleHeavy">lifecycle heavy</a>.</p>
+     * @see #STATE_BIT_VISIBLE
      */
     void setVisible(boolean wait, boolean visible);
 
+    /**
+     * @see #STATE_BIT_VISIBLE
+     * @see #setVisible(boolean, boolean)
+     */
     boolean isVisible();
 
     /**
@@ -388,14 +571,85 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
      */
     void setTopLevelPosition(int x, int y);
 
+    /**
+     * @see {@link #STATE_BIT_UNDECORATED}
+     * @see {@link #STATE_MASK_UNDECORATED}
+     */
     void setUndecorated(boolean value);
-
+    /**
+     * @see {@link #STATE_BIT_UNDECORATED}
+     * @see {@link #STATE_MASK_UNDECORATED}
+     */
     boolean isUndecorated();
 
+    /**
+     * <p>Operation is ignored if this instance {@link #isChildWindow() is a child window}.</p>
+     * @see {@link #STATE_BIT_ALWAYSONTOP}
+     * @see {@link #STATE_MASK_ALWAYSONTOP}
+     */
     void setAlwaysOnTop(boolean value);
-
+    /**
+     * @see {@link #STATE_BIT_ALWAYSONTOP}
+     * @see {@link #STATE_MASK_ALWAYSONTOP}
+     */
     boolean isAlwaysOnTop();
 
+    /**
+     * <p>Operation is ignored if this instance {@link #isChildWindow() is a child window}.</p>
+     * @see {@link #STATE_BIT_ALWAYSONBOTTOM}
+     * @see {@link #STATE_MASK_ALWAYSONBOTTOM}
+     */
+    void setAlwaysOnBottom(boolean value);
+    /**
+     * @see {@link #STATE_BIT_ALWAYSONBOTTOM}
+     * @see {@link #STATE_MASK_ALWAYSONBOTTOM}
+     */
+    boolean isAlwaysOnBottom();
+
+    /**
+     * <p>Operation is ignored if this instance {@link #isChildWindow() is a child window}.</p>
+     * @see {@link #STATE_BIT_RESIZABLE}
+     * @see {@link #STATE_MASK_RESIZABLE}
+     */
+    void setResizable(final boolean value);
+    /**
+     * @see {@link #STATE_BIT_RESIZABLE}
+     * @see {@link #STATE_MASK_RESIZABLE}
+     */
+    boolean isResizable();
+
+    /**
+     * <p>Operation is ignored if this instance {@link #isChildWindow() is a child window}.</p>
+     * @see {@link #STATE_BIT_STICKY}
+     * @see {@link #STATE_MASK_STICKY}
+     */
+    void setSticky(final boolean value);
+    /**
+     * @see {@link #STATE_BIT_STICKY}
+     * @see {@link #STATE_MASK_STICKY}
+     */
+    boolean isSticky();
+
+    /**
+     * <p>Operation is ignored in {@link #isFullscreen() fullscreen mode}.</p>
+     * <p>Operation is ignored if this instance {@link #isChildWindow() is a child window}.</p>
+     * @see {@link #STATE_BIT_MAXIMIZED_HORZ}
+     * @see {@link #STATE_BIT_MAXIMIZED_VERT}
+     * @see {@link #STATE_MASK_MAXIMIZED_HORZ}
+     * @see {@link #STATE_MASK_MAXIMIZED_VERT}
+     */
+    void setMaximized(final boolean horz, final boolean vert);
+    /**
+     * @see {@link #STATE_BIT_MAXIMIZED_VERT}
+     * @see {@link #STATE_MASK_MAXIMIZED_VERT}
+     */
+    boolean isMaximizedVert();
+    /**
+     * @see {@link #STATE_BIT_MAXIMIZED_HORZ}
+     * @see {@link #STATE_MASK_MAXIMIZED_HORZ}
+     */
+    boolean isMaximizedHorz();
+
     void setTitle(String title);
 
     String getTitle();
@@ -496,6 +750,15 @@ public interface Window extends NativeWindow, WindowClosingProtocol, ScalableSur
     ReparentOperation reparentWindow(NativeWindow newParent, int x, int y, int hints);
 
     /**
+     * Returns {@code true} if this window is a child window,
+     * i.e. has been {@link #reparentWindow(NativeWindow, int, int, int) reparented}.
+     * <p>
+     * Otherwise return {@code false}, i.e. this window is a top-level window.
+     * </p>
+     */
+    boolean isChildWindow();
+
+    /**
      * Enable or disable fullscreen mode for this window.
      * <p>
      * Fullscreen mode is established on the {@link #getMainMonitor() main monitor}.
index 3ef017d..f15c87b 100644 (file)
@@ -226,6 +226,26 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     //
 
     @Override
+    public final int getStatePublicBitCount() {
+        return window.getStatePublicBitCount();
+    }
+
+    @Override
+    public final int getStatePublicBitmask() {
+        return window.getStatePublicBitmask();
+    }
+
+    @Override
+    public final int getStateMask() {
+        return window.getStateMask();
+    }
+
+    @Override
+    public final String getStateMaskString() {
+        return window.getStateMaskString();
+    }
+
+    @Override
     public CapabilitiesChooser setCapabilitiesChooser(final CapabilitiesChooser chooser) {
         return window.setCapabilitiesChooser(chooser);
     }
@@ -326,6 +346,51 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     }
 
     @Override
+    public final void setAlwaysOnBottom(final boolean value) {
+        window.setAlwaysOnBottom(value);
+    }
+
+    @Override
+    public final boolean isAlwaysOnBottom() {
+        return window.isAlwaysOnBottom();
+    }
+
+    @Override
+    public final void setResizable(final boolean value) {
+        window.setResizable(value);
+    }
+
+    @Override
+    public final boolean isResizable() {
+        return window.isResizable();
+    }
+
+    @Override
+    public final void setSticky(final boolean value) {
+        window.setSticky(value);
+    }
+
+    @Override
+    public final boolean isSticky() {
+        return window.isSticky();
+    }
+
+    @Override
+    public final void setMaximized(final boolean horz, final boolean vert) {
+        window.setMaximized(horz, vert);
+    }
+
+    @Override
+    public final boolean isMaximizedVert() {
+        return window.isMaximizedVert();
+    }
+
+    @Override
+    public final boolean isMaximizedHorz() {
+        return window.isMaximizedHorz();
+    }
+
+    @Override
     public final void setFocusAction(final FocusRunnable focusAction) {
         window.setFocusAction(focusAction);
     }
@@ -469,6 +534,10 @@ public class GLWindow extends GLAutoDrawableBase implements GLAutoDrawable, Wind
     public final ReparentOperation reparentWindow(final NativeWindow newParent, final int x, final int y, final int hints) {
         return window.reparentWindow(newParent, x, y, hints);
     }
+    @Override
+    public final boolean isChildWindow() {
+        return window.isChildWindow();
+    }
 
     @Override
     public final boolean removeChild(final NativeWindow win) {
index fa9bd21..09e3189 100644 (file)
@@ -120,8 +120,8 @@ public class OffscreenWindow extends WindowImpl implements MutableSurface {
     @Override
     protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
         sizeChanged(false, width, height, false);
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) {
+            visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
         } else {
             /**
              * silently ignore:
index 2a05f2c..491f984 100644 (file)
@@ -173,30 +173,224 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     protected CapabilitiesChooser capabilitiesChooser = null; // default null -> default
     private List<MonitorDevice> fullscreenMonitors = null;
 
+    private final RectangleImmutable undefSize = new Rectangle(0, 0, 0, 0);
+    private final Rectangle minmax_size = new Rectangle(undefSize); // current min/max size or undef
     private int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets
     private NativeWindow nfs_parent = null;          // non fullscreen parent, in case explicit reparenting is performed (offscreen)
     private String title = "Newt Window";
     private PointerIconImpl pointerIcon = null;
     private LifecycleHook lifecycleHook = null;
 
-    /* pp */ static final int STATE_AUTOPOSITION = 0; // default: true (allow WM to choose top-level position, if not set by user)
-    /* pp */ static final int STATE_VISIBLE = 1; // lifecycle critical
-    /* pp */ static final int STATE_FOCUSED = 2;
-    /* pp */ static final int STATE_FOCUS_CHANGE_BROKEN = 3;
-    /* pp */ static final int STATE_UNDECORATED = 4;
-    /* pp */ static final int STATE_ALWAYSONTOP = 5;
-    /* pp */ static final int STATE_FULLSCREEN = 6;
-    /* pp */ static final int STATE_FULLSCREEN_MAINMONITOR = 7; // true
-    /* pp */ static final int STATE_FULLSCREEN_NFS_ALWAYSONTOP = 8; // non fullscreen alwaysOnTop setting
-    /* pp */ static final int STATE_POINTERVISIBLE = 9; // true
-    /* pp */ static final int STATE_POINTERCONFINED = 10;
+    //
+    // State Mask
+    //
+
+    /**
+     * Number of all public state bits, {@value}.
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    protected static final int STATE_BIT_COUNT_ALL_PUBLIC = 15;
+    /** Bitmask for {@link #STATE_BIT_COUNT_ALL_PUBLIC} */
+    protected static final int STATE_MASK_ALL_PUBLIC = ( 1 << STATE_BIT_COUNT_ALL_PUBLIC ) - 1;
+
+    //
+    // Additional private state-mask bits and mask values
+    //
+    /**
+     * <p>Bit number {@value}.</p>
+     * <p>Defaults to {@code false}.</p>
+     * @see #getStateMask()
+     */
+    /* pp */ static final int STATE_BIT_FULLSCREEN_SPAN = 12;
+    /* pp */ static final int PSTATE_BIT_MINMAXSIZE_SET = 27;
+    /* pp */ static final int PSTATE_BIT_FOCUS_CHANGE_BROKEN = 28;
+    /* pp */ static final int PSTATE_BIT_FULLSCREEN_MAINMONITOR = 29; // true
+    /* pp */ static final int PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP = 30; // non fullscreen alwaysOnTop setting
+    /* pp */ static final int PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE = 31; // non fullscreen resizable setting
+
+    /** Bitmask for {@link #STATE_BIT_FULLSCREEN_SPAN}, {@value}. */
+    /* pp */ static final int STATE_MASK_FULLSCREEN_SPAN = 1 << STATE_BIT_FULLSCREEN_SPAN;
+    /* pp */ static final int PSTATE_MASK_FOCUS_CHANGE_BROKEN = 1 << PSTATE_BIT_FOCUS_CHANGE_BROKEN;
+    /* pp */ static final int PSTATE_MASK_FULLSCREEN_MAINMONITOR = 1 << PSTATE_BIT_FULLSCREEN_MAINMONITOR;
+    /* pp */ static final int PSTATE_MASK_FULLSCREEN_NFS_ALWAYSONTOP = 1 << PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP;
+    /* pp */ static final int PSTATE_MASK_FULLSCREEN_NFS_RESIZABLE = 1 << PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE;
+
+    /**
+     * Reconfig mask for createNativeImpl(..) taking out from {@link #getStateMask()}:
+     * <ul>
+     *   <li>{@link #STATE_MASK_VISIBLE}</li>
+     *   <li>{@link #STATE_MASK_FULLSCREEN}</li>
+     *   <li>{@link #STATE_MASK_POINTERVISIBLE}</li>
+     *   <li>{@link #STATE_MASK_POINTERCONFINED}</li>
+     * </ul>
+     * Above taken out states are achieved from caller createNative() 'manually'.
+     */
+    protected final int STATE_MASK_CREATENATIVE = STATE_MASK_UNDECORATED |
+                                                  STATE_MASK_ALWAYSONTOP |
+                                                  STATE_MASK_ALWAYSONBOTTOM |
+                                                  STATE_MASK_STICKY |
+                                                  STATE_MASK_RESIZABLE |
+                                                  STATE_MASK_MAXIMIZED_VERT |
+                                                  STATE_MASK_MAXIMIZED_HORZ;
+    //
+    // Additional private state-mask mask values for reconfiguration only
+    // (keep in sync w/ src/newt/native/Window.h)
+    //
+    protected static final int CHANGE_MASK_VISIBILITY      = 1 << 31;
+    protected static final int CHANGE_MASK_VISIBILITY_FAST = 1 << 30; // fast visibility change, i.e. skip WM
+    protected static final int CHANGE_MASK_PARENTING       = 1 << 29;
+    protected static final int CHANGE_MASK_DECORATION      = 1 << 28;
+    protected static final int CHANGE_MASK_ALWAYSONTOP     = 1 << 27;
+    protected static final int CHANGE_MASK_ALWAYSONBOTTOM  = 1 << 26;
+    protected static final int CHANGE_MASK_STICKY          = 1 << 25;
+    protected static final int CHANGE_MASK_RESIZABLE       = 1 << 24;
+    protected static final int CHANGE_MASK_MAXIMIZED_VERT  = 1 << 23;
+    protected static final int CHANGE_MASK_MAXIMIZED_HORZ  = 1 << 22;
+    protected static final int CHANGE_MASK_FULLSCREEN      = 1 << 21;
 
     /* pp */ final Bitfield stateMask = Bitfield.Factory.synchronize(Bitfield.Factory.create(32));
     /* pp */ final void resetStateMask() {
         stateMask.clearField(false);
-        stateMask.set(STATE_AUTOPOSITION);
-        stateMask.set(STATE_FULLSCREEN_MAINMONITOR);
-        stateMask.set(STATE_POINTERVISIBLE);
+        stateMask.set(STATE_BIT_AUTOPOSITION);
+        stateMask.put(STATE_BIT_CHILDWIN, null != parentWindow);
+        stateMask.set(STATE_BIT_RESIZABLE);
+        stateMask.set(STATE_BIT_POINTERVISIBLE);
+        stateMask.set(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE);
+        stateMask.set(PSTATE_BIT_FULLSCREEN_MAINMONITOR);
+    }
+
+    @Override
+    public final int getStatePublicBitCount() {
+        return STATE_BIT_COUNT_ALL_PUBLIC;
+    }
+    @Override
+    public final int getStatePublicBitmask() {
+        return STATE_MASK_ALL_PUBLIC;
+    }
+
+    @Override
+    public final int getStateMask() {
+        return stateMask.get32(0, STATE_BIT_COUNT_ALL_PUBLIC);
+    }
+    @Override
+    public final String getStateMaskString() {
+        return appendStateBits(new StringBuilder(), stateMask.get32(0, STATE_BIT_COUNT_ALL_PUBLIC), false).toString();
+    }
+
+    protected static StringBuilder appendStateBits(final StringBuilder sb, final int mask, final boolean showChangeFlags) {
+        sb.append("[");
+
+        if( showChangeFlags && 0 != ( CHANGE_MASK_VISIBILITY & mask) ) {
+            sb.append("*");
+            if( 0 != ( CHANGE_MASK_VISIBILITY_FAST & mask) ) {
+                sb.append("*");
+            }
+        }
+        sb.append((0 != ( STATE_MASK_VISIBLE & mask))?"visible":"invisible");
+        sb.append(", ");
+
+        sb.append((0 != ( STATE_MASK_AUTOPOSITION & mask))?"autopos, ":"");
+
+        if( showChangeFlags && 0 != ( CHANGE_MASK_PARENTING & mask) ) {
+            sb.append("*");
+            sb.append((0 != ( STATE_MASK_CHILDWIN & mask))?"child":"top");
+            sb.append(", ");
+        } else if( 0 != ( STATE_MASK_CHILDWIN & mask) ) {
+            sb.append("child");
+            sb.append(", ");
+        }
+
+        sb.append((0 != ( STATE_MASK_FOCUSED & mask))?"focused, ":"");
+
+        if( showChangeFlags && 0 != ( CHANGE_MASK_DECORATION & mask) ) {
+            sb.append("*");
+            sb.append((0 != ( STATE_MASK_UNDECORATED & mask))?"undecor":"decor");
+            sb.append(", ");
+        } else if( 0 != ( STATE_MASK_UNDECORATED & mask) ) {
+            sb.append("undecor");
+            sb.append(", ");
+        }
+
+        if( showChangeFlags && 0 != ( CHANGE_MASK_ALWAYSONTOP & mask) ) {
+            sb.append("*");
+            sb.append((0 != ( STATE_MASK_ALWAYSONTOP & mask))?"aontop":"!aontop");
+            sb.append(", ");
+        } else if( 0 != ( STATE_MASK_ALWAYSONTOP & mask) ) {
+            sb.append("aontop");
+            sb.append(", ");
+        }
+
+        if( showChangeFlags && 0 != ( CHANGE_MASK_ALWAYSONBOTTOM & mask) ) {
+            sb.append("*");
+            sb.append((0 != ( STATE_MASK_ALWAYSONBOTTOM & mask))?"aonbottom":"!aonbottom");
+            sb.append(", ");
+        } else if( 0 != ( STATE_MASK_ALWAYSONBOTTOM & mask) ) {
+            sb.append("aonbottom");
+            sb.append(", ");
+        }
+
+        if( showChangeFlags && 0 != ( CHANGE_MASK_STICKY & mask) ) {
+            sb.append("*");
+            sb.append((0 != ( STATE_MASK_STICKY & mask))?"sticky":"unsticky");
+            sb.append(", ");
+        } else if( 0 != ( STATE_MASK_STICKY & mask) ) {
+            sb.append("sticky");
+            sb.append(", ");
+        }
+
+        if( showChangeFlags && 0 != ( CHANGE_MASK_RESIZABLE & mask) ) {
+            sb.append("*");
+            sb.append((0 != ( STATE_MASK_RESIZABLE & mask))?"resizable":"unresizable");
+            sb.append(", ");
+        } else if( 0 == ( STATE_MASK_RESIZABLE & mask) ) {
+            sb.append("unresizable");
+            sb.append(", ");
+        }
+
+        if( showChangeFlags && 0 != ( ( CHANGE_MASK_MAXIMIZED_HORZ | CHANGE_MASK_MAXIMIZED_VERT ) & mask) ) {
+            sb.append("max=");
+            if( 0 != ( STATE_MASK_MAXIMIZED_HORZ & mask) ) {
+                sb.append("h");
+            }
+            if( 0 != ( STATE_MASK_MAXIMIZED_VERT & mask) ) {
+                sb.append("v");
+            }
+            sb.append(", ");
+        } else if( 0 != ( ( STATE_MASK_MAXIMIZED_HORZ | STATE_MASK_MAXIMIZED_VERT ) & mask) ) {
+            sb.append("max=");
+            if( 0 != ( STATE_MASK_MAXIMIZED_HORZ & mask) ) {
+                sb.append("h");
+            }
+            if( 0 != ( STATE_MASK_MAXIMIZED_VERT & mask) ) {
+                sb.append("v");
+            }
+            sb.append(", ");
+        }
+
+        if( showChangeFlags && 0 != ( CHANGE_MASK_FULLSCREEN & mask) ) {
+            sb.append("*");
+            sb.append((0 != ( STATE_MASK_FULLSCREEN & mask))?"fullscreen":"window");
+            sb.append((0 != ( STATE_MASK_FULLSCREEN_SPAN & mask))?"[span]":"[]");
+            sb.append(", ");
+        } else if( 0 != ( STATE_MASK_FULLSCREEN & mask) ) {
+            sb.append("fullscreen");
+            sb.append(", ");
+        }
+
+        if( 0 == ( ( STATE_MASK_POINTERVISIBLE | STATE_MASK_POINTERCONFINED ) & mask) ) {
+            sb.append("pointer[");
+            if( 0 == ( STATE_MASK_POINTERVISIBLE & mask) ) {
+                sb.append("invisible");
+                sb.append(", ");
+            }
+            if( 0 != ( STATE_MASK_POINTERCONFINED & mask) ) {
+                sb.append("confined");
+            }
+            sb.append("]");
+        }
+        sb.append("]");
+        return sb;
     }
 
     private Runnable windowDestroyNotifyAction = null;
@@ -434,7 +628,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         final boolean hasParent = null != parentWindow || 0 != this.parentWindowHandle;
 
         // child window: position defaults to 0/0, no auto position, no negative position
-        if( hasParent && ( stateMask.get(STATE_AUTOPOSITION) || 0>getX() || 0>getY() ) ) {
+        if( hasParent && ( stateMask.get(STATE_BIT_AUTOPOSITION) || 0>getX() || 0>getY() ) ) {
             definePosition(0, 0);
         }
         boolean postParentlockFocus = false;
@@ -447,7 +641,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 if(canCreateNativeImpl()) {
                     final int wX, wY;
                     final boolean usePosition;
-                    if( stateMask.get(STATE_AUTOPOSITION) ) {
+                    if( stateMask.get(STATE_BIT_AUTOPOSITION) ) {
                         wX = 0;
                         wY = 0;
                         usePosition = false;
@@ -461,20 +655,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     screen.addMonitorModeListener(monitorModeListenerImpl);
                     setTitleImpl(title);
                     setPointerIconIntern(pointerIcon);
-                    setPointerVisibleIntern(stateMask.get(STATE_POINTERVISIBLE));
-                    confinePointerImpl(stateMask.get(STATE_POINTERCONFINED));
+                    setPointerVisibleIntern(stateMask.get(STATE_BIT_POINTERVISIBLE));
+                    confinePointerImpl(stateMask.get(STATE_BIT_POINTERCONFINED));
                     setKeyboardVisible(keyboardVisible);
                     final long remainingV = waitForVisible(true, false);
                     if( 0 <= remainingV ) {
                         if(isFullscreen()) {
                             synchronized(fullScreenAction) {
-                                stateMask.clear(STATE_FULLSCREEN); // trigger a state change
+                                stateMask.clear(STATE_BIT_FULLSCREEN); // trigger a state change
                                 fullScreenAction.init(true);
                                 fullScreenAction.run();
                             }
-                        } else if ( !hasParent ) {
-                            // Wait until position is reached within tolerances, either auto-position or custom position.
-                            waitForPosition(usePosition, wX, wY, Window.TIMEOUT_NATIVEWINDOW);
+                        } else {
+                            if ( !hasParent ) {
+                                // Wait until position is reached within tolerances, either auto-position or custom position.
+                                waitForPosition(usePosition, wX, wY, Window.TIMEOUT_NATIVEWINDOW);
+                            }
                         }
                         if (DEBUG_IMPLEMENTATION) {
                             System.err.println("Window.createNative(): elapsed "+(System.currentTimeMillis()-t0)+" ms");
@@ -513,8 +709,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         if(null!=parentWindow) {
             parentWindowHandle = getNativeWindowHandle(parentWindow);
             return 0 != parentWindowHandle ;
+        } else {
+            return true;
         }
-        return true;
     }
 
     private static long getNativeWindowHandle(final NativeWindow nativeWindow) {
@@ -631,19 +828,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
      */
     protected abstract void requestFocusImpl(boolean force);
 
-    public static final int FLAG_CHANGE_PARENTING       = 1 <<  0;
-    public static final int FLAG_CHANGE_DECORATION      = 1 <<  1;
-    public static final int FLAG_CHANGE_FULLSCREEN      = 1 <<  2;
-    public static final int FLAG_CHANGE_ALWAYSONTOP     = 1 <<  3;
-    public static final int FLAG_CHANGE_VISIBILITY      = 1 <<  4;
-
-    public static final int FLAG_HAS_PARENT             = 1 <<  8;
-    public static final int FLAG_IS_UNDECORATED         = 1 <<  9;
-    public static final int FLAG_IS_FULLSCREEN          = 1 << 10;
-    public static final int FLAG_IS_FULLSCREEN_SPAN     = 1 << 11;
-    public static final int FLAG_IS_ALWAYSONTOP         = 1 << 12;
-    public static final int FLAG_IS_VISIBLE             = 1 << 13;
-
     /**
      * The native implementation should invoke the referenced java state callbacks
      * to notify this Java object of state changes.
@@ -667,62 +851,23 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     /**
      * Tests whether a single reconfigure flag is supported by implementation.
      * <p>
-     * Default is all but {@link #FLAG_IS_FULLSCREEN_SPAN}
+     * Default is all but {@link #STATE_MASK_FULLSCREEN_SPAN}
      * </p>
      */
-    protected boolean isReconfigureFlagSupported(final int changeFlags) {
-        return 0 == ( changeFlags & FLAG_IS_FULLSCREEN_SPAN );
+    protected boolean isReconfigureMaskSupported(final int changeFlags) {
+        return 0 == ( changeFlags & STATE_MASK_FULLSCREEN_SPAN );
     }
 
-    protected int getReconfigureFlags(final int changeFlags, final boolean visible) {
-        return changeFlags | ( ( 0 != getParentWindowHandle() ) ? FLAG_HAS_PARENT : 0 ) |
-                             ( isUndecorated() ? FLAG_IS_UNDECORATED : 0 ) |
-                             ( isFullscreen() ? FLAG_IS_FULLSCREEN : 0 ) |
-                             ( isAlwaysOnTop() ? FLAG_IS_ALWAYSONTOP : 0 ) |
-                             ( visible ? FLAG_IS_VISIBLE : 0 ) ;
+    protected int getReconfigureMask(final int changeFlags, final boolean visible) {
+        final int smask = stateMask.get32(0, STATE_BIT_COUNT_ALL_PUBLIC);
+        return changeFlags
+               | ( smask & ~STATE_MASK_VISIBLE )
+               | ( visible ? STATE_MASK_VISIBLE : 0 )
+               | ( isUndecorated(smask) ? STATE_MASK_UNDECORATED : 0 )
+               ;
     }
-    protected static String getReconfigureFlagsAsString(StringBuilder sb, final int flags) {
-        if(null == sb) { sb = new StringBuilder(); }
-        sb.append("[");
-
-        if( 0 != ( FLAG_CHANGE_PARENTING & flags) ) {
-            sb.append("*");
-        }
-        sb.append("PARENT ");
-        sb.append(0 != ( FLAG_HAS_PARENT & flags));
-        sb.append(", ");
-
-        if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
-            sb.append("*");
-        }
-        sb.append("FS ");
-        sb.append(0 != ( FLAG_IS_FULLSCREEN & flags));
-        sb.append("[span ");
-        sb.append(0 != ( FLAG_IS_FULLSCREEN_SPAN & flags));
-        sb.append("], ");
-
-        if( 0 != ( FLAG_CHANGE_DECORATION & flags) ) {
-            sb.append("*");
-        }
-        sb.append("UNDECOR ");
-        sb.append(0 != ( FLAG_IS_UNDECORATED & flags));
-        sb.append(", ");
-
-        if( 0 != ( FLAG_CHANGE_ALWAYSONTOP & flags) ) {
-            sb.append("*");
-        }
-        sb.append("ALWAYSONTOP ");
-        sb.append(0 != ( FLAG_IS_ALWAYSONTOP & flags));
-        sb.append(", ");
-
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            sb.append("*");
-        }
-        sb.append("VISIBLE ");
-        sb.append(0 != ( FLAG_IS_VISIBLE & flags));
-
-        sb.append("]");
-        return sb.toString();
+    protected static String getReconfigStateMaskString(final int flags) {
+        return appendStateBits(new StringBuilder(), flags, true).toString();
     }
 
     protected void setTitleImpl(final String title) {}
@@ -945,13 +1090,20 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     /**
      * @param visible
+     * @param fast {@code true} hints that the WM shall be skiped (no animation)
      * @param x client-area position in window units, or <0 if unchanged
      * @param y client-area position in window units, or <0 if unchanged
      * @param width client-area size in window units, or <=0 if unchanged
      * @param height client-area size in window units, or <=0 if unchanged
      */
-    protected final void setVisibleImpl(final boolean visible, final int x, final int y, final int width, final int height) {
-        reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, visible));
+    protected final void setVisibleImpl(final boolean visible, final boolean fast, final int x, final int y, final int width, final int height) {
+        final int mask;
+        if( fast ) {
+            mask = getReconfigureMask(CHANGE_MASK_VISIBILITY | CHANGE_MASK_VISIBILITY_FAST, visible);
+        } else {
+            mask = getReconfigureMask(CHANGE_MASK_VISIBILITY, visible);
+        }
+        reconfigureWindowImpl(x, y, width, height, mask);
     }
     final void setVisibleActionImpl(final boolean visible) {
         boolean nativeWindowCreated = false;
@@ -976,14 +1128,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     madeVisible = nativeWindowCreated;
                 }
                 // always flag visible, allowing a retry ..
-                stateMask.set(STATE_VISIBLE);
-            } else if(stateMask.get(STATE_VISIBLE) != visible) {
+                stateMask.set(STATE_BIT_VISIBLE);
+            } else if(stateMask.get(STATE_BIT_VISIBLE) != visible) {
                 if(isNativeValid()) {
-                    setVisibleImpl(visible, getX(), getY(), getWidth(), getHeight());
+                    setVisibleImpl(visible /* visible */, false /* fast */, getX(), getY(), getWidth(), getHeight());
                     WindowImpl.this.waitForVisible(visible, false);
                     madeVisible = visible;
                 } else {
-                    stateMask.set(STATE_VISIBLE);
+                    stateMask.set(STATE_BIT_VISIBLE);
                 }
             }
 
@@ -1002,7 +1154,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
               }
             }
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window setVisible: END ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+stateMask.get(STATE_FULLSCREEN)+", windowHandle "+toHexString(windowHandle)+", visible: "+stateMask.get(STATE_VISIBLE)+", nativeWindowCreated: "+nativeWindowCreated+", madeVisible: "+madeVisible);
+                System.err.println("Window setVisible: END ("+getThreadName()+") state "+getStateMaskString()+
+                        ", nativeWindowCreated: "+nativeWindowCreated+", madeVisible: "+madeVisible+
+                        ", geom "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+
+                        ", windowHandle "+toHexString(windowHandle));
             }
         } finally {
             if(null!=lifecycleHook) {
@@ -1030,7 +1185,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     @Override
     public final void setVisible(final boolean wait, final boolean visible) {
         if(DEBUG_IMPLEMENTATION) {
-            System.err.println("Window setVisible: START ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+stateMask.get(STATE_FULLSCREEN)+", windowHandle "+toHexString(windowHandle)+", visible: "+stateMask.get(STATE_VISIBLE)+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow));
+            System.err.println("Window setVisible: START ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", windowHandle "+toHexString(windowHandle)+", state "+getStateMaskString()+" -> visible "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow));
         }
         runOnEDTIfAvail(wait, new VisibleAction(visible));
     }
@@ -1056,10 +1211,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             _lock.lock();
             try {
                 if ( force || ( !isFullscreen() && ( getWidth() != width || getHeight() != height ) ) ) {
-                    final boolean _visible = stateMask.get(STATE_VISIBLE);
                     if(DEBUG_IMPLEMENTATION) {
-                        System.err.println("Window setSize: START force "+force+", "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+stateMask.get(STATE_FULLSCREEN)+", windowHandle "+toHexString(windowHandle)+", visible "+_visible);
+                        System.err.println("Window setSize: START force "+force+", "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", windowHandle "+toHexString(windowHandle)+", state "+getStateMaskString());
                     }
+                    final boolean _visible = stateMask.get(STATE_BIT_VISIBLE);
                     int visibleAction; // 0 nop, 1 invisible, 2 visible (create)
                     if ( _visible && isNativeValid() && ( 0 >= width || 0 >= height ) ) {
                         visibleAction=1; // invisible
@@ -1070,7 +1225,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     } else if ( _visible && isNativeValid() ) {
                         visibleAction = 0;
                         // this width/height will be set by windowChanged, called by the native implementation
-                        reconfigureWindowImpl(getX(), getY(), width, height, getReconfigureFlags(0, isVisible()));
+                        reconfigureWindowImpl(getX(), getY(), width, height, getReconfigureMask(0, isVisible()));
                         WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW);
                     } else {
                         // invisible or invalid w/ 0 size
@@ -1222,7 +1377,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     @Override
     public void destroy() {
-        stateMask.clear(STATE_VISIBLE); // Immediately mark synchronized visibility flag, avoiding possible recreation
+        stateMask.clear(STATE_BIT_VISIBLE); // Immediately mark synchronized visibility flag, avoiding possible recreation
         runOnEDTIfAvail(true, destroyAction);
     }
 
@@ -1280,7 +1435,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 // Bug 924: Ignore reparent when in fullscreen - otherwise may confuse WM
                 if( DEBUG_IMPLEMENTATION) {
                     System.err.println("Window.reparent: NOP (in fullscreen, "+getThreadName()+") valid "+isNativeValid()+
-                                       ", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+                                       ", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+", state "+getStateMaskString());
                 }
                 return;
             }
@@ -1333,7 +1488,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 if( DEBUG_IMPLEMENTATION) {
                     System.err.println("Window.reparent: START ("+getThreadName()+") valid "+isNativeValid()+
                                        ", windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)+
-                                       ", visible "+wasVisible+", becomesVisible "+becomesVisible+
+                                       ", state "+getStateMaskString()+" -> visible "+becomesVisible+
                                        ", forceDestroyCreate "+forceDestroyCreate+
                                        ", DEBUG_TEST_REPARENT_INCOMPATIBLE "+DEBUG_TEST_REPARENT_INCOMPATIBLE+
                                        ", HINT_FORCE_RECREATION "+( 0 != ( REPARENT_HINT_FORCE_RECREATION & hints ) )+
@@ -1464,6 +1619,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     ((Window)parentWindow).removeChild(WindowImpl.this);
                 }
                 parentWindow = newParentWindow;
+                stateMask.put(STATE_BIT_CHILDWIN, null != parentWindow);
                 if(parentWindow instanceof Window) {
                     ((Window)parentWindow).addChild(WindowImpl.this);
                 }
@@ -1474,7 +1630,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
                     // TOP -> CLIENT: !visible first (fixes X11 unsuccessful return to parent window)
                     if( null != parentWindow && wasVisible && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
-                        setVisibleImpl(false, oldX, oldY, oldWidth, oldHeight);
+                        setVisibleImpl(false /* visible */, true /* fast */, oldX, oldY, oldWidth, oldHeight);
                         WindowImpl.this.waitForVisible(false, false);
                         // FIXME: Some composite WM behave slacky .. give 'em chance to change state -> invisible,
                         // even though we do exactly that (KDE+Composite)
@@ -1496,7 +1652,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     }
                     boolean ok = false;
                     try {
-                        ok = reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_PARENTING | FLAG_CHANGE_DECORATION, isVisible()));
+                        ok = reconfigureWindowImpl(x, y, width, height, getReconfigureMask(CHANGE_MASK_PARENTING | CHANGE_MASK_DECORATION, isVisible()));
                     } finally {
                         if(null!=parentWindowLocked) {
                             parentWindowLocked.unlockSurface();
@@ -1508,12 +1664,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     if(ok) {
                         display.dispatchMessagesNative(); // status up2date
                         if(wasVisible) {
-                            setVisibleImpl(true, x, y, width, height);
+                            setVisibleImpl(true /* visible */, true /* fast */, x, y, width, height);
                             ok = 0 <= WindowImpl.this.waitForVisible(true, false);
                             if(ok) {
                                 if( isAlwaysOnTop() && 0 == parentWindowHandle && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true) ) {
                                     // Reinforce ALWAYSONTOP when CHILD -> TOP reparenting, since reparenting itself cause X11 WM to loose it's state.
-                                    reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
+                                    reconfigureWindowImpl(x, y, width, height, getReconfigureMask(CHANGE_MASK_ALWAYSONTOP, isVisible()));
                                 }
                                 ok = WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW);
                             }
@@ -1547,7 +1703,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                         if( null != parentWindow ) {
                             // TOP -> CLIENT: Setup Parent's Pointer State
                             setOffscreenPointerIcon(pointerIcon);
-                            setOffscreenPointerVisible(stateMask.get(STATE_POINTERVISIBLE), pointerIcon);
+                            setOffscreenPointerVisible(stateMask.get(STATE_BIT_POINTERVISIBLE), pointerIcon);
                         }
                     }
                 } else {
@@ -1561,8 +1717,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 }
 
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("Window.reparent: END-1 ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+
-                                       ", visible: "+stateMask.get(STATE_VISIBLE)+", parentWindowHandle "+toHexString(parentWindowHandle)+
+                    System.err.println("Window.reparent: END-1 ("+getThreadName()+") state "+getStateMaskString()+
+                                       ", windowHandle "+toHexString(windowHandle)+
+                                       ", parentWindowHandle "+toHexString(parentWindowHandle)+
                                        ", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+
                                        getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
                 }
@@ -1588,8 +1745,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 }
             }
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.reparent: END-X ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+
-                                   ", visible: "+stateMask.get(STATE_VISIBLE)+", parentWindowHandle "+toHexString(parentWindowHandle)+
+                System.err.println("Window.reparent: END-X ("+getThreadName()+") state "+getStateMaskString()+
+                                   ", windowHandle "+toHexString(windowHandle)+
+                                   ", parentWindowHandle "+toHexString(parentWindowHandle)+
                                    ", parentWindow "+ Display.hashCodeNullSafe(parentWindow)+" "+
                                    getX()+"/"+getY()+" "+getWidth()+"x"+getHeight());
             }
@@ -1603,7 +1761,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             _lock.lock();
             try {
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("Window.reparent: ReparentActionRecreate ("+getThreadName()+") windowHandle "+toHexString(windowHandle)+", visible: "+stateMask.get(STATE_VISIBLE)+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+Display.hashCodeNullSafe(parentWindow));
+                    System.err.println("Window.reparent: ReparentActionRecreate ("+getThreadName()+") state "+getStateMaskString()+", windowHandle "+toHexString(windowHandle)+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+Display.hashCodeNullSafe(parentWindow));
                 }
                 setVisibleActionImpl(true); // native creation
                 requestFocusInt( 0 == parentWindowHandle /* skipFocusAction if top-level */);
@@ -1618,6 +1776,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         runOnEDTIfAvail(true, reparentAction);
         return reparentAction.getOp();
     }
+    @Override
+    public final boolean isChildWindow() {
+        return stateMask.get(STATE_BIT_CHILDWIN);
+    }
 
     @Override
     public final CapabilitiesChooser setCapabilitiesChooser(final CapabilitiesChooser chooser) {
@@ -1648,7 +1810,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             final RecursiveLock _lock = windowLock;
             _lock.lock();
             try {
-                if( stateMask.put(STATE_UNDECORATED, undecorated) != undecorated ) {
+                if( stateMask.put(STATE_BIT_UNDECORATED, undecorated) != undecorated ) {
                     if( isNativeValid() && !isFullscreen() ) {
                         // Mirror pos/size so native change notification can get overwritten
                         final int x = getX();
@@ -1658,7 +1820,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
                         final DisplayImpl display = (DisplayImpl) screen.getDisplay();
                         display.dispatchMessagesNative(); // status up2date
-                        reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_DECORATION, isVisible()));
+                        reconfigureWindowImpl(x, y, width, height, getReconfigureMask(CHANGE_MASK_DECORATION, isVisible()));
                         display.dispatchMessagesNative(); // status up2date
                     }
                 }
@@ -1673,10 +1835,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     public final void setUndecorated(final boolean value) {
         runOnEDTIfAvail(true, new DecorationAction(value));
     }
-
     @Override
     public final boolean isUndecorated() {
-        return 0 != parentWindowHandle || stateMask.get(STATE_UNDECORATED) || stateMask.get(STATE_FULLSCREEN) ;
+        return isUndecorated(getStateMask());
+    }
+    private static final boolean isUndecorated(final int smask) {
+        return 0 != ( smask & ( STATE_MASK_CHILDWIN | STATE_MASK_UNDECORATED | STATE_MASK_FULLSCREEN ) );
     }
 
     private class AlwaysOnTopAction implements Runnable {
@@ -1691,7 +1855,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             final RecursiveLock _lock = windowLock;
             _lock.lock();
             try {
-                if( stateMask.put(STATE_ALWAYSONTOP, alwaysOnTop) != alwaysOnTop ) {
+                if( stateMask.put(STATE_BIT_ALWAYSONTOP, alwaysOnTop) != alwaysOnTop ) {
                     if( isNativeValid() ) {
                         // Mirror pos/size so native change notification can get overwritten
                         final int x = getX();
@@ -1701,7 +1865,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
                         final DisplayImpl display = (DisplayImpl) screen.getDisplay();
                         display.dispatchMessagesNative(); // status up2date
-                        reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
+                        reconfigureWindowImpl(x, y, width, height, getReconfigureMask(CHANGE_MASK_ALWAYSONTOP, isVisible()));
                         display.dispatchMessagesNative(); // status up2date
                     }
                 }
@@ -1711,19 +1875,222 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
         }
     }
-
     @Override
     public final void setAlwaysOnTop(final boolean value) {
+        if( isChildWindow() ) {
+            return; // ignore for child windows
+        }
         if( isFullscreen() ) {
-            stateMask.put(STATE_FULLSCREEN_NFS_ALWAYSONTOP, value);
+            if( value && isAlwaysOnBottom() ) {
+                setAlwaysOnBottom(false);
+            }
+            stateMask.put(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP, value);
         } else {
+            if( value && isAlwaysOnBottom() ) {
+                setAlwaysOnBottom(false);
+            }
             runOnEDTIfAvail(true, new AlwaysOnTopAction(value));
         }
     }
-
     @Override
     public final boolean isAlwaysOnTop() {
-        return stateMask.get(STATE_ALWAYSONTOP);
+        return stateMask.get(STATE_BIT_ALWAYSONTOP);
+    }
+
+    private class AlwaysOnBottomAction implements Runnable {
+        boolean alwaysOnBottom;
+
+        private AlwaysOnBottomAction(final boolean alwaysOnBottom) {
+            this.alwaysOnBottom = alwaysOnBottom;
+        }
+
+        @Override
+        public final void run() {
+            final RecursiveLock _lock = windowLock;
+            _lock.lock();
+            try {
+                if( stateMask.put(STATE_BIT_ALWAYSONBOTTOM, alwaysOnBottom) != alwaysOnBottom ) {
+                    if( isNativeValid() ) {
+                        // Mirror pos/size so native change notification can get overwritten
+                        final int x = getX();
+                        final int y = getY();
+                        final int width = getWidth();
+                        final int height = getHeight();
+
+                        final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+                        display.dispatchMessagesNative(); // status up2date
+                        reconfigureWindowImpl(x, y, width, height, getReconfigureMask(CHANGE_MASK_ALWAYSONBOTTOM, isVisible()));
+                        display.dispatchMessagesNative(); // status up2date
+                    }
+                }
+            } finally {
+                _lock.unlock();
+            }
+            sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
+        }
+    }
+    @Override
+    public final void setAlwaysOnBottom(final boolean value) {
+        if( isChildWindow() ) {
+            return; // ignore for child windows
+        }
+        if( value && isAlwaysOnTop() ) {
+            setAlwaysOnTop(false);
+        }
+        runOnEDTIfAvail(true, new AlwaysOnBottomAction(value));
+    }
+    @Override
+    public final boolean isAlwaysOnBottom() {
+        return stateMask.get(STATE_BIT_ALWAYSONBOTTOM);
+    }
+
+    private class ResizableAction implements Runnable {
+        boolean resizable;
+
+        private ResizableAction(final boolean resizable) {
+            this.resizable = resizable;
+        }
+
+        @Override
+        public final void run() {
+            final RecursiveLock _lock = windowLock;
+            _lock.lock();
+            try {
+                if( stateMask.put(STATE_BIT_RESIZABLE, resizable) != resizable ) {
+                    if( isNativeValid() ) {
+                        // Mirror pos/size so native change notification can get overwritten
+                        final int x = getX();
+                        final int y = getY();
+                        final int width = getWidth();
+                        final int height = getHeight();
+
+                        final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+                        display.dispatchMessagesNative(); // status up2date
+                        reconfigureWindowImpl(x, y, width, height, getReconfigureMask(CHANGE_MASK_RESIZABLE, isVisible()));
+                        display.dispatchMessagesNative(); // status up2date
+                    }
+                }
+            } finally {
+                _lock.unlock();
+            }
+            sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
+        }
+    }
+    @Override
+    public final void setResizable(final boolean value) {
+        if( isChildWindow() ) {
+            return; // ignore for child windows
+        }
+        if( isFullscreen() ) {
+            stateMask.put(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE, value);
+        } else {
+            runOnEDTIfAvail(true, new ResizableAction(value));
+        }
+    }
+    @Override
+    public final boolean isResizable() {
+        return stateMask.get(STATE_BIT_RESIZABLE);
+    }
+
+    private class StickyAction implements Runnable {
+        boolean sticky;
+
+        private StickyAction(final boolean sticky) {
+            this.sticky = sticky;
+        }
+
+        @Override
+        public final void run() {
+            final RecursiveLock _lock = windowLock;
+            _lock.lock();
+            try {
+                if( stateMask.put(STATE_BIT_STICKY, sticky) != sticky ) {
+                    if( isNativeValid() ) {
+                        // Mirror pos/size so native change notification can get overwritten
+                        final int x = getX();
+                        final int y = getY();
+                        final int width = getWidth();
+                        final int height = getHeight();
+
+                        final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+                        display.dispatchMessagesNative(); // status up2date
+                        reconfigureWindowImpl(x, y, width, height, getReconfigureMask(CHANGE_MASK_STICKY, isVisible()));
+                        display.dispatchMessagesNative(); // status up2date
+                    }
+                }
+            } finally {
+                _lock.unlock();
+            }
+            sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
+        }
+    }
+    @Override
+    public final void setSticky(final boolean value) {
+        if( isChildWindow() ) {
+            return; // ignore for child windows
+        }
+        runOnEDTIfAvail(true, new StickyAction(value));
+    }
+    @Override
+    public final boolean isSticky() {
+        return stateMask.get(STATE_BIT_STICKY);
+    }
+
+    private class MaximizeAction implements Runnable {
+        boolean horz, vert;
+
+        private MaximizeAction(final boolean horz, final boolean vert) {
+            this.horz = horz;
+            this.vert = vert;
+        }
+
+        @Override
+        public final void run() {
+            final RecursiveLock _lock = windowLock;
+            _lock.lock();
+            try {
+                int cmask = 0;
+                if( stateMask.put(STATE_BIT_MAXIMIZED_VERT, vert) != vert ) {
+                    cmask |= CHANGE_MASK_MAXIMIZED_VERT;
+                }
+                if( stateMask.put(STATE_BIT_MAXIMIZED_HORZ, horz) != horz ) {
+                    cmask |= CHANGE_MASK_MAXIMIZED_HORZ;
+                }
+                if( 0 != cmask ) {
+                    if( isNativeValid() ) {
+                        // Mirror pos/size so native change notification can get overwritten
+                        final int x = getX();
+                        final int y = getY();
+                        final int width = getWidth();
+                        final int height = getHeight();
+
+                        final DisplayImpl display = (DisplayImpl) screen.getDisplay();
+                        display.dispatchMessagesNative(); // status up2date
+
+                        reconfigureWindowImpl(x, y, width, height, getReconfigureMask(cmask, isVisible()));
+                        display.dispatchMessagesNative(); // status up2date
+                    }
+                }
+            } finally {
+                _lock.unlock();
+            }
+            sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener
+        }
+    }
+    @Override
+    public final void setMaximized(final boolean horz, final boolean vert) {
+        if( isChildWindow() || isFullscreen() ) {
+            return; // ignore for child windows
+        }
+        runOnEDTIfAvail(true, new MaximizeAction(horz, vert));
+    }
+    @Override
+    public final boolean isMaximizedVert() {
+        return stateMask.get(STATE_BIT_MAXIMIZED_VERT);
+    }
+    @Override
+    public final boolean isMaximizedHorz() {
+        return stateMask.get(STATE_BIT_MAXIMIZED_HORZ);
     }
 
     @Override
@@ -1743,17 +2110,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     @Override
     public final boolean isPointerVisible() {
-        return stateMask.get(STATE_POINTERVISIBLE);
+        return stateMask.get(STATE_BIT_POINTERVISIBLE);
     }
     @Override
     public final void setPointerVisible(final boolean pointerVisible) {
-        if(stateMask.get(STATE_POINTERVISIBLE) != pointerVisible) {
+        if(stateMask.get(STATE_BIT_POINTERVISIBLE) != pointerVisible) {
             boolean setVal = 0 == getWindowHandle();
             if(!setVal) {
                 setVal = setPointerVisibleIntern(pointerVisible);
             }
             if(setVal) {
-                stateMask.put(STATE_POINTERVISIBLE, pointerVisible);
+                stateMask.put(STATE_BIT_POINTERVISIBLE, pointerVisible);
             }
         }
     }
@@ -1853,11 +2220,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     @Override
     public final boolean isPointerConfined() {
-        return stateMask.get(STATE_POINTERCONFINED);
+        return stateMask.get(STATE_BIT_POINTERCONFINED);
     }
     @Override
     public final void confinePointer(final boolean confine) {
-        if(stateMask.get(STATE_POINTERCONFINED) != confine) {
+        if(stateMask.get(STATE_BIT_POINTERCONFINED) != confine) {
             boolean setVal = 0 == getWindowHandle();
             if(!setVal) {
                 if(confine) {
@@ -1874,7 +2241,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 }
             }
             if(setVal) {
-                stateMask.put(STATE_POINTERCONFINED, confine);
+                stateMask.put(STATE_BIT_POINTERCONFINED, confine);
             }
         }
     }
@@ -1996,7 +2363,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         return ppmmStore;
     }
 
-    protected final boolean autoPosition() { return stateMask.get(STATE_AUTOPOSITION); }
+    protected final boolean autoPosition() { return stateMask.get(STATE_BIT_AUTOPOSITION); }
 
     /** Sets the position fields {@link #x} and {@link #y} in window units to the given values and {@link #autoPosition} to false. */
     protected final void definePosition(final int x, final int y) {
@@ -2004,7 +2371,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             System.err.println("definePosition: "+this.x+"/"+this.y+" -> "+x+"/"+y);
             // ExceptionUtils.dumpStackTrace(System.err);
         }
-        stateMask.clear(STATE_AUTOPOSITION);
+        stateMask.clear(STATE_BIT_AUTOPOSITION);
         this.x = x; this.y = y;
     }
 
@@ -2013,7 +2380,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
      * and {@link #pixWidth} and {@link #pixHeight} in pixel units according to {@link #convertToPixelUnits(int[])}.
      */
     protected final void defineSize(final int winWidth, final int winHeight) {
-        final int pixWidth = SurfaceScaleUtils.scale(winWidth, getPixelScaleX());   // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology
+        // FIXME HiDPI: Shortcut, may need to adjust if we change scaling methodology
+        final int pixWidth = SurfaceScaleUtils.scale(winWidth, getPixelScaleX());
         final int pixHeight = SurfaceScaleUtils.scale(winHeight, getPixelScaleY());
 
         if(DEBUG_IMPLEMENTATION) {
@@ -2027,12 +2395,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     @Override
     public final boolean isVisible() {
-        return stateMask.get(STATE_VISIBLE);
+        return stateMask.get(STATE_BIT_VISIBLE);
     }
 
     @Override
     public final boolean isFullscreen() {
-        return stateMask.get(STATE_FULLSCREEN);
+        return stateMask.get(STATE_BIT_FULLSCREEN);
     }
 
     //----------------------------------------------------------------------
@@ -2087,16 +2455,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     public final String toString() {
         final StringBuilder sb = new StringBuilder();
 
-        sb.append(getClass().getName()+"[Config "+config+
+        sb.append(getClass().getName()+"[State "+getStateMaskString()+
                     ",\n "+screen+
+                    ",\n window["+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" wu, "+getSurfaceWidth()+"x"+getSurfaceHeight()+" pixel]"+
+                    ",\n Config "+config+
                     ",\n ParentWindow "+parentWindow+
                     ",\n ParentWindowHandle "+toHexString(parentWindowHandle)+" ("+(0!=getParentWindowHandle())+")"+
                     ",\n WindowHandle "+toHexString(getWindowHandle())+
                     ",\n SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+windowLock.isLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+
-                    ",\n window["+getX()+"/"+getY()+" (auto "+autoPosition()+") "+getWidth()+"x"+getHeight()+"], pixel["+getSurfaceWidth()+"x"+getSurfaceHeight()+
-                    "],\n Visible "+isVisible()+", focus "+hasFocus()+
-                    ",\n Undecorated "+stateMask.get(STATE_UNDECORATED)+" ("+isUndecorated()+")"+
-                    ",\n AlwaysOnTop "+stateMask.get(STATE_ALWAYSONTOP)+", Fullscreen "+stateMask.get(STATE_FULLSCREEN)+
                     ",\n WrappedSurface "+getWrappedSurface()+
                     ",\n ChildWindows "+childWindows.size());
 
@@ -2141,7 +2507,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         @Override
         public final void run() {
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.RequestFocusAction: force 0 - ("+getThreadName()+"): "+stateMask.get(STATE_FOCUSED)+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+                System.err.println("Window.RequestFocusAction: force 0 - ("+getThreadName()+"): state "+getStateMaskString()+" -> focus true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
             }
             WindowImpl.this.requestFocusImpl(false);
         }
@@ -2150,7 +2516,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         @Override
         public final void run() {
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.RequestFocusAction: force 1 - ("+getThreadName()+"): "+stateMask.get(STATE_FOCUSED)+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+                System.err.println("Window.RequestFocusAction: force 1 - ("+getThreadName()+"): state "+getStateMaskString()+" -> focus true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
             }
             WindowImpl.this.requestFocusImpl(true);
         }
@@ -2158,7 +2524,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     @Override
     public final boolean hasFocus() {
-        return stateMask.get(STATE_FOCUSED);
+        return stateMask.get(STATE_BIT_FOCUSED);
     }
 
     @Override
@@ -2168,7 +2534,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     @Override
     public final void requestFocus(final boolean wait) {
-        requestFocus(wait /* wait */, false /* skipFocusAction */, stateMask.get(STATE_FOCUS_CHANGE_BROKEN) /* force */);
+        requestFocus(wait /* wait */, false /* skipFocusAction */, stateMask.get(PSTATE_BIT_FOCUS_CHANGE_BROKEN) /* force */);
     }
 
     private void requestFocus(final boolean wait, final boolean skipFocusAction, final boolean force) {
@@ -2183,7 +2549,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     private void requestFocusInt(final boolean skipFocusAction) {
         if( skipFocusAction || !focusAction() ) {
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.RequestFocusInt: forcing - ("+getThreadName()+"): skipFocusAction "+skipFocusAction+", focus "+stateMask.get(STATE_FOCUSED)+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+                System.err.println("Window.RequestFocusInt: forcing - ("+getThreadName()+"): skipFocusAction "+
+                        skipFocusAction+", state "+getStateMaskString()+" -> focus true - windowHandle "+
+                        toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
             }
             requestFocusImpl(true);
         }
@@ -2211,7 +2579,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
     }
 
     protected final void setBrokenFocusChange(final boolean v) {
-        stateMask.put(STATE_FOCUS_CHANGE_BROKEN, v);
+        stateMask.put(PSTATE_BIT_FOCUS_CHANGE_BROKEN, v);
     }
 
     @Override
@@ -2233,13 +2601,13 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             _lock.lock();
             try {
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("Window setPosition: "+getX()+"/"+getY()+" -> "+x+"/"+y+", fs "+stateMask.get(STATE_FULLSCREEN)+", windowHandle "+toHexString(windowHandle));
+                    System.err.println("Window setPosition: "+getX()+"/"+getY()+" -> "+x+"/"+y+", fs "+stateMask.get(STATE_BIT_FULLSCREEN)+", windowHandle "+toHexString(windowHandle));
                 }
                 // Let the window be positioned if !fullscreen and position changed or being a child window.
                 if ( !isFullscreen() && ( getX() != x || getY() != y || null != getParent()) ) {
                     if(isNativeValid()) {
                         // this.x/this.y will be set by sizeChanged, triggered by windowing event system
-                        reconfigureWindowImpl(x, y, getWidth(), getHeight(), getReconfigureFlags(0, isVisible()));
+                        reconfigureWindowImpl(x, y, getWidth(), getHeight(), getReconfigureMask(0, isVisible()));
                         if( null == parentWindow ) {
                             // Wait until custom position is reached within tolerances
                             waitForPosition(true, x, y, Window.TIMEOUT_NATIVEWINDOW);
@@ -2256,7 +2624,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     @Override
     public void setPosition(final int x, final int y) {
-        stateMask.clear(STATE_AUTOPOSITION);
+        stateMask.clear(STATE_BIT_AUTOPOSITION);
         runOnEDTIfAvail(true, new SetPositionAction(x, y));
     }
 
@@ -2273,7 +2641,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 this._fullscreen = fullscreen;
                 return isFullscreen() != fullscreen;
             } else {
-                stateMask.put(STATE_FULLSCREEN, fullscreen); // set current state for createNative(..)
+                stateMask.put(STATE_BIT_FULLSCREEN, fullscreen); // set current state for createNative(..)
                 return false;
             }
         }
@@ -2294,11 +2662,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
                 final RectangleImmutable sviewport = screen.getViewportInWindowUnits(); // window units
                 final RectangleImmutable viewport; // window units
-                final int fs_span_flag;
-                final boolean alwaysOnTopChange;
+                final boolean alwaysOnTopChange, resizableChange;
                 if(_fullscreen) {
                     if( null == fullscreenMonitors ) {
-                        if( stateMask.get(STATE_FULLSCREEN_MAINMONITOR) ) {
+                        if( stateMask.get(PSTATE_BIT_FULLSCREEN_MAINMONITOR) ) {
                             fullscreenMonitors = new ArrayList<MonitorDevice>();
                             fullscreenMonitors.add( getMainMonitor() );
                         } else {
@@ -2310,34 +2677,42 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                         MonitorDevice.unionOfViewports(null, viewportInWindowUnits, fullscreenMonitors);
                         viewport = viewportInWindowUnits;
                     }
-                    if( isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN) &&
+                    if( isReconfigureMaskSupported(STATE_MASK_FULLSCREEN_SPAN) &&
                         ( fullscreenMonitors.size() > 1 || sviewport.compareTo(viewport) > 0 ) ) {
-                        fs_span_flag = FLAG_IS_FULLSCREEN_SPAN;
+                        stateMask.set(STATE_BIT_FULLSCREEN_SPAN);
                     } else {
-                        fs_span_flag = 0;
+                        stateMask.clear(STATE_BIT_FULLSCREEN_SPAN);
                     }
                     nfs_x = oldX;
                     nfs_y = oldY;
                     nfs_width = oldWidth;
                     nfs_height = oldHeight;
-                    stateMask.copy(STATE_ALWAYSONTOP, STATE_FULLSCREEN_NFS_ALWAYSONTOP);
+                    stateMask.copy(STATE_BIT_ALWAYSONTOP, PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP);
+                    stateMask.copy(STATE_BIT_RESIZABLE, PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE);
                     x = viewport.getX();
                     y = viewport.getY();
                     w = viewport.getWidth();
                     h = viewport.getHeight();
-                    stateMask.clear(STATE_ALWAYSONTOP);
-                    alwaysOnTopChange = stateMask.get(STATE_FULLSCREEN_NFS_ALWAYSONTOP); // != stateMask.get(STATE_ALWAYSONTOP);
+                    stateMask.clear(STATE_BIT_ALWAYSONTOP); // special aontop handling for fullscreen
+                    stateMask.set(STATE_BIT_RESIZABLE);     // allow fullscreen to resize to max
+                    alwaysOnTopChange = stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP);
+                    resizableChange = !stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE);
                 } else {
-                    stateMask.set(STATE_FULLSCREEN_MAINMONITOR);
+                    stateMask.set(PSTATE_BIT_FULLSCREEN_MAINMONITOR);
                     fullscreenMonitors = null;
-                    fs_span_flag = 0;
+                    stateMask.clear(STATE_BIT_FULLSCREEN_SPAN);
                     viewport = null;
                     x = nfs_x;
                     y = nfs_y;
                     w = nfs_width;
                     h = nfs_height;
-                    alwaysOnTopChange = stateMask.get(STATE_FULLSCREEN_NFS_ALWAYSONTOP) != stateMask.get(STATE_ALWAYSONTOP);
-                    stateMask.copy(STATE_FULLSCREEN_NFS_ALWAYSONTOP, STATE_ALWAYSONTOP);
+                    alwaysOnTopChange = stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP) != stateMask.get(STATE_BIT_ALWAYSONTOP);
+                    // alwaysOnBottomChange = stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONBOTTOM) != stateMask.get(STATE_BIT_ALWAYSONBOTTOM);
+                    resizableChange = stateMask.get(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE) != stateMask.get(STATE_BIT_RESIZABLE);
+                    stateMask.copy(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP, STATE_BIT_ALWAYSONTOP);
+                    stateMask.copy(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE, STATE_BIT_RESIZABLE);
+                    stateMask.clear(PSTATE_BIT_FULLSCREEN_NFS_ALWAYSONTOP);
+                    stateMask.set(PSTATE_BIT_FULLSCREEN_NFS_RESIZABLE);
 
                     if(null!=parentWindow) {
                         // reset position to 0/0 within parent space
@@ -2360,18 +2735,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 final boolean tempInvisible = !_fullscreen && wasVisible && NativeWindowFactory.TYPE_X11 == NativeWindowFactory.getNativeWindowType(true);
 
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("Window fs: "+_fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+
+                    System.err.println("Window "+x+"/"+y+" "+w+"x"+h+
                                        ", virtl-screenSize: "+sviewport+" [wu], monitorsViewport "+viewport+" [wu]"+
-                                       ", spanning "+(0!=fs_span_flag)+
-                                       ", alwaysOnTop "+stateMask.get(STATE_ALWAYSONTOP)+(alwaysOnTopChange?"*":"")+
                                        ", wasVisible "+wasVisible+", tempInvisible "+tempInvisible+
                                        ", hasParent "+(null!=parentWindow)+
+                                       ", state "+getStateMaskString()+
                                        " @ "+Thread.currentThread().getName());
                 }
 
                 // fullscreen off: !visible first (fixes X11 unsuccessful return to parent window _and_ wrong window size propagation)
                 if( tempInvisible ) {
-                    setVisibleImpl(false, oldX, oldY, oldWidth, oldHeight);
+                    setVisibleImpl(false /* visible */, true /* fast */, oldX, oldY, oldWidth, oldHeight);
                     WindowImpl.this.waitForVisible(false, false);
                     try { Thread.sleep(100); } catch (final InterruptedException e) { }
                     display.dispatchMessagesNative(); // status up2date
@@ -2387,20 +2761,28 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 } else {
                     parentWindowLocked = null;
                 }
+                final int changeMask;
                 try {
-                    if(alwaysOnTopChange && _fullscreen) {
-                        // Enter fullscreen - Disable alwaysOnTop
-                        reconfigureWindowImpl(oldX, oldY, oldWidth, oldHeight, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
+                    {
+                        // Enter fullscreen - Disable alwaysOnTop/alwaysOnBottom/resizableChange
+                        int cm = 0;
+                        if( alwaysOnTopChange ) {
+                            cm = CHANGE_MASK_ALWAYSONTOP;
+                        }
+                        if( resizableChange ) {
+                            cm |= CHANGE_MASK_RESIZABLE;
+                        }
+                        changeMask = cm;
+                    }
+                    if( _fullscreen && 0 != changeMask ) {
+                        // Enter fullscreen - Disable alwaysOnTop/alwaysOnBottom/resizableChange
+                        reconfigureWindowImpl(oldX, oldY, oldWidth, oldHeight, getReconfigureMask(changeMask, isVisible()));
                     }
 
-                    stateMask.put(STATE_FULLSCREEN, _fullscreen);
+                    stateMask.put(STATE_BIT_FULLSCREEN, _fullscreen);
                     reconfigureWindowImpl(x, y, w, h,
-                                          getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) |
-                                                               fs_span_flag | FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, isVisible()) );
-                    if(alwaysOnTopChange && !_fullscreen) {
-                        // Leave fullscreen - Restore alwaysOnTop
-                        reconfigureWindowImpl(x, y, w, h, getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()));
-                    }
+                                          getReconfigureMask( ( ( null != parentWindowLocked ) ? CHANGE_MASK_PARENTING : 0 ) |
+                                                               CHANGE_MASK_FULLSCREEN | CHANGE_MASK_DECORATION, isVisible()) );
                 } finally {
                     if(null!=parentWindowLocked) {
                         parentWindowLocked.unlockSurface();
@@ -2414,7 +2796,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                         try { Thread.sleep(100); } catch (final InterruptedException e) { }
                         display.dispatchMessagesNative(); // status up2date
                     }
-                    setVisibleImpl(true, x, y, w, h);
+                    setVisibleImpl(true /* visible */, true /* fast */, x, y, w, h);
                     boolean ok = 0 <= WindowImpl.this.waitForVisible(true, false);
                     if(ok) {
                         ok = WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW);
@@ -2423,6 +2805,21 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                         // Position mismatch shall not lead to fullscreen failure
                         WindowImpl.this.waitForPosition(true, x, y, TIMEOUT_NATIVEWINDOW);
                     }
+                    if( ok ) {
+                        // Restore certain states ..
+                        if( !_fullscreen && 0 != changeMask ) {
+                            // Restore alwaysOnTop/resizableChange when leaving fullscreen
+                            reconfigureWindowImpl(x, y, w, h, getReconfigureMask(changeMask, isVisible()));
+                        }
+                        if( isAlwaysOnBottom() ) {
+                            // Re-Init alwaysOnBottom always
+                            reconfigureWindowImpl(x, y, w, h, getReconfigureMask(CHANGE_MASK_ALWAYSONBOTTOM, isVisible()));
+                        }
+                        if( isSticky() ) {
+                            // Re-Init sticky always
+                            reconfigureWindowImpl(x, y, w, h, getReconfigureMask(CHANGE_MASK_STICKY, isVisible()));
+                        }
+                    }
                     if(ok) {
                         requestFocusInt(_fullscreen /* skipFocusAction if fullscreen */);
                         display.dispatchMessagesNative(); // status up2date
@@ -2454,7 +2851,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         synchronized(fullScreenAction) {
             fullscreenMonitors = monitors;
 
-            stateMask.put(STATE_FULLSCREEN_MAINMONITOR, useMainMonitor);
+            stateMask.put(PSTATE_BIT_FULLSCREEN_MAINMONITOR, useMainMonitor);
             if( fullScreenAction.init(fullscreen) ) {
                 if( fullScreenAction.fsOn() && isOffscreenInstance(WindowImpl.this, parentWindow) ) {
                     // enable fullscreen on offscreen instance
@@ -2474,7 +2871,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                     nfs_parent = null;
                 }
             }
-            return stateMask.get(STATE_FULLSCREEN);
+            return stateMask.get(STATE_BIT_FULLSCREEN);
         }
     }
 
@@ -2493,9 +2890,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         @Override
         public void monitorModeChangeNotify(final MonitorEvent me) {
             hadFocus = hasFocus();
-            final boolean fullscreen = stateMask.get(STATE_FULLSCREEN);
+            final boolean fullscreen = stateMask.get(STATE_BIT_FULLSCREEN);
             final boolean isOSX = NativeWindowFactory.TYPE_MACOSX == NativeWindowFactory.getNativeWindowType(true);
-            final boolean quirkFSPause = fullscreen && isReconfigureFlagSupported(FLAG_IS_FULLSCREEN_SPAN);
+            final boolean quirkFSPause = fullscreen && isReconfigureMaskSupported(STATE_MASK_FULLSCREEN_SPAN);
             final boolean quirkHide = !quirkFSPause && !fullscreen && isVisible() && isOSX;
             if(DEBUG_IMPLEMENTATION) {
                 System.err.println("Window.monitorModeChangeNotify: hadFocus "+hadFocus+", qFSPause "+quirkFSPause+", qHide "+quirkHide+", "+me+" @ "+Thread.currentThread().getName());
@@ -2510,7 +2907,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 }
                 fullscreenPaused = true;
                 _fullscreenMonitors = fullscreenMonitors;
-                _fullscreenUseMainMonitor = stateMask.get(STATE_FULLSCREEN_MAINMONITOR);
+                _fullscreenUseMainMonitor = stateMask.get(PSTATE_BIT_FULLSCREEN_MAINMONITOR);
                 setFullscreenImpl(false, true, null);
             }
             if( quirkHide ) {
@@ -2527,7 +2924,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 // Didn't pass above notify method. probably detected screen change after it happened.
                 animatorPaused = lifecycleHook.pauseRenderingAction();
             }
-            final boolean fullscreen = stateMask.get(STATE_FULLSCREEN);
+            final boolean fullscreen = stateMask.get(STATE_BIT_FULLSCREEN);
             if(DEBUG_IMPLEMENTATION) {
                 System.err.println("Window.monitorModeChanged.0: success: "+success+", hadFocus "+hadFocus+", animPaused "+animatorPaused+
                                    ", hidden "+hidden+", FS "+fullscreen+", FS-paused "+fullscreenPaused+
@@ -3714,15 +4111,32 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         }
     }
 
+    /** Triggered by implementation's WM events to update the position. */
+    protected final void minMaxSizeChanged(final int min_width, final int min_height, final int max_width, final int max_height) {
+        if( 0 <= min_width && 0 <= min_height && 0 <= max_width && 0 <= max_height) {
+            final RectangleImmutable sz = new Rectangle(min_width, min_height, max_width, max_height);
+            if( !minmax_size.equals(sz) ) {
+                stateMask.put(PSTATE_BIT_MINMAXSIZE_SET, !sz.equals(undefSize));
+                if(DEBUG_IMPLEMENTATION) {
+                    System.err.println("Window.minMaxSizeChanged: ("+getThreadName()+"): Current "+minmax_size+" -> "+sz);
+                }
+                minmax_size.set(sz);
+            }
+        }
+    }
+
     /** Triggered by implementation's WM events to update the focus state. */
     protected void focusChanged(final boolean defer, final boolean focusGained) {
-        if( stateMask.get(STATE_FOCUS_CHANGE_BROKEN) ||
-            stateMask.get(STATE_FOCUSED) != focusGained )
+        if( stateMask.get(PSTATE_BIT_FOCUS_CHANGE_BROKEN) ||
+            stateMask.get(STATE_BIT_FOCUSED) != focusGained )
         {
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.focusChanged: ("+getThreadName()+"): (defer: "+defer+") "+stateMask.get(STATE_FOCUSED)+" -> "+focusGained+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+                System.err.println("Window.focusChanged: ("+getThreadName()+"): (defer: "+defer+") state "+
+                        getStateMaskString()+" -> focus "+focusGained+
+                        " - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+
+                        toHexString(parentWindowHandle));
             }
-            stateMask.put(STATE_FOCUSED, focusGained);
+            stateMask.put(STATE_BIT_FOCUSED, focusGained);
             final int evt = focusGained ? WindowEvent.EVENT_WINDOW_GAINED_FOCUS : WindowEvent.EVENT_WINDOW_LOST_FOCUS ;
             if(!defer) {
                 sendWindowEvent(evt);
@@ -3734,9 +4148,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
 
     /** Triggered by implementation's WM events to update the visibility state. */
     protected final void visibleChanged(final boolean defer, final boolean visible) {
-        if( stateMask.put(STATE_VISIBLE, visible) != visible ) {
+        if( stateMask.put(STATE_BIT_VISIBLE, visible) != visible ) {
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("Window.visibleChanged ("+getThreadName()+"): (defer: "+defer+") "+(!visible)+" -> "+visible+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
+                System.err.println("Window.visibleChanged ("+getThreadName()+"): (defer: "+defer+") visible "+(!visible)+" -> state "+getStateMaskString()+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
             }
         }
     }
@@ -3751,11 +4165,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
         final DisplayImpl display = (DisplayImpl) screen.getDisplay();
         display.dispatchMessagesNative(); // status up2date
         long remaining;
-        boolean _visible = stateMask.get(STATE_VISIBLE);
+        boolean _visible = stateMask.get(STATE_BIT_VISIBLE);
         for(remaining = timeOut; 0 < remaining && _visible != visible; remaining-=10 ) {
             try { Thread.sleep(10); } catch (final InterruptedException ie) {}
             display.dispatchMessagesNative(); // status up2date
-            _visible = stateMask.get(STATE_VISIBLE);
+            _visible = stateMask.get(STATE_BIT_VISIBLE);
         }
         if( visible != _visible ) {
             final String msg = "Visibility not reached as requested within "+timeOut+"ms : requested "+visible+", is "+_visible;
@@ -3794,6 +4208,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             if(DEBUG_IMPLEMENTATION) {
                 System.err.println("Window.sizeChanged: ("+getThreadName()+"): (defer: "+defer+") force "+force+", "+
                                    getWidth()+"x"+getHeight()+" -> "+newWidth+"x"+newHeight+
+                                   ", state "+getStateMaskString()+
                                    " - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle));
             }
             if(0>newWidth || 0>newHeight) {
@@ -3845,7 +4260,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
                 enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED);
             }
         } else {
-            stateMask.clear(STATE_AUTOPOSITION); // ensure it's off even w/ same position
+            stateMask.clear(STATE_BIT_AUTOPOSITION); // ensure it's off even w/ same position
         }
     }
 
@@ -3870,7 +4285,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer
             if( useCustomPosition ) {
                 ok = Math.abs(x - getX()) <= maxDX && Math.abs(y - getY()) <= maxDY ;
             } else {
-                _autopos = stateMask.get(STATE_AUTOPOSITION);
+                _autopos = stateMask.get(STATE_BIT_AUTOPOSITION);
                 ok = !_autopos;
             }
             if( !ok ) {
index 8522bb9..83832ee 100644 (file)
@@ -29,7 +29,6 @@
 package jogamp.newt.driver.android;
 
 import jogamp.common.os.android.StaticContext;
-import jogamp.newt.WindowImpl;
 import jogamp.newt.driver.android.event.AndroidNewtEventFactory;
 import jogamp.newt.driver.android.event.AndroidNewtEventTranslator;
 
@@ -41,7 +40,6 @@ import com.jogamp.nativewindow.NativeWindowException;
 import com.jogamp.nativewindow.VisualIDHolder;
 import com.jogamp.nativewindow.util.Insets;
 import com.jogamp.nativewindow.util.Point;
-import com.jogamp.nativewindow.util.Rectangle;
 import com.jogamp.nativewindow.util.RectangleImmutable;
 import com.jogamp.opengl.GLCapabilitiesChooser;
 import com.jogamp.opengl.GLCapabilitiesImmutable;
@@ -460,7 +458,7 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
     protected final boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
         boolean res = true;
 
-        if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
+        if( 0 != ( CHANGE_MASK_FULLSCREEN & flags) ) {
             Log.d(MD.TAG, "reconfigureWindowImpl.setFullscreen post creation (setContentView()) n/a");
             return false;
         }
@@ -480,8 +478,8 @@ public class WindowDriver extends jogamp.newt.WindowImpl implements Callback2 {
                 definePosition(x, y);
             }
         }
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) {
+            visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
         }
         return res;
     }
index 9f776ef..edc8843 100644 (file)
@@ -144,7 +144,7 @@ public class WindowDriver extends WindowImpl {
             new AWTWindowAdapter(new LocalWindowListener(), this).addTo(awtCanvas); // fwd all AWT Window events to here
         }
 
-        reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true));
+        reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureMask(CHANGE_MASK_VISIBILITY | CHANGE_MASK_DECORATION, true));
         // throws exception if failed ..
 
         final NativeWindow nw = awtCanvas.getNativeWindow();
@@ -234,9 +234,9 @@ public class WindowDriver extends WindowImpl {
     protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
         if(DEBUG_IMPLEMENTATION) {
             System.err.println("AWTWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
-                               getReconfigureFlagsAsString(null, flags));
+                               getReconfigStateMaskString(flags));
         }
-        if(0 != ( FLAG_CHANGE_DECORATION & flags) && null!=awtFrame) {
+        if(0 != ( CHANGE_MASK_DECORATION & flags) && null!=awtFrame) {
             if(!awtContainer.isDisplayable()) {
                 awtFrame.setUndecorated(isUndecorated());
             } else {
@@ -246,8 +246,8 @@ public class WindowDriver extends WindowImpl {
             }
         }
 
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            if( 0 != ( FLAG_IS_VISIBLE & flags) ) {
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) {
+            if( 0 != ( STATE_MASK_VISIBLE & flags) ) {
                 setCanvasSizeImpl(width, height);
                 awtContainer.setVisible( true );
             } else {
@@ -266,8 +266,8 @@ public class WindowDriver extends WindowImpl {
             awtContainer.setLocation(x, y);
         }
 
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            if( 0 != ( FLAG_IS_VISIBLE & flags ) ) {
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) {
+            if( 0 != ( STATE_MASK_VISIBLE & flags ) ) {
                 if( !hasDeviceChanged() ) {
                     // oops ??
                     final AWTGraphicsConfiguration cfg = awtCanvas.getAWTGraphicsConfiguration();
@@ -277,7 +277,7 @@ public class WindowDriver extends WindowImpl {
                     setGraphicsConfiguration(cfg);
                 }
             }
-            visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+            visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
         }
 
         return true;
index d737dbf..f20f938 100644 (file)
@@ -96,8 +96,8 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
     @Override
     protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, final int flags) {
         if(0!=getWindowHandle()) {
-            if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) {
-                if( 0 != ( FLAG_IS_FULLSCREEN & flags) ) {
+            if(0 != ( CHANGE_MASK_FULLSCREEN & flags)) {
+                if( 0 != ( STATE_MASK_FULLSCREEN & flags) ) {
                     // n/a in BroadcomEGL
                     System.err.println("setFullscreen n/a in BroadcomEGL");
                     return false;
@@ -116,8 +116,8 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
             System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL");
         }
 
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) {
+            visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
         }
         return true;
     }
index 69a8ccd..a083f42 100644 (file)
@@ -107,11 +107,11 @@ public class WindowDriver extends jogamp.newt.WindowImpl {
             SetBounds0(surfaceHandle, getScreen().getWidth(), getScreen().getHeight(), x, y, width, height);
         }
 
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            if(0 != ( FLAG_IS_VISIBLE & flags)) {
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) {
+            if(0 != ( STATE_MASK_VISIBLE & flags)) {
                 ((DisplayDriver)getScreen().getDisplay()).setFocus(this);
             }
-            visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+            visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
         }
 
         return true;
index 0117300..242f644 100644 (file)
@@ -97,14 +97,14 @@ public class WindowDriver extends WindowImpl {
 
     @Override
     protected boolean reconfigureWindowImpl(final int x, final int y, int width, int height, final int flags) {
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            setVisible0(eglWindowHandle, 0 != ( FLAG_IS_VISIBLE & flags));
-            visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) {
+            setVisible0(eglWindowHandle, 0 != ( STATE_MASK_VISIBLE & flags));
+            visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
         }
 
         if(0!=eglWindowHandle) {
-            if(0 != ( FLAG_CHANGE_FULLSCREEN & flags)) {
-                final boolean fs = 0 != ( FLAG_IS_FULLSCREEN & flags) ;
+            if(0 != ( CHANGE_MASK_FULLSCREEN & flags)) {
+                final boolean fs = 0 != ( STATE_MASK_FULLSCREEN & flags) ;
                 setFullScreen0(eglWindowHandle, fs);
                 if(fs) {
                     return true;
@@ -122,8 +122,8 @@ public class WindowDriver extends WindowImpl {
             }
         }
 
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) {
+            visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
         }
 
         return true;
index 66119ff..deaba5f 100644 (file)
@@ -196,7 +196,7 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
             throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this);
         }
         setGraphicsConfiguration(cfg);
-        reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true));
+        reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureMask(CHANGE_MASK_VISIBILITY, true));
         if (0 == getWindowHandle()) {
             throw new NativeWindowException("Error creating window");
         }
@@ -406,7 +406,6 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
             }
         }
 
-        final boolean setVisible = 0 != ( FLAG_IS_VISIBLE & flags);
         final boolean hasFocus = hasFocus();
 
         if(DEBUG_IMPLEMENTATION) {
@@ -420,11 +419,13 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                                ", isOffscreenInstance(sscSurfaceHandle "+toHexString(sscSurfaceHandle)+
                                ", ioi: "+_isOffscreenInstance+
                                ") -> "+isOffscreenInstance+
-                               "\n\t, "+getReconfigureFlagsAsString(null, flags)+", setVisible "+setVisible+", hasFocus "+hasFocus);
+                               "\n\t, "+getReconfigStateMaskString(flags));
             // Thread.dumpStack();
         }
 
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && !setVisible ) {
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) &&
+            0 != ( STATE_MASK_VISIBLE & flags) )
+        {
             if ( !isOffscreenInstance ) {
                 OSXUtil.RunOnMainThread(false, false, new Runnable() {
                         @Override
@@ -436,21 +437,21 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                 visibleChanged(true, false);
             }
         }
-        if( 0 == getWindowHandle() && setVisible ||
-            0 != ( FLAG_CHANGE_DECORATION & flags) ||
-            0 != ( FLAG_CHANGE_PARENTING & flags) ||
-            0 != ( FLAG_CHANGE_FULLSCREEN & flags) ) {
+        if( ( 0 == getWindowHandle() && 0 != ( STATE_MASK_VISIBLE & flags) ) ||
+            0 != ( CHANGE_MASK_PARENTING & flags)  ||
+            0 != ( CHANGE_MASK_DECORATION & flags) ||
+            0 != ( CHANGE_MASK_RESIZABLE & flags)  ||
+            0 != ( CHANGE_MASK_FULLSCREEN & flags) ) {
             if(isOffscreenInstance) {
-                createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, false, setVisible, false);
+                createWindow(true, 0 != getWindowHandle(), pClientLevelOnSreen, 64, 64, flags);
             } else {
-                createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height,
-                                    0 != ( FLAG_IS_FULLSCREEN & flags), setVisible, 0 != ( FLAG_IS_ALWAYSONTOP & flags));
+                createWindow(false, 0 != getWindowHandle(), pClientLevelOnSreen, width, height, flags);
             }
             // no native event (fullscreen, some reparenting)
             positionChanged(false,  x, y);
             updatePixelScaleByWindowHandle(false /* sendEvent */);
             super.sizeChanged(false, width, height, true);
-            visibleChanged(false, setVisible);
+            visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
             if( hasFocus ) {
                 requestFocusImpl(true);
             }
@@ -460,14 +461,18 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                     OSXUtil.RunOnMainThread(false, false, new Runnable() {
                             @Override
                             public void run() {
-                                setWindowClientTopLeftPointAndSize0(getWindowHandle(), pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(), width, height, setVisible);
+                                setWindowClientTopLeftPointAndSize0(getWindowHandle(),
+                                        pClientLevelOnSreen.getX(), pClientLevelOnSreen.getY(),
+                                        width, height, 0 != ( STATE_MASK_VISIBLE & flags));
                             } } );
                 } // else offscreen size is realized via recreation
                 // no native event (fullscreen, some reparenting)
                 positionChanged(true,  x, y);
                 super.sizeChanged(true, width, height, false);
             }
-            if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) && setVisible ) {
+            if( 0 != ( CHANGE_MASK_VISIBILITY & flags) &&
+                0 != ( STATE_MASK_VISIBLE & flags) )
+            {
                 if( !isOffscreenInstance ) {
                     OSXUtil.RunOnMainThread(false, false, new Runnable() {
                             @Override
@@ -480,7 +485,8 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                 }
             }
             if( !isOffscreenInstance ) {
-                setAlwaysOnTop0(getWindowHandle(), 0 != ( FLAG_IS_ALWAYSONTOP & flags));
+                setAlwaysOnTop0(getWindowHandle(), 0 != ( STATE_MASK_ALWAYSONTOP & flags));
+                setAlwaysOnBottom0(getWindowHandle(), 0 != ( STATE_MASK_ALWAYSONBOTTOM & flags));
             }
         }
         if(DEBUG_IMPLEMENTATION) {
@@ -656,16 +662,16 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
 
     private void createWindow(final boolean offscreenInstance, final boolean recreate,
                               final PointImmutable pS, final int width, final int height,
-                              final boolean fullscreen, final boolean visible, final boolean alwaysOnTop) {
-
+                              final int flags)
+    {
         final long parentWinHandle = getParentWindowHandle();
         final long preWinHandle = getWindowHandle();
 
         if(DEBUG_IMPLEMENTATION) {
             System.err.println("MacWindow.createWindow on thread "+Thread.currentThread().getName()+
                                ": offscreen "+offscreenInstance+", recreate "+recreate+
-                               ", pS "+pS+", "+width+"x"+height+", fullscreen "+fullscreen+", visible "+visible+
-                               ", alwaysOnTop "+alwaysOnTop+", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+
+                               ", pS "+pS+", "+width+"x"+height+", state "+getReconfigStateMaskString(flags)+
+                               ", preWinHandle "+toHexString(preWinHandle)+", parentWin "+toHexString(parentWinHandle)+
                                ", surfaceHandle "+toHexString(surfaceHandle));
             // Thread.dumpStack();
         }
@@ -692,9 +698,22 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                 }
             }
 
-            final long newWin = createWindow0( pS.getX(), pS.getY(), width, height, fullscreen,
-                                               ( isUndecorated() || offscreenInstance ) ? NSBorderlessWindowMask :
-                                               NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask,
+            final int windowStyle;
+            {
+                int ws = 0;
+                if( 0 != ( STATE_MASK_UNDECORATED & flags) || offscreenInstance ) {
+                    ws = NSBorderlessWindowMask;
+                } else {
+                    ws = NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask;
+                }
+                if( 0 != ( STATE_MASK_RESIZABLE & flags) ) {
+                    ws |= NSResizableWindowMask;
+                }
+                windowStyle = ws;
+            }
+            final long newWin = createWindow0( pS.getX(), pS.getY(), width, height,
+                                               0 != ( STATE_MASK_FULLSCREEN & flags),
+                                               windowStyle,
                                                NSBackingStoreBuffered, surfaceHandle);
             if ( newWin == 0 ) {
                 throw new NativeWindowException("Could not create native window "+Thread.currentThread().getName()+" "+this);
@@ -707,12 +726,15 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
                     @Override
                     public void run() {
                         initWindow0( parentWinHandle, newWin, pS.getX(), pS.getY(), width, height, reqPixelScale[0] /* HiDPI uniformPixelScale */,
-                                     isOpaque, visible && !offscreenInstance, surfaceHandle);
+                                     isOpaque,
+                                     !offscreenInstance && 0 != ( STATE_MASK_VISIBLE & flags),
+                                     surfaceHandle);
                         if( offscreenInstance ) {
                             orderOut0(0!=parentWinHandle ? parentWinHandle : newWin);
                         } else {
                             setTitle0(newWin, getTitle());
-                            setAlwaysOnTop0(getWindowHandle(), alwaysOnTop);
+                            setAlwaysOnTop0(getWindowHandle(), 0 != ( STATE_MASK_ALWAYSONTOP & flags));
+                            setAlwaysOnBottom0(getWindowHandle(), 0 != ( STATE_MASK_ALWAYSONBOTTOM & flags));
                         }
                     } });
         } catch (final Exception ie) {
@@ -751,6 +773,8 @@ public class WindowDriver extends WindowImpl implements MutableSurface, DriverCl
     private native void setWindowClientTopLeftPoint0(long window, int x, int y, boolean display);
     /** Must be called on Main-Thread */
     private native void setAlwaysOnTop0(long window, boolean atop);
+    /** Must be called on Main-Thread */
+    private native void setAlwaysOnBottom0(long window, boolean abottom);
     private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y);
     private static native void setPointerIcon0(long windowHandle, long handle);
     private static native void setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible);
index cf286e5..83604a3 100644 (file)
@@ -141,8 +141,7 @@ public class WindowDriver extends WindowImpl {
         }
         setGraphicsConfiguration(cfg);
         final VersionNumber winVer = Platform.getOSVersionNumber();
-        final int flags = getReconfigureFlags(0, true) &
-                          ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
+        final int flags = getReconfigureMask(0, true) & STATE_MASK_CREATENATIVE;
         final long _windowHandle = CreateWindow0(DisplayDriver.getHInstance(), display.getWindowClassName(), display.getWindowClassName(),
                                                  winVer.getMajor(), winVer.getMinor(),
                                                  getParentWindowHandle(),
@@ -192,10 +191,10 @@ public class WindowDriver extends WindowImpl {
     protected boolean reconfigureWindowImpl(int x, int y, int width, int height, final int flags) {
         if(DEBUG_IMPLEMENTATION) {
             System.err.println("WindowsWindow reconfig: "+x+"/"+y+" "+width+"x"+height+", "+
-                               getReconfigureFlagsAsString(null, flags));
+                               getReconfigStateMaskString(flags));
         }
 
-        if(0 == ( FLAG_IS_UNDECORATED & flags)) {
+        if(0 == ( STATE_MASK_UNDECORATED & flags)) {
             final InsetsImmutable i = getInsets();
 
             // client position -> top-level window position
@@ -210,8 +209,8 @@ public class WindowDriver extends WindowImpl {
         }
         reconfigureWindow0( getParentWindowHandle(), getWindowHandle(), x, y, width, height, flags);
 
-        if( 0 != ( FLAG_CHANGE_VISIBILITY & flags) ) {
-            visibleChanged(false, 0 != ( FLAG_IS_VISIBLE & flags));
+        if( 0 != ( CHANGE_MASK_VISIBILITY & flags) ) {
+            visibleChanged(false, 0 != ( STATE_MASK_VISIBLE & flags));
         }
         return true;
     }
index 6cf9727..fb2a593 100644 (file)
@@ -123,33 +123,35 @@ public class WindowDriver extends WindowImpl {
             throw new NativeWindowException("Chosen Configuration w/o native visual ID: "+cfg);
         }
         setGraphicsConfiguration(cfg);
-        final int flags = getReconfigureFlags(0, true) &
-                          ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ;
+        final int flags = getReconfigureMask(0, true) & STATE_MASK_CREATENATIVE;
         edtDevice.lock();
         try {
-            setWindowHandle(CreateWindow(getParentWindowHandle(),
-                                   edtDevice.getHandle(), screen.getIndex(), visualID,
-                                   display.getJavaObjectAtom(), display.getWindowDeleteAtom(),
-                                   getX(), getY(), getWidth(), getHeight(), autoPosition(), flags,
-                                   defaultIconDataSize, defaultIconData));
+            final long[] handles = CreateWindow(getParentWindowHandle(),
+                                                edtDevice.getHandle(), screen.getIndex(), visualID,
+                                                display.getJavaObjectAtom(), display.getWindowDeleteAtom(),
+                                                getX(), getY(), getWidth(), getHeight(), flags,
+                                                defaultIconDataSize, defaultIconData, DEBUG_IMPLEMENTATION);
+            if (null == handles || 2 != handles.length || 0 == handles[0] || 0 == handles[1] ) {
+                throw new NativeWindowException("Error creating window");
+            }
+            if(DEBUG_IMPLEMENTATION) { // FIXME
+                System.err.println("X11Window.createNativeImpl() handles "+toHexString(handles[0])+", "+toHexString(handles[1]));
+            }
+            setWindowHandle(handles[0]);
+            javaWindowHandle = handles[1];
         } finally {
             edtDevice.unlock();
         }
-        windowHandleClose = getWindowHandle();
-        if (0 == windowHandleClose) {
-            throw new NativeWindowException("Error creating window");
-        }
     }
 
     @Override
     protected void closeNativeImpl() {
-        if(0!=windowHandleClose && null!=getScreen() ) {
+        if(0!=javaWindowHandle && null!=getScreen() ) {
             final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
             final AbstractGraphicsDevice edtDevice = display.getGraphicsDevice();
             edtDevice.lock();
             try {
-                CloseWindow0(edtDevice.getHandle(), windowHandleClose,
-                             display.getJavaObjectAtom(), display.getWindowDeleteAtom() /* , display.getKbdHandle() */, // XKB disabled for now
+                CloseWindow0(edtDevice.getHandle(), javaWindowHandle /* , display.getKbdHandle() */, // XKB disabled for now
                              display.getRandREventBase(), display.getRandRErrorBase());
             } catch (final Throwable t) {
                 if(DEBUG_IMPLEMENTATION) {
@@ -158,7 +160,7 @@ public class WindowDriver extends WindowImpl {
                 }
             } finally {
                 edtDevice.unlock();
-                windowHandleClose = 0;
+                javaWindowHandle = 0;
             }
         }
         if(null != renderDevice) {
@@ -174,7 +176,7 @@ public class WindowDriver extends WindowImpl {
      * {@inheritDoc}
      */
     @Override
-    protected boolean isReconfigureFlagSupported(final int changeFlags) {
+    protected boolean isReconfigureMaskSupported(final int changeFlags) {
         return true; // all flags!
     }
 
@@ -182,7 +184,7 @@ public class WindowDriver extends WindowImpl {
     protected boolean reconfigureWindowImpl(final int x, final int y, final int width, final int height, int flags) {
         final int _x, _y;
         final InsetsImmutable _insets;
-        if( 0 == ( FLAG_IS_UNDECORATED & flags) ) {
+        if( 0 == ( STATE_MASK_UNDECORATED & flags) ) {
             // client position -> top-level window position
             _insets = getInsets();
             _x = x - _insets.getLeftWidth() ;
@@ -193,27 +195,27 @@ public class WindowDriver extends WindowImpl {
             _y = y;
         }
         if(DEBUG_IMPLEMENTATION) {
-            System.err.println("X11Window reconfig: "+x+"/"+y+" -> "+_x+"/"+_y+" "+width+"x"+height+", insets "+_insets+", "+ getReconfigureFlagsAsString(null, flags));
+            System.err.println("X11Window reconfig: "+x+"/"+y+" -> "+_x+"/"+_y+" "+width+"x"+height+", insets "+_insets+", "+ getReconfigStateMaskString(flags));
         }
-        if( 0 != ( FLAG_CHANGE_FULLSCREEN & flags ) ) {
-            if( 0 != ( FLAG_IS_FULLSCREEN & flags) && 0 == ( FLAG_IS_ALWAYSONTOP & flags) ) {
+        if( 0 != ( CHANGE_MASK_FULLSCREEN & flags ) ) {
+            if( 0 != ( STATE_MASK_FULLSCREEN & flags) &&
+                0 == ( STATE_MASK_ALWAYSONTOP & flags) &&
+                0 == ( STATE_MASK_ALWAYSONBOTTOM & flags) ) {
                 tempFSAlwaysOnTop = true;
-                flags |= FLAG_IS_ALWAYSONTOP;
+                flags |= STATE_MASK_ALWAYSONTOP;
                 if(DEBUG_IMPLEMENTATION) {
-                    System.err.println("X11Window reconfig.2: temporary "+getReconfigureFlagsAsString(null, flags));
+                    System.err.println("X11Window reconfig.2: temporary "+getReconfigStateMaskString(flags));
                 }
             } else {
                 tempFSAlwaysOnTop = false;
             }
         }
         final int fflags = flags;
-        final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
         runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
             @Override
             public Object run(final long dpy) {
                 reconfigureWindow0( dpy, getScreenIndex(),
-                                    getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
-                                    _x, _y, width, height, fflags);
+                                    getParentWindowHandle(), javaWindowHandle, _x, _y, width, height, fflags);
                 return null;
             }
         });
@@ -229,18 +231,17 @@ public class WindowDriver extends WindowImpl {
      */
     @Override
     protected void focusChanged(final boolean defer, final boolean focusGained) {
-        if( isNativeValid() && isFullscreen() && tempFSAlwaysOnTop && hasFocus() != focusGained ) {
-            final int flags = getReconfigureFlags(FLAG_CHANGE_ALWAYSONTOP, isVisible()) | ( focusGained ? FLAG_IS_ALWAYSONTOP : 0 );
+        if( isNativeValid() && isFullscreen() && !isAlwaysOnBottom() && tempFSAlwaysOnTop && hasFocus() != focusGained ) {
+            final int flags = getReconfigureMask(CHANGE_MASK_ALWAYSONTOP, isVisible()) |
+                              ( focusGained ? STATE_MASK_ALWAYSONTOP : 0 );
             if(DEBUG_IMPLEMENTATION) {
-                System.err.println("X11Window reconfig.3 (focus): temporary "+getReconfigureFlagsAsString(null, flags));
+                System.err.println("X11Window reconfig.3 (focus): temporary "+getReconfigStateMaskString(flags));
             }
-            final DisplayDriver display = (DisplayDriver) getScreen().getDisplay();
             runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
                 @Override
                 public Object run(final long dpy) {
                     reconfigureWindow0( dpy, getScreenIndex(),
-                                        getParentWindowHandle(), getWindowHandle(), display.getWindowDeleteAtom(),
-                                        getX(), getY(), getWidth(), getHeight(), flags);
+                                        getParentWindowHandle(), javaWindowHandle, getX(), getY(), getWidth(), getHeight(), flags);
                     return null;
                 }
             });
@@ -260,7 +261,7 @@ public class WindowDriver extends WindowImpl {
         runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
             @Override
             public Object run(final long dpy) {
-                requestFocus0(dpy, getWindowHandle(), force);
+                requestFocus0(dpy, javaWindowHandle, force);
                 return null;
             }
         });
@@ -271,7 +272,7 @@ public class WindowDriver extends WindowImpl {
         runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
             @Override
             public Object run(final long dpy) {
-                setTitle0(dpy, getWindowHandle(), title);
+                setTitle0(dpy, javaWindowHandle, title);
                 return null;
             }
         });
@@ -283,7 +284,7 @@ public class WindowDriver extends WindowImpl {
             @Override
             public Object run(final long dpy) {
                 try {
-                    setPointerIcon0(dpy, getWindowHandle(), null != pi ? pi.validatedHandle() : 0);
+                    setPointerIcon0(dpy, javaWindowHandle, null != pi ? pi.validatedHandle() : 0);
                 } catch (final Exception e) {
                     e.printStackTrace();
                 }
@@ -300,10 +301,10 @@ public class WindowDriver extends WindowImpl {
                 final PointerIconImpl pi = (PointerIconImpl)getPointerIcon();
                 final boolean res;
                 if( pointerVisible && null != pi ) {
-                    setPointerIcon0(dpy, getWindowHandle(), pi.validatedHandle());
+                    setPointerIcon0(dpy, javaWindowHandle, pi.validatedHandle());
                     res = true;
                 } else {
-                    res = setPointerVisible0(dpy, getWindowHandle(), pointerVisible);
+                    res = setPointerVisible0(dpy, javaWindowHandle, pointerVisible);
                 }
                 return Boolean.valueOf(res);
             }
@@ -315,7 +316,7 @@ public class WindowDriver extends WindowImpl {
         return runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Boolean>() {
             @Override
             public Boolean run(final long dpy) {
-                return Boolean.valueOf(confinePointer0(dpy, getWindowHandle(), confine));
+                return Boolean.valueOf(confinePointer0(dpy, javaWindowHandle, confine));
             }
         }).booleanValue();
     }
@@ -325,7 +326,7 @@ public class WindowDriver extends WindowImpl {
         runWithLockedDisplayDevice( new DisplayImpl.DisplayRunnable<Object>() {
             @Override
             public Object run(final long dpy) {
-                warpPointer0(dpy, getWindowHandle(), x, y);
+                warpPointer0(dpy, javaWindowHandle, x, y);
                 return null;
             }
         });
@@ -434,39 +435,41 @@ public class WindowDriver extends WindowImpl {
 
     protected static native boolean initIDs0();
 
-    private long CreateWindow(final long parentWindowHandle, final long display, final int screen_index,
-                              final int visualID, final long javaObjectAtom, final long windowDeleteAtom,
-                              final int x, final int y, final int width, final int height, final boolean autoPosition, final int flags,
-                              final int pixelDataSize, final Buffer pixels) {
+    private long[] CreateWindow(final long parentWindowHandle, final long display, final int screen_index,
+                                final int visualID, final long javaObjectAtom, final long windowDeleteAtom,
+                                final int x, final int y, final int width, final int height, final int flags,
+                                final int pixelDataSize, final Buffer pixels, final boolean verbose) {
         // NOTE: MUST BE DIRECT BUFFER, since _NET_WM_ICON Atom uses buffer directly!
         if( !Buffers.isDirect(pixels) ) {
             throw new IllegalArgumentException("data buffer is not direct "+pixels);
         }
         return CreateWindow0(parentWindowHandle, display, screen_index,
                              visualID, javaObjectAtom, windowDeleteAtom,
-                             x, y, width, height, autoPosition, flags,
-                             pixelDataSize,
-                             pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */);
+                             x, y, width, height, flags,
+                             pixelDataSize, pixels, Buffers.getDirectBufferByteOffset(pixels), true /* pixels_is_direct */, verbose);
     }
-    private native long CreateWindow0(long parentWindowHandle, long display, int screen_index,
-                                      int visualID, long javaObjectAtom, long windowDeleteAtom,
-                                      int x, int y, int width, int height, boolean autoPosition, int flags,
-                                      int pixelDataSize, Object pixels, int pixels_byte_offset, boolean pixels_is_direct);
-    private native void CloseWindow0(long display, long windowHandle, long javaObjectAtom, long windowDeleteAtom /*, long kbdHandle*/, // XKB disabled for now
+    /** returns long[2] { X11-window-handle, JavaWindow-handle } */
+    private native long[] CreateWindow0(long parentWindowHandle, long display, int screen_index,
+                                        int visualID, long javaObjectAtom, long windowDeleteAtom,
+                                        int x, int y, int width, int height, int flags,
+                                        int pixelDataSize, Object pixels, int pixels_byte_offset, boolean pixels_is_direct,
+                                        boolean verbose);
+    private native long GetNativeWindowHandle0(long javaWindowHandle);
+    private native void CloseWindow0(long display, long javaWindowHandle /*, long kbdHandle*/, // XKB disabled for now
                                      final int randr_event_base, final int randr_error_base);
-    private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long windowHandle,
-                                           long windowDeleteAtom, int x, int y, int width, int height, int flags);
-    private native void requestFocus0(long display, long windowHandle, boolean force);
+    private native void reconfigureWindow0(long display, int screen_index, long parentWindowHandle, long javaWindowHandle,
+                                           int x, int y, int width, int height, int flags);
+    private native void requestFocus0(long display, long javaWindowHandle, boolean force);
 
-    private static native void setTitle0(long display, long windowHandle, String title);
+    private static native void setTitle0(long display, long javaWindowHandle, String title);
 
-    private static native void setPointerIcon0(long display, long windowHandle, long handle);
+    private static native void setPointerIcon0(long display, long javaWindowHandle, long handle);
 
-    private static native long getParentWindow0(long display, long windowHandle);
-    private static native boolean setPointerVisible0(long display, long windowHandle, boolean visible);
-    private static native boolean confinePointer0(long display, long windowHandle, boolean grab);
-    private static native void warpPointer0(long display, long windowHandle, int x, int y);
+    private static native boolean setPointerVisible0(long display, long javaWindowHandle, boolean visible);
+    private static native boolean confinePointer0(long display, long javaWindowHandle, boolean grab);
+    private static native void warpPointer0(long display, long javaWindowHandle, int x, int y);
 
-    private long   windowHandleClose;
+    /** Of native type JavaWindow, containing 'jobject window', X11 Window, beside other states. */
+    private volatile long javaWindowHandle = 0; // lifecycle critical
     private X11GraphicsDevice renderDevice;
 }
index 5593cd6..b59e19e 100644 (file)
@@ -1438,6 +1438,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnTo
 
 /*
  * Class:     jogamp_newt_driver_macosx_WindowDriver
+ * Method:    setAlwaysOnBottom0
+ * Signature: (JZ)V
+ */
+JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_WindowDriver_setAlwaysOnBottom0
+  (JNIEnv *env, jobject unused, jlong window, jboolean abottom)
+{
+    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+    NSWindow* win = (NSWindow*) ((intptr_t) window);
+
+    DBG_PRINT( "setAlwaysOnBottom0 - window: %p, abottom %d (START)\n", win, (int)abottom);
+
+    if(abottom) {
+        [win setLevel:NSScreenSaverWindowLevel]; // ??
+    } else {
+        [win setLevel:NSNormalWindowLevel];
+    }
+
+    DBG_PRINT( "setAlwaysOnBottom0 - window: %p, abottom %d (END)\n", win, (int)abottom);
+
+    [pool release];
+}
+
+/*
+ * Class:     jogamp_newt_driver_macosx_WindowDriver
  * Method:    getLocationOnScreen0
  * Signature: (JII)Lcom/jogamp/nativewindow/util/Point;
  */
index d9ee5fd..ada886d 100644 (file)
 #ifndef _WINDOW_H_
 #define _WINDOW_H_
 
-#define FLAG_CHANGE_PARENTING       ( 1 <<  0 )
-#define FLAG_CHANGE_DECORATION      ( 1 <<  1 )
-#define FLAG_CHANGE_FULLSCREEN      ( 1 <<  2 )
-#define FLAG_CHANGE_ALWAYSONTOP     ( 1 <<  3 )
-#define FLAG_CHANGE_VISIBILITY      ( 1 <<  4 )
+#define FLAG_CHANGE_VISIBILITY      ( 1 << 31 )
+#define FLAG_CHANGE_VISIBILITY_FAST ( 1 << 30 )
+#define FLAG_CHANGE_PARENTING       ( 1 << 29 )
+#define FLAG_CHANGE_DECORATION      ( 1 << 28 )
+#define FLAG_CHANGE_ALWAYSONTOP     ( 1 << 27 )
+#define FLAG_CHANGE_ALWAYSONBOTTOM  ( 1 << 26 )
+#define FLAG_CHANGE_STICKY          ( 1 << 25 )
+#define FLAG_CHANGE_RESIZABLE       ( 1 << 24 )
+#define FLAG_CHANGE_MAXIMIZED_VERT  ( 1 << 23 )
+#define FLAG_CHANGE_MAXIMIZED_HORZ  ( 1 << 22 )
+#define FLAG_CHANGE_FULLSCREEN      ( 1 << 21 )
 
-#define FLAG_HAS_PARENT             ( 1 <<  8 )
-#define FLAG_IS_UNDECORATED         ( 1 <<  9 )
-#define FLAG_IS_FULLSCREEN          ( 1 << 10 )
-#define FLAG_IS_FULLSCREEN_SPAN     ( 1 << 11 )
-#define FLAG_IS_ALWAYSONTOP         ( 1 << 12 )
-#define FLAG_IS_VISIBLE             ( 1 << 13 )
+#define FLAG_IS_VISIBLE             ( 1 <<  0 )
+#define FLAG_IS_AUTOPOSITION        ( 1 <<  1 )
+#define FLAG_IS_CHILD               ( 1 <<  2 )
+#define FLAG_IS_FOCUSED             ( 1 <<  3 )
+#define FLAG_IS_UNDECORATED         ( 1 <<  4 )
+#define FLAG_IS_ALWAYSONTOP         ( 1 <<  5 )
+#define FLAG_IS_ALWAYSONBOTTOM      ( 1 <<  6 )
+#define FLAG_IS_STICKY              ( 1 <<  7 )
+#define FLAG_IS_RESIZABLE           ( 1 <<  8 )
+#define FLAG_IS_MAXIMIZED_VERT      ( 1 <<  9 )
+#define FLAG_IS_MAXIMIZED_HORZ      ( 1 << 10 )
+#define FLAG_IS_FULLSCREEN          ( 1 << 11 )
+#define FLAG_IS_FULLSCREEN_SPAN     ( 1 << 12 )
 
+#define TST_FLAG_CHANGE_VISIBILITY(f)  ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) ) 
+#define TST_FLAG_CHANGE_VISIBILITY_FAST(f) ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY_FAST ) ) 
 #define TST_FLAG_CHANGE_PARENTING(f)   ( 0 != ( (f) & FLAG_CHANGE_PARENTING ) ) 
 #define TST_FLAG_CHANGE_DECORATION(f)  ( 0 != ( (f) & FLAG_CHANGE_DECORATION ) ) 
-#define TST_FLAG_CHANGE_FULLSCREEN(f)  ( 0 != ( (f) & FLAG_CHANGE_FULLSCREEN ) ) 
 #define TST_FLAG_CHANGE_ALWAYSONTOP(f) ( 0 != ( (f) & FLAG_CHANGE_ALWAYSONTOP ) ) 
-#define TST_FLAG_CHANGE_VISIBILITY(f)  ( 0 != ( (f) & FLAG_CHANGE_VISIBILITY ) ) 
+#define TST_FLAG_CHANGE_ALWAYSONBOTTOM(f) ( 0 != ( (f) & FLAG_CHANGE_ALWAYSONBOTTOM ) ) 
+#define TST_FLAG_CHANGE_ALWAYSONANY(f) ( 0 != ( (f) & ( FLAG_CHANGE_ALWAYSONTOP | FLAG_CHANGE_ALWAYSONBOTTOM ) ) ) 
+#define TST_FLAG_CHANGE_STICKY(f)      ( 0 != ( (f) & FLAG_CHANGE_STICKY ) ) 
+#define TST_FLAG_CHANGE_RESIZABLE(f)   ( 0 != ( (f) & FLAG_CHANGE_RESIZABLE ) ) 
+#define TST_FLAG_CHANGE_MAXIMIZED_VERT(f) ( 0 != ( (f) & FLAG_CHANGE_MAXIMIZED_VERT ) ) 
+#define TST_FLAG_CHANGE_MAXIMIZED_HORZ(f) ( 0 != ( (f) & FLAG_CHANGE_MAXIMIZED_HORZ ) ) 
+#define TST_FLAG_CHANGE_MAXIMIZED_ANY(f)  ( 0 != ( (f) & ( FLAG_CHANGE_MAXIMIZED_VERT | FLAG_CHANGE_MAXIMIZED_HORZ ) ) ) 
+#define TST_FLAG_CHANGE_FULLSCREEN(f)  ( 0 != ( (f) & FLAG_CHANGE_FULLSCREEN ) ) 
 
-#define TST_FLAG_HAS_PARENT(f)         ( 0 != ( (f) & FLAG_HAS_PARENT ) ) 
+#define TST_FLAG_IS_VISIBLE(f)         ( 0 != ( (f) & FLAG_IS_VISIBLE ) ) 
+#define TST_FLAG_IS_AUTOPOSITION(f)    ( 0 != ( (f) & FLAG_IS_AUTOPOSITION ) ) 
+#define TST_FLAG_IS_CHILD(f)           ( 0 != ( (f) & FLAG_IS_CHILD ) ) 
+#define TST_FLAG_IS_FOCUSED(f)         ( 0 != ( (f) & FLAG_IS_FOCUSED ) ) 
 #define TST_FLAG_IS_UNDECORATED(f)     ( 0 != ( (f) & FLAG_IS_UNDECORATED ) ) 
+#define TST_FLAG_IS_ALWAYSONTOP(f)     ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) ) 
+#define TST_FLAG_IS_ALWAYSONBOTTOM(f)  ( 0 != ( (f) & FLAG_IS_ALWAYSONBOTTOM ) ) 
+#define TST_FLAG_IS_ALWAYSONANY(f)     ( 0 != ( (f) & ( FLAG_IS_ALWAYSONTOP | FLAG_IS_ALWAYSONBOTTOM ) ) ) 
+#define TST_FLAG_IS_STICKY(f)          ( 0 != ( (f) & FLAG_IS_STICKY ) ) 
+#define TST_FLAG_IS_RESIZABLE(f)       ( 0 != ( (f) & FLAG_IS_RESIZABLE ) ) 
+#define TST_FLAG_IS_MAXIMIZED_VERT(f)  ( 0 != ( (f) & FLAG_IS_MAXIMIZED_VERT ) ) 
+#define TST_FLAG_IS_MAXIMIZED_HORZ(f)  ( 0 != ( (f) & FLAG_IS_MAXIMIZED_HORZ ) ) 
+#define TST_FLAG_IS_MAXIMIZED_ANY(f)   ( 0 != ( (f) & ( FLAG_IS_MAXIMIZED_VERT | FLAG_IS_MAXIMIZED_HORZ ) ) ) 
 #define TST_FLAG_IS_FULLSCREEN(f)      ( 0 != ( (f) & FLAG_IS_FULLSCREEN ) ) 
 #define TST_FLAG_IS_FULLSCREEN_SPAN(f) ( 0 != ( (f) & FLAG_IS_FULLSCREEN_SPAN ) ) 
-#define TST_FLAG_IS_ALWAYSONTOP(f)     ( 0 != ( (f) & FLAG_IS_ALWAYSONTOP ) ) 
-#define TST_FLAG_IS_VISIBLE(f)         ( 0 != ( (f) & FLAG_IS_VISIBLE ) ) 
 
 #endif
index 8c29978..ad4111e 100644 (file)
@@ -2297,9 +2297,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_windows_WindowDriver_reconfigureW
 #endif
 
 
-    DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d, isChild %d, isFullscreen %d\n",
+    DBG_PRINT( "*** WindowsWindow: reconfigureWindow0 parent %p, window %p, %d/%d %dx%d, parentChange %d, isChild %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d, alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d -> styleChange %d, isChild %d, isFullscreen %d\n",
         parent, window, x, y, width, height,
-        TST_FLAG_CHANGE_PARENTING(flags),   TST_FLAG_HAS_PARENT(flags),
+        TST_FLAG_CHANGE_PARENTING(flags),   TST_FLAG_IS_CHILD(flags),
         TST_FLAG_CHANGE_DECORATION(flags),  TST_FLAG_IS_UNDECORATED(flags),
         TST_FLAG_CHANGE_FULLSCREEN(flags),  TST_FLAG_IS_FULLSCREEN(flags),
         TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
diff --git a/src/newt/native/X11AllowedWMActions.c b/src/newt/native/X11AllowedWMActions.c
new file mode 100644 (file)
index 0000000..47448cb
--- /dev/null
@@ -0,0 +1,131 @@
+
+#ifdef VERBOSE_ON
+    #define _NET_WM_ACTION_FLAG_RESERVED         ( 1 <<  0 ) /* for the ATOM COMMAND */
+    #define _NET_WM_ACTION_FLAG_MOVE             ( 1 <<  1 )
+    #define _NET_WM_ACTION_FLAG_RESIZE           ( 1 <<  2 )
+    #define _NET_WM_ACTION_FLAG_MINIMIZE         ( 1 <<  3 )
+    #define _NET_WM_ACTION_FLAG_SHADE            ( 1 <<  4 )
+    #define _NET_WM_ACTION_FLAG_STICK            ( 1 <<  5 )
+    #define _NET_WM_ACTION_FLAG_MAXIMIZE_HORZ    ( 1 <<  6 )
+    #define _NET_WM_ACTION_FLAG_MAXIMIZE_VERT    ( 1 <<  7 )
+    #define _NET_WM_ACTION_FLAG_FULLSCREEN       ( 1 <<  8 )
+    #define _NET_WM_ACTION_FLAG_CHANGE_DESKTOP   ( 1 <<  9 )
+    #define _NET_WM_ACTION_FLAG_CLOSE            ( 1 << 10 )
+    #define _NET_WM_ACTION_FLAG_ABOVE            ( 1 << 11 )
+    #define _NET_WM_ACTION_FLAG_BELOW            ( 1 << 12 )
+    #define _NET_WM_ACTION_FLAG_ALL              ( ( 1 << 13 ) - 1 )
+    static const char * _NET_WM_AACTION_NAMES[] = { 
+        "_NET_WM_ALLOWED_ACTIONS",
+        "_NET_WM_ACTION_MOVE",
+        "_NET_WM_ACTION_RESIZE",
+        "_NET_WM_ACTION_MINIMIZE",
+        "_NET_WM_ACTION_SHADE",
+        "_NET_WM_ACTION_STICK",
+        "_NET_WM_ACTION_MAXIMIZE_HORZ",
+        "_NET_WM_ACTION_MAXIMIZE_VERT",
+        "_NET_WM_ACTION_FULLSCREEN",
+        "_NET_WM_ACTION_CHANGE_DESKTOP",
+        "_NET_WM_ACTION_CLOSE",
+        "_NET_WM_ACTION_ABOVE",
+        "_NET_WM_ACTION_BELOW"
+    };
+    static const int _NET_WM_AACTION_COUNT = sizeof(_NET_WM_AACTION_NAMES)/sizeof(const char *);
+    static const int _UNDEF_AACTION_MAX = 16;
+    static int NewtWindows_getAllowedWindowActionEWMH(Display *dpy, const Atom * allDefinedActions, const Atom action, const int num) {
+        int i;
+        for(i=1; i<_NET_WM_AACTION_COUNT; i++) {
+            if( action == allDefinedActions[i] ) {
+                DBG_PRINT( "...... [%d] -> [%d/%d]: %s\n", num, i, _NET_WM_AACTION_COUNT, _NET_WM_AACTION_NAMES[i]);
+                return 1 << i;
+            }
+        }
+    #ifdef VERBOSE_ON
+        char * astr = XGetAtomName(dpy, action);
+        DBG_PRINT( "...... [%d] -> [_/%d]: %s (undef)\n", num, _NET_WM_AACTION_COUNT, astr);
+        XFree(astr);
+    #endif
+        return 0;
+    }
+    static int NewtWindows_getAllowedWindowActionsEWMH1(Display *dpy, Window w, Atom * _NET_WM_AACTIONS) {
+        Atom * actions = NULL;
+        Atom type = 0;
+        unsigned long action_len = 0, remain = 0;
+        int res = 0, form = 0, i = 0;
+        Status s;
+
+        XSync(dpy, False);
+        DBG_PRINT( "**************** X11: AACTIONS EWMH CHECK for Window: %p:\n", w);
+        if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_AACTIONS[0], 0, 1024, False, AnyPropertyType,
+                                                &type, &form, &action_len, &remain, (unsigned char**)&actions)) ) {
+            if( NULL != actions ) {
+                for(i=0; i<action_len; i++) {
+                    res |= NewtWindows_getAllowedWindowActionEWMH(dpy, _NET_WM_AACTIONS, actions[i], i);
+                }
+                XFree(actions);
+            }
+            DBG_PRINT( "**************** X11: AACTIONS EWMH CHECK: 0x%X\n", res);
+        } else {
+            DBG_PRINT( "**************** X11: AACTIONS EWMH CHECK: XGetWindowProperty failed: %d\n", s);
+            res = _NET_WM_ACTION_FLAG_FULLSCREEN; // default ..
+        }
+        return res;
+    }
+    static int NewtWindows_getAllowedWindowActionsEWMH0(Display *dpy, Window w) {
+        Atom _NET_WM_AACTIONS[_NET_WM_AACTION_COUNT];
+        if( 0 == XInternAtoms( dpy, (char **)_NET_WM_AACTION_NAMES, _NET_WM_AACTION_COUNT, False, _NET_WM_AACTIONS) ) {
+            // error
+            DBG_PRINT( "**************** X11: AACTIONS EWMH CHECK: XInternAtoms failed\n");
+            return _NET_WM_ACTION_FLAG_FULLSCREEN; // default ..
+        }
+        return NewtWindows_getAllowedWindowActionsEWMH1(dpy, w, _NET_WM_AACTIONS);
+    }
+    static int NewtWindows_setAllowedWindowActionsEWMH(Display *dpy, Window w, int new_action_mask) {
+        Atom _NET_WM_AACTIONS[_NET_WM_AACTION_COUNT];
+        if( 0 == XInternAtoms( dpy, (char **)_NET_WM_AACTION_NAMES, _NET_WM_AACTION_COUNT, False, _NET_WM_AACTIONS) ) {
+            // error
+            DBG_PRINT( "**************** X11: AACTIONS EWMH SET: XInternAtoms failed\n");
+            return _NET_WM_ACTION_FLAG_FULLSCREEN; // default ..
+        }
+        Atom * actions = NULL;
+        Atom type = 0;
+        unsigned long action_len = 0, remain = 0;
+        int res = 0, form = 0, i = 0, j = 0;
+        Status s;
+        Atom _NET_WM_NEWACTIONS[_NET_WM_AACTION_COUNT+_UNDEF_AACTION_MAX]; // +_UNDEF_AACTION_MAX undefined props
+
+        DBG_PRINT( "**************** X11: AACTIONS EWMH SET for Window: %p:\n", w);
+        if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_AACTIONS[0], 0, 1024, False, AnyPropertyType,
+                                                &type, &form, &action_len, &remain, (unsigned char**)&actions)) ) {
+            if( NULL != actions ) {
+                for(i=0; i<action_len; i++) {
+                    const int r = NewtWindows_getAllowedWindowActionEWMH(dpy, _NET_WM_AACTIONS, actions[i], i);
+                    if( 0 == r && j < _UNDEF_AACTION_MAX ) {
+                        // conserve undefined action
+                        _NET_WM_NEWACTIONS[j++] = actions[i];
+                    }
+                    res |= r;
+                }
+                XFree(actions);
+            }
+            DBG_PRINT( "**************** X11: AACTIONS EWMH SET: Has 0x%X\n", res);
+            for(i=1; i<_NET_WM_AACTION_COUNT; i++) {
+                const int m = 1 << i;
+                if( 0 != ( m & new_action_mask ) ) {
+                    // requested
+                    _NET_WM_NEWACTIONS[j++] = _NET_WM_AACTIONS[i];
+                    res |= m;
+                }
+            }
+            DBG_PRINT( "**************** X11: AACTIONS EWMH SET: New 0x%X\n", res);
+            XChangeProperty( dpy, w, _NET_WM_AACTIONS[0], XA_ATOM, 32, PropModeReplace, (unsigned char*)_NET_WM_NEWACTIONS, j); 
+            XSync(dpy, False);
+            const int res2 = NewtWindows_getAllowedWindowActionsEWMH1(dpy, w, _NET_WM_AACTIONS);
+            DBG_PRINT( "**************** X11: AACTIONS EWMH SET: Val 0x%X\n", res2);
+        } else {
+            DBG_PRINT( "**************** X11: AACTIONS EWMH SET: XGetWindowProperty failed: %d\n", s);
+            res = _NET_WM_ACTION_FLAG_FULLSCREEN; // default ..
+        }
+        return res;
+    }
+#endif
+
index e58cdb7..309e626 100644 (file)
 extern jclass X11NewtWindowClazz;
 extern jmethodID insetsChangedID;
 extern jmethodID visibleChangedID;
+extern jmethodID minMaxSizeChangedID;
 
-jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning);
+typedef struct {
+    Window window;
+    jobject jwindow;
+    Atom * allAtoms;
+    Atom javaObjectAtom;
+    Atom windowDeleteAtom;
+    uint32_t supportedAtoms;
+    uint32_t lastDesktop;
+} JavaWindow;
+
+JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning);
 
 Status NewtWindows_getRootAndParent (Display *dpy, Window w, Window * root_return, Window * parent_return);
-Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom);
+Status NewtWindows_updateInsets(JNIEnv *env, Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom);
+void NewtWindows_updateMinMaxSize(JNIEnv *env, Display *dpy, JavaWindow * w);
 
 #endif /* _X11COMMON_H_ */
 
index b79c1ee..0ba454a 100644 (file)
@@ -35,6 +35,7 @@
 jclass X11NewtWindowClazz = NULL;
 jmethodID insetsChangedID = NULL;
 jmethodID visibleChangedID = NULL;
+jmethodID minMaxSizeChangedID = NULL;
 
 static const char * const ClazzNameX11NewtWindow = "jogamp/newt/driver/x11/WindowDriver";
 
@@ -253,6 +254,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
     positionChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "positionChanged", "(ZII)V");
     focusChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "focusChanged", "(ZZ)V");
     visibleChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "visibleChanged", "(ZZ)V");
+    minMaxSizeChangedID = (*env)->GetMethodID(env, X11NewtWindowClazz, "minMaxSizeChanged", "(IIII)V");
     reparentNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "reparentNotify", "(J)V");
     windowDestroyNotifyID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowDestroyNotify", "(Z)Z");
     windowRepaintID = (*env)->GetMethodID(env, X11NewtWindowClazz, "windowRepaint", "(ZIIII)V");
@@ -269,6 +271,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_initIDs0
         positionChangedID == NULL ||
         focusChangedID == NULL ||
         visibleChangedID == NULL ||
+        minMaxSizeChangedID == NULL ||
         reparentNotifyID == NULL ||
         windowDestroyNotifyID == NULL ||
         windowRepaintID == NULL ||
@@ -377,7 +380,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
 
     // Periodically take a break
     while( num_events > 0 ) {
-        jobject jwindow = NULL;
+        JavaWindow *jw = NULL;
         XEvent evt;
         KeySym keySym = 0;
         KeyCode keyCode = 0;
@@ -418,7 +421,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
 
         // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
 
-        jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+        jw = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
         #ifdef VERBOSE_ON
                 True
         #else
@@ -426,7 +429,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
         #endif
             );
 
-        if(NULL==jwindow) {
+        if(NULL==jw) {
             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);
             continue;
         }
@@ -519,30 +522,30 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
 
         switch(evt.type) {
             case ButtonPress:
-                (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, 
+                (*env)->CallVoidMethod(env, jw->jwindow, requestFocusID, JNI_FALSE);
+                (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_PRESSED, 
                                       modifiers,
                                       (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
                 break;
             case ButtonRelease:
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, 
+                (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_RELEASED, 
                                       modifiers,
                                       (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jshort) evt.xbutton.button, 0.0f /*rotation*/);
                 break;
             case MotionNotify:
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, 
+                (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_MOVED, 
                                       modifiers,
                                       (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jshort) 0, 0.0f /*rotation*/); 
                 break;
             case EnterNotify:
                 DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED, 
+                (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_ENTERED, 
                                       modifiers,
                                       (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); 
                 break;
             case LeaveNotify:
                 DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED, 
+                (*env)->CallVoidMethod(env, jw->jwindow, sendMouseEventID, (jshort) EVENT_MOUSE_EXITED, 
                                       modifiers,
                                       (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jshort) 0, 0.0f /*rotation*/); 
                 break;
@@ -551,11 +554,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
                 XRefreshKeyboardMapping(&evt.xmapping);
                 break;
             case KeyPress:
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, 
+                (*env)->CallVoidMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_PRESSED, 
                                       modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
                 break;
             case KeyRelease:
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, 
+                (*env)->CallVoidMethod(env, jw->jwindow, sendKeyEventID, (jshort) EVENT_KEY_RELEASED, 
                                       modifiers, javaVKeyUS, javaVKeyNN, (jchar) keyChar, keyString);
                 break;
             case DestroyNotify:
@@ -579,11 +582,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
                     {
                         // update insets
                         int left, right, top, bottom;
-                        NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+                        NewtWindows_updateInsets(env, dpy, jw, &left, &right, &top, &bottom);
                     }
-                    (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE,
+                    NewtWindows_updateMinMaxSize(env, dpy, jw);
+                    (*env)->CallVoidMethod(env, jw->jwindow, sizeChangedID, JNI_FALSE,
                                             (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
-                    (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE,
+                    (*env)->CallVoidMethod(env, jw->jwindow, positionChangedID, JNI_FALSE,
                                             (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
                 }
                 break;
@@ -592,7 +596,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
                     jboolean closed;
                     DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n", 
                         (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
-                    closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE);
+                    closed = (*env)->CallBooleanMethod(env, jw->jwindow, windowDestroyNotifyID, JNI_FALSE);
                     DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, closed: %d\n", 
                         (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, (int)closed);
                     // Called by Window.java: CloseWindow(); 
@@ -602,12 +606,12 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
 
             case FocusIn:
                 DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
-                (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE);
+                (*env)->CallVoidMethod(env, jw->jwindow, focusChangedID, JNI_FALSE, JNI_TRUE);
                 break;
 
             case FocusOut:
                 DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
-                (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE);
+                (*env)->CallVoidMethod(env, jw->jwindow, focusChangedID, JNI_FALSE, JNI_FALSE);
                 break;
 
             case Expose:
@@ -615,7 +619,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
                     evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count);
 
                 if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) {
-                    (*env)->CallVoidMethod(env, jwindow, windowRepaintID, JNI_FALSE,
+                    (*env)->CallVoidMethod(env, jw->jwindow, windowRepaintID, JNI_FALSE,
                         evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
                 }
                 break;
@@ -629,9 +633,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
                     {
                         // update insets
                         int left, right, top, bottom;
-                        NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+                        NewtWindows_updateInsets(env, dpy, jw, &left, &right, &top, &bottom);
                     }
-                    (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
+                    (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
                 }
                 break;
 
@@ -641,7 +645,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
                     evt.xunmap.event!=evt.xunmap.window);
                 if( evt.xunmap.event == evt.xunmap.window ) {
                     // ignore child window notification
-                    (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE);
+                    (*env)->CallVoidMethod(env, jw->jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE);
                 }
                 break;
 
@@ -674,7 +678,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessage
                             (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
                             (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
                     #endif
-                    (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent);
+                    (*env)->CallVoidMethod(env, jw->jwindow, reparentNotifyID, (jlong)evt.xreparent.parent);
                 }
                 break;
 
index 32a55c6..d0567c1 100644 (file)
@@ -12,7 +12,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
 
     // Periodically take a break
     while( num_events > 0 ) {
-        jobject jwindow = NULL;
+        JavaWindow *w = NULL;
         XEvent evt;
         KeySym keySym = 0;
         jint modifiers = 0;
@@ -45,7 +45,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
 
         // DBG_PRINT( "X11: DispatchMessages dpy %p, win %p, Event %d\n", (void*)dpy, (void*)evt.xany.window, (int)evt.type);
 
-        jwindow = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
+        w = getJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom,
         #ifdef VERBOSE_ON
                 True
         #else
@@ -53,7 +53,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
         #endif
             );
 
-        if(NULL==jwindow) {
+        if(NULL==w) {
             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);
             continue;
         }
@@ -99,35 +99,35 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
 
         switch(evt.type) {
             case ButtonPress:
-                (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+                (*env)->CallVoidMethod(env, w->jwindow, requestFocusID, JNI_FALSE);
                 #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, 
+                (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, 
                                       modifiers,
                                       (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
                 #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, 
+                (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, 
                                       modifiers,
                                       (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
                 #endif
                 break;
             case ButtonRelease:
                 #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, 
+                (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, 
                                       modifiers,
                                       (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
                 #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, 
+                (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, 
                                       modifiers,
                                       (jint) evt.xbutton.x, (jint) evt.xbutton.y, (jint) evt.xbutton.button, 0.0f /*rotation*/);
                 #endif
                 break;
             case MotionNotify:
                 #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, 
+                (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, 
                                       modifiers,
                                       (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/); 
                 #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, 
+                (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, 
                                       modifiers,
                                       (jint) evt.xmotion.x, (jint) evt.xmotion.y, (jint) 0, 0.0f /*rotation*/); 
                 #endif
@@ -135,11 +135,11 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
             case EnterNotify:
                 DBG_PRINT( "X11: event . EnterNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
                 #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, 
+                (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_ENTERED, 
                                       modifiers,
                                       (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); 
                 #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, 
+                (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_ENTERED, 
                                       modifiers,
                                       (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); 
                 #endif
@@ -147,31 +147,31 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
             case LeaveNotify:
                 DBG_PRINT( "X11: event . LeaveNotify call %p %d/%d\n", (void*)evt.xcrossing.window, evt.xcrossing.x, evt.xcrossing.y);
                 #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, 
+                (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_EXITED, 
                                       modifiers,
                                       (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); 
                 #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, 
+                (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_EXITED, 
                                       modifiers,
                                       (jint) evt.xcrossing.x, (jint) evt.xcrossing.y, (jint) 0, 0.0f /*rotation*/); 
                 #endif
                 break;
             case KeyPress:
                 #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, 
+                (*env)->CallVoidMethod(env, w->jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, 
                                       modifiers, keySym, (jchar) -1);
                 #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, 
+                (*env)->CallVoidMethod(env, w->jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, 
                                       modifiers, keySym, (jchar) -1);
                 #endif
 
                 break;
             case KeyRelease:
                 #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, 
+                (*env)->CallVoidMethod(env, w->jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, 
                                       modifiers, keySym, (jchar) -1);
                 #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, 
+                (*env)->CallVoidMethod(env, w->jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, 
                                       modifiers, keySym, (jchar) -1);
                 #endif
 
@@ -197,11 +197,11 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                     {
                         // update insets
                         int left, right, top, bottom;
-                        NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+                        NewtWindows_updateInsets(env, w->jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
                     }
-                    (*env)->CallVoidMethod(env, jwindow, sizeChangedID, JNI_FALSE,
+                    (*env)->CallVoidMethod(env, w->jwindow, sizeChangedID, JNI_FALSE,
                                             (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
-                    (*env)->CallVoidMethod(env, jwindow, positionChangedID, JNI_FALSE,
+                    (*env)->CallVoidMethod(env, w->jwindow, positionChangedID, JNI_FALSE,
                                             (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
                 }
                 break;
@@ -210,7 +210,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                     jboolean closed;
                     DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X ..\n", 
                         (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
-                    closed = (*env)->CallBooleanMethod(env, jwindow, windowDestroyNotifyID, JNI_FALSE);
+                    closed = (*env)->CallBooleanMethod(env, w->jwindow, windowDestroyNotifyID, JNI_FALSE);
                     DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X, closed: %d\n", 
                         (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type, (int)closed);
                     // Called by Window.java: CloseWindow(); 
@@ -220,12 +220,12 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
 
             case FocusIn:
                 DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
-                (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_TRUE);
+                (*env)->CallVoidMethod(env, w->jwindow, focusChangedID, JNI_FALSE, JNI_TRUE);
                 break;
 
             case FocusOut:
                 DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
-                (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE, JNI_FALSE);
+                (*env)->CallVoidMethod(env, w->jwindow, focusChangedID, JNI_FALSE, JNI_FALSE);
                 break;
 
             case Expose:
@@ -233,7 +233,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                     evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height, evt.xexpose.count);
 
                 if (evt.xexpose.count == 0 && evt.xexpose.width > 0 && evt.xexpose.height > 0) {
-                    (*env)->CallVoidMethod(env, jwindow, windowRepaintID, JNI_FALSE,
+                    (*env)->CallVoidMethod(env, w->jwindow, windowRepaintID, JNI_FALSE,
                         evt.xexpose.x, evt.xexpose.y, evt.xexpose.width, evt.xexpose.height);
                 }
                 break;
@@ -247,9 +247,9 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                     {
                         // update insets
                         int left, right, top, bottom;
-                        NewtWindows_updateInsets(env, jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
+                        NewtWindows_updateInsets(env, w->jwindow, dpy, evt.xany.window, &left, &right, &top, &bottom);
                     }
-                    (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
+                    (*env)->CallVoidMethod(env, w->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
                 }
                 break;
 
@@ -259,7 +259,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                     evt.xunmap.event!=evt.xunmap.window);
                 if( evt.xunmap.event == evt.xunmap.window ) {
                     // ignore child window notification
-                    (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE);
+                    (*env)->CallVoidMethod(env, w->jwindow, visibleChangedID, JNI_FALSE, JNI_FALSE);
                 }
                 break;
 
@@ -292,7 +292,7 @@ void X11EventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                             (void*)evt.xreparent.parent, (void*)parentRoot, (void*)parentTopParent,
                             (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
                     #endif
-                    (*env)->CallVoidMethod(env, jwindow, reparentNotifyID, (jlong)evt.xreparent.parent);
+                    (*env)->CallVoidMethod(env, w->jwindow, reparentNotifyID, (jlong)evt.xreparent.parent);
                 }
                 break;
 
index e640b0c..ca76824 100644 (file)
@@ -82,27 +82,176 @@ static uintptr_t getPtrOut32Long(unsigned long * src) {
     return res;
 }
 
-static void setJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, jobject jwindow) {
-    unsigned long jogl_java_object_data[2]; // X11 is based on 'unsigned long'
-    int nitems_32 = putPtrIn32Long( jogl_java_object_data, (uintptr_t) jwindow);
+#define _NET_WM_STATE_REMOVE 0
+#define _NET_WM_STATE_ADD 1
 
-    {
-        jobject test = (jobject) getPtrOut32Long(jogl_java_object_data);
-        if( ! (jwindow==test) ) {
-            NewtCommon_FatalError(env, "Internal Error .. Encoded Window ref not the same %p != %p !", jwindow, test);
+#define _MASK_NET_WM_STATE                   ( 1 <<  0 )
+#define _MASK_NET_WM_STATE_MODAL             ( 1 <<  1 )
+#define _MASK_NET_WM_STATE_STICKY            ( 1 <<  2 )
+#define _MASK_NET_WM_STATE_MAXIMIZED_VERT    ( 1 <<  3 )
+#define _MASK_NET_WM_STATE_MAXIMIZED_HORZ    ( 1 <<  4 )
+#define _MASK_NET_WM_STATE_SHADED            ( 1 <<  5 )
+#define _MASK_NET_WM_STATE_HIDDEN            ( 1 <<  8 )
+#define _MASK_NET_WM_STATE_FULLSCREEN        ( 1 <<  9 )
+#define _MASK_NET_WM_STATE_ABOVE             ( 1 << 10 )
+#define _MASK_NET_WM_STATE_BELOW             ( 1 << 11 )
+#define _MASK_NET_WM_STATE_DEMANDS_ATTENTION ( 1 << 12 )
+#define _MASK_NET_WM_STATE_FOCUSED           ( 1 << 13 )
+#define _MASK_NET_WM_BYPASS_COMPOSITOR       ( 1 << 14 )
+#define _MASK_NET_WM_DESKTOP                 ( 1 << 15 )
+#define _MASK_NET_CURRENT_DESKTOP            ( 1 << 16 )
+#define _MASK_NET_WM_WINDOW_TYPE             ( 1 << 17 )
+#define _MASK_NET_WM_WINDOW_TYPE_NORMAL      ( 1 << 18 )
+#define _MASK_NET_WM_WINDOW_TYPE_POPUP_MENU  ( 1 << 19 )
+#define _MASK_NET_FRAME_EXTENTS              ( 1 << 20 )
+#define _MASK_NET_SUPPORTED                  ( 1 << 21 )
+#define _MASK_WM_CHANGE_STATE                ( 1 << 22 )
+#define _MASK_MOTIF_WM_HINTS                 ( 1 << 23 )
+
+#define _NET_WM_STATE_IDX 0
+#define _NET_WM_STATE_MODAL_IDX 1
+#define _NET_WM_STATE_STICKY_IDX 2
+#define _NET_WM_STATE_MAXIMIZED_VERT_IDX 3
+#define _NET_WM_STATE_MAXIMIZED_HORZ_IDX 4
+#define _NET_WM_STATE_SHADED_IDX 5
+#define _NET_WM_STATE_SKIP_TASKBAR_IDX 6
+#define _NET_WM_STATE_SKIP_PAGER_IDX 7
+#define _NET_WM_STATE_HIDDEN_IDX 8
+#define _NET_WM_STATE_FULLSCREEN_IDX 9
+#define _NET_WM_STATE_ABOVE_IDX 10
+#define _NET_WM_STATE_BELOW_IDX 11
+#define _NET_WM_STATE_DEMANDS_ATTENTION_IDX 12
+#define _NET_WM_STATE_FOCUSED_IDX 13
+#define _NET_WM_BYPASS_COMPOSITOR_IDX 14
+#define _NET_WM_DESKTOP_IDX 15
+#define _NET_CURRENT_DESKTOP_IDX 16
+#define _NET_WM_WINDOW_TYPE_IDX 17
+#define _NET_WM_WINDOW_TYPE_NORMAL_IDX 18
+#define _NET_WM_WINDOW_TYPE_POPUP_MENU_IDX 19
+#define _NET_FRAME_EXTENTS_IDX 20
+#define _NET_SUPPORTED_IDX 21
+#define _WM_CHANGE_STATE_IDX 22
+#define _MOTIF_WM_HINTS_IDX 23
+static const char * _ALL_ATOM_NAMES[] = { 
+    /*  0 */ "_NET_WM_STATE",
+    /*  1 */ "_NET_WM_STATE_MODAL",
+    /*  2 */ "_NET_WM_STATE_STICKY",
+    /*  3 */ "_NET_WM_STATE_MAXIMIZED_VERT",
+    /*  4 */ "_NET_WM_STATE_MAXIMIZED_HORZ",
+    /*  5 */ "_NET_WM_STATE_SHADED",
+    /*  6 */ "_NET_WM_STATE_SKIP_TASKBAR",
+    /*  7 */ "_NET_WM_STATE_SKIP_PAGER",
+    /*  8 */ "_NET_WM_STATE_HIDDEN",
+    /*  9 */ "_NET_WM_STATE_FULLSCREEN",
+    /* 10 */ "_NET_WM_STATE_ABOVE",
+    /* 11 */ "_NET_WM_STATE_BELOW",
+    /* 12 */ "_NET_WM_STATE_DEMANDS_ATTENTION",
+    /* 13 */ "_NET_WM_STATE_FOCUSED",
+    /* 14 */ "_NET_WM_BYPASS_COMPOSITOR",
+    /* 15 */ "_NET_WM_DESKTOP",
+    /* 16 */ "_NET_CURRENT_DESKTOP",
+    /* 17 */ "_NET_WM_WINDOW_TYPE",
+    /* 18 */ "_NET_WM_WINDOW_TYPE_NORMAL",
+    /* 19 */ "_NET_WM_WINDOW_TYPE_POPUP_MENU",
+    /* 20 */ "_NET_FRAME_EXTENTS",
+    /* 21 */ "_NET_SUPPORTED",
+    /* 22 */ "WM_CHANGE_STATE",
+    /* 23 */ "_MOTIF_WM_HINTS"
+};
+static const uint32_t _ALL_ATOM_COUNT = (uint32_t)(sizeof(_ALL_ATOM_NAMES)/sizeof(const char *));
+
+static uint32_t NewtWindows_getSupportedFeatureEWMH(Display *dpy, const Atom * allAtoms, const Atom action, const int num, Bool verbose) {
+    uint32_t i;
+    for(i=1; i<_ALL_ATOM_COUNT; i++) {
+        if( action == allAtoms[i] ) {
+            if(verbose) {
+                fprintf(stderr, "...... [%d] -> [%d/%d]: %s\n", num, i, _ALL_ATOM_COUNT, _ALL_ATOM_NAMES[i]);
+            }
+            return 1U << i;
         }
     }
+    if(verbose) {
+        char * astr = XGetAtomName(dpy, action);
+        fprintf(stderr, "...... [%d] -> [_/%d]: %s (undef)\n", num, _ALL_ATOM_COUNT, astr);
+        XFree(astr);
+    }
+    return 0;
+}
+static uint32_t NewtWindows_getSupportedFeaturesEWMH(Display *dpy, Window root, Atom * allAtoms, Bool verbose) {
+    Atom * actions = NULL;
+    Atom type = 0;
+    unsigned long action_len = 0, remain = 0;
+    int form = 0, i = 0;
+    uint32_t res = 0;
+    Status s;
 
+    XSync(dpy, False);
+    if ( Success == (s = XGetWindowProperty(dpy, root, allAtoms[_NET_SUPPORTED_IDX], 0, 1024, False, AnyPropertyType,
+                                            &type, &form, &action_len, &remain, (unsigned char**)&actions)) ) {
+        if( NULL != actions ) {
+            for(i=0; i<action_len; i++) {
+                res |= NewtWindows_getSupportedFeatureEWMH(dpy, allAtoms, actions[i], i, verbose);
+            }
+            XFree(actions);
+        }
+        if(verbose) {
+            fprintf(stderr, "**************** X11: Feature EWMH CHECK: 0x%X\n", res);
+        }
+    } else if(verbose) {
+        fprintf(stderr, "**************** X11: Feature EWMH CHECK: XGetWindowProperty failed: %d\n", s);
+    }
+    return res;
+}
+
+static JavaWindow* createJavaWindowProperty(JNIEnv *env, Display *dpy, Window root, Window window, 
+                                            jlong javaObjectAtom, jlong windowDeleteAtom, jobject obj, Bool verbose) {
+    jobject jwindow = (*env)->NewGlobalRef(env, obj);
+    JavaWindow * res;
+    {
+        Atom * allAtoms = calloc(_ALL_ATOM_COUNT, sizeof(Atom));
+        if( 0 == XInternAtoms( dpy, (char **)_ALL_ATOM_NAMES, _ALL_ATOM_COUNT, False, allAtoms) ) {
+            // error
+            fprintf(stderr, "**************** X11: XInternAtoms failed\n");
+            return NULL;
+        }
+        res = calloc(1, sizeof(JavaWindow));
+        res->window = window;
+        res->jwindow = jwindow;
+        res->allAtoms = allAtoms;
+        res->javaObjectAtom = (Atom)javaObjectAtom;
+        res->windowDeleteAtom = (Atom)windowDeleteAtom;
+        res->supportedAtoms = NewtWindows_getSupportedFeaturesEWMH(dpy, root, allAtoms, verbose);
+        res->lastDesktop = 0; //undef
+    }
+    unsigned long jogl_java_object_data[2]; // X11 is based on 'unsigned long'
+    int nitems_32 = putPtrIn32Long( jogl_java_object_data, (uintptr_t) res);
+    {
+        JavaWindow * test = (JavaWindow *) getPtrOut32Long(jogl_java_object_data);
+        if( res != test ) {
+            NewtCommon_FatalError(env, "Internal Error .. Encoded Window ref not the same %p != %p !", res, test);
+        }
+    }
     XChangeProperty( dpy, window, (Atom)javaObjectAtom, (Atom)javaObjectAtom, 32, PropModeReplace, 
                                      (unsigned char *)&jogl_java_object_data, nitems_32);
+    return res;
 }
-
-jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) {
+static void destroyJavaWindow(JNIEnv *env, JavaWindow *w) {
+    if( NULL != w ) {
+        (*env)->DeleteGlobalRef(env, w->jwindow);
+        w->jwindow = 0;
+        if( NULL != w->allAtoms ) {
+            free(w->allAtoms);
+            w->allAtoms = NULL;
+        }
+        free(w);
+    }
+}
+JavaWindow * getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong javaObjectAtom, Bool showWarning) {
     Atom actual_type = 0;
     int actual_format = 0;
     int nitems_32 = ( sizeof(uintptr_t) == 8 ) ? 2 : 1 ;
     unsigned char * jogl_java_object_data_pp = NULL;
-    jobject jwindow = 0;
+    JavaWindow * res = NULL;
 
     {
         unsigned long nitems= 0;
@@ -133,15 +282,15 @@ jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, jlong ja
         }
     }
 
-    jwindow = (jobject) getPtrOut32Long( (unsigned long *) jogl_java_object_data_pp ) ;
+    res = (JavaWindow *) getPtrOut32Long( (unsigned long *) jogl_java_object_data_pp ) ;
     XFree(jogl_java_object_data_pp);
 
 #ifdef VERBOSE_ON
-    if(JNI_FALSE == (*env)->IsInstanceOf(env, jwindow, X11NewtWindowClazz)) {
-        NewtCommon_throwNewRuntimeException(env, "fetched Atom NEWT_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !", jwindow);
+    if(JNI_FALSE == (*env)->IsInstanceOf(env, res->jwindow, X11NewtWindowClazz)) {
+        NewtCommon_throwNewRuntimeException(env, "fetched Atom NEWT_JAVA_OBJECT window is not a NEWT Window: javaWindow 0x%X !", res->jwindow);
     }
 #endif
-    return jwindow;
+    return res;
 }
 
 /** @return zero if fails, non zero if OK */
@@ -190,19 +339,18 @@ static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window
     }
     return 0; // Error
 }
-static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left, int *right, int *top, int *bottom) {
+static Status NewtWindows_getFrameExtends(Display *dpy, JavaWindow *w, int *left, int *right, int *top, int *bottom) {
     Atom actual_type = 0;
     int actual_format = 0;
     int nitems_32 = 4; // l, r, t, b
     unsigned char * frame_extends_data_pp = NULL;
 
     {
-        Atom _NET_FRAME_EXTENTS = XInternAtom( dpy, "_NET_FRAME_EXTENTS", False );
         unsigned long nitems = 0;
         unsigned long bytes_after = 0;
         int res;
 
-        res = XGetWindowProperty(dpy, window, _NET_FRAME_EXTENTS, 0, nitems_32, False, 
+        res = XGetWindowProperty(dpy, w->window, w->allAtoms[_NET_FRAME_EXTENTS_IDX], 0, nitems_32, False, 
                                  AnyPropertyType, &actual_type, &actual_format, 
                                  &nitems, &bytes_after, &frame_extends_data_pp);
 
@@ -241,46 +389,44 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left
 #define MWM_HINTS_DECORATIONS   (1L << 1)
 #define PROP_MWM_HINTS_ELEMENTS 5
 
-static void NewtWindows_setDecorations (Display *dpy, Window w, Bool decorated) {
+static void NewtWindows_setDecorations (Display *dpy, JavaWindow *w, Bool decorated) {
 
 #ifdef DECOR_USE_MWM
     unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
-    Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
 #endif
 
 #ifdef DECOR_USE_EWMH
-    Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False );
     Atom types[3]={0};
     int ntypes=0;
     if(True==decorated) {
-        types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False );
+        types[ntypes++] = w->allAtoms[_NET_WM_WINDOW_TYPE_NORMAL_IDX];
     } else {
-        types[ntypes++] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_POPUP_MENU", False );
+        types[ntypes++] = w->allAtoms[_NET_WM_WINDOW_TYPE_POPUP_MENU_IDX];
     }
 #endif
 
 #ifdef DECOR_USE_MWM
-    XChangeProperty( dpy, w, _MOTIF_WM_HINTS, _MOTIF_WM_HINTS, 32, PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS);
+    XChangeProperty( dpy, w->window, w->allAtoms[_MOTIF_WM_HINTS_IDX], w->allAtoms[_MOTIF_WM_HINTS_IDX], 32, PropModeReplace, 
+                     (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS);
 #endif
 
 #ifdef DECOR_USE_EWMH
-    XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
+    XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_WINDOW_TYPE_IDX], XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, ntypes);
 #endif
 
     XSync(dpy, False);
 }
 
-static Bool NewtWindows_hasDecorations (Display *dpy, Window w) {
+static Bool NewtWindows_hasDecorations (Display *dpy, JavaWindow * w) {
     Bool decor = False;
 
 #ifdef DECOR_USE_MWM
-    Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
     unsigned char *wm_data = NULL;
     Atom wm_type = 0;
     int wm_format = 0;
     unsigned long wm_nitems = 0, wm_bytes_after = 0;
  
-    if( Success == XGetWindowProperty(dpy, w, _MOTIF_WM_HINTS, 0, PROP_MWM_HINTS_ELEMENTS, False, AnyPropertyType, 
+    if( Success == XGetWindowProperty(dpy, w->window, w->allAtoms[_MOTIF_WM_HINTS_IDX], 0, PROP_MWM_HINTS_ELEMENTS, False, AnyPropertyType, 
                                       &wm_type, &wm_format, &wm_nitems, &wm_bytes_after, &wm_data) ) {
         if(wm_type != None && NULL != wm_data && wm_nitems >= PROP_MWM_HINTS_ELEMENTS) {
             // unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
@@ -292,22 +438,184 @@ static Bool NewtWindows_hasDecorations (Display *dpy, Window w) {
         }
     }
 #endif
-
     return decor;
 }
 
-static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
-    Atom _NET_WM_WINDOW_TYPE = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE", False );
-    Atom types[1]={0};
-    types[0] = XInternAtom( dpy, "_NET_WM_WINDOW_TYPE_NORMAL", False );
-    XChangeProperty( dpy, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1);
+static void NewtWindows_requestFocus (Display *dpy, JavaWindow * jw, Bool force) {
+    XWindowAttributes xwa;
+    Window focus_return;
+    int revert_to_return;
+
+    XSync(dpy, False);
+    XGetInputFocus(dpy, &focus_return, &revert_to_return);
+    DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)jw->window, force, focus_return==jw->window);
+
+    if( True==force || focus_return!=jw->window) {
+        DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)jw->window);
+        XRaiseWindow(dpy, jw->window);
+        NewtWindows_setCWAbove(dpy, jw->window);
+        // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable
+        XGetWindowAttributes(dpy, jw->window, &xwa);
+        DBG_PRINT( "X11: XSetInputFocus dpy %p,win %p, isViewable %d\n", dpy, (void*)jw->window, (xwa.map_state == IsViewable));
+        if(xwa.map_state == IsViewable) {
+            XSetInputFocus(dpy, jw->window, RevertToParent, CurrentTime);
+        }
+    }
+    DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)jw->window, force);
     XSync(dpy, False);
 }
 
-#define _NET_WM_STATE_REMOVE 0
-#define _NET_WM_STATE_ADD 1
-#define _NET_WM_STATE_FLAG_FULLSCREEN        ( 1 << 0 )
-#define _NET_WM_STATE_FLAG_ABOVE             ( 1 << 1 )
+Status NewtWindows_updateInsets(JNIEnv *env, Display *dpy, JavaWindow * w, int *left, int *right, int *top, int *bottom) {
+    if(0 != NewtWindows_getFrameExtends(dpy, w, left, right, top, bottom)) {
+        DBG_PRINT( "NewtWindows_updateInsets: insets by _NET_FRAME_EXTENTS [ l %d, r %d, t %d, b %d ]\n",
+            *left, *right, *top, *bottom);
+        (*env)->CallVoidMethod(env, w->jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom);
+        return 1; // OK
+    }
+
+    Bool hasDecor = NewtWindows_hasDecorations (dpy, w);
+    if(hasDecor) {
+        // The following logic only works if window is top-level _and_ the WM
+        // has 'decorated' our client window w/ another parent window _within_ the actual 'framed' window.
+        Window parent = NewtWindows_getParent(dpy, w->window);
+        if(0 != NewtWindows_getWindowPositionRelative2Parent (dpy, parent, left, top)) {
+            *right = *left; *bottom = *top;
+            DBG_PRINT( "NewtWindows_updateInsets: insets by parent position [ l %d, r %d, t %d, b %d ]\n",
+                *left, *right, *top, *bottom);
+            (*env)->CallVoidMethod(env, w->jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom);
+            return 1; // OK
+        }
+    }
+    DBG_PRINT( "NewtWindows_updateInsets: cannot determine insets - hasDecor %d\n", hasDecor);
+    return 0; // Error
+}
+
+void NewtWindows_updateMinMaxSize(JNIEnv *env, Display *dpy, JavaWindow * w) {
+    XSizeHints * xsh = XAllocSizeHints();
+    long xsh_bits = 0;
+    int min_width=-1, min_height=-1;
+    int max_width=-1, max_height=-1;
+    if( NULL != xsh ) {
+        xsh->flags = 0;
+        xsh->min_width=0;
+        xsh->min_height=0;
+        xsh->max_width=0;
+        xsh->max_height=0;
+        if( 0 != XGetWMNormalHints(dpy, w->window, xsh, &xsh_bits) ) {
+            // OK
+            if( 0 != ( xsh_bits & PMinSize ) ) {
+                min_width  = xsh->min_width;
+                min_height = xsh->min_height;
+            }
+            if( 0 != ( xsh_bits & PMaxSize ) ) {
+                max_width  = xsh->max_width;
+                max_height = xsh->max_height;
+            }
+            DBG_PRINT( "NewtWindows_updateMinMaxSize: XGetWMNormalHints 0x%X / 0x%X for window %p on display %p\n", xsh_bits, xsh->flags, (void*)w->window, dpy);
+            (*env)->CallVoidMethod(env, w->jwindow, minMaxSizeChangedID, min_width, min_height, max_width, max_height);
+        } else {
+            DBG_PRINT( "NewtWindows_updateMinMaxSize: XGetWMNormalHints failed (0x%X / 0x%X) for window %p on display %p\n", xsh_bits, xsh->flags, (void*)w->window, dpy);
+        }
+        XFree(xsh);
+    }
+}
+
+static void NewtWindows_setMinMaxSize(Display *dpy, JavaWindow *w, int min_width, int min_height, int max_width, int max_height) {
+    XSizeHints * xsh = XAllocSizeHints();
+    if( NULL != xsh ) {
+        if( -1 != min_width && -1 != min_height && -1 != max_width && -1 != max_height ) {
+            xsh->flags = PMinSize | PMaxSize;
+            xsh->min_width=min_width;
+            xsh->min_height=min_height;
+            xsh->max_width=max_width;
+            xsh->max_height=max_height;
+        }
+#if 0
+        XSetWMNormalHints(dpy, w->window, xsh);
+#else
+        XSetWMSizeHints(dpy, w->window, xsh, XA_WM_NORMAL_HINTS);
+#endif
+        XFree(xsh);
+    }
+}
+
+static void NewtWindows_setWindowTypeEWMH (Display *dpy, JavaWindow * w, int typeIdx) {
+    Atom types[1]={0};
+    if( _NET_WM_WINDOW_TYPE_NORMAL_IDX == typeIdx ) {
+        types[0] = w->allAtoms[_NET_WM_WINDOW_TYPE_NORMAL_IDX];
+    } // else { }
+    if( 0 != types[0] ) {
+        XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_WINDOW_TYPE_IDX], XA_ATOM, 32, PropModeReplace, (unsigned char *)&types, 1);
+        XSync(dpy, False);
+    }
+}
+
+static void NewtWindows_sendNET_WM_STATE(Display *dpy, Window root, JavaWindow *w, int prop1Idx, int prop2Idx, Bool enable) {
+    XEvent xev;
+    int i=0;
+    
+    memset ( &xev, 0, sizeof(xev) );
+    
+    xev.type = ClientMessage;
+    xev.xclient.window = w->window;
+    xev.xclient.message_type = w->allAtoms[_NET_WM_STATE_IDX];
+    xev.xclient.format = 32;
+        
+    xev.xclient.data.l[i++] = enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
+    if( 0 < prop1Idx ) {
+        xev.xclient.data.l[i++] = w->allAtoms[prop1Idx];
+    }
+    if( 0 < prop2Idx ) {
+        xev.xclient.data.l[i++] = w->allAtoms[prop2Idx];
+    }
+    xev.xclient.data.l[3] = 1; //source indication for normal applications
+
+    XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev );
+}
+static unsigned long NewtWindows_getDesktopNum(Display *dpy, Window root, JavaWindow * w) {
+    unsigned long res = 0;
+    unsigned long * data_pp = NULL;
+
+    Atom actual_type = 0;
+    int actual_format = 0;
+    unsigned long nitems= 0;
+    unsigned long bytes_after= 0;
+
+    if( Success == XGetWindowProperty(dpy, w->window, w->allAtoms[_NET_WM_DESKTOP_IDX], 0, 1, False, 
+                                      AnyPropertyType, &actual_type, &actual_format, 
+                                      &nitems, &bytes_after, (unsigned char **)&data_pp) ) 
+    {
+        if(XA_CARDINAL==actual_type && 32==actual_format && 1<=nitems && NULL!=data_pp) {
+            res = *data_pp;
+            DBG_PRINT("Info: NEWT X11Window: _NET_WM_DESKTOP: %ld\n", res);
+        } else {
+            DBG_PRINT("Warning: NEWT X11Window: Fetch _NET_WM_DESKTOP failed: nitems %ld, bytes_after %ld, actual_type %ld, actual_format %d, data_pp %p\n", 
+                nitems, bytes_after, (long)actual_type, actual_format, data_pp);
+            if( NULL != data_pp ) {
+                DBG_PRINT("Warning:  *data_pp = %ld\n", *data_pp);
+            }
+        }
+        if(NULL!=data_pp) {
+            XFree(data_pp);
+        }
+    } else {
+        DBG_PRINT("Warning: NEWT X11Window: Could not fetch _NET_WM_DESKTOP, nitems %ld, bytes_after %ld, result 0!\n", nitems, bytes_after);
+    }
+    return res;
+}
+static void NewtWindows_sendNET_WM_DESKTOP(Display *dpy, Window root, JavaWindow * w, unsigned long deskNum) {
+    XEvent xev;
+    memset ( &xev, 0, sizeof(xev) );
+
+    xev.type = ClientMessage;
+    xev.xclient.window = w->window;
+    xev.xclient.message_type = w->allAtoms[_NET_WM_DESKTOP_IDX];
+    xev.xclient.format = 32;
+    xev.xclient.data.l[0] = deskNum;
+    xev.xclient.data.l[1] = 1; //source indication for normal applications
+    XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev );
+}
+
 
 /**
  * Set fullscreen using Extended Window Manager Hints (EWMH)
@@ -320,151 +628,98 @@ static void NewtWindows_setNormalWindowEWMH (Display *dpy, Window w) {
  * and resets it when leaving FS.
  * The same is assumed for the decoration state.
  */
-static int NewtWindows_getSupportedStackingEWMHFlags(Display *dpy, Window w) {
-#ifdef VERBOSE_ON
-    // Code doesn't work reliable on KDE4 ...
-    Atom _NET_WM_ALLOWED_ACTIONS = XInternAtom( dpy, "_NET_WM_ALLOWED_ACTIONS", False );
-    Atom _NET_WM_ACTION_FULLSCREEN = XInternAtom( dpy, "_NET_WM_ACTION_FULLSCREEN", False );
-    Atom _NET_WM_ACTION_ABOVE = XInternAtom( dpy, "_NET_WM_ACTION_ABOVE", False );
-    Atom * actions = NULL;
-    Atom type = 0;
-    unsigned long action_len = 0, remain = 0;
-    int res = 0, form = 0, i = 0;
-    Status s;
-
-    if ( Success == (s = XGetWindowProperty(dpy, w, _NET_WM_ALLOWED_ACTIONS, 0, 1024, False, AnyPropertyType,
-                                            &type, &form, &action_len, &remain, (unsigned char**)&actions)) ) {
-        if( NULL != actions ) {
-            for(i=0; i<action_len; i++) {
-                if(_NET_WM_ACTION_FULLSCREEN == actions[i]) {
-                    DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_FULLSCREEN (*)\n", i);
-                    res |= _NET_WM_STATE_FLAG_FULLSCREEN ;
-                } else if(_NET_WM_ACTION_ABOVE == actions[i]) {
-                    DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: _NET_WM_ACTION_ABOVE (*)\n", i);
-                    res |= _NET_WM_STATE_FLAG_ABOVE ;
-                }
-                else {
-                    char * astr = XGetAtomName(dpy, actions[i]);
-                    DBG_PRINT( "**************** X11: FS EWMH CHECK[%d]: %s (unused)\n", i, astr);
-                    XFree(astr);
-                }
-            }
-            XFree(actions);
-        }
-        DBG_PRINT( "**************** X11: FS EWMH CHECK: 0x%X\n", res);
-    } else {
-        DBG_PRINT( "**************** X11: FS EWMH CHECK: XGetWindowProperty failed: %d\n", s);
+static void NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, JavaWindow * w, int ewmhFlags, Bool enable) {
+    if( 0 == ewmhFlags ) {
+        return;
     }
-#endif
-    return _NET_WM_STATE_FLAG_FULLSCREEN | _NET_WM_STATE_FLAG_ABOVE ;
-}
-
-static Bool NewtWindows_setStackingEWMHFlags (Display *dpy, Window root, Window w, int ewmhFlags, Bool isVisible, Bool enable) {
-    Atom _NET_WM_STATE = XInternAtom( dpy, "_NET_WM_STATE", False );
-    Atom _NET_WM_STATE_ABOVE = XInternAtom( dpy, "_NET_WM_STATE_ABOVE", False );
-    Atom _NET_WM_STATE_FULLSCREEN = XInternAtom( dpy, "_NET_WM_STATE_FULLSCREEN", False );
-    int ewmhMask = NewtWindows_getSupportedStackingEWMHFlags(dpy, w);
-    Bool changeFullscreen = 0 != ( ( _NET_WM_STATE_FLAG_FULLSCREEN & ewmhMask ) & ewmhFlags ) ;
-    Bool changeAbove =      0 != ( ( _NET_WM_STATE_FLAG_ABOVE      & ewmhMask ) & ewmhFlags ) ;
-    Bool res = False;
-
-    if(0 == ewmhMask) { 
-        return res;
-    }
-
-    // _NET_WM_STATE: fullscreen and/or above
-    if( changeFullscreen || changeAbove ) {
-        {
-            // _NET_WM_STATE as event to root window
-            XEvent xev;
-            long mask = SubstructureNotifyMask | SubstructureRedirectMask ;
-            int i=0;
-            
-            memset ( &xev, 0, sizeof(xev) );
-            
-            xev.type = ClientMessage;
-            xev.xclient.window = w;
-            xev.xclient.message_type = _NET_WM_STATE;
-            xev.xclient.format = 32;
-                
-            xev.xclient.data.l[i++] = enable ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE ;
-            if( changeFullscreen ) {
-                xev.xclient.data.l[i++] = _NET_WM_STATE_FULLSCREEN;
-            }
-            if( changeAbove ) {
-                xev.xclient.data.l[i++] = _NET_WM_STATE_ABOVE;
-            }
-            xev.xclient.data.l[3] = 1; //source indication for normal applications
-
-            XSendEvent ( dpy, root, False, mask, &xev );
+    Bool changeSticky =     0 != ( _MASK_NET_WM_STATE_STICKY         & ewmhFlags ) ;
+    Bool changeFullscreen = 0 != ( _MASK_NET_WM_STATE_FULLSCREEN     & ewmhFlags ) ;
+    Bool changeAbove =      0 != ( _MASK_NET_WM_STATE_ABOVE          & ewmhFlags ) ;
+    Bool changeBelow =      0 != ( _MASK_NET_WM_STATE_BELOW          & ewmhFlags ) ;
+    Bool changeMaxVert =    0 != ( _MASK_NET_WM_STATE_MAXIMIZED_VERT & ewmhFlags ) ;
+    Bool changeMaxHorz =    0 != ( _MASK_NET_WM_STATE_MAXIMIZED_HORZ & ewmhFlags ) ;
+
+    if( changeSticky ) {
+        unsigned long deskNum;
+        if( enable ) {
+            w->lastDesktop = NewtWindows_getDesktopNum(dpy, root, w);
+            deskNum = 0xFFFFFFFFU;
+        } else {
+            deskNum = w->lastDesktop;
+        }
+        NewtWindows_sendNET_WM_STATE(dpy, root, w, _NET_WM_STATE_STICKY_IDX, 0, enable);
+        NewtWindows_sendNET_WM_DESKTOP(dpy, root, w, deskNum);
+    } else if( changeFullscreen || changeAbove || changeBelow ) {
+        int prop2Idx;
+        if( changeAbove ) {
+            prop2Idx = _NET_WM_STATE_ABOVE_IDX;
+        } else if( changeBelow ) {
+            prop2Idx = _NET_WM_STATE_BELOW_IDX;
+        } else {
+            prop2Idx = 0;
         }
+        NewtWindows_sendNET_WM_STATE(dpy, root, w,
+                                     changeFullscreen ? _NET_WM_STATE_FULLSCREEN_IDX : 0, 
+                                     prop2Idx, 
+                                     enable);
         // Also change _NET_WM_BYPASS_COMPOSITOR!
         //   A value of 0 indicates no preference. 
         //   A value of 1 hints the compositor to disabling compositing of this window. 
         //   A value of 2 hints the compositor to not disabling compositing of this window
-        {
-            Atom _NET_WM_BYPASS_COMPOSITOR = XInternAtom( dpy, "_NET_WM_BYPASS_COMPOSITOR", False );
+        if( changeFullscreen ) {
             unsigned long value = enable ? 1 : 0;
-            XChangeProperty( dpy, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1); 
+            XChangeProperty( dpy, w->window, w->allAtoms[_NET_WM_BYPASS_COMPOSITOR_IDX], XA_CARDINAL, 32, PropModeReplace, (unsigned char*)&value, 1); 
         }
-        XSync(dpy, False);
-        res = True;
+    } else if( changeMaxVert || changeMaxHorz ) {
+        NewtWindows_sendNET_WM_STATE(dpy, root, w,
+                                     changeMaxVert ? _NET_WM_STATE_MAXIMIZED_VERT_IDX : 0, 
+                                     changeMaxHorz ? _NET_WM_STATE_MAXIMIZED_HORZ_IDX : 0, 
+                                     enable);
     }
-    DBG_PRINT( "X11: setStackingEWMHFlags ON %d, changeFullscreen %d, changeAbove %d, visible %d: %d\n", 
-        enable, changeFullscreen, changeAbove, isVisible, res);
-    return res;
+    XSync(dpy, False);
+    DBG_PRINT( "X11: setStackingEWMHFlags ON %d, change[Sticky %d, Fullscreen %d, Above %d, Below %d, MaxV %d, MaxH %d]\n", 
+        enable, changeSticky, changeFullscreen, changeAbove, changeBelow, changeMaxVert, changeMaxHorz);
 }
 
-
-Status NewtWindows_updateInsets(JNIEnv *env, jobject jwindow, Display *dpy, Window window, int *left, int *right, int *top, int *bottom) {
-    if(0 != NewtWindows_getFrameExtends(dpy, window, left, right, top, bottom)) {
-        DBG_PRINT( "NewtWindows_updateInsets: insets by _NET_FRAME_EXTENTS [ l %d, r %d, t %d, b %d ]\n",
-            *left, *right, *top, *bottom);
-        (*env)->CallVoidMethod(env, jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom);
-        return 1; // OK
-    }
-
-    Bool hasDecor = NewtWindows_hasDecorations (dpy, window);
-    if(hasDecor) {
-        // The following logic only works if window is top-level _and_ the WM
-        // has 'decorated' our client window w/ another parent window _within_ the actual 'framed' window.
-        Window parent = NewtWindows_getParent(dpy, window);
-        if(0 != NewtWindows_getWindowPositionRelative2Parent (dpy, parent, left, top)) {
-            *right = *left; *bottom = *top;
-            DBG_PRINT( "NewtWindows_updateInsets: insets by parent position [ l %d, r %d, t %d, b %d ]\n",
-                *left, *right, *top, *bottom);
-            (*env)->CallVoidMethod(env, jwindow, insetsChangedID, JNI_FALSE, *left, *right, *top, *bottom);
-            return 1; // OK
-        }
-    }
-    DBG_PRINT( "NewtWindows_updateInsets: cannot determine insets - hasDecor %d\n", hasDecor);
-    return 0; // Error
+static Bool WaitForMapNotify( Display *dpy, XEvent *event, XPointer arg ) {
+    return (event->type == MapNotify) && (event->xmap.window == (Window) arg);
 }
 
-static void NewtWindows_requestFocus (Display *dpy, Window w, Bool force) {
-    XWindowAttributes xwa;
-    Window focus_return;
-    int revert_to_return;
-
-    XSync(dpy, False);
-    XGetInputFocus(dpy, &focus_return, &revert_to_return);
-    DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d, hasFocus %d\n", dpy, (void*)w, force, focus_return==w);
+static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) {
+    return (event->type == UnmapNotify) && (event->xmap.window == (Window) arg);
+}
 
-    if( True==force || focus_return!=w) {
-        DBG_PRINT( "X11: XRaiseWindow dpy %p, win %p\n", dpy, (void*)w);
-        XRaiseWindow(dpy, w);
-        NewtWindows_setCWAbove(dpy, w);
-        // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable
-        XGetWindowAttributes(dpy, w, &xwa);
-        DBG_PRINT( "X11: XSetInputFocus dpy %p,win %p, isViewable %d\n", dpy, (void*)w, (xwa.map_state == IsViewable));
-        if(xwa.map_state == IsViewable) {
-            XSetInputFocus(dpy, w, RevertToParent, CurrentTime);
+static void NewtWindows_setVisible(Display *dpy, Window root, JavaWindow* jw, Bool visible, Bool useWM, Bool waitForMapNotify) {
+    XEvent event;
+    if( !visible && useWM && 0 != ( _MASK_NET_WM_STATE_HIDDEN & jw->supportedAtoms ) ) {
+        XEvent xev;
+        memset ( &xev, 0, sizeof(xev) );
+        xev.type = ClientMessage;
+        xev.xclient.window = jw->window;
+        xev.xclient.message_type = jw->allAtoms[_WM_CHANGE_STATE_IDX];
+        xev.xclient.format = 32;
+        xev.xclient.data.l[0] = IconicState;
+        XSendEvent ( dpy, root, False, SubstructureNotifyMask | SubstructureRedirectMask, &xev );
+        // NewtWindows_sendNET_WM_STATE(dpy, root, jw, _NET_WM_STATE_HIDDEN_IDX, 0, !visible);
+        if(waitForMapNotify) {
+            XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) jw->window );
+        }
+    } else {
+        if( visible ) {
+            XMapRaised(dpy, jw->window);
+            if(waitForMapNotify) {
+                XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) jw->window );
+            }
+        } else {
+            XUnmapWindow(dpy, jw->window);
+            if(waitForMapNotify) {
+                XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) jw->window );
+            }
         }
     }
-    DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force);
-    XSync(dpy, False);
 }
 
+
 /**
  * Window
  */
@@ -480,15 +735,7 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_initIDs0
     return JNI_TRUE;
 }
 
-static Bool WaitForMapNotify( Display *dpy, XEvent *event, XPointer arg ) {
-    return (event->type == MapNotify) && (event->xmap.window == (Window) arg);
-}
-
-static Bool WaitForUnmapNotify( Display *dpy, XEvent *event, XPointer arg ) {
-    return (event->type == UnmapNotify) && (event->xmap.window == (Window) arg);
-}
-
-static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint width, jint height) {
+static void NewtWindows_setPosSize(Display *dpy, JavaWindow* w, jint x, jint y, jint width, jint height) {
     if( ( width>0 && height>0 ) || ( x>=0 && y>=0 ) ) { // resize/position if requested
         XWindowChanges xwc;
         int flags = CWX | CWY;
@@ -502,27 +749,27 @@ static void NewtWindows_setPosSize(Display *dpy, Window w, jint x, jint y, jint
             xwc.width=width;
             xwc.height=height;
         }
-        XConfigureWindow(dpy, w, flags, &xwc);
+        XConfigureWindow(dpy, w->window, flags, &xwc);
         XSync(dpy, False);
     }
 }
 
 static void NewtWindows_setIcon(Display *dpy, Window w, int data_size, const unsigned char * data_ptr) {
-    Atom _NET_WM_ICON = XInternAtom(dpy, "_NET_WM_ICON", False);
-    Atom CARDINAL = XInternAtom(dpy, "CARDINAL", False);
-    XChangeProperty(dpy, w, _NET_WM_ICON, CARDINAL, 32, PropModeReplace, data_ptr, data_size);
+    Atom _NET_WM_ICON = XInternAtom( dpy, "_NET_WM_ICON", False );
+    XChangeProperty(dpy, w, _NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, data_ptr, data_size);
 }
 
 /*
  * Class:     jogamp_newt_driver_x11_WindowDriver
  * Method:    CreateWindow
  */
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
+JNIEXPORT jlongArray JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
   (JNIEnv *env, jobject obj, jlong parent, jlong display, jint screen_index, 
                              jint visualID, 
                              jlong javaObjectAtom, jlong windowDeleteAtom, 
-                             jint x, jint y, jint width, jint height, jboolean autoPosition, int flags,
-                             jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct)
+                             jint x, jint y, jint width, jint height, int flags,
+                             jint pixelDataSize, jobject pixels, jint pixels_byte_offset, jboolean pixels_is_direct, 
+                             jboolean verbose)
 {
     Display * dpy = (Display *)(intptr_t)display;
     Atom wm_delete_atom = (Atom)windowDeleteAtom;
@@ -530,7 +777,9 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
     Window root = RootWindow(dpy, scrn_idx);
     Window  windowParent = (Window) parent;
     Window  window = 0;
-    jobject jwindow = 0;
+    JavaWindow * javaWindow = NULL;
+    jlong handles[2];
+    jlongArray jhandles;
 
     XVisualInfo visualTemplate;
     XVisualInfo *pVisualQuery = NULL;
@@ -558,9 +807,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
     if(0==windowParent) {
         windowParent = root;
     }
-    DBG_PRINT( "X11: CreateWindow dpy %p, screen %d, visualID 0x%X, parent %p, %d/%d %dx%d, undeco %d, alwaysOnTop %d, autoPosition %d\n", 
+    DBG_PRINT( "X11: CreateWindow dpy %p, screen %d, visualID 0x%X, parent %p, %d/%d %dx%d, undeco %d, alwaysOn[Top %d, Bottom %d], autoPos %d, resizable %d\n", 
         (void*)dpy, scrn_idx, (int)visualID, (void*)windowParent, x, y, width, height,
-        TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), autoPosition);
+        TST_FLAG_IS_UNDECORATED(flags), TST_FLAG_IS_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONBOTTOM(flags),
+        TST_FLAG_IS_AUTOPOSITION(flags), TST_FLAG_IS_RESIZABLE(flags));
 
     // try given VisualID on screen
     memset(&visualTemplate, 0, sizeof(XVisualInfo));
@@ -608,7 +858,7 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
 
     {
         int _x = x, _y = y; // pos for CreateWindow, might be tweaked
-        if(JNI_TRUE == autoPosition) {
+        if( TST_FLAG_IS_AUTOPOSITION(flags) ) {
             // user didn't requested specific position, use WM default
             _x = 0;
             _y = 0;
@@ -631,11 +881,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
     }
 
     XSetWMProtocols(dpy, window, &wm_delete_atom, 1); // windowDeleteAtom
-    jwindow = (*env)->NewGlobalRef(env, obj);
-    setJavaWindowProperty(env, dpy, window, javaObjectAtom, jwindow);
+    javaWindow = createJavaWindowProperty(env, dpy, root, window, javaObjectAtom, windowDeleteAtom, obj, verbose);
 
-    NewtWindows_setNormalWindowEWMH(dpy, window);
-    NewtWindows_setDecorations(dpy, window, TST_FLAG_IS_UNDECORATED(flags) ? False : True );
+    NewtWindows_setWindowTypeEWMH(dpy, javaWindow, _NET_WM_WINDOW_TYPE_NORMAL_IDX);
+    NewtWindows_setDecorations(dpy, javaWindow, TST_FLAG_IS_UNDECORATED(flags) ? False : True );
 
     // since native creation happens at setVisible(true) .. 
     // we can pre-map the window here to be able to gather the insets and position.
@@ -664,30 +913,54 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
         }
 
         // send insets before visibility, allowing java code a proper sync point!
-        NewtWindows_updateInsets(env, jwindow, dpy, window, &left, &right, &top, &bottom);
-        (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
+        NewtWindows_updateInsets(env, dpy, javaWindow, &left, &right, &top, &bottom);
+        (*env)->CallVoidMethod(env, javaWindow->jwindow, visibleChangedID, JNI_FALSE, JNI_TRUE);
 
-        if(JNI_TRUE == autoPosition) {
+        if( TST_FLAG_IS_AUTOPOSITION(flags) ) {
             // get position from WM
             int dest_x, dest_y;
             Window child;
             XTranslateCoordinates(dpy, window, windowParent, 0, 0, &dest_x, &dest_y, &child);
             x = (int)dest_x; y = (int)dest_y;
         }
-        DBG_PRINT("X11: [CreateWindow]: client: %d/%d %dx%d (autoPosition %d)\n", x, y, width, height, autoPosition);
+        DBG_PRINT("X11: [CreateWindow]: client: %d/%d %dx%d, autoPos %d\n", x, y, width, height, TST_FLAG_IS_AUTOPOSITION(flags));
 
         x -= left; // top-level
         y -= top;  // top-level
         DBG_PRINT("X11: [CreateWindow]: top-level: %d/%d\n", x, y);
-        NewtWindows_setPosSize(dpy, window, x, y, width, height);
+        NewtWindows_setPosSize(dpy, javaWindow, x, y, width, height);
 
         if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
-            NewtWindows_setStackingEWMHFlags(dpy, root, window, _NET_WM_STATE_FLAG_ABOVE, True, True);
+            NewtWindows_setStackingEWMHFlags(dpy, root, javaWindow, _MASK_NET_WM_STATE_ABOVE, True);
+        } else if( TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) {
+            NewtWindows_setStackingEWMHFlags(dpy, root, javaWindow, _MASK_NET_WM_STATE_BELOW, True);
+        }
+        if( TST_FLAG_IS_STICKY(flags) ) {
+            NewtWindows_setStackingEWMHFlags(dpy, root, javaWindow, _MASK_NET_WM_STATE_STICKY, True);
+        }
+        if( TST_FLAG_IS_MAXIMIZED_ANY(flags) ) {
+            int cmd = 0;
+            if( TST_FLAG_IS_MAXIMIZED_VERT(flags) ) {
+                cmd = _MASK_NET_WM_STATE_MAXIMIZED_VERT;
+            } 
+            if( TST_FLAG_IS_MAXIMIZED_HORZ(flags) ) {
+                cmd |= _MASK_NET_WM_STATE_MAXIMIZED_HORZ;
+            } 
+            NewtWindows_setStackingEWMHFlags(dpy, root, javaWindow, cmd, True);
+        }
+        if( !TST_FLAG_IS_RESIZABLE(flags) ) {
+            NewtWindows_setMinMaxSize(dpy, javaWindow, width, height, width, height);
         }
     }
-
-    DBG_PRINT( "X11: [CreateWindow] created window %p on display %p\n", (void*)window, dpy);
-    return (jlong) window;
+    handles[0] = (jlong)(intptr_t)window;
+    handles[1] = (jlong)(intptr_t)javaWindow;
+    jhandles = (*env)->NewLongArray(env, 2);
+    if (jhandles == NULL) {
+        NewtCommon_throwNewRuntimeException(env, "Could not allocate long array of size 2");
+    }
+    (*env)->SetLongArrayRegion(env, jhandles, 0, 2, handles);
+    DBG_PRINT( "X11: [CreateWindow] created window %p -> %p on display %p\n", (void*)window, (void*)javaWindow, dpy);
+    return jhandles;
 }
 
 /*
@@ -696,47 +969,53 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CreateWindow0
  * Signature: (JJ)V
  */
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_CloseWindow0
-  (JNIEnv *env, jobject obj, jlong display, jlong window, jlong javaObjectAtom, jlong windowDeleteAtom /*, jlong kbdHandle*/, // XKB disabled for now
+  (JNIEnv *env, jobject obj, jlong display, jlong javaWindow /*, jlong kbdHandle*/, // XKB disabled for now
                              jint randr_event_base, jint randr_error_base)
 {
     Display * dpy = (Display *) (intptr_t) display;
-    Window w = (Window)window;
-    jobject jwindow;
+    JavaWindow * jw, * jw0;
     XWindowAttributes xwa;
 
+    DBG_PRINT( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)javaWindow);
     if(dpy==NULL) {
         NewtCommon_FatalError(env, "invalid display connection..");
     }
-
-    DBG_PRINT( "X11: CloseWindow START dpy %p, win %p\n", (void*)dpy, (void*)w);
-
-    jwindow = getJavaWindowProperty(env, dpy, w, javaObjectAtom, True);
-    if(NULL==jwindow) {
+    jw = (JavaWindow*)(intptr_t)javaWindow;
+    if(jw==NULL) {
+        NewtCommon_FatalError(env, "invalid JavaWindow connection..");
+    }
+    jw0 = getJavaWindowProperty(env, dpy, jw->window, jw->javaObjectAtom, True);
+    if(NULL==jw) {
         NewtCommon_throwNewRuntimeException(env, "could not fetch Java Window object, bail out!");
         return;
     }
-    if ( JNI_FALSE == (*env)->IsSameObject(env, jwindow, obj) ) {
+    if ( jw != jw0 ) {
+        NewtCommon_throwNewRuntimeException(env, "Internal Error .. JavaWindow not the same!");
+        return;
+    }
+    if ( JNI_FALSE == (*env)->IsSameObject(env, jw->jwindow, obj) ) {
         NewtCommon_throwNewRuntimeException(env, "Internal Error .. Window global ref not the same!");
         return;
     }
 
     XSync(dpy, False);
     memset(&xwa, 0, sizeof(XWindowAttributes));
-    XGetWindowAttributes(dpy, w, &xwa); // prefetch colormap to be destroyed after window destruction
-    XSelectInput(dpy, w, 0);
-    XUnmapWindow(dpy, w);
+    XGetWindowAttributes(dpy, jw->window, &xwa); // prefetch colormap to be destroyed after window destruction
+    XSelectInput(dpy, jw->window, 0);
+    XUnmapWindow(dpy, jw->window);
 
     // Drain all events related to this window ..
-    Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, javaObjectAtom, windowDeleteAtom /*, kbdHandle */, // XKB disabled for now
-                                                                          randr_event_base, randr_error_base);
+    Java_jogamp_newt_driver_x11_DisplayDriver_DispatchMessages0(env, obj, display, 
+                                     (jlong)(intptr_t)jw->javaObjectAtom, (jlong)(intptr_t)jw->windowDeleteAtom /*, kbdHandle */, // XKB disabled for now
+                                     randr_event_base, randr_error_base);
 
-    XDestroyWindow(dpy, w);
+    XDestroyWindow(dpy, jw->window);
     if( None != xwa.colormap ) {
         XFreeColormap(dpy, xwa.colormap);
     }
     XSync(dpy, True); // discard all events now, no more handler
 
-    (*env)->DeleteGlobalRef(env, jwindow);
+    destroyJavaWindow(env, jw);
 
     DBG_PRINT( "X11: CloseWindow END\n");
 }
@@ -764,12 +1043,12 @@ static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) {
  */
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindow0
   (JNIEnv *env, jobject obj, jlong jdisplay, jint screen_index,
-   jlong jparent, jlong jwindow, jlong windowDeleteAtom,
+   jlong jparent, jlong javaWindow,
    jint x, jint y, jint width, jint height, jint flags)
 {
     Display * dpy = (Display *) (intptr_t) jdisplay;
-    Window w = (Window)jwindow;
-    Atom wm_delete_atom = (Atom)windowDeleteAtom;
+    JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow;
+    Atom wm_delete_atom = jw->windowDeleteAtom;
     Window root = RootWindow(dpy, screen_index);
     Window parent = (0!=jparent)?(Window)jparent:root;
     XEvent event;
@@ -779,34 +1058,45 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
     int fsEWMHFlags = 0;
     if( TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
         if( !TST_FLAG_IS_FULLSCREEN_SPAN(flags) ) {      // doesn't work w/ spanning across monitors. See also Bug 770 & Bug 771
-            fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN;
+            fsEWMHFlags |= _MASK_NET_WM_STATE_FULLSCREEN;
         }
         if( TST_FLAG_IS_FULLSCREEN(flags) ) {
             if( TST_FLAG_IS_ALWAYSONTOP(flags) ) {
-                fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE; // fs on,  above on
+                fsEWMHFlags |= _MASK_NET_WM_STATE_ABOVE; // fs on,  above on
+            } else if( TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) {
+                fsEWMHFlags |= _MASK_NET_WM_STATE_BELOW; // fs on,  below on
             } // else { }                                // fs on,  above off
         } else if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) {
-            fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE;     // fs off, above off
-        } // else { }                                    // fs off, above on
+            fsEWMHFlags |= _MASK_NET_WM_STATE_ABOVE;     // fs off, above off
+        } else if( !TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) {
+            fsEWMHFlags |= _MASK_NET_WM_STATE_BELOW;     // fs off, below off
+        } // else { }                                    // fs off, above/below on
     } else if( TST_FLAG_CHANGE_PARENTING(flags) ) {
         // Fix for Unity WM, i.e. _remove_ persistent previous states
-        fsEWMHFlags |= _NET_WM_STATE_FLAG_FULLSCREEN;    // fs off
+        fsEWMHFlags |= _MASK_NET_WM_STATE_FULLSCREEN;    // fs off
         if( !TST_FLAG_IS_ALWAYSONTOP(flags) ) {
-            fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE;     // above off
+            fsEWMHFlags |= _MASK_NET_WM_STATE_ABOVE;     // above off
+        } else if( !TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) {
+            fsEWMHFlags |= _MASK_NET_WM_STATE_BELOW;     // below off
         }
     } else if( TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) {
-        fsEWMHFlags |= _NET_WM_STATE_FLAG_ABOVE;         // toggle above
+        fsEWMHFlags |= _MASK_NET_WM_STATE_ABOVE;         // toggle above
+    } else if( TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags) ) {
+        fsEWMHFlags |= _MASK_NET_WM_STATE_BELOW;         // toggle below
     }
 
-    DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, hasParent %d, decorationChange %d, undecorated %d, fullscreenChange %d, fullscreen %d (span %d), alwaysOnTopChange %d, alwaysOnTop %d, visibleChange %d, visible %d, tempInvisible %d, fsEWMHFlags %d\n",
-        (void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)w,
+    DBG_PRINT( "X11: reconfigureWindow0 dpy %p, scrn %d, parent %p/%p, win %p, %d/%d %dx%d, parentChange %d, isChild %d, undecorated[change %d, val %d], fullscreen[change %d, val %d (span %d)], alwaysOn[Top[change %d, val %d], Bottom[change %d, val %d]], visible[change %d, val %d, tempInvisible %d], resizable[change %d, val %d], sticky[change %d, val %d], fsEWMHFlags %d\n",
+        (void*)dpy, screen_index, (void*) jparent, (void*)parent, (void*)jw->window,
         x, y, width, height, 
-        TST_FLAG_CHANGE_PARENTING(flags),   TST_FLAG_HAS_PARENT(flags),
+        TST_FLAG_CHANGE_PARENTING(flags),   TST_FLAG_IS_CHILD(flags),
         TST_FLAG_CHANGE_DECORATION(flags),  TST_FLAG_IS_UNDECORATED(flags),
         TST_FLAG_CHANGE_FULLSCREEN(flags),  TST_FLAG_IS_FULLSCREEN(flags), TST_FLAG_IS_FULLSCREEN_SPAN(flags),
-        TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags),
-        TST_FLAG_CHANGE_VISIBILITY(flags),  TST_FLAG_IS_VISIBLE(flags), 
-        tempInvisible, fsEWMHFlags);
+        TST_FLAG_CHANGE_ALWAYSONTOP(flags), TST_FLAG_IS_ALWAYSONTOP(flags), 
+        TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags), TST_FLAG_IS_ALWAYSONBOTTOM(flags), 
+        TST_FLAG_CHANGE_VISIBILITY(flags),  TST_FLAG_IS_VISIBLE(flags), tempInvisible, 
+        TST_FLAG_CHANGE_RESIZABLE(flags), TST_FLAG_IS_RESIZABLE(flags), 
+        TST_FLAG_CHANGE_STICKY(flags), TST_FLAG_IS_STICKY(flags),
+        fsEWMHFlags);
 
     // FS Note: To toggle FS, utilizing the _NET_WM_STATE_FULLSCREEN WM state should be enough.
     //          However, we have to consider other cases like reparenting and WM which don't support it.
@@ -815,93 +1105,128 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
         !TST_FLAG_IS_FULLSCREEN_SPAN(flags) &&
         ( TST_FLAG_CHANGE_FULLSCREEN(flags) || TST_FLAG_CHANGE_ALWAYSONTOP(flags) ) ) {
         Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ;
-        if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
-            if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration
-                NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
-            }
-            DBG_PRINT( "X11: reconfigureWindow0 X (fs.atop.fast)\n");
-            return;
+        NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, enable);
+        if ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) { // FS off - restore decoration
+            NewtWindows_setDecorations (dpy, jw, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
         }
+        DBG_PRINT( "X11: reconfigureWindow0 X (fs.atop.fast)\n");
+        return;
     }
     #endif
-    // Toggle ALWAYSONTOP (only) w/o visibility or window stacking sideffects
-    if( isVisible && fsEWMHFlags && TST_FLAG_CHANGE_ALWAYSONTOP(flags) &&
-        !TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_CHANGE_FULLSCREEN(flags) ) {
-        if( NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, TST_FLAG_IS_ALWAYSONTOP(flags)) ) {
-            DBG_PRINT( "X11: reconfigureWindow0 X (atop.fast)\n");
-            return;
-        }
+    // Toggle ALWAYSONTOP/BOTTOM (only) w/o visibility or window stacking sideffects
+    if( isVisible && fsEWMHFlags && TST_FLAG_CHANGE_ALWAYSONANY(flags) &&
+        !TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_CHANGE_RESIZABLE(flags) ) {
+        NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, TST_FLAG_IS_ALWAYSONANY(flags));
+        DBG_PRINT( "X11: reconfigureWindow0 X (atop.fast)\n");
+        return;
     }
 
     if( tempInvisible ) {
         DBG_PRINT( "X11: reconfigureWindow0 TEMP VISIBLE OFF\n");
-        XUnmapWindow(dpy, w);
-        XIfEvent( dpy, &event, WaitForUnmapNotify, (XPointer) w );
+        NewtWindows_setVisible(dpy, root, jw, False /* visible */, False /* useWM */, True /* wait */);
         // no need to notify the java side .. just temp change
     }
 
-    if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags)  && !TST_FLAG_IS_FULLSCREEN(flags) ) ||     // FS off
-                         ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop off
-        NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False);
+    if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags)  && !TST_FLAG_IS_FULLSCREEN(flags) ) ||           // FS off
+                         ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ||          // AlwaysOnTop off
+                         ( TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags) && !TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) ) ) { // AlwaysOnBottom off
+        NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, False);
     }
 
-    if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) {
+    if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_IS_CHILD(flags) ) {
         // TOP: in -> out
         DBG_PRINT( "X11: reconfigureWindow0 PARENTING in->out\n");
-        XReparentWindow( dpy, w, parent, x, y ); // actual reparent call
+        XReparentWindow( dpy, jw->window, parent, x, y ); // actual reparent call
         #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
-            XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+            XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) jw->window );
         #endif
         XSync(dpy, False);
-        XSetWMProtocols(dpy, w, &wm_delete_atom, 1); // windowDeleteAtom
+        XSetWMProtocols(dpy, jw->window, &wm_delete_atom, 1); // windowDeleteAtom
         // Fix for Unity WM, i.e. _remove_ persistent previous states
-        NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, False);
+        NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, False);
     }
 
     if( TST_FLAG_CHANGE_DECORATION(flags) ) {
         DBG_PRINT( "X11: reconfigureWindow0 DECORATIONS %d\n", !TST_FLAG_IS_UNDECORATED(flags));
-        NewtWindows_setDecorations (dpy, w, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
+        NewtWindows_setDecorations (dpy, jw, TST_FLAG_IS_UNDECORATED(flags) ? False : True);
     }
 
-    DBG_PRINT( "X11: reconfigureWindow0 setPosSize %d/%d %dx%d\n", x, y, width, height);
-    NewtWindows_setPosSize(dpy, w, x, y, width, height);
+    if( TST_FLAG_CHANGE_MAXIMIZED_ANY(flags) ) {
+        int cmd = 0;
+        if( TST_FLAG_CHANGE_MAXIMIZED_VERT(flags) && 
+            TST_FLAG_CHANGE_MAXIMIZED_HORZ(flags) &&
+            TST_FLAG_IS_MAXIMIZED_VERT(flags) == TST_FLAG_IS_MAXIMIZED_HORZ(flags) ) {
+            // max-both on or off
+            cmd = _MASK_NET_WM_STATE_MAXIMIZED_VERT | 
+                  _MASK_NET_WM_STATE_MAXIMIZED_HORZ;
+            NewtWindows_setStackingEWMHFlags(dpy, root, jw, cmd, TST_FLAG_IS_MAXIMIZED_ANY(flags)?True:False);
+        } else {
+            // max each on or off
+            if( TST_FLAG_CHANGE_MAXIMIZED_VERT(flags) ) {
+                cmd = _MASK_NET_WM_STATE_MAXIMIZED_VERT;
+                NewtWindows_setStackingEWMHFlags(dpy, root, jw, cmd, TST_FLAG_IS_MAXIMIZED_VERT(flags)?True:False);
+            } 
+            if( TST_FLAG_CHANGE_MAXIMIZED_HORZ(flags) ) {
+                cmd = _MASK_NET_WM_STATE_MAXIMIZED_HORZ;
+                NewtWindows_setStackingEWMHFlags(dpy, root, jw, cmd, TST_FLAG_IS_MAXIMIZED_HORZ(flags)?True:False);
+            } 
+        }
+    } else {
+        if( !TST_FLAG_IS_MAXIMIZED_ANY(flags) ) {
+            DBG_PRINT( "X11: reconfigureWindow0 setPosSize %d/%d %dx%d\n", x, y, width, height);
+            NewtWindows_setPosSize(dpy, jw, x, y, width, height);
+        }
+    }
 
-    if( TST_FLAG_CHANGE_PARENTING(flags) && TST_FLAG_HAS_PARENT(flags) ) {
+    if( TST_FLAG_CHANGE_PARENTING(flags) && TST_FLAG_IS_CHILD(flags) ) {
         // CHILD: out -> in
         DBG_PRINT( "X11: reconfigureWindow0 PARENTING out->in\n");
-        XReparentWindow( dpy, w, parent, x, y ); // actual reparent call
+        XReparentWindow( dpy, jw->window, parent, x, y ); // actual reparent call
         #ifdef REPARENT_WAIT_FOR_REPARENT_NOTIFY
-            XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) w );
+            XIfEvent( dpy, &event, WaitForReparentNotify, (XPointer) jw->window );
         #endif
         XSync(dpy, False);
     }
 
     if( tempInvisible ) {
         DBG_PRINT( "X11: reconfigureWindow0 TEMP VISIBLE ON\n");
-        XMapRaised(dpy, w);
-        XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) w );
+        NewtWindows_setVisible(dpy, root, jw, True /* visible */, False /* useWM */, True /* wait */);
         // no need to notify the java side .. just temp change
     } else if( TST_FLAG_CHANGE_VISIBILITY(flags) ) {
+        Bool useWM = TST_FLAG_CHANGE_VISIBILITY_FAST(flags) ? False : True;
         if( TST_FLAG_IS_VISIBLE(flags) ) {
             DBG_PRINT( "X11: reconfigureWindow0 VISIBLE ON\n");
-            XMapRaised(dpy, w);
+            NewtWindows_setVisible(dpy, root, jw, True /* visible */, useWM, False /* wait */);
             XSync(dpy, False);
-            // WM may disregard pos/size XConfigureWindow requests for invisible windows!
-            DBG_PRINT( "X11: reconfigureWindow0 setPosSize.2 %d/%d %dx%d\n", x, y, width, height);
-            NewtWindows_setPosSize(dpy, w, x, y, width, height);
+            if( !TST_FLAG_IS_MAXIMIZED_ANY(flags) ) {
+                // WM may disregard pos/size XConfigureWindow requests for invisible windows!
+                DBG_PRINT( "X11: reconfigureWindow0 setPosSize.2 %d/%d %dx%d\n", x, y, width, height);
+                NewtWindows_setPosSize(dpy, jw, x, y, width, height);
+            }
         } else {
             DBG_PRINT( "X11: reconfigureWindow0 VISIBLE OFF\n");
-            XUnmapWindow(dpy, w);
+            NewtWindows_setVisible(dpy, root, jw, False /* visible */, useWM, False /* wait */);
             XSync(dpy, False);
         }
     }
 
-    if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags)  && TST_FLAG_IS_FULLSCREEN(flags) ) ||     // FS on
-                         ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // AlwaysOnTop on
-        NewtWindows_requestFocus (dpy, w, True);
-        NewtWindows_setStackingEWMHFlags(dpy, root, w, fsEWMHFlags, isVisible, True);
+    if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags)  && TST_FLAG_IS_FULLSCREEN(flags) ) ||           // FS on
+                         ( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ||          // AlwaysOnTop on
+                         ( TST_FLAG_CHANGE_ALWAYSONBOTTOM(flags) && TST_FLAG_IS_ALWAYSONBOTTOM(flags) ) ) ) { // AlwaysOnBottom on
+        NewtWindows_requestFocus (dpy, jw, True);
+        NewtWindows_setStackingEWMHFlags(dpy, root, jw, fsEWMHFlags, True);
+    }
+    if( TST_FLAG_CHANGE_STICKY(flags) ) {
+        NewtWindows_setStackingEWMHFlags(dpy, root, jw, _MASK_NET_WM_STATE_STICKY, TST_FLAG_IS_STICKY(flags)?True:False);
+    }
+    if( TST_FLAG_CHANGE_RESIZABLE(flags) ) {
+        if( !TST_FLAG_IS_RESIZABLE(flags) ) {
+            NewtWindows_setMinMaxSize(dpy, jw, width, height, width, height);
+        } else {
+            // NewtWindows_setMinMaxSize(dpy, jw, 0, 0, 32767, 32767); // FIXME: ..
+            NewtWindows_setMinMaxSize(dpy, jw, -1, -1, -1, -1); // FIXME: ..
+        }
     }
-
     DBG_PRINT( "X11: reconfigureWindow0 X (full)\n");
 }
 
@@ -911,20 +1236,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_reconfigureWindo
  * Signature: (JJZ)V
  */
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_requestFocus0
-  (JNIEnv *env, jobject obj, jlong display, jlong window, jboolean force)
-{
-    NewtWindows_requestFocus ( (Display *) (intptr_t) display, (Window)window, JNI_TRUE==force?True:False ) ;
-}
-
-/*
- * Class:     jogamp_newt_driver_x11_WindowDriver
- * Method:    getParentWindow0
- * Signature: (JJ)J
- */
-JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_getParentWindow0
-  (JNIEnv *env, jclass clazz, jlong display, jlong window)
+  (JNIEnv *env, jobject obj, jlong display, jlong javaWindow, jboolean force)
 {
-    return (jlong) NewtWindows_getParent ((Display *) (intptr_t) display, (Window)window);
+    NewtWindows_requestFocus ( (Display *) (intptr_t) display, (JavaWindow*)(intptr_t)javaWindow, JNI_TRUE==force?True:False ) ;
 }
 
 /*
@@ -933,10 +1247,10 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_WindowDriver_getParentWindow
  * Signature: (JJLjava/lang/String;)V
  */
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0
-  (JNIEnv *env, jclass clazz, jlong display, jlong window, jstring title)
+  (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jstring title)
 {
     Display * dpy = (Display *) (intptr_t) display;
-    Window w = (Window)window;
+    JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow;
 
 #if 1
     const char* title_str;
@@ -944,7 +1258,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0
         title_str = (*env)->GetStringUTFChars(env, title, NULL);
         if(NULL != title_str) {
             DBG_PRINT( "X11: setTitle: <%s> SET\n", title_str);
-            XStoreName(dpy, w, title_str);
+            XStoreName(dpy, jw->window, title_str);
             (*env)->ReleaseStringUTFChars(env, title, title_str);
         } else {
             DBG_PRINT( "X11: setTitle: NULL - NOT SET (1)\n");
@@ -965,7 +1279,7 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0
             }
             if(NULL!=text_prop.value) {
                 DBG_PRINT( "X11: setTitle: <%s> SET\n", str_list[0]);
-                XSetWMName(dpy, w, &text_prop);
+                XSetWMName(dpy, jw->window, &text_prop);
                 XFree(text_prop.value);
             } else {
                 DBG_PRINT( "X11: setTitle: <%s> NOT SET (1)\n", str_list[0]);
@@ -984,18 +1298,18 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setTitle0
  * Signature: (JJILjava/lang/Object;I)V
  */
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerIcon0
-  (JNIEnv *env, jclass clazz, jlong display, jlong window, jlong handle)
+  (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jlong handle)
 {
     Display * dpy = (Display *) (intptr_t) display;
-    Window w = (Window)window;
+    JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow;
 
     if( 0 == handle ) {
         DBG_PRINT( "X11: setPointerIcon0: reset\n");
-        XUndefineCursor(dpy, w);
+        XUndefineCursor(dpy, jw->window);
     } else {
         Cursor c = (Cursor) (intptr_t) handle;
         DBG_PRINT( "X11: setPointerIcon0: %p\n", (void*)c);
-        XDefineCursor(dpy, w, c);
+        XDefineCursor(dpy, jw->window, c);
     }
 }
 
@@ -1005,28 +1319,28 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerIcon0
  * Signature: (JJZ)Z
  */
 JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerVisible0
-  (JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean mouseVisible)
+  (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jboolean mouseVisible)
 {
     static char noData[] = { 0,0,0,0,0,0,0,0 };
     static XColor black = { 0 };
 
     Display * dpy = (Display *) (intptr_t) display;
-    Window w = (Window)window;
+    JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow;
 
     DBG_PRINT( "X11: setPointerVisible0: %d\n", mouseVisible);
 
     if(JNI_TRUE == mouseVisible) {
-        XUndefineCursor(dpy, w);
+        XUndefineCursor(dpy, jw->window);
     } else {
         Pixmap bitmapNoData;
         Cursor invisibleCursor;
 
-        bitmapNoData = XCreateBitmapFromData(dpy, w, noData, 8, 8);
+        bitmapNoData = XCreateBitmapFromData(dpy, jw->window, noData, 8, 8);
         if(None == bitmapNoData) {
             return JNI_FALSE;
         }
         invisibleCursor = XCreatePixmapCursor(dpy, bitmapNoData, bitmapNoData, &black, &black, 0, 0);
-        XDefineCursor(dpy, w, invisibleCursor);
+        XDefineCursor(dpy, jw->window, invisibleCursor);
         XFreeCursor(dpy, invisibleCursor);
         XFreePixmap(dpy, bitmapNoData);
     }
@@ -1039,17 +1353,17 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_setPointerVi
  * Signature: (JJZ)Z
  */
 JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_confinePointer0
-  (JNIEnv *env, jclass clazz, jlong display, jlong window, jboolean confine)
+  (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jboolean confine)
 {
     Display * dpy = (Display *) (intptr_t) display;
-    Window w = (Window)window;
+    JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow;
 
     DBG_PRINT( "X11: confinePointer0: %d\n", confine);
 
     if(JNI_TRUE == confine) {
-        return GrabSuccess == XGrabPointer(dpy, w, True, 
+        return GrabSuccess == XGrabPointer(dpy, jw->window, True, 
                                            X11_MOUSE_EVENT_MASK,
-                                           GrabModeAsync, GrabModeAsync, w, None, CurrentTime)
+                                           GrabModeAsync, GrabModeAsync, jw->window, None, CurrentTime)
                ? JNI_TRUE : JNI_FALSE ;
     }
     XUngrabPointer(dpy, CurrentTime);
@@ -1062,13 +1376,13 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_x11_WindowDriver_confinePoint
  * Signature: (JJII)V
  */
 JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_WindowDriver_warpPointer0
-  (JNIEnv *env, jclass clazz, jlong display, jlong window, jint x, jint y)
+  (JNIEnv *env, jclass clazz, jlong display, jlong javaWindow, jint x, jint y)
 {
     Display * dpy = (Display *) (intptr_t) display;
-    Window w = (Window)window;
+    JavaWindow *jw = (JavaWindow*)(intptr_t)javaWindow;
 
     DBG_PRINT( "X11: warpPointer0: %d/%d\n", x, y);
 
-    XWarpPointer(dpy, None, w, 0, 0, 0, 0, x, y);
+    XWarpPointer(dpy, None, jw->window, 0, 0, 0, 0, x, y);
 }
 
index d02d5a4..f27d30b 100644 (file)
@@ -24,7 +24,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
 
     // Periodically take a break
     while( num_events > 0 ) {
-        jobject jwindow = NULL;
+        JavaWindow *w = NULL;
         xcb_generic_event_t *evt;
         // KeySym keySym = 0;
         jint modifiers = 0;
@@ -54,11 +54,11 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
 
         // X11WindowDisplayErrorHandlerEnable(1, env);
 
-        // jwindow = X11WindowGetJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, VERBOSE_BOOL);
+        // w = X11WindowGetJavaWindowProperty(env, dpy, evt.xany.window, javaObjectAtom, VERBOSE_BOOL);
 
         //X11WindowDisplayErrorHandlerEnable(0, env);
 
-        /*if(NULL==jwindow) {
+        /*if(NULL==w) {
             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);
             continue;
@@ -109,14 +109,14 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                 (void*)dpy, xcb_event_type);
             continue;
         }
-        jwindow = getJavaWindowProperty(env, dpy, event_window, javaObjectAtom,
+        w = getJavaWindowProperty(env, dpy, event_window, javaObjectAtom,
         #ifdef VERBOSE_ON
                 True
         #else
                 False
         #endif
             );
-        if(NULL==jwindow) {
+        if(NULL==w) {
             fprintf(stderr, "Warning: NEWT X11 DisplayDispatch %p, Couldn't handle event %d for X11 window %p\n", 
                 (void*)(intptr_t)dpy, xcb_event_type, (void*)(intptr_t)event_window);
             continue;
@@ -125,13 +125,13 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
         switch( xcb_event_type ) {
             case XCB_BUTTON_PRESS: {
                     xcb_button_press_event_t *_evt = (xcb_button_press_event_t *)evt;
-                    (*env)->CallVoidMethod(env, jwindow, requestFocusID, JNI_FALSE);
+                    (*env)->CallVoidMethod(env, w->jwindow, requestFocusID, JNI_FALSE);
                     #ifdef USE_SENDIO_DIRECT
-                    (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, 
+                    (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, 
                                           modifiers,
                                           (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
                     #else
-                    (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, 
+                    (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_PRESSED, 
                                           modifiers,
                                           (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
                     #endif
@@ -139,11 +139,11 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
             case XCB_BUTTON_RELEASE: {
                     xcb_button_release_event_t *_evt = (xcb_button_release_event_t *)evt;
                     #ifdef USE_SENDIO_DIRECT
-                    (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, 
+                    (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_RELEASED, 
                                           modifiers,
                                           (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
                     #else
-                    (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, 
+                    (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_RELEASED, 
                                           modifiers,
                                           (jint) _evt->event_x, (jint) _evt->event_y, (jint) _evt->state, 0.0f /*rotation*/);
                     #endif
@@ -151,11 +151,11 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
             case XCB_MOTION_NOTIFY: {
                     xcb_motion_notify_event_t *_evt = (xcb_motion_notify_event_t *)evt;
                     #ifdef USE_SENDIO_DIRECT
-                    (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, 
+                    (*env)->CallVoidMethod(env, w->jwindow, sendMouseEventID, (jint) EVENT_MOUSE_MOVED, 
                                           modifiers,
                                           (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
                     #else
-                    (*env)->CallVoidMethod(env, jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, 
+                    (*env)->CallVoidMethod(env, w->jwindow, enqueueMouseEventID, JNI_FALSE, (jint) EVENT_MOUSE_MOVED, 
                                           modifiers,
                                           (jint) _evt->event_x, (jint) _evt->event_y, (jint)0, 0.0f /*rotation*/);
                     #endif
@@ -163,10 +163,10 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
             case XCB_KEY_PRESS: {
                     xcb_key_press_event_t *_evt = (xcb_key_press_event_t *)evt;
                     #ifdef USE_SENDIO_DIRECT
-                    (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, 
+                    (*env)->CallVoidMethod(env, w->jwindow, sendKeyEventID, (jint) EVENT_KEY_PRESSED, 
                                           modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
                     #else
-                    (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, 
+                    (*env)->CallVoidMethod(env, w->jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_PRESSED, 
                                           modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
                     #endif
                 } break;
@@ -174,10 +174,10 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                     xcb_key_release_event_t *_evt = (xcb_key_release_event_t *)evt;
                 event_window = ((xcb_key_release_event_t *)evt)->event;
                 #ifdef USE_SENDIO_DIRECT
-                (*env)->CallVoidMethod(env, jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, 
+                (*env)->CallVoidMethod(env, w->jwindow, sendKeyEventID, (jint) EVENT_KEY_RELEASED, 
                                       modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
                 #else
-                (*env)->CallVoidMethod(env, jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, 
+                (*env)->CallVoidMethod(env, w->jwindow, enqueueKeyEventID, JNI_FALSE, (jint) EVENT_KEY_RELEASED, 
                                       modifiers, X11KeySym2NewtVKey(_evt->state), (jchar) keyChar);
                 #endif
 
@@ -201,9 +201,9 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                             evt.xconfigure.override_redirect, evt.xconfigure.window != evt.xconfigure.event);
                 if ( evt.xconfigure.window == evt.xconfigure.event ) {
                     // ignore child window change notification
-                    (*env)->CallVoidMethod(env, jwindow, sizeChangedID, 
+                    (*env)->CallVoidMethod(env, w->jwindow, sizeChangedID, 
                                             (jint) evt.xconfigure.width, (jint) evt.xconfigure.height, JNI_FALSE);
-                    (*env)->CallVoidMethod(env, jwindow, positionChangedID, 
+                    (*env)->CallVoidMethod(env, w->jwindow, positionChangedID, 
                                             (jint) evt.xconfigure.x, (jint) evt.xconfigure.y);
                 }
                 break;
@@ -211,7 +211,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                 if (evt.xclient.send_event==True && evt.xclient.data.l[0]==(Atom)wmDeleteAtom) {
                     DBG_PRINT( "X11: event . ClientMessage call %p type 0x%X !!!\n", 
                         (void*)evt.xclient.window, (unsigned int)evt.xclient.message_type);
-                    (*env)->CallVoidMethod(env, jwindow, windowDestroyNotifyID);
+                    (*env)->CallVoidMethod(env, w->jwindow, windowDestroyNotifyID);
                     // Called by Window.java: CloseWindow(); 
                     num_events = 0; // end loop in case of destroyed display
                 }
@@ -219,12 +219,12 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
 
             case FocusIn:
                 DBG_PRINT( "X11: event . FocusIn call %p\n", (void*)evt.xvisibility.window);
-                (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_TRUE);
+                (*env)->CallVoidMethod(env, w->jwindow, focusChangedID, JNI_TRUE);
                 break;
 
             case FocusOut:
                 DBG_PRINT( "X11: event . FocusOut call %p\n", (void*)evt.xvisibility.window);
-                (*env)->CallVoidMethod(env, jwindow, focusChangedID, JNI_FALSE);
+                (*env)->CallVoidMethod(env, w->jwindow, focusChangedID, JNI_FALSE);
                 break;
                 */
 
@@ -234,7 +234,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                         _evt->x, _evt->y, _evt->width, _evt->height, _evt->count);
 
                     if (_evt->count == 0 && _evt->width > 0 && _evt->height > 0) {
-                        (*env)->CallVoidMethod(env, jwindow, windowRepaintID, 
+                        (*env)->CallVoidMethod(env, w->jwindow, windowRepaintID, 
                             _evt->x, _evt->y, _evt->width, _evt->height);
                     }
                 } break;
@@ -246,7 +246,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                         _evt->event!=_evt->window);
                     if( _evt->event == _evt->window ) {
                         // ignore child window notification
-                        (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_TRUE);
+                        (*env)->CallVoidMethod(env, w->jwindow, visibleChangedID, JNI_TRUE);
                     }
                 } break;
 
@@ -257,7 +257,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                         _evt->event!=_evt->window);
                     if( _evt->event == _evt->window ) {
                         // ignore child window notification
-                        (*env)->CallVoidMethod(env, jwindow, visibleChangedID, JNI_FALSE);
+                        (*env)->CallVoidMethod(env, w->jwindow, visibleChangedID, JNI_FALSE);
                     }
                 } break;
                 /*
@@ -291,7 +291,7 @@ void XCBEventPoll(JNIEnv *env, jobject obj, Display *dpy, jlong javaObjectAtom,
                             (void*)evt.xreparent.window, (void*)winRoot, (void*)winTopParent);
                     #endif
 
-                    (*env)->CallVoidMethod(env, jwindow, windowReparentedID, parentResult);
+                    (*env)->CallVoidMethod(env, w->jwindow, windowReparentedID, parentResult);
                 }
                 break;
                 */
index f70df89..e1abcc7 100644 (file)
@@ -587,12 +587,6 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen
         return "GearsES2[obj "+sid()+" isInit "+isInit+", usesShared "+usesSharedGears+", 1 "+gear1+", 2 "+gear2+", 3 "+gear3+", sharedGears "+sharedGears+"]";
     }
 
-    boolean confinedFixedCenter = false;
-
-    public void setConfinedFixedCenter(final boolean v) {
-        confinedFixedCenter = v;
-    }
-
     class GearsKeyAdapter extends KeyAdapter {
         public void keyPressed(final KeyEvent e) {
             final int kc = e.getKeyCode();
@@ -669,8 +663,8 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen
         }
 
         private void navigate(final MouseEvent e) {
-            int x = e.getX();
-            int y = e.getY();
+            final int x = e.getX();
+            final int y = e.getY();
 
             int width, height;
             final Object source = e.getSource();
@@ -694,11 +688,6 @@ public class GearsES2 implements StereoGLEventListener, TileRendererBase.TileRen
             final float thetaX = 360.0f * ( (float)(prevMouseY-y)/(float)height);
             view_rotx += thetaX;
             view_roty += thetaY;
-            if(e.isConfined() && confinedFixedCenter && null!=window) {
-                x=window.getSurfaceWidth()/2;
-                y=window.getSurfaceHeight()/2;
-                window.warpPointer(x, y);
-            }
             prevMouseX = x;
             prevMouseY = y;
             // System.err.println("rotXY.1: "+view_rotx+"/"+view_roty+", source "+e);
index 90164d3..d5afdcf 100644 (file)
@@ -30,31 +30,24 @@ package com.jogamp.opengl.test.junit.jogl.demos.es2.newt;
 
 import java.io.IOException;
 import java.lang.reflect.InvocationTargetException;
-import java.net.URLConnection;
 
-import com.jogamp.common.util.IOUtil;
 import com.jogamp.junit.util.JunitTracer;
 import com.jogamp.newt.Display;
 import com.jogamp.newt.Display.PointerIcon;
 import com.jogamp.newt.NewtFactory;
 import com.jogamp.newt.Screen;
 import com.jogamp.newt.Window;
-import com.jogamp.newt.event.KeyAdapter;
-import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.MouseAdapter;
-import com.jogamp.newt.event.MouseEvent;
 import com.jogamp.newt.event.WindowEvent;
 import com.jogamp.newt.event.WindowAdapter;
 import com.jogamp.newt.opengl.GLWindow;
 import com.jogamp.newt.util.EDTUtil;
 import com.jogamp.opengl.test.junit.util.AWTRobotUtil;
 import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.NEWTDemoListener;
 import com.jogamp.opengl.test.junit.util.UITestCase;
 import com.jogamp.opengl.test.junit.util.QuitAdapter;
 import com.jogamp.opengl.util.Animator;
 import com.jogamp.opengl.util.AnimatorBase;
-import com.jogamp.opengl.util.Gamma;
-import com.jogamp.opengl.util.PNGPixelRect;
 import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
 
 import com.jogamp.nativewindow.NativeWindowFactory;
@@ -71,7 +64,6 @@ import com.jogamp.opengl.GLEventListener;
 import com.jogamp.opengl.GLProfile;
 
 import jogamp.newt.DefaultEDTUtil;
-import jogamp.newt.driver.PNGIcon;
 
 import org.junit.Assert;
 import org.junit.BeforeClass;
@@ -92,6 +84,11 @@ public class TestGearsES2NEWT extends UITestCase {
     static int forceAlpha = -1;
     static boolean undecorated = false;
     static boolean alwaysOnTop = false;
+    static boolean alwaysOnBottom = false;
+    static boolean resizable = true;
+    static boolean sticky = false;
+    static boolean max_vert= false;
+    static boolean max_horz= false;
     static boolean fullscreen = false;
     static int swapInterval = 1;
     static boolean waitForKey = false;
@@ -123,13 +120,6 @@ public class TestGearsES2NEWT extends UITestCase {
     public static void releaseClass() {
     }
 
-    private void setTitle(final Window win, final GLCapabilitiesImmutable caps) {
-        final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
-        final float[] sDPI = win.getPixelsPerMM(new float[2]);
-        sDPI[0] *= 25.4f;
-        sDPI[1] *= 25.4f;
-        win.setTitle("GLWindow["+capsA+"], swapI "+swapInterval+", win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]);
-    }
     protected void runTestGL(final GLCapabilitiesImmutable caps, final boolean undecorated) throws InterruptedException {
         System.err.println("requested: vsync "+swapInterval+", "+caps);
         final Display dpy = NewtFactory.createDisplay(null);
@@ -144,6 +134,10 @@ public class TestGearsES2NEWT extends UITestCase {
         }
         glWindow.setUndecorated(undecorated);
         glWindow.setAlwaysOnTop(alwaysOnTop);
+        glWindow.setAlwaysOnBottom(alwaysOnBottom);
+        glWindow.setResizable(resizable);
+        glWindow.setSticky(sticky);
+        glWindow.setMaximized(max_horz, max_vert);
         glWindow.setFullscreen(fullscreen);
         glWindow.setPointerVisible(mouseVisible);
         glWindow.confinePointer(mouseConfined);
@@ -187,238 +181,23 @@ public class TestGearsES2NEWT extends UITestCase {
         glWindow.addWindowListener(new WindowAdapter() {
             public void windowResized(final WindowEvent e) {
                 System.err.println("window resized: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
-                setTitle(glWindow, caps);
+                NEWTDemoListener.setTitle(glWindow);
             }
             public void windowMoved(final WindowEvent e) {
                 System.err.println("window moved:   "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight());
-                setTitle(glWindow, caps);
+                NEWTDemoListener.setTitle(glWindow);
             }
         });
 
-        final PointerIcon[] pointerIcons = { null, null, null, null, null };
-        {
-            final Display disp = glWindow.getScreen().getDisplay();
-            disp.createNative();
-            int idx = 0;
-            {
-                PointerIcon _pointerIcon = null;
-                final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } );
-                try {
-                    _pointerIcon = disp.createPointerIcon(res, 8, 8);
-                    System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
-                } catch (final Exception e) {
-                    e.printStackTrace();
-                }
-                pointerIcons[idx] = _pointerIcon;
-            }
-            idx++;
-            {
-                PointerIcon _pointerIcon = null;
-                final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/pointer-grey-alpha-16x24.png" } );
-                try {
-                    _pointerIcon = disp.createPointerIcon(res, 0, 0);
-                    System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
-                } catch (final Exception e) {
-                    e.printStackTrace();
-                }
-                pointerIcons[idx] = _pointerIcon;
-            }
-            idx++;
-            {
-                PointerIcon _pointerIcon = null;
-                final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-red-alpha-64x64.png" } );
-                try {
-                    _pointerIcon = disp.createPointerIcon(res, 0, 0);
-                    System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
-                } catch (final Exception e) {
-                    e.printStackTrace();
-                }
-                pointerIcons[idx] = _pointerIcon;
-            }
-            idx++;
-            {
-                PointerIcon _pointerIcon = null;
-                final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "arrow-blue-alpha-64x64.png" } );
-                try {
-                    _pointerIcon = disp.createPointerIcon(res, 0, 0);
-                    System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
-                } catch (final Exception e) {
-                    e.printStackTrace();
-                }
-                pointerIcons[idx] = _pointerIcon;
-            }
-            idx++;
-            if( PNGIcon.isAvailable() ) {
-                PointerIcon _pointerIcon = null;
-                final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } );
-                try {
-                    final URLConnection urlConn = res.resolve(0);
-                    final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
-                    System.err.printf("Create PointerIcon #%02d: %s%n", idx, image.toString());
-                    _pointerIcon = disp.createPointerIcon(image, 32, 0);
-                    System.err.printf("Create PointerIcon #%02d: %s%n", idx, _pointerIcon.toString());
-                } catch (final Exception e) {
-                    e.printStackTrace();
-                }
-                pointerIcons[idx] = _pointerIcon;
-            }
-            idx++;
-        }
+        final PointerIcon[] pointerIcons = NEWTDemoListener.createPointerIcons(glWindow);
         if( setPointerIcon ) {
             glWindow.setPointerIcon(pointerIcons[0]);
             System.err.println("Set PointerIcon: "+glWindow.getPointerIcon());
         }
 
-        glWindow.addKeyListener(new KeyAdapter() {
-            int pointerIconIdx = 0;
-            float gamma = 1f;
-            float brightness = 0f;
-            float contrast = 1f;
-
-            @Override
-            public void keyPressed(final KeyEvent e) {
-                if( e.isAutoRepeat() ) {
-                    return;
-                }
-                if(e.getKeyChar()=='f') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set fullscreen  pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                            if( glWindow.isFullscreen() ) {
-                                glWindow.setFullscreen( false );
-                            } else {
-                                if( e.isAltDown() ) {
-                                    glWindow.setFullscreen( null );
-                                } else {
-                                    glWindow.setFullscreen( true );
-                                }
-                            }
-                            System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if( e.getKeySymbol()== KeyEvent.VK_G ) {
-                    new Thread() {
-                        public void run() {
-                            final float newGamma = gamma + ( e.isShiftDown() ? -0.1f : 0.1f );
-                            System.err.println("[set gamma]: "+gamma+" -> "+newGamma);
-                            if( Gamma.setDisplayGamma(glWindow, newGamma, brightness, contrast) ) {
-                                gamma = newGamma;
-                            }
-                    } }.start();
-                } else if(e.getKeyChar()=='a') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set alwaysontop pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                            glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
-                            System.err.println("[set alwaysontop post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='d') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            // while( null != glWindow.getExclusiveContextThread() ) ;
-                            System.err.println("[set undecorated  pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets());
-                            glWindow.setUndecorated(!glWindow.isUndecorated());
-                            System.err.println("[set undecorated post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='s') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set position  pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
-                            glWindow.setPosition(100, 100);
-                            System.err.println("[set position post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='c') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set pointer-icon pre]");
-                            final PointerIcon currentPI = glWindow.getPointerIcon();
-                            final PointerIcon newPI;
-                            if( pointerIconIdx >= pointerIcons.length ) {
-                                newPI=null;
-                                pointerIconIdx=0;
-                            } else {
-                                newPI=pointerIcons[pointerIconIdx++];
-                            }
-                            glWindow.setPointerIcon( newPI );
-                            System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='i') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible());
-                            glWindow.setPointerVisible(!glWindow.isPointerVisible());
-                            System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='j') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
-                            glWindow.confinePointer(!glWindow.isPointerConfined());
-                            System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
-                            if(!glWindow.isPointerConfined()) {
-                                demo.setConfinedFixedCenter(false);
-                            }
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='J') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
-                            glWindow.confinePointer(!glWindow.isPointerConfined());
-                            System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
-                            demo.setConfinedFixedCenter(glWindow.isPointerConfined());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='w') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set mouse pos pre]");
-                            glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2);
-                            System.err.println("[set mouse pos post]");
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='x') {
-                    final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]);
-                    final float[] reqSurfacePixelScale;
-                    if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
-                        reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
-                    } else {
-                        reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-                    }
-                    System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
-                    glWindow.setSurfaceScale(reqSurfacePixelScale);
-                    final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
-                    final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]);
-                    System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
-                            reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
-                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
-                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
-                    setTitle(glWindow, caps);
-                }
-            }
-        });
-        glWindow.addMouseListener(new MouseAdapter() {
-            public void mouseClicked(final MouseEvent e) {
-                if(e.getClickCount() == 2 && e.getPointerCount() == 1) {
-                    glWindow.setFullscreen(!glWindow.isFullscreen());
-                    System.err.println("setFullscreen: "+glWindow.isFullscreen());
-                }
-            }
-         });
+        final NEWTDemoListener newtDemoListener = new NEWTDemoListener(glWindow, pointerIcons);
+        glWindow.addKeyListener(newtDemoListener);
+        glWindow.addMouseListener(newtDemoListener);
 
         if( useAnimator ) {
             animator.add(glWindow);
@@ -484,7 +263,7 @@ public class TestGearsES2NEWT extends UITestCase {
         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
-        setTitle(glWindow, caps);
+        NEWTDemoListener.setTitle(glWindow);
 
         snap.setMakeSnapshot();
 
@@ -620,6 +399,16 @@ public class TestGearsES2NEWT extends UITestCase {
                 undecorated = true;
             } else if(args[i].equals("-atop")) {
                 alwaysOnTop = true;
+            } else if(args[i].equals("-abottom")) {
+                alwaysOnBottom = true;
+            } else if(args[i].equals("-noresize")) {
+                resizable = false;
+            } else if(args[i].equals("-sticky")) {
+                sticky = true;
+            } else if(args[i].equals("-maxv")) {
+                max_vert = true;
+            } else if(args[i].equals("-maxh")) {
+                max_horz = true;
             } else if(args[i].equals("-fullscreen")) {
                 fullscreen = true;
             } else if(args[i].equals("-vsync")) {
@@ -705,6 +494,11 @@ public class TestGearsES2NEWT extends UITestCase {
         System.err.println("forceAlpha "+forceAlpha);
         System.err.println("undecorated "+undecorated);
         System.err.println("atop "+alwaysOnTop);
+        System.err.println("abottom "+alwaysOnBottom);
+        System.err.println("resizable "+resizable);
+        System.err.println("sticky "+sticky);
+        System.err.println("max_vert "+max_vert);
+        System.err.println("max_horz "+max_horz);
         System.err.println("fullscreen "+fullscreen);
         System.err.println("mouseVisible "+mouseVisible);
         System.err.println("mouseConfined "+mouseConfined);
index f43635e..39d13f6 100644 (file)
@@ -43,9 +43,7 @@ import com.jogamp.common.os.Platform;
 import com.jogamp.newt.Display;
 import com.jogamp.newt.NewtFactory;
 import com.jogamp.newt.Screen;
-import com.jogamp.newt.Window;
 import com.jogamp.newt.awt.NewtCanvasAWT;
-import com.jogamp.newt.event.KeyEvent;
 import com.jogamp.newt.event.WindowEvent;
 import com.jogamp.newt.event.WindowAdapter;
 import com.jogamp.newt.opengl.GLWindow;
@@ -175,18 +173,6 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase {
         }
     }
 
-    private void setTitle(final Frame frame, final NewtCanvasAWT glc, final Window win, final GLCapabilitiesImmutable caps) {
-        final String capsA = caps.isBackgroundOpaque() ? "opaque" : "transl";
-        {
-            final java.awt.Rectangle b = glc.getBounds();
-            frame.setTitle("NewtCanvasAWT["+capsA+"], swapI "+swapInterval+", win: ["+b.x+"/"+b.y+" "+b.width+"x"+b.height+"], pix: "+glc.getNativeWindow().getSurfaceWidth()+"x"+glc.getNativeWindow().getSurfaceHeight());
-        }
-        final float[] sDPI = win.getPixelsPerMM(new float[2]);
-        sDPI[0] *= 25.4f;
-        sDPI[1] *= 25.4f;
-        win.setTitle("GLWindow["+capsA+"], swapI "+swapInterval+", win: "+win.getBounds()+", pix: "+win.getSurfaceWidth()+"x"+win.getSurfaceHeight()+", sDPI "+sDPI[0]+" x "+sDPI[1]);
-    }
-
     // public enum ResizeBy { GLWindow, Component, Frame };
     protected void runTestGL(final GLCapabilitiesImmutable caps, final ResizeBy resizeBy, final FrameLayout frameLayout) throws InterruptedException, InvocationTargetException {
         System.err.println("requested: vsync "+swapInterval+", "+caps);
@@ -265,12 +251,12 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase {
         frame.addComponentListener(new ComponentListener() {
             @Override
             public void componentResized(final ComponentEvent e) {
-                setTitle(frame, newtCanvasAWT, glWindow, caps);
+                NewtAWTReparentingKeyAdapter.setTitle(frame, newtCanvasAWT, glWindow);
             }
 
             @Override
             public void componentMoved(final ComponentEvent e) {
-                setTitle(frame, newtCanvasAWT, glWindow, caps);
+                NewtAWTReparentingKeyAdapter.setTitle(frame, newtCanvasAWT, glWindow);
             }
 
             @Override
@@ -301,32 +287,9 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase {
             }
         });
 
-        glWindow.addKeyListener(new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow, quitAdapter));
-        glWindow.addKeyListener(new com.jogamp.newt.event.KeyAdapter() {
-            @Override
-            public void keyPressed(final KeyEvent e) {
-                if( e.isAutoRepeat() ) {
-                    return;
-                }
-                if(e.getKeyChar()=='x') {
-                    final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]);
-                    final float[] reqSurfacePixelScale;
-                    if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
-                        reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
-                    } else {
-                        reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-                    }
-                    System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
-                    glWindow.setSurfaceScale(reqSurfacePixelScale);
-                    final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
-                    final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]);
-                    System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
-                                       reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
-                                       valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
-                                       hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
-                    setTitle(frame, newtCanvasAWT, glWindow, caps);
-                }
-            } } );
+        final NewtAWTReparentingKeyAdapter newtDemoListener = new NewtAWTReparentingKeyAdapter(frame, newtCanvasAWT, glWindow, quitAdapter);
+        glWindow.addKeyListener(newtDemoListener);
+        glWindow.addMouseListener(newtDemoListener);
 
         if( useAnimator ) {
             animator.add(glWindow);
@@ -361,7 +324,7 @@ public class TestGearsES2NewtCanvasAWT extends UITestCase {
         System.err.println("HiDPI PixelScale: "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
-        setTitle(frame, newtCanvasAWT, glWindow, caps);
+        NewtAWTReparentingKeyAdapter.setTitle(frame, newtCanvasAWT, glWindow);
 
         if( null != rwsize ) {
             Thread.sleep(500); // 500ms delay
index eec6af1..d109c56 100644 (file)
@@ -37,17 +37,14 @@ import com.jogamp.newt.Display.PointerIcon;
 import com.jogamp.newt.NewtFactory;
 import com.jogamp.newt.Screen;
 import com.jogamp.newt.Window;
-import com.jogamp.newt.event.KeyAdapter;
-import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.MouseAdapter;
-import com.jogamp.newt.event.MouseEvent;
 import com.jogamp.newt.event.WindowEvent;
 import com.jogamp.newt.event.WindowAdapter;
 import com.jogamp.newt.opengl.GLWindow;
 import com.jogamp.opengl.test.junit.util.UITestCase;
+import com.jogamp.opengl.test.junit.util.MiscUtils;
+import com.jogamp.opengl.test.junit.util.NEWTDemoListener;
 import com.jogamp.opengl.test.junit.util.QuitAdapter;
 import com.jogamp.opengl.util.Animator;
-import com.jogamp.opengl.util.Gamma;
 import com.jogamp.opengl.util.PNGPixelRect;
 import com.jogamp.opengl.test.junit.jogl.demos.es2.GearsES2;
 
@@ -72,6 +69,7 @@ public class TestGearsES2SimpleNEWT extends UITestCase {
     static final int swapInterval = 1;
 
     static long duration = 500; // ms
+    static boolean opaque = true;
 
     private void setTitle(final Window win, final GLCapabilitiesImmutable caps) {
         final float[] sDPI = win.getPixelsPerMM(new float[2]);
@@ -183,156 +181,9 @@ public class TestGearsES2SimpleNEWT extends UITestCase {
             idx++;
         }
 
-        glWindow.addKeyListener(new KeyAdapter() {
-            int pointerIconIdx = 0;
-            float gamma = 1f;
-            float brightness = 0f;
-            float contrast = 1f;
-
-            @Override
-            public void keyPressed(final KeyEvent e) {
-                if( e.isAutoRepeat() ) {
-                    return;
-                }
-                if(e.getKeyChar()=='f') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set fullscreen  pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                            if( glWindow.isFullscreen() ) {
-                                glWindow.setFullscreen( false );
-                            } else {
-                                if( e.isAltDown() ) {
-                                    glWindow.setFullscreen( null );
-                                } else {
-                                    glWindow.setFullscreen( true );
-                                }
-                            }
-                            System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if( e.getKeySymbol()== KeyEvent.VK_G ) {
-                    new Thread() {
-                        public void run() {
-                            final float newGamma = gamma + ( e.isShiftDown() ? -0.1f : 0.1f );
-                            System.err.println("[set gamma]: "+gamma+" -> "+newGamma);
-                            if( Gamma.setDisplayGamma(glWindow, newGamma, brightness, contrast) ) {
-                                gamma = newGamma;
-                            }
-                    } }.start();
-                } else if(e.getKeyChar()=='a') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set alwaysontop pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                            glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
-                            System.err.println("[set alwaysontop post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='d') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            // while( null != glWindow.getExclusiveContextThread() ) ;
-                            System.err.println("[set undecorated  pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets());
-                            glWindow.setUndecorated(!glWindow.isUndecorated());
-                            System.err.println("[set undecorated post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", d "+glWindow.isUndecorated()+", "+glWindow.getInsets());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='s') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set position  pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
-                            glWindow.setPosition(100, 100);
-                            System.err.println("[set position post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", "+glWindow.getInsets());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='c') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set pointer-icon pre]");
-                            final PointerIcon currentPI = glWindow.getPointerIcon();
-                            final PointerIcon newPI;
-                            if( pointerIconIdx >= pointerIcons.length ) {
-                                newPI=null;
-                                pointerIconIdx=0;
-                            } else {
-                                newPI=pointerIcons[pointerIconIdx++];
-                            }
-                            glWindow.setPointerIcon( newPI );
-                            System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='i') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible());
-                            glWindow.setPointerVisible(!glWindow.isPointerVisible());
-                            System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='j') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
-                            glWindow.confinePointer(!glWindow.isPointerConfined());
-                            System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
-                            if(!glWindow.isPointerConfined()) {
-                                demo.setConfinedFixedCenter(false);
-                            }
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='J') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
-                            glWindow.confinePointer(!glWindow.isPointerConfined());
-                            System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
-                            demo.setConfinedFixedCenter(glWindow.isPointerConfined());
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='w') {
-                    new Thread() {
-                        public void run() {
-                            final Thread t = glWindow.setExclusiveContextThread(null);
-                            System.err.println("[set mouse pos pre]");
-                            glWindow.warpPointer(glWindow.getSurfaceWidth()/2, glWindow.getSurfaceHeight()/2);
-                            System.err.println("[set mouse pos post]");
-                            glWindow.setExclusiveContextThread(t);
-                    } }.start();
-                } else if(e.getKeyChar()=='x') {
-                    final float[] hadSurfacePixelScale = glWindow.getCurrentSurfaceScale(new float[2]);
-                    final float[] reqSurfacePixelScale;
-                    if( hadSurfacePixelScale[0] == ScalableSurface.IDENTITY_PIXELSCALE ) {
-                        reqSurfacePixelScale = new float[] { ScalableSurface.AUTOMAX_PIXELSCALE, ScalableSurface.AUTOMAX_PIXELSCALE };
-                    } else {
-                        reqSurfacePixelScale = new float[] { ScalableSurface.IDENTITY_PIXELSCALE, ScalableSurface.IDENTITY_PIXELSCALE };
-                    }
-                    System.err.println("[set PixelScale pre]: had "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" -> req "+reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]);
-                    glWindow.setSurfaceScale(reqSurfacePixelScale);
-                    final float[] valReqSurfacePixelScale = glWindow.getRequestedSurfaceScale(new float[2]);
-                    final float[] hasSurfacePixelScale1 = glWindow.getCurrentSurfaceScale(new float[2]);
-                    System.err.println("[set PixelScale post]: "+hadSurfacePixelScale[0]+"x"+hadSurfacePixelScale[1]+" (had) -> "+
-                            reqSurfacePixelScale[0]+"x"+reqSurfacePixelScale[1]+" (req) -> "+
-                            valReqSurfacePixelScale[0]+"x"+valReqSurfacePixelScale[1]+" (val) -> "+
-                            hasSurfacePixelScale1[0]+"x"+hasSurfacePixelScale1[1]+" (has)");
-                    setTitle(glWindow, caps);
-                }
-            }
-        });
-        glWindow.addMouseListener(new MouseAdapter() {
-            public void mouseClicked(final MouseEvent e) {
-                if(e.getClickCount() == 2 && e.getPointerCount() == 1) {
-                    glWindow.setFullscreen(!glWindow.isFullscreen());
-                    System.err.println("setFullscreen: "+glWindow.isFullscreen());
-                }
-            }
-         });
+        final NEWTDemoListener newtDemoListener = new NEWTDemoListener(glWindow, pointerIcons);
+        glWindow.addKeyListener(newtDemoListener);
+        glWindow.addMouseListener(newtDemoListener);
 
         animator.add(glWindow);
         animator.start();
@@ -368,11 +219,20 @@ public class TestGearsES2SimpleNEWT extends UITestCase {
     public void test01_GL2ES2() throws InterruptedException {
         final GLProfile glp = GLProfile.getGL2ES2();
         final GLCapabilities caps = new GLCapabilities( glp );
+        caps.setBackgroundOpaque(opaque);
         runTestGL(caps, false);
     }
 
     public static void main(final String args[]) throws IOException {
         duration = 1000000; // ~16 min by default per main launch
+        for(int i=0; i<args.length; i++) {
+            if(args[i].equals("-time")) {
+                i++;
+                duration = MiscUtils.atol(args[i], duration);
+            } else if(args[i].equals("-translucent")) {
+                opaque = false;
+            }
+        }
         org.junit.runner.JUnitCore.main(TestGearsES2SimpleNEWT.class.getName());
     }
 }
index 0bdd514..ae873ea 100644 (file)
 package com.jogamp.opengl.test.junit.newt.parenting;
 
 import java.awt.Frame;
-import java.net.URLConnection;
 
+import com.jogamp.nativewindow.CapabilitiesImmutable;
 import com.jogamp.nativewindow.util.InsetsImmutable;
-
-import com.jogamp.common.util.IOUtil;
-import com.jogamp.newt.Display;
-import com.jogamp.newt.Display.PointerIcon;
+import com.jogamp.newt.Window;
 import com.jogamp.newt.awt.NewtCanvasAWT;
-import com.jogamp.newt.event.KeyAdapter;
 import com.jogamp.newt.event.KeyEvent;
 import com.jogamp.newt.opengl.GLWindow;
+import com.jogamp.opengl.test.junit.util.NEWTDemoListener;
 import com.jogamp.opengl.test.junit.util.QuitAdapter;
-import com.jogamp.opengl.util.PNGPixelRect;
 
-public class NewtAWTReparentingKeyAdapter extends KeyAdapter {
+public class NewtAWTReparentingKeyAdapter extends NEWTDemoListener {
     final Frame frame;
     final NewtCanvasAWT newtCanvasAWT;
-    final GLWindow glWindow;
-    final QuitAdapter quitAdapter;
-    PointerIcon[] pointerIcons = null;
-    int pointerIconIdx = 0;
 
     public NewtAWTReparentingKeyAdapter(final Frame frame, final NewtCanvasAWT newtCanvasAWT, final GLWindow glWindow, final QuitAdapter quitAdapter) {
+        super(glWindow, quitAdapter, null);
         this.frame = frame;
         this.newtCanvasAWT = newtCanvasAWT;
-        this.glWindow = glWindow;
-        this.quitAdapter = quitAdapter;
     }
 
-    public void keyReleased(final KeyEvent e) {
-        if( !e.isPrintableKey() || e.isAutoRepeat() ) {
+    public void keyPressed(final KeyEvent e) {
+        if( e.isAutoRepeat() || e.isConsumed() ) {
             return;
         }
-        if( e.getKeySymbol() == KeyEvent.VK_L ) {
-            final com.jogamp.nativewindow.util.Point p0 = newtCanvasAWT.getNativeWindow().getLocationOnScreen(null);
-            final com.jogamp.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null);
-            System.err.println("NewtCanvasAWT position: "+p0+", "+p1);
-        } else if( e.getKeySymbol() == KeyEvent.VK_D ) {
-            glWindow.setUndecorated(!glWindow.isUndecorated());
-        } else if( e.getKeySymbol() == KeyEvent.VK_S ) {
-            if(glWindow.getParent()==null) {
-                System.err.println("XXX glWin to 100/100");
-                glWindow.setPosition(100, 100);
-            } else {
-                System.err.println("XXX glWin to 0/0");
-                glWindow.setPosition(0, 0);
-            }
-        } else if( e.getKeySymbol() == KeyEvent.VK_F ) {
-            if( null != quitAdapter ) {
-                quitAdapter.enable(false);
-            }
-            new Thread() {
-                public void run() {
-                    final Thread t = glWindow.setExclusiveContextThread(null);
-                    System.err.println("[set fullscreen  pre]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                    glWindow.setFullscreen(!glWindow.isFullscreen());
-                    System.err.println("[set fullscreen post]: "+glWindow.getX()+"/"+glWindow.getY()+" "+glWindow.getSurfaceWidth()+"x"+glWindow.getSurfaceHeight()+", f "+glWindow.isFullscreen()+", a "+glWindow.isAlwaysOnTop()+", "+glWindow.getInsets());
-                    glWindow.setExclusiveContextThread(t);
-                    if( null != quitAdapter ) {
-                        quitAdapter.clear();
-                        quitAdapter.enable(true);
-                    }
-            } }.start();
-        } else if( e.getKeySymbol() == KeyEvent.VK_P ) {
-            new Thread() {
-                public void run() {
-                    if(glWindow.getAnimator().isPaused()) {
-                        glWindow.getAnimator().resume();
-                    } else {
-                        glWindow.getAnimator().pause();
-                    }
-                }
-            }.run();
-        } else if( e.getKeySymbol() == KeyEvent.VK_A ) {
-            new Thread() {
-                public void run() {
-                    glWindow.setAlwaysOnTop(!glWindow.isAlwaysOnTop());
-                }
-            }.run();
-        } else if( e.getKeySymbol() == KeyEvent.VK_R ) {
-            if( null != quitAdapter ) {
-                quitAdapter.enable(false);
-            }
-            new Thread() {
-                public void run() {
-                    final Thread t = glWindow.setExclusiveContextThread(null);
-                    if(glWindow.getParent()==null) {
-                        System.err.println("XXX glWin to HOME");
-                        glWindow.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, 0 /* hints */);
-                    } else {
-                        if( null != frame ) {
-                            final InsetsImmutable nInsets = glWindow.getInsets();
-                            final java.awt.Insets aInsets = frame.getInsets();
-                            int dx, dy;
-                            if( nInsets.getTotalHeight()==0 ) {
-                                dx = aInsets.left;
-                                dy = aInsets.top;
+        if( 0 == e.getModifiers() ) { // all modifiers go to super class ..
+          final int keySymbol = e.getKeySymbol();
+          switch (keySymbol) {
+            case KeyEvent.VK_L:
+                e.setConsumed(true);
+                final com.jogamp.nativewindow.util.Point p0 = newtCanvasAWT.getNativeWindow().getLocationOnScreen(null);
+                final com.jogamp.nativewindow.util.Point p1 = glWindow.getLocationOnScreen(null);
+                printlnState("[location]", "AWT "+p0+", NEWT "+p1);
+                break;
+            case KeyEvent.VK_R:
+                e.setConsumed(true);
+                quitAdapterOff();
+                new Thread() {
+                    public void run() {
+                        final Thread t = glWindow.setExclusiveContextThread(null);
+                        if(glWindow.getParent()==null) {
+                            printlnState("[reparent pre - glWin to HOME]");
+                            glWindow.reparentWindow(newtCanvasAWT.getNativeWindow(), -1, -1, 0 /* hints */);
+                        } else {
+                            if( null != frame ) {
+                                final InsetsImmutable nInsets = glWindow.getInsets();
+                                final java.awt.Insets aInsets = frame.getInsets();
+                                int dx, dy;
+                                if( nInsets.getTotalHeight()==0 ) {
+                                    dx = aInsets.left;
+                                    dy = aInsets.top;
+                                } else {
+                                    dx = nInsets.getLeftWidth();
+                                    dy = nInsets.getTopHeight();
+                                }
+                                final int topLevelX = frame.getX()+frame.getWidth()+dx;
+                                final int topLevelY = frame.getY()+dy;
+                                printlnState("[reparent pre - glWin to TOP.1]", topLevelX+"/"+topLevelY+" - insets " + nInsets + ", " + aInsets);
+                                glWindow.reparentWindow(null, topLevelX, topLevelY, 0 /* hint */);
                             } else {
-                                dx = nInsets.getLeftWidth();
-                                dy = nInsets.getTopHeight();
+                                printlnState("[reparent pre - glWin to TOP.0]");
+                                glWindow.reparentWindow(null, -1, -1, 0 /* hints */);
                             }
-                            final int topLevelX = frame.getX()+frame.getWidth()+dx;
-                            final int topLevelY = frame.getY()+dy;
-                            System.err.println("XXX glWin to TOP.1 "+topLevelX+"/"+topLevelY+" - insets " + nInsets + ", " + aInsets);
-                            glWindow.reparentWindow(null, topLevelX, topLevelY, 0 /* hint */);
-                        } else {
-                            System.err.println("XXX glWin to TOP.0");
-                            glWindow.reparentWindow(null, -1, -1, 0 /* hints */);
-                        }
-                    }
-                    glWindow.requestFocus();
-                    glWindow.setExclusiveContextThread(t);
-                    if( null != quitAdapter ) {
-                        quitAdapter.clear();
-                        quitAdapter.enable(true);
-                    }
-            } }.start();
-        } else if(e.getKeySymbol() == KeyEvent.VK_C ) {
-            if( null == pointerIcons ) {
-                {
-                    pointerIcons = new PointerIcon[3];
-                    final Display disp = glWindow.getScreen().getDisplay();
-                    {
-                        PointerIcon _pointerIcon = null;
-                        final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/cross-grey-alpha-16x16.png" } );
-                        try {
-                            _pointerIcon = disp.createPointerIcon(res, 8, 8);
-                            System.err.println("Create PointerIcon #01: "+_pointerIcon);
-                        } catch (final Exception ex) {
-                            ex.printStackTrace();
-                        }
-                        pointerIcons[0] = _pointerIcon;
-                    }
-                    {
-                        PointerIcon _pointerIcon = null;
-                        final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "newt/data/pointer-grey-alpha-16x24.png" } );
-                        try {
-                            _pointerIcon = disp.createPointerIcon(res, 0, 0);
-                            System.err.println("Create PointerIcon #02: "+_pointerIcon);
-                        } catch (final Exception ex) {
-                            ex.printStackTrace();
                         }
-                        pointerIcons[1] = _pointerIcon;
-                    }
-                    {
-                        PointerIcon _pointerIcon = null;
-                        final IOUtil.ClassResources res = new IOUtil.ClassResources(glWindow.getClass(), new String[] { "jogamp-pointer-64x64.png" } );
-                        try {
-                            final URLConnection urlConn = res.resolve(0);
-                            final PNGPixelRect image = PNGPixelRect.read(urlConn.getInputStream(), null, false /* directBuffer */, 0 /* destMinStrideInBytes */, false /* destIsGLOriented */);
-                            System.err.println("Create PointerIcon #03: "+image);
-                            _pointerIcon = disp.createPointerIcon(image, 32, 0);
-                            System.err.println("Create PointerIcon #03: "+_pointerIcon);
-                        } catch (final Exception ex) {
-                            ex.printStackTrace();
-                        }
-                        pointerIcons[2] = _pointerIcon;
-                    }
-                }
-            }
-            new Thread() {
-                public void run() {
-                    final Thread t = glWindow.setExclusiveContextThread(null);
-                    System.err.println("[set pointer-icon pre]");
-                    final PointerIcon currentPI = glWindow.getPointerIcon();
-                    final PointerIcon newPI;
-                    if( pointerIconIdx >= pointerIcons.length ) {
-                        newPI=null;
-                        pointerIconIdx=0;
-                    } else {
-                        newPI=pointerIcons[pointerIconIdx++];
-                    }
-                    glWindow.setPointerIcon( newPI );
-                    System.err.println("[set pointer-icon post] "+currentPI+" -> "+glWindow.getPointerIcon());
-                    glWindow.setExclusiveContextThread(t);
-            } }.start();
-        } else if( e.getKeySymbol() == KeyEvent.VK_I ) {
-            new Thread() {
-                public void run() {
-                    final Thread t = glWindow.setExclusiveContextThread(null);
-                    System.err.println("[set mouse visible pre]: "+glWindow.isPointerVisible());
-                    glWindow.setPointerVisible(!glWindow.isPointerVisible());
-                    System.err.println("[set mouse visible post]: "+glWindow.isPointerVisible());
-                    glWindow.setExclusiveContextThread(t);
-            } }.start();
-        } else if(e.getKeySymbol() == KeyEvent.VK_J ) {
-            new Thread() {
-                public void run() {
-                    final Thread t = glWindow.setExclusiveContextThread(null);
-                    System.err.println("[set mouse confined pre]: "+glWindow.isPointerConfined());
-                    glWindow.confinePointer(!glWindow.isPointerConfined());
-                    System.err.println("[set mouse confined post]: "+glWindow.isPointerConfined());
-                    glWindow.setExclusiveContextThread(t);
-            } }.start();
-        } else if(e.getKeySymbol() == KeyEvent.VK_W ) {
-            new Thread() {
-               public void run() {
-