diff options
Diffstat (limited to 'src/newt')
21 files changed, 2001 insertions, 715 deletions
diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 2afa464d6..37147d1ca 100644 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -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}. diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index 3ef017d1b..f15c87beb 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -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) { diff --git a/src/newt/classes/jogamp/newt/OffscreenWindow.java b/src/newt/classes/jogamp/newt/OffscreenWindow.java index fa9bd21bb..09e318957 100644 --- a/src/newt/classes/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/jogamp/newt/OffscreenWindow.java @@ -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: diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 2a05f2ce6..491f984f2 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -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 ) { diff --git a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java index 8522bb9e4..83832eeb4 100644 --- a/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/android/WindowDriver.java @@ -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; } diff --git a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java index 9f776ef22..edc884366 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/awt/WindowDriver.java @@ -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; diff --git a/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java index d737dbf75..f20f938b6 100644 --- a/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/bcm/egl/WindowDriver.java @@ -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; } diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java index 69a8ccd37..a083f420f 100644 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/WindowDriver.java @@ -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; diff --git a/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java index 01173007c..242f644f6 100644 --- a/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/kd/WindowDriver.java @@ -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; diff --git a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java index 66119ffe0..deaba5f0c 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/WindowDriver.java @@ -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); diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java index cf286e54b..83604a380 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowDriver.java @@ -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; } diff --git a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java index 6cf9727f2..fb2a593bc 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java +++ b/src/newt/classes/jogamp/newt/driver/x11/WindowDriver.java @@ -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; } diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m index 5593cd682..b59e19e4e 100644 --- a/src/newt/native/MacWindow.m +++ b/src/newt/native/MacWindow.m @@ -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; */ diff --git a/src/newt/native/Window.h b/src/newt/native/Window.h index d9ee5fd1f..ada886d24 100644 --- a/src/newt/native/Window.h +++ b/src/newt/native/Window.h @@ -29,30 +29,60 @@ #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 diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index 8c29978f0..ad4111ec7 100644 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -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 index 000000000..47448cba9 --- /dev/null +++ b/src/newt/native/X11AllowedWMActions.c @@ -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 + diff --git a/src/newt/native/X11Common.h b/src/newt/native/X11Common.h index e58cdb755..309e62683 100644 --- a/src/newt/native/X11Common.h +++ b/src/newt/native/X11Common.h @@ -71,11 +71,23 @@ 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_ */ diff --git a/src/newt/native/X11Display.c b/src/newt/native/X11Display.c index b79c1ee95..0ba454a00 100644 --- a/src/newt/native/X11Display.c +++ b/src/newt/native/X11Display.c @@ -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; diff --git a/src/newt/native/X11Event.c b/src/newt/native/X11Event.c index 32a55c67c..d0567c16b 100644 --- a/src/newt/native/X11Event.c +++ b/src/newt/native/X11Event.c @@ -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; diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index e640b0c20..ca768240f 100644 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -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); } diff --git a/src/newt/native/XCBEvent.c b/src/newt/native/XCBEvent.c index d02d5a4ba..f27d30b28 100644 --- a/src/newt/native/XCBEvent.c +++ b/src/newt/native/XCBEvent.c @@ -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; */ |