diff options
Diffstat (limited to 'src/newt/classes')
12 files changed, 386 insertions, 257 deletions
diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index a71c6106d..413dd2fe9 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -136,20 +136,32 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto public boolean isApplet() { return jawtWindow.isApplet(); } + + boolean isParent() { + return null!=newtChild && jawtWindow == newtChild.getParent(); + } + + boolean isFullscreen() { + return null != newtChild && newtChild.isFullscreen(); + } class FocusAction implements Window.FocusRunnable { public boolean run() { + final boolean isParent = isParent(); + final boolean isFullscreen = isFullscreen(); if(DEBUG) { - System.err.println("NewtCanvasAWT.FocusAction: "+Display.getThreadName()+", isOnscreen "+isOnscreen+", hasFocus "+hasFocus()); + System.err.println("NewtCanvasAWT.FocusAction: "+Display.getThreadName()+", isOnscreen "+isOnscreen+", hasFocus "+hasFocus()+", isParent "+isParent+", isFS "+isFullscreen); } - // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus. - if(!hasFocus()) { - // Acquire the AWT focus 1st for proper AWT traversal - NewtCanvasAWT.super.requestFocus(); - } - if(isOnscreen) { - // Remove the AWT focus in favor of the native NEWT focus - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + if(isParent && !isFullscreen) { + // Newt-EDT -> AWT-EDT may freeze Window's native peer requestFocus. + if(!hasFocus()) { + // Acquire the AWT focus 1st for proper AWT traversal + NewtCanvasAWT.super.requestFocus(); + } + if(isOnscreen) { + // Remove the AWT focus in favor of the native NEWT focus + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + } } return false; // NEWT shall proceed requesting the native focus } @@ -159,7 +171,9 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto WindowListener clearAWTMenusOnNewtFocus = new WindowAdapter() { @Override public void windowGainedFocus(WindowEvent arg0) { - MenuSelectionManager.defaultManager().clearSelectedPath(); + if( isParent() && !isFullscreen() ) { + MenuSelectionManager.defaultManager().clearSelectedPath(); + } } }; @@ -167,10 +181,14 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto boolean suppress = false; public void keyPressed(KeyEvent e) { - handleKey(e, false); + if( isParent() && !isFullscreen() ) { + handleKey(e, false); + } } public void keyReleased(KeyEvent e) { - handleKey(e, true); + if( isParent() && !isFullscreen() ) { + handleKey(e, true); + } } public void keyTyped(KeyEvent e) { if(suppress) { @@ -217,21 +235,25 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto public void propertyChange(PropertyChangeEvent evt) { final Object oldF = evt.getOldValue(); final Object newF = evt.getNewValue(); + final boolean isParent = isParent(); + final boolean isFullscreen = isFullscreen(); if(DEBUG) { - System.err.println("NewtCanvasAWT.FocusProperty: "+evt.getPropertyName()+", src "+evt.getSource()+", "+oldF+" -> "+newF); + System.err.println("NewtCanvasAWT.FocusProperty: "+evt.getPropertyName()+", src "+evt.getSource()+", "+oldF+" -> "+newF+", isParent "+isParent+", isFS "+isFullscreen); } - if(oldF == NewtCanvasAWT.this && newF == null) { - // focus traversal to NEWT - NOP - if(DEBUG) { - System.err.println("NewtCanvasAWT.FocusProperty: NEWT focus traversal"); - } - } else if(null != newF && newF != NewtCanvasAWT.this) { - // focus traversal to another AWT component - if(DEBUG) { - System.err.println("NewtCanvasAWT.FocusProperty: lost focus - clear focus"); - } - if(newtChild.getDelegatedWindow() instanceof DriverClearFocus) { - ((DriverClearFocus)newtChild.getDelegatedWindow()).clearFocus(); + if(isParent && !isFullscreen) { + if(oldF == NewtCanvasAWT.this && newF == null) { + // focus traversal to NEWT - NOP + if(DEBUG) { + System.err.println("NewtCanvasAWT.FocusProperty: NEWT focus traversal"); + } + } else if(null != newF && newF != NewtCanvasAWT.this) { + // focus traversal to another AWT component + if(DEBUG) { + System.err.println("NewtCanvasAWT.FocusProperty: lost focus - clear focus"); + } + if(newtChild.getDelegatedWindow() instanceof DriverClearFocus) { + ((DriverClearFocus)newtChild.getDelegatedWindow()).clearFocus(); + } } } } @@ -294,7 +316,7 @@ public class NewtCanvasAWT extends java.awt.Canvas implements WindowClosingProto throw new InternalError("XXX"); } isOnscreen = jawtWindow.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); - awtAdapter = new AWTParentWindowAdapter(newtChild).addTo(this); + awtAdapter = new AWTParentWindowAdapter(jawtWindow, newtChild).addTo(this); newtChild.addWindowListener(clearAWTMenusOnNewtFocus); newtChild.setFocusAction(focusAction); // enable AWT focus traversal newtChildCloseOp = newtChild.setDefaultCloseOperation(WindowClosingProtocol.DO_NOTHING_ON_CLOSE); diff --git a/src/newt/classes/jogamp/newt/WindowImpl.java b/src/newt/classes/jogamp/newt/WindowImpl.java index 6564857e4..29056ee04 100644 --- a/src/newt/classes/jogamp/newt/WindowImpl.java +++ b/src/newt/classes/jogamp/newt/WindowImpl.java @@ -78,6 +78,9 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer { public static final boolean DEBUG_TEST_REPARENT_INCOMPATIBLE = Debug.isPropertyDefined("newt.test.Window.reparent.incompatible", true); + /** Timeout of queued events (repaint and resize) */ + static final long QUEUED_EVENT_TO = 1200; // ms + private volatile long windowHandle = 0; // lifecycle critical private volatile boolean visible = false; // lifecycle critical private RecursiveLock windowLock = LockFactory.createRecursiveLock(); // Window instance wide lock @@ -90,16 +93,17 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private AbstractGraphicsConfiguration config = null; // control access due to delegation protected CapabilitiesImmutable capsRequested = null; protected CapabilitiesChooser capabilitiesChooser = null; // default null -> default - protected boolean fullscreen = false, hasFocus = false; - protected int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user - protected int x = 64, y = 64; // client-area pos w/o insets - protected boolean autoPosition = true; // default: true (allow WM to choose if not set by user) - protected Insets insets = new Insets(); // insets of decoration (if top-level && decorated) + private boolean fullscreen = false, hasFocus = false; + private int width = 128, height = 128; // client-area size w/o insets, default: may be overwritten by user + private int x = 64, y = 64; // client-area pos w/o insets + private boolean autoPosition = true; // default: true (allow WM to choose top-level position, if not set by user) + private Insets insets = new Insets(); // insets of decoration (if top-level && decorated) - protected int nfs_width, nfs_height, nfs_x, nfs_y; // non fullscreen client-area size/pos w/o insets - protected String title = "Newt Window"; - protected boolean undecorated = false; - protected boolean alwaysOnTop = false; + 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 boolean undecorated = false; + private boolean alwaysOnTop = false; private boolean pointerVisible = true; private boolean pointerConfined = false; private LifecycleHook lifecycleHook = null; @@ -109,7 +113,6 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private ReparentActionRecreate reparentActionRecreate = new ReparentActionRecreate(); - private RequestFocusAction requestFocusAction = new RequestFocusAction(); private FocusRunnable focusAction = null; private KeyListener keyboardFocusHandler = null; @@ -122,8 +125,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private int mouseButtonPressed = 0; // current pressed mouse button number private long lastMousePressed = 0; // last time when a mouse button was pressed private int lastMouseClickCount = 0; // last mouse button click count - protected boolean mouseInWindow = false;// mouse entered window - is inside the window (may be synthetic) - protected Point lastMousePosition = new Point(); + private boolean mouseInWindow = false;// mouse entered window - is inside the window (may be synthetic) + private Point lastMousePosition = new Point(); private ArrayList<KeyListener> keyListeners = new ArrayList<KeyListener>(); @@ -276,10 +279,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( null != parentWindow && NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindow.lockSurface() ) { throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow); - } - if( ( 0>x || 0>y ) && null != parentWindow ) { - // min. child window position is 0/0 - x = 0; y = 0; + } + + // child window: position defaults to 0/0, no auto position, no negative position + if( null != parentWindow && ( autoPosition || 0>getX() || 0>getY() ) ) { + definePosition(0, 0); } try { if(validateParentWindowHandle()) { @@ -296,10 +300,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer confinePointerImpl(pointerConfined); if(waitForVisible(true, false)) { if(isFullscreen()) { - fullscreen = false; - FullScreenActionImpl fsa = new FullScreenActionImpl(true); - fsa.run(); + synchronized(fullScreenAction) { + fullscreen = false; // trigger a state change + fullScreenAction.init(true); + fullScreenAction.run(); + } } + // harmonize focus behavior for all platforms: focus on creation + requestFocusInt(isFullscreen() /* skipFocusAction */, true/* force */); + ((DisplayImpl) screen.getDisplay()).dispatchMessagesNative(); // status up2date } } } @@ -713,7 +722,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } if(!isNativeValid() && visible) { - if( 0<width*height ) { + if( 0<getWidth()*getHeight() ) { nativeWindowCreated = createNative(); madeVisible = nativeWindowCreated; } @@ -721,7 +730,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer WindowImpl.this.visible = true; } else if(WindowImpl.this.visible != visible) { if(isNativeValid()) { - setVisibleImpl(visible, x, y, width, height); + setVisibleImpl(visible, getX(), getY(), getWidth(), getHeight()); WindowImpl.this.waitForVisible(visible, true); madeVisible = visible; } @@ -742,7 +751,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setVisible: END ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+WindowImpl.this.visible+", nativeWindowCreated: "+nativeWindowCreated+", madeVisible: "+madeVisible); + System.err.println("Window setVisible: END ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+WindowImpl.this.visible+", nativeWindowCreated: "+nativeWindowCreated+", madeVisible: "+madeVisible); } } finally { windowLock.unlock(); @@ -764,7 +773,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public void setVisible(boolean visible) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setVisible: START ("+getThreadName()+") "+x+"/"+y+" "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow)); + System.err.println("Window setVisible: START ("+getThreadName()+") "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible: "+this.visible+" -> "+visible+", parentWindowHandle "+toHexString(parentWindowHandle)+", parentWindow "+(null!=parentWindow)); Thread.dumpStack(); } runOnEDTIfAvail(true, new VisibleAction(visible)); @@ -775,10 +784,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer windowLock.lock(); try { int visibleAction = 0; // 1 invisible, 2 visible (create) - if ( !fullscreen && ( width != WindowImpl.this.width || WindowImpl.this.height != height ) ) { + if ( !fullscreen && ( getWidth() != width || getHeight() != height ) ) { recreate = isNativeValid() && !getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setSize: START "+WindowImpl.this.width+"x"+WindowImpl.this.height+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible+", recreate "+recreate); + System.err.println("Window setSize: START "+getWidth()+"x"+getHeight()+" -> "+width+"x"+height+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)+", visible "+visible+", recreate "+recreate); } if(recreate) { // will trigger visibleAction:=2 -> create if wasVisible @@ -789,21 +798,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } if ( isNativeValid() && 0>=width*height && visible ) { visibleAction=1; // invisible - WindowImpl.this.width = 0; - WindowImpl.this.height = 0; + defineSize(0, 0); } else if ( !isNativeValid() && 0<width*height && visible ) { visibleAction = 2; // visible (create) - WindowImpl.this.width = width; - WindowImpl.this.height = height; + defineSize(width, height); } else if ( isNativeValid() ) { // this width/height will be set by windowChanged, called by the native implementation - reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(0, isVisible())); + reconfigureWindowImpl(getX(), getY(), width, height, getReconfigureFlags(0, isVisible())); } else { - WindowImpl.this.width = width; - WindowImpl.this.height = height; + defineSize(width, height); } if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setSize: END "+WindowImpl.this.width+"x"+WindowImpl.this.height+", visibleAction "+visibleAction); + System.err.println("Window setSize: END "+getWidth()+"x"+getHeight()+", visibleAction "+visibleAction); } switch(visibleAction) { case 1: setVisibleActionImpl(false); break; @@ -976,10 +982,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer private void reparent() { // mirror pos/size so native change notification can get overwritten - int x = WindowImpl.this.x; - int y = WindowImpl.this.y; - int width = WindowImpl.this.width; - int height = WindowImpl.this.height; + int x = getX(); + int y = getY(); + int width = getWidth(); + int height = getHeight(); boolean wasVisible; windowLock.lock(); @@ -1122,10 +1128,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if( ACTION_NATIVE_CREATION_PENDING == reparentAction ) { // make size and position persistent for proper recreation - WindowImpl.this.x = x; - WindowImpl.this.y = y; - WindowImpl.this.width = width; - WindowImpl.this.height = height; + definePosition(x, y); + defineSize(width, height); return; } @@ -1174,7 +1178,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer ok = WindowImpl.this.waitForSize(width, height, false, TIMEOUT_NATIVEWINDOW); } if(ok) { - requestFocusInt(true); + requestFocusInt(false /* skipFocusAction */, true/* force */); display.dispatchMessagesNative(); // status up2date } } @@ -1183,10 +1187,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if(!ok || !wasVisible) { // make size and position persistent manual, // since we don't have a WM feedback (invisible or recreation) - WindowImpl.this.x = x; - WindowImpl.this.y = y; - WindowImpl.this.width = width; - WindowImpl.this.height = height; + definePosition(x, y); + defineSize(width, height); } if(!ok) { @@ -1284,10 +1286,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // Change decoration on active window // Mirror pos/size so native change notification can get overwritten - final int x = WindowImpl.this.x; - final int y = WindowImpl.this.y; - final int width = WindowImpl.this.width; - final int height = WindowImpl.this.height; + final int x = getX(); + final int y = getY(); + final int width = getWidth(); + final int height = getHeight(); if( isNativeValid() ) { DisplayImpl display = (DisplayImpl) screen.getDisplay(); @@ -1333,10 +1335,10 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // Change decoration on active window // Mirror pos/size so native change notification can get overwritten - final int x = WindowImpl.this.x; - final int y = WindowImpl.this.y; - final int width = WindowImpl.this.width; - final int height = WindowImpl.this.height; + final int x = getX(); + final int y = getY(); + final int width = getWidth(); + final int height = getHeight(); if( isNativeValid() ) { DisplayImpl display = (DisplayImpl) screen.getDisplay(); @@ -1398,7 +1400,7 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer if(!setVal) { if(confine) { requestFocus(); - warpPointer(width/2, height/2); + warpPointer(getWidth()/2, getHeight()/2); } setVal = confinePointerImpl(confine); if(confine) { @@ -1445,6 +1447,27 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer return y; } + protected final boolean autoPosition() { return autoPosition; } + + /** Sets the position fields {@link #x} and {@link #y} to the given values and {@link #autoPosition} to false. */ + protected final void definePosition(int x, int y) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("definePosition: "+this.x+"/"+this.y+" -> "+x+"/"+y); + // Thread.dumpStack(); + } + autoPosition = false; + this.x = x; this.y = y; + } + + /** Sets the size fields {@link #width} and {@link #height} to the given values. */ + protected final void defineSize(int width, int height) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("defineSize: "+this.width+"x"+this.height+" -> "+width+"x"+height); + // Thread.dumpStack(); + } + this.width = width; this.height = height; + } + public final boolean isVisible() { return visible; } @@ -1519,8 +1542,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer "\n, ParentWindowHandle "+toHexString(parentWindowHandle)+" ("+(0!=getParentWindowHandle())+")"+ "\n, WindowHandle "+toHexString(getWindowHandle())+ "\n, SurfaceHandle "+toHexString(getSurfaceHandle())+ " (lockedExt window "+isWindowLockedByOtherThread()+", surface "+isSurfaceLockedByOtherThread()+")"+ - "\n, Pos "+getX()+"/"+getY()+", size "+getWidth()+"x"+getHeight()+ - "\n, Visible "+isVisible()+ + "\n, Pos "+getX()+"/"+getY()+" (auto "+autoPosition()+"), size "+getWidth()+"x"+getHeight()+ + "\n, Visible "+isVisible()+", focus "+hasFocus()+ "\n, Undecorated "+undecorated+" ("+isUndecorated()+")"+ "\n, AlwaysOnTop "+alwaysOnTop+", Fullscreen "+fullscreen+ "\n, WrappedWindow "+getWrappedWindow()+ @@ -1560,14 +1583,22 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer d.runOnEDTIfAvail(wait, task); } - private class RequestFocusAction implements Runnable { + private Runnable requestFocusAction = new Runnable() { public final void run() { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.RequestFocusAction: ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); + System.err.println("Window.RequestFocusAction: force 0 - ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); } WindowImpl.this.requestFocusImpl(false); } - } + }; + private Runnable requestFocusActionForced = new Runnable() { + public final void run() { + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.RequestFocusAction: force 1 - ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); + } + WindowImpl.this.requestFocusImpl(true); + } + }; public final boolean hasFocus() { return hasFocus; @@ -1578,14 +1609,23 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer } public void requestFocus(boolean wait) { - if(isNativeValid() && !focusAction()) { - runOnEDTIfAvail(wait, requestFocusAction); + requestFocus(wait /* wait */, false /* skipFocusAction */, false /* force */); + } + + private void requestFocus(boolean wait, boolean skipFocusAction, boolean force) { + if( isNativeValid() && + ( force || !hasFocus() ) && + ( skipFocusAction || !focusAction() ) ) { + runOnEDTIfAvail(wait, force ? requestFocusActionForced : requestFocusAction); } } /** Internal request focus on current thread */ - private void requestFocusInt(boolean force) { - if(!focusAction()) { + private void requestFocusInt(boolean skipFocusAction, boolean force) { + if( skipFocusAction || !focusAction() ) { + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window.RequestFocusInt: force "+force+" - ("+getThreadName()+"): "+hasFocus+" -> true - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); + } requestFocusImpl(force); } } @@ -1625,16 +1665,15 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer windowLock.lock(); try { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window setPosition: "+WindowImpl.this.x+"/"+WindowImpl.this.y+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)); + System.err.println("Window setPosition: "+getX()+"/"+getY()+" -> "+x+"/"+y+", fs "+fullscreen+", windowHandle "+toHexString(windowHandle)); } - if ( WindowImpl.this.x != x || WindowImpl.this.y != y ) { + if ( getX() != x || getY() != y ) { if(!fullscreen) { if(0!=windowHandle) { // this.x/this.y will be set by sizeChanged, triggered by windowing event system - reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(0, isVisible())); + reconfigureWindowImpl(x, y, getWidth(), getHeight(), getReconfigureFlags(0, isVisible())); } else { - WindowImpl.this.x = x; - WindowImpl.this.y = y; + definePosition(x, y); } } } @@ -1652,110 +1691,135 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer public void setTopLevelPosition(int x, int y) { setPosition(x + getInsets().getLeftWidth(), y + getInsets().getTopHeight()); } - + private class FullScreenActionImpl implements Runnable { boolean fullscreen; + boolean nativeFullscreenChange; - private FullScreenActionImpl (boolean fullscreen) { + private FullScreenActionImpl() { } + + public void init(boolean fullscreen) { this.fullscreen = fullscreen; - } + this.nativeFullscreenChange = isNativeValid() && isFullscreen() != fullscreen ; + } + public boolean nativeFullscreenChange() { return nativeFullscreenChange; } + public boolean nativeFullscreenOn() { return nativeFullscreenChange && fullscreen; } + public boolean nativeFullscreenOff() { return nativeFullscreenChange && !fullscreen; } public final void run() { windowLock.lock(); try { - if(WindowImpl.this.fullscreen != fullscreen) { - final boolean nativeFullscreenChange = isNativeValid() && - isFullscreen() != fullscreen ; - // set current state WindowImpl.this.fullscreen = fullscreen; - if( nativeFullscreenChange ) { - int x,y,w,h; + int x,y,w,h; + + if(fullscreen) { + nfs_x = getX(); + nfs_y = getY(); + nfs_width = getWidth(); + nfs_height = getHeight(); + x = screen.getX(); + y = screen.getY(); + w = screen.getWidth(); + h = screen.getHeight(); + } else { + x = nfs_x; + y = nfs_y; + w = nfs_width; + h = nfs_height; - if(fullscreen) { - nfs_x = WindowImpl.this.x; - nfs_y = WindowImpl.this.y; - nfs_width = WindowImpl.this.width; - nfs_height = WindowImpl.this.height; - x = screen.getX(); - y = screen.getY(); - w = screen.getWidth(); - h = screen.getHeight(); - } else { - x = nfs_x; - y = nfs_y; - w = nfs_width; - h = nfs_height; - - if(null!=parentWindow) { - // reset position to 0/0 within parent space - x = 0; - y = 0; - - // refit if size is bigger than parent - if( w > parentWindow.getWidth() ) { - w = parentWindow.getWidth(); - } - if( h > parentWindow.getHeight() ) { - h = parentWindow.getHeight(); - } + if(null!=parentWindow) { + // reset position to 0/0 within parent space + x = 0; + y = 0; + + // refit if size is bigger than parent + if( w > parentWindow.getWidth() ) { + w = parentWindow.getWidth(); + } + if( h > parentWindow.getHeight() ) { + h = parentWindow.getHeight(); } } - if(DEBUG_IMPLEMENTATION) { - System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen); - } + } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()+", "+screen); + } - DisplayImpl display = (DisplayImpl) screen.getDisplay(); - display.dispatchMessagesNative(); // status up2date - boolean wasVisible = isVisible(); - - // Lock parentWindow only during reparenting (attempt) - final NativeWindow parentWindowLocked; - if( null != parentWindow ) { - parentWindowLocked = parentWindow; - if( NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindowLocked.lockSurface() ) { - throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow); - } - } else { - parentWindowLocked = null; + DisplayImpl display = (DisplayImpl) screen.getDisplay(); + display.dispatchMessagesNative(); // status up2date + boolean wasVisible = isVisible(); + + // Lock parentWindow only during reparenting (attempt) + final NativeWindow parentWindowLocked; + if( null != parentWindow ) { + parentWindowLocked = parentWindow; + if( NativeSurface.LOCK_SURFACE_NOT_READY >= parentWindowLocked.lockSurface() ) { + throw new NativeWindowException("Parent surface lock: not ready: "+parentWindow); } - try { - reconfigureWindowImpl(x, y, w, h, - getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) | - FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) ); - } finally { - if(null!=parentWindowLocked) { - parentWindowLocked.unlockSurface(); - } + } else { + parentWindowLocked = null; + } + try { + reconfigureWindowImpl(x, y, w, h, + getReconfigureFlags( ( ( null != parentWindowLocked ) ? FLAG_CHANGE_PARENTING : 0 ) | + FLAG_CHANGE_FULLSCREEN | FLAG_CHANGE_DECORATION, wasVisible) ); + } finally { + if(null!=parentWindowLocked) { + parentWindowLocked.unlockSurface(); } - display.dispatchMessagesNative(); // status up2date + } + display.dispatchMessagesNative(); // status up2date + + if(wasVisible) { + setVisibleImpl(true, x, y, w, h); + WindowImpl.this.waitForVisible(true, false); + display.dispatchMessagesNative(); // status up2date + WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW); + display.dispatchMessagesNative(); // status up2date - if(wasVisible) { - setVisibleImpl(true, x, y, w, h); - WindowImpl.this.waitForVisible(true, false); - display.dispatchMessagesNative(); // status up2date - WindowImpl.this.waitForSize(w, h, false, TIMEOUT_NATIVEWINDOW); - display.dispatchMessagesNative(); // status up2date - requestFocusInt(true); - display.dispatchMessagesNative(); // status up2date - - if(DEBUG_IMPLEMENTATION) { - System.err.println("Window fs done: " + WindowImpl.this); - } + if(DEBUG_IMPLEMENTATION) { + System.err.println("Window fs done: " + WindowImpl.this); } } - } } finally { windowLock.unlock(); } sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); // trigger a resize/relayout and repaint to listener } } + private FullScreenActionImpl fullScreenAction = new FullScreenActionImpl(); public boolean setFullscreen(boolean fullscreen) { - runOnEDTIfAvail(true, new FullScreenActionImpl(fullscreen)); - return this.fullscreen; + synchronized(fullScreenAction) { + fullScreenAction.init(fullscreen); + if( fullScreenAction.nativeFullscreenChange() ) { + if(fullScreenAction.nativeFullscreenOn() && + isOffscreenInstance(WindowImpl.this, parentWindow)) { + // enable fullscreen on offscreen instance + if(null != parentWindow) { + nfs_parent = parentWindow; + reparentWindow(null, true); + } else { + throw new InternalError("Offscreen instance w/o parent unhandled"); + } + } + + runOnEDTIfAvail(true, fullScreenAction); + + if(fullScreenAction.nativeFullscreenOff() && null != nfs_parent) { + // disable fullscreen on offscreen instance + reparentWindow(nfs_parent, true); + nfs_parent = null; + } + + if(isVisible()) { + requestFocus(true /* wait */, this.fullscreen /* skipFocusAction */, true /* force */); + } + } + return this.fullscreen; + } } private class ScreenModeListenerImpl implements ScreenModeListener { @@ -1841,11 +1905,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer // make sure only one repaint event is queued if(!repaintQueued) { repaintQueued=true; + final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.consumeEvent: queued "+e); + System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO); // Thread.dumpStack(); - } - return false; + } + return discardTO; // discardTO:=true -> consumed } return true; } @@ -1856,11 +1921,12 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer case WindowEvent.EVENT_WINDOW_RESIZED: // queue event in case window is locked, ie in operation if( isWindowLocked() ) { + final boolean discardTO = QUEUED_EVENT_TO <= System.currentTimeMillis()-e.getWhen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.consumeEvent: queued "+e); + System.err.println("Window.consumeEvent: "+Thread.currentThread().getName()+" - queued "+e+", discard-to "+discardTO); // Thread.dumpStack(); } - return false; + return discardTO; // discardTO:=true -> consumed } break; default: @@ -1918,11 +1984,11 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer y = lastMousePosition.getY(); } // clip coordinates to window dimension - x = Math.min(Math.max(x, 0), width-1); - y = Math.min(Math.max(y, 0), height-1); + x = Math.min(Math.max(x, 0), getWidth()-1); + y = Math.min(Math.max(y, 0), getHeight()-1); mouseInWindow = eventType == MouseEvent.EVENT_MOUSE_ENTERED; } - if(x<0||y<0||x>=width||y>=height) { + if(x<0||y<0||x>=getWidth()||y>=getHeight()) { return; // .. invalid .. } if(DEBUG_MOUSE_EVENT) { @@ -2308,15 +2374,14 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer /** Triggered by implementation's WM events to update the client-area size w/o insets/decorations. */ protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { - if(force || width != newWidth || height != newHeight) { + if(force || getWidth() != newWidth || getHeight() != newHeight) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.sizeChanged: ("+getThreadName()+"): (defer: "+defer+") force "+force+", "+width+"x"+height+" -> "+newWidth+"x"+newHeight+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); + System.err.println("Window.sizeChanged: ("+getThreadName()+"): (defer: "+defer+") force "+force+", "+getWidth()+"x"+getHeight()+" -> "+newWidth+"x"+newHeight+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); } if(0>newWidth || 0>newHeight) { throw new NativeWindowException("Illegal width or height "+newWidth+"x"+newHeight+" (must be >= 0)"); } - width = newWidth; - height = newHeight; + defineSize(newWidth, newHeight); if(isNativeValid()) { if(!defer) { sendWindowEvent(WindowEvent.EVENT_WINDOW_RESIZED); @@ -2353,18 +2418,18 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer /** Triggered by implementation's WM events to update the position. */ protected void positionChanged(boolean defer, int newX, int newY) { - autoPosition = false; - if ( x != newX || y != newY ) { + if ( getX() != newX || getY() != newY ) { if(DEBUG_IMPLEMENTATION) { - System.err.println("Window.positionChanged: ("+getThreadName()+"): (defer: "+defer+") "+x+"/"+y+" -> "+newX+"/"+newY+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); + System.err.println("Window.positionChanged: ("+getThreadName()+"): (defer: "+defer+") "+getX()+"/"+getY()+" -> "+newX+"/"+newY+" - windowHandle "+toHexString(windowHandle)+" parentWindowHandle "+toHexString(parentWindowHandle)); } - x = newX; - y = newY; + definePosition(newX, newY); if(!defer) { sendWindowEvent(WindowEvent.EVENT_WINDOW_MOVED); } else { enqueueWindowEvent(false, WindowEvent.EVENT_WINDOW_MOVED); } + } else { + autoPosition = false; // ensure it's off even w/ same position } } @@ -2419,8 +2484,8 @@ public abstract class WindowImpl implements Window, NEWTEventConsumer * Triggered by implementation's WM events to update the content */ protected void windowRepaint(boolean defer, int x, int y, int width, int height) { - width = ( 0 >= width ) ? this.width : width; - height = ( 0 >= height ) ? this.height : height; + width = ( 0 >= width ) ? getWidth() : width; + height = ( 0 >= height ) ? getHeight() : height; if(DEBUG_IMPLEMENTATION) { System.err.println("Window.windowRepaint "+getThreadName()+" (defer: "+defer+") "+x+"/"+y+" "+width+"x"+height); } diff --git a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java index 8e9c028d4..ce8ed7c49 100644 --- a/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java +++ b/src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java @@ -30,6 +30,8 @@ package jogamp.newt.awt.event; import java.awt.KeyboardFocusManager; +import javax.media.nativewindow.NativeWindow; + import jogamp.newt.driver.DriverUpdatePosition; import com.jogamp.newt.event.awt.AWTAdapter; @@ -43,8 +45,11 @@ public class AWTParentWindowAdapter extends AWTWindowAdapter implements java.awt.event.HierarchyListener { - public AWTParentWindowAdapter(com.jogamp.newt.Window downstream) { + NativeWindow downstreamParent; + + public AWTParentWindowAdapter(NativeWindow downstreamParent, com.jogamp.newt.Window downstream) { super(downstream); + this.downstreamParent = downstreamParent; } public AWTAdapter addTo(java.awt.Component awtComponent) { @@ -61,13 +66,17 @@ public class AWTParentWindowAdapter // forward focus to NEWT child final com.jogamp.newt.Window newtChild = getNewtWindow(); final boolean isOnscreen = newtChild.isNativeValid() && newtChild.getGraphicsConfiguration().getChosenCapabilities().isOnscreen(); + final boolean isParent = downstreamParent == newtChild.getParent(); + final boolean isFullscreen = newtChild.isFullscreen(); if(DEBUG_IMPLEMENTATION) { - System.err.println("AWT: focusGained: onscreen "+ isOnscreen+", "+e); + System.err.println("AWT: focusGained: onscreen "+ isOnscreen+", "+e+", isParent: "+isParent+", isFS "+isFullscreen); } - if(isOnscreen) { - KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + if(isParent) { + if(isOnscreen && !isFullscreen) { + KeyboardFocusManager.getCurrentKeyboardFocusManager().clearGlobalFocusOwner(); + } + newtChild.requestFocus(false); } - newtChild.requestFocus(false); } public void focusLost(java.awt.event.FocusEvent e) { diff --git a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java index 6348cf19e..52c789a4d 100644 --- a/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java +++ b/src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java @@ -177,19 +177,18 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { // sh.setType(SurfaceHolder.SURFACE_TYPE_NORMAL); // default size -> TBD ! - this.width = 0; - this.height = 0; + defineSize(0, 0); } public SurfaceView getAndroidView() { return androidView; } public void setAndroidWindow(android.view.Window window) { - System.err.println("setandroidWindow: "+window+", "+width+"x"+height); + System.err.println("setandroidWindow: "+window+", "+getWidth()+"x"+getHeight()); androidWindow = window; androidWindowConfigurationPreCreate(); - if(width>0 && height>0 && !isFullscreen()) { + if(getWidth()>0 && getHeight()>0 && !isFullscreen()) { if(null != androidWindow) { - androidWindow.setLayout(width, height); + androidWindow.setLayout(getWidth(), getHeight()); } } } @@ -205,7 +204,7 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { @Override protected void createNativeImpl() { Log.d(MD.TAG, "createNativeImpl 0 - surfaceHandle 0x"+Long.toHexString(surfaceHandle)+ - ", format "+format+", "+x+"/"+y+" "+width+"x"+height+" - "+Thread.currentThread().getName()); + ", format "+format+", "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()+" - "+Thread.currentThread().getName()); Thread.dumpStack(); if(0!=getParentWindowHandle()) { throw new NativeWindowException("Window parenting not supported (yet)"); @@ -328,7 +327,7 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { // public void surfaceCreated(SurfaceHolder holder) { - Log.d(MD.TAG, "surfaceCreated: "+x+"/"+y+" "+width+"x"+height); + Log.d(MD.TAG, "surfaceCreated: "+getX()+"/"+getY()+" "+getWidth()+"x"+getHeight()); } public void surfaceChanged(SurfaceHolder aHolder, int aFormat, int aWidth, int aHeight) { @@ -347,9 +346,7 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { getScreen().getCurrentScreenMode(); // if ScreenMode changed .. trigger ScreenMode event } - if(0>x || 0>y) { - x = 0; - y = 0; + if(0>getX() || 0>getY()) { positionChanged(false, 0, 0); } @@ -365,7 +362,7 @@ public class AndroidWindow extends jogamp.newt.WindowImpl implements Callback2 { Log.d(MD.TAG, "surfaceRealized: isValid: "+surface.isValid()+ ", new surfaceHandle 0x"+Long.toHexString(surfaceHandle)+", format: "+format+ - ", "+x+"/"+y+" "+nWidth+"x"+nHeight+", visible: "+isVisible()); + ", "+getX()+"/"+getY()+" "+nWidth+"x"+nHeight+", visible: "+isVisible()); if(isVisible()) { setVisible(true); diff --git a/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java b/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java index e9e3ec0ba..2c921e7b2 100644 --- a/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java +++ b/src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java @@ -59,13 +59,12 @@ public class AWTWindow extends WindowImpl { this(null); } - public static Class[] getCustomConstructorArgumentTypes() { - return new Class[] { Container.class } ; + public static Class<?>[] getCustomConstructorArgumentTypes() { + return new Class<?>[] { Container.class } ; } public AWTWindow(Container container) { super(); - title = "AWT NewtWindow"; this.container = container; if(container instanceof Frame) { frame = (Frame) container; @@ -99,10 +98,8 @@ public class AWTWindow extends WindowImpl { owningFrame=true; } else { owningFrame=false; - width = container.getWidth(); - height = container.getHeight(); - x = container.getX(); - y = container.getY(); + defineSize(container.getWidth(), container.getHeight()); + definePosition(container.getX(), container.getY()); } if(null!=frame) { frame.setTitle(getTitle()); @@ -117,11 +114,11 @@ public class AWTWindow extends WindowImpl { // canvas.addComponentListener(listener); container.add(canvas, BorderLayout.CENTER); - container.setSize(width, height); - container.setLocation(x, y); + container.setSize(getWidth(), getHeight()); + container.setLocation(getX(), getY()); new AWTWindowAdapter(this).addTo(container); // fwd all AWT Window events to here - reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true)); + reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY | FLAG_CHANGE_DECORATION, true)); // throws exception if failed .. setWindowHandle(1); // just a marker .. @@ -221,15 +218,13 @@ public class AWTWindow extends WindowImpl { @Override public void windowMoved(com.jogamp.newt.event.WindowEvent e) { if(null!=container) { - x = container.getX(); - y = container.getY(); + definePosition(container.getX(), container.getY()); } } @Override public void windowResized(com.jogamp.newt.event.WindowEvent e) { if(null!=canvas) { - width = canvas.getWidth(); - height = canvas.getHeight(); + defineSize(canvas.getWidth(), canvas.getHeight()); } } } diff --git a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java index 6f66eedd3..bd63f83ab 100644 --- a/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java +++ b/src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java @@ -35,7 +35,6 @@ package jogamp.newt.driver.broadcom.egl; import jogamp.opengl.egl.*; import javax.media.nativewindow.*; -import javax.media.nativewindow.awt.AWTGraphicsConfiguration; import javax.media.nativewindow.util.Insets; import javax.media.nativewindow.util.Point; import javax.media.opengl.GLCapabilitiesImmutable; @@ -62,7 +61,7 @@ public class Window extends jogamp.newt.WindowImpl { setGraphicsConfiguration(cfg); setSizeImpl(getScreen().getWidth(), getScreen().getHeight()); - setWindowHandle(realizeWindow(true, width, height)); + setWindowHandle(realizeWindow(true, getWidth(), getHeight())); if (0 == getWindowHandle()) { throw new NativeWindowException("Error native Window Handle is null"); } @@ -81,8 +80,7 @@ public class Window extends jogamp.newt.WindowImpl { // n/a in BroadcomEGL System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); } else { - this.width = width; - this.height = height; + defineSize(width, height); } } @@ -101,8 +99,7 @@ public class Window extends jogamp.newt.WindowImpl { // n/a in BroadcomEGL System.err.println("BCEGL Window.setSizeImpl n/a in BroadcomEGL with realized window"); } else { - this.width=(width>0)?width:this.width; - this.height=(height>0)?height:this.height; + defineSize((width>0)?width:getWidth(), (height>0)?height:getHeight()); } } if(x>=0 || y>=0) { @@ -152,8 +149,7 @@ public class Window extends jogamp.newt.WindowImpl { } private void windowCreated(int cfgID, int width, int height) { - this.width = width; - this.height = height; + defineSize(width, height); GLCapabilitiesImmutable capsReq = (GLCapabilitiesImmutable) getGraphicsConfiguration().getRequestedCapabilities(); final AbstractGraphicsConfiguration cfg = EGLGraphicsConfiguration.create(capsReq, getScreen().getGraphicsScreen(), cfgID); if (null == cfg) { diff --git a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java b/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java index 873d0a0c1..09e0e3016 100644 --- a/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java +++ b/src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java @@ -64,7 +64,7 @@ public class Window extends jogamp.newt.WindowImpl { synchronized(Window.class) { setWindowHandle(nextWindowHandle++); // just a marker - surfaceHandle = CreateSurface(aDevice.getHandle(), getScreen().getWidth(), getScreen().getHeight(), x, y, width, height); + surfaceHandle = CreateSurface(aDevice.getHandle(), getScreen().getWidth(), getScreen().getHeight(), getX(), getY(), getWidth(), getHeight()); if (surfaceHandle == 0) { throw new NativeWindowException("Error creating window"); } @@ -138,10 +138,8 @@ public class Window extends jogamp.newt.WindowImpl { private native void SetBounds0(long surfaceHandle, int scrn_width, int scrn_height, int x, int y, int width, int height); private void updateBounds(int x, int y, int width, int height) { - this.x = x; - this.y = y; - this.width = width; - this.height = height; + definePosition(x, y); + defineSize(width, height); } private long surfaceHandle; diff --git a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java b/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java index 92f8251bc..8ae0b6587 100644 --- a/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java +++ b/src/newt/classes/jogamp/newt/driver/kd/KDWindow.java @@ -34,7 +34,6 @@ package jogamp.newt.driver.kd; import jogamp.newt.*; -import jogamp.newt.driver.intel.gdl.Display; import jogamp.opengl.egl.*; import javax.media.nativewindow.*; import javax.media.nativewindow.util.Insets; @@ -102,8 +101,8 @@ public class KDWindow extends WindowImpl { } // int _x=(x>=0)?x:this.x; // int _y=(x>=0)?y:this.y; - width=(width>0)?width:this.width; - height=(height>0)?height:this.height; + width=(width>0)?width:getWidth(); + height=(height>0)?height:getHeight(); if(width>0 || height>0) { setSize0(eglWindowHandle, width, height); } @@ -145,8 +144,8 @@ public class KDWindow extends WindowImpl { @Override protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { - if(fullscreen) { - ((KDScreen)getScreen()).sizeChanged(width, height); + if(isFullscreen()) { + ((KDScreen)getScreen()).sizeChanged(getWidth(), getHeight()); } super.sizeChanged(defer, newWidth, newHeight, force); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java b/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java index 3204982be..b9c725fd4 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java @@ -38,16 +38,24 @@ import java.util.List; import javax.media.nativewindow.DefaultGraphicsScreen; import javax.media.nativewindow.util.Dimension; +import javax.media.nativewindow.util.DimensionImmutable; import javax.media.nativewindow.util.Point; import jogamp.newt.ScreenImpl; +import com.jogamp.common.util.IntObjectHashMap; import com.jogamp.newt.ScreenMode; import com.jogamp.newt.util.ScreenModeUtil; public class MacScreen extends ScreenImpl { + + // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) + private static IntObjectHashMap/*<int, DimensionImmutable>*/ scrnIdx2Dimension; + static { MacDisplay.initSingleton(); + scrnIdx2Dimension = new IntObjectHashMap(); + scrnIdx2Dimension.setKeyNotFoundValue(null); } public MacScreen() { @@ -63,7 +71,18 @@ public class MacScreen extends ScreenImpl { private static native int getHeightImpl0(int scrn_idx); private int[] getScreenModeIdx(int idx) { - int[] modeProps = getScreenMode0(screen_idx, idx); + // caching native CGDisplayScreenSize() results, since it's ridiculous slow (~6 ms each call) + DimensionImmutable dim = (DimensionImmutable) scrnIdx2Dimension.get(screen_idx); + if(null == dim) { + int[] res = getScreenSizeMM0(screen_idx); + if(null == res || 0 == res.length) { + return null; + } + dim = new Dimension(res[0], res[1]); + scrnIdx2Dimension.put(screen_idx, dim); + } + + int[] modeProps = getScreenMode0(screen_idx, idx, dim.getWidth(), dim.getHeight()); if (null == modeProps || 0 == modeProps.length) { return null; } @@ -117,7 +136,8 @@ public class MacScreen extends ScreenImpl { virtualSize.setWidth(getWidthImpl0(screen_idx)); virtualSize.setHeight(getHeightImpl0(screen_idx)); } - - private native int[] getScreenMode0(int screen_index, int mode_index); + + private native int[] getScreenSizeMM0(int screen_idx); + private native int[] getScreenMode0(int screen_index, int mode_index, int widthMM, int heightMM); private native boolean setScreenMode0(int screen_index, int mode_idx); } diff --git a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java index 75a3cf6d5..c926d44ee 100644 --- a/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java +++ b/src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java @@ -67,7 +67,7 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl throw new NativeWindowException("Error choosing GraphicsConfiguration creating window: "+this); } setGraphicsConfiguration(cfg); - reconfigureWindowImpl(x, y, width, height, getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true)); + reconfigureWindowImpl(getX(), getY(), getWidth(), getHeight(), getReconfigureFlags(FLAG_CHANGE_VISIBILITY, true)); if (0 == getWindowHandle()) { throw new NativeWindowException("Error creating window"); } @@ -247,8 +247,8 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl @Override protected void sizeChanged(boolean defer, int newWidth, int newHeight, boolean force) { - if(width != newWidth || height != newHeight) { - final Point p0S = getTopLevelLocationOnScreen(x, y); + if(getWidth() != newWidth || getHeight() != newHeight) { + final Point p0S = getTopLevelLocationOnScreen(getX(), getY()); setFrameTopLeftPoint0(getParentWindowHandle(), getWindowHandle(), p0S.getX(), p0S.getY()); } super.sizeChanged(defer, newWidth, newHeight, force); @@ -271,7 +271,7 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl @Override protected boolean setPointerVisibleImpl(final boolean pointerVisible) { if( !isOffscreenInstance ) { - return setPointerVisible0(getWindowHandle(), pointerVisible); + return setPointerVisible0(getWindowHandle(), hasFocus(), pointerVisible); } // else may need offscreen solution ? FIXME return false; } @@ -296,10 +296,13 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl // Note that we send the key char for the key code on this // platform -- we do not get any useful key codes out of the system final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); - if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)); - // only deliver keyChar on key Typed events, harmonizing platform behavior - keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; - super.sendKeyEvent(eventType, modifiers, keyCode2, keyChar); + final boolean valid = validateKeyEvent(eventType, modifiers, keyCode); + if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.sendKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid); + if(valid) { + // only deliver keyChar on key Typed events, harmonizing platform behavior + keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; + super.sendKeyEvent(eventType, modifiers, keyCode2, keyChar); + } } @Override @@ -307,12 +310,37 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl // Note that we send the key char for the key code on this // platform -- we do not get any useful key codes out of the system final int keyCode2 = MacKeyUtil.validateKeyCode(keyCode, keyChar); - if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)); - // only deliver keyChar on key Typed events, harmonizing platform behavior - keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; - super.enqueueKeyEvent(wait, eventType, modifiers, keyCode2, keyChar); + final boolean valid = validateKeyEvent(eventType, modifiers, keyCode); + if(DEBUG_IMPLEMENTATION) System.err.println("MacWindow.enqueueKeyEvent "+Thread.currentThread().getName()+" char: 0x"+Integer.toHexString(keyChar)+", code 0x"+Integer.toHexString(keyCode)+" -> 0x"+Integer.toHexString(keyCode2)+", valid "+valid); + if(valid) { + // only deliver keyChar on key Typed events, harmonizing platform behavior + keyChar = KeyEvent.EVENT_KEY_TYPED == eventType ? keyChar : (char)-1; + super.enqueueKeyEvent(wait, eventType, modifiers, keyCode2, keyChar); + } } + private int keyDownModifiers = 0; + private int keyDownCode = 0; + + private boolean validateKeyEvent(int eventType, int modifiers, int keyCode) { + switch(eventType) { + case KeyEvent.EVENT_KEY_PRESSED: + keyDownModifiers = modifiers; + keyDownCode = keyCode; + return true; + case KeyEvent.EVENT_KEY_RELEASED: + return keyDownModifiers == modifiers && keyDownCode == keyCode; + case KeyEvent.EVENT_KEY_TYPED: + final boolean matchKeyDown = keyDownModifiers == modifiers && keyDownCode == keyCode; + keyDownModifiers = 0; + keyDownCode = 0; + return matchKeyDown; + default: + throw new NativeWindowException("Unexpected key event type " + eventType); + } + } + + //---------------------------------------------------------------------- // Internals only // @@ -381,7 +409,7 @@ public class MacWindow extends WindowImpl implements SurfaceChangeable, DriverCl private native void setFrameTopLeftPoint0(long parentWindowHandle, long window, int x, int y); private native void setAlwaysOnTop0(long window, boolean atop); private static native Object getLocationOnScreen0(long windowHandle, int src_x, int src_y); - private static native boolean setPointerVisible0(long windowHandle, boolean visible); + private static native boolean setPointerVisible0(long windowHandle, boolean hasFocus, boolean visible); private static native boolean confinePointer0(long windowHandle, boolean confine); private static native void warpPointer0(long windowHandle, int x, int y); diff --git a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java index ff3bd5ef6..d14c47f5a 100644 --- a/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java +++ b/src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java @@ -115,7 +115,7 @@ public class WindowsWindow extends WindowImpl { final int flags = getReconfigureFlags(0, true) & ( FLAG_IS_ALWAYSONTOP | FLAG_IS_UNDECORATED ) ; setWindowHandle(CreateWindow0(display.getHInstance(), display.getWindowClassName(), display.getWindowClassName(), - getParentWindowHandle(), x, y, width, height, autoPosition, flags)); + getParentWindowHandle(), getX(), getY(), getWidth(), getHeight(), autoPosition(), flags)); if (getWindowHandle() == 0) { throw new NativeWindowException("Error creating window"); } @@ -220,7 +220,7 @@ public class WindowsWindow extends WindowImpl { public void run() { final Point p0 = getLocationOnScreenImpl(0, 0); res[0] = Boolean.valueOf(confinePointer0(getWindowHandle(), confine, - p0.getX(), p0.getY(), p0.getX()+width, p0.getY()+height)); + p0.getX(), p0.getY(), p0.getX()+getWidth(), p0.getY()+getHeight())); } }); return res[0].booleanValue(); diff --git a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java index 33b541c34..c975306b4 100644 --- a/src/newt/classes/jogamp/newt/driver/x11/X11Window.java +++ b/src/newt/classes/jogamp/newt/driver/x11/X11Window.java @@ -79,7 +79,7 @@ public class X11Window extends WindowImpl { setWindowHandle(CreateWindow0(getParentWindowHandle(), display.getEDTHandle(), screen.getIndex(), visualID, display.getJavaObjectAtom(), display.getWindowDeleteAtom(), - x, y, width, height, autoPosition, flags)); + getX(), getY(), getWidth(), getHeight(), autoPosition(), flags)); windowHandleClose = getWindowHandle(); if (0 == windowHandleClose) { throw new NativeWindowException("Error creating window"); |