aboutsummaryrefslogtreecommitdiffstats
path: root/src/newt
diff options
context:
space:
mode:
Diffstat (limited to 'src/newt')
-rw-r--r--src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java74
-rw-r--r--src/newt/classes/jogamp/newt/WindowImpl.java393
-rw-r--r--src/newt/classes/jogamp/newt/awt/event/AWTParentWindowAdapter.java19
-rw-r--r--src/newt/classes/jogamp/newt/driver/android/AndroidWindow.java19
-rw-r--r--src/newt/classes/jogamp/newt/driver/awt/AWTWindow.java23
-rw-r--r--src/newt/classes/jogamp/newt/driver/broadcom/egl/Window.java12
-rw-r--r--src/newt/classes/jogamp/newt/driver/intel/gdl/Window.java8
-rw-r--r--src/newt/classes/jogamp/newt/driver/kd/KDWindow.java9
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacScreen.java26
-rw-r--r--src/newt/classes/jogamp/newt/driver/macosx/MacWindow.java54
-rw-r--r--src/newt/classes/jogamp/newt/driver/windows/WindowsWindow.java4
-rw-r--r--src/newt/classes/jogamp/newt/driver/x11/X11Window.java2
-rw-r--r--src/newt/native/MacWindow.m89
-rw-r--r--src/newt/native/NewtMacWindow.h27
-rw-r--r--src/newt/native/NewtMacWindow.m257
-rw-r--r--src/newt/native/X11Window.c166
16 files changed, 748 insertions, 434 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");
diff --git a/src/newt/native/MacWindow.m b/src/newt/native/MacWindow.m
index ddd59f0a1..6d96e01fb 100644
--- a/src/newt/native/MacWindow.m
+++ b/src/newt/native/MacWindow.m
@@ -44,6 +44,10 @@
#import <stdio.h>
+#ifdef DBG_PERF
+ #include "timespec.h"
+#endif
+
static const char * const ClazzNamePoint = "javax/media/nativewindow/util/Point";
static const char * const ClazzAnyCstrName = "<init>";
static const char * const ClazzNamePointCstrSignature = "(II)V";
@@ -315,11 +319,60 @@ static long GetDictionaryLong(CFDictionaryRef theDict, const void* key)
/*
* Class: jogamp_newt_driver_macosx_MacScreen
+ * Method: getScreenSizeMM0
+ * Signature: (I)[I
+ */
+JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenSizeMM0
+ (JNIEnv *env, jobject obj, jint scrn_idx)
+{
+ NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
+
+#ifdef DBG_PERF
+ struct timespec t0, t1, td;
+ long td_ms;
+ timespec_now(&t0);
+#endif
+
+ NSScreen *screen = NewtScreen_getNSScreenByIndex((int)scrn_idx);
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "MacScreen_getScreenSizeMM0.1: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "MacScreen_getScreenSizeMM0.2: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ CGSize screenDim = CGDisplayScreenSize(display);
+#ifdef DBG_PERF
+ timespec_now(&t1); timespec_subtract(&td, &t1, &t0); td_ms = timespec_milliseconds(&td);
+ fprintf(stderr, "MacScreen_getScreenSizeMM0.3: %ld ms\n", td_ms); fflush(NULL);
+#endif
+
+ jint prop[ 2 ];
+ prop[0] = (jint) screenDim.width;
+ prop[1] = (jint) screenDim.height;
+
+ jintArray properties = (*env)->NewIntArray(env, 2);
+ if (properties == NULL) {
+ NewtCommon_throwNewRuntimeException(env, "Could not allocate int array of size 2");
+ }
+ (*env)->SetIntArrayRegion(env, properties, 0, 2, prop);
+
+ [pool release];
+
+ return properties;
+}
+
+/*
+ * Class: jogamp_newt_driver_macosx_MacScreen
* Method: getScreenMode0
- * Signature: (II)[I
+ * Signature: (IIII)[I
*/
JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMode0
- (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx)
+ (JNIEnv *env, jobject obj, jint scrn_idx, jint mode_idx, jint widthMM, jint heightMM)
{
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
@@ -360,7 +413,6 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo
}
// mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
- CGSize screenDim = CGDisplayScreenSize(display);
int mWidth = CGDDGetModeWidth(mode);
int mHeight = CGDDGetModeHeight(mode);
@@ -383,8 +435,8 @@ JNIEXPORT jintArray JNICALL Java_jogamp_newt_driver_macosx_MacScreen_getScreenMo
prop[propIndex++] = mWidth;
prop[propIndex++] = mHeight;
prop[propIndex++] = CGDDGetModeBitsPerPixel(mode);
- prop[propIndex++] = (jint) screenDim.width;
- prop[propIndex++] = (jint) screenDim.height;
+ prop[propIndex++] = widthMM;
+ prop[propIndex++] = heightMM;
prop[propIndex++] = CGDDGetModeRefreshRate(mode);
prop[propIndex++] = ccwRot;
prop[propIndex - NUM_SCREEN_MODE_PROPERTIES_ALL] = ( -1 < mode_idx ) ? propIndex-1 : propIndex ; // count == NUM_SCREEN_MODE_PROPERTIES_ALL
@@ -421,9 +473,10 @@ JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacScreen_setScreenMod
CGDirectDisplayID display = NewtScreen_getCGDirectDisplayIDByNSScreen(screen);
CFArrayRef availableModes = CGDisplayAvailableModes(display);
+#ifdef VERBOSE_ON
CFIndex numberOfAvailableModes = CFArrayGetCount(availableModes);
CFIndex numberOfAvailableModesRots = ROTMODES_PER_REALMODE * numberOfAvailableModes;
-
+#endif
CFDictionaryRef mode = (CFDictionaryRef)CFArrayGetValueAtIndex(availableModes, mode_idx / ROTMODES_PER_REALMODE);
// mode = CGDisplayModeRetain(mode); // 10.6 on CGDisplayModeRef
@@ -525,7 +578,8 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_macosx_MacWindow_createWindow0
styleMask: (NSUInteger) styleMask
backing: (NSBackingStoreType) bufferingType
defer: NO
- screen: myScreen];
+ screen: myScreen
+ isFullscreenWindow: fullscreen];
[myWindow setReleasedWhenClosed: YES]; // default
[myWindow setPreservesContentDuringLiveResize: NO];
@@ -645,6 +699,19 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_macosx_MacWindow_close0
DBG_PRINT( "windowClose.0 - %p,%d view %p,%d, parent %p\n",
mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin);
+ if(NULL!=mView) {
+ jobject javaWindowObject = [mView getJavaWindowObject];
+ if( false == [mView getDestroyNotifySent] ) {
+ [mView setDestroyNotifySent: true];
+ } else if(NULL!=javaWindowObject) {
+ DBG_PRINT( "windowClose.Error: javaWindowObject not NULL (%p), destroyNotifySent==true\n", javaWindowObject);
+ }
+ if(NULL!=javaWindowObject) {
+ (*env)->DeleteGlobalRef(env, javaWindowObject);
+ [mView setJavaWindowObject: NULL];
+ }
+ }
+
NS_DURING
if(NULL!=mView) {
// Available >= 10.5 - Makes the menubar disapear
@@ -670,7 +737,8 @@ NS_ENDHANDLER
// This probably happens b/c it sends events to the main loop
// but our resources are gone ?!
// However, issuing a simple release seems to work quite well.
- [mWin release];
+ // [mWin release];
+ [mWin performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
DBG_PRINT( "windowClose.X - %p,%d view %p,%d, parent %p\n",
mWin, getRetainCount(mWin), mView, getRetainCount(mView), pWin);
@@ -991,10 +1059,11 @@ JNIEXPORT jobject JNICALL Java_jogamp_newt_driver_macosx_MacWindow_getLocationOn
* Signature: (JZ)Z
*/
JNIEXPORT jboolean JNICALL Java_jogamp_newt_driver_macosx_MacWindow_setPointerVisible0
- (JNIEnv *env, jclass clazz, jlong window, jboolean mouseVisible)
+ (JNIEnv *env, jclass clazz, jlong window, jboolean hasFocus, jboolean mouseVisible)
{
NewtMacWindow *mWin = (NewtMacWindow*) ((intptr_t) window);
- [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO];
+ [mWin setMouseVisible: ( JNI_TRUE == mouseVisible ) ? YES : NO
+ hasFocus: ( JNI_TRUE == hasFocus ) ? YES : NO];
return JNI_TRUE;
}
diff --git a/src/newt/native/NewtMacWindow.h b/src/newt/native/NewtMacWindow.h
index 3ba89de1e..f576f75f7 100644
--- a/src/newt/native/NewtMacWindow.h
+++ b/src/newt/native/NewtMacWindow.h
@@ -104,6 +104,7 @@
@interface NewtMacWindow : NSWindow
#endif
{
+ BOOL isFullscreenWindow;
BOOL mouseConfined;
BOOL mouseVisible;
BOOL mouseInside;
@@ -119,7 +120,8 @@
styleMask: (NSUInteger) windowStyle
backing: (NSBackingStoreType) bufferingType
defer: (BOOL) deferCreation
- screen:(NSScreen *)screen;
+ screen:(NSScreen *)screen
+ isFullscreenWindow:(BOOL)isfs;
- (void) updateInsets: (JNIEnv*) env;
- (void) attachToParent: (NSWindow*) parent;
@@ -130,17 +132,36 @@
- (NSPoint) getLocationOnScreen: (NSPoint) p;
- (NSPoint) screenPos2NewtClientWinPos: (NSPoint) p;
+- (BOOL) isMouseInside;
- (void) cursorHide:(BOOL)v;
-- (void) setMouseVisible:(BOOL)v;
+- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus;
- (void) setMouseConfined:(BOOL)v;
- (void) setMousePosition:(NSPoint)p;
+- (void) sendKeyEvent: (NSEvent*) event eventType: (jint) evType;
+- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType;
+- (void) focusChanged: (BOOL) gained;
+
- (BOOL) becomeFirstResponder;
- (BOOL) resignFirstResponder;
+- (BOOL) canBecomeKeyWindow;
- (void) becomeKeyWindow;
- (void) resignKeyWindow;
- (void) windowDidBecomeKey: (NSNotification *) notification;
- (void) windowDidResignKey: (NSNotification *) notification;
-- (void) focusChanged: (BOOL) gained;
+- (void) keyDown: (NSEvent*) theEvent;
+- (void) keyUp: (NSEvent*) theEvent;
+- (void) mouseEntered: (NSEvent*) theEvent;
+- (void) mouseExited: (NSEvent*) theEvent;
+- (void) mouseMoved: (NSEvent*) theEvent;
+- (void) scrollWheel: (NSEvent*) theEvent;
+- (void) mouseDown: (NSEvent*) theEvent;
+- (void) mouseDragged: (NSEvent*) theEvent;
+- (void) mouseUp: (NSEvent*) theEvent;
+- (void) rightMouseDown: (NSEvent*) theEvent;
+- (void) rightMouseDragged: (NSEvent*) theEvent;
+- (void) rightMouseUp: (NSEvent*) theEvent;
+- (void) otherMouseDown: (NSEvent*) theEvent;
+- (void) otherMouseUp: (NSEvent*) theEvent;
@end
diff --git a/src/newt/native/NewtMacWindow.m b/src/newt/native/NewtMacWindow.m
index ce41673c4..402389e71 100644
--- a/src/newt/native/NewtMacWindow.m
+++ b/src/newt/native/NewtMacWindow.m
@@ -238,10 +238,14 @@ static jmethodID windowRepaintID = NULL;
DBG_PRINT("*************** dirtyRect: %p %lf/%lf %lfx%lf\n",
javaWindowObject, dirtyRect.origin.x, dirtyRect.origin.y, dirtyRect.size.width, dirtyRect.size.height);
+ if(NULL==javaWindowObject) {
+ DBG_PRINT("drawRect: null javaWindowObject\n");
+ return;
+ }
int shallBeDetached = 0;
JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
if(NULL==env) {
- DBG_PRINT("viewDidHide: null JNIEnv\n");
+ DBG_PRINT("drawRect: null JNIEnv\n");
return;
}
@@ -258,6 +262,10 @@ static jmethodID windowRepaintID = NULL;
- (void) viewDidHide
{
+ if(NULL==javaWindowObject) {
+ DBG_PRINT("viewDidHide: null javaWindowObject\n");
+ return;
+ }
int shallBeDetached = 0;
JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
if(NULL==env) {
@@ -276,10 +284,14 @@ static jmethodID windowRepaintID = NULL;
- (void) viewDidUnhide
{
+ if(NULL==javaWindowObject) {
+ DBG_PRINT("viewDidUnhide: null javaWindowObject\n");
+ return;
+ }
int shallBeDetached = 0;
JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, jvmVersion, &shallBeDetached);
if(NULL==env) {
- DBG_PRINT("viewDidHide: null JNIEnv\n");
+ DBG_PRINT("viewDidUnhide: null JNIEnv\n");
return;
}
@@ -328,12 +340,14 @@ static jmethodID windowRepaintID = NULL;
backing: (NSBackingStoreType) bufferingType
defer: (BOOL) deferCreation
screen:(NSScreen *)screen
+ isFullscreenWindow:(BOOL)isfs
{
id res = [super initWithContentRect: contentRect
styleMask: windowStyle
backing: bufferingType
defer: deferCreation
screen: screen];
+ isFullscreenWindow = isfs;
// Why is this necessary? Without it we don't get any of the
// delegate methods like resizing and window movement.
[self setDelegate: self];
@@ -389,8 +403,10 @@ static jmethodID windowRepaintID = NULL;
{
DBG_PRINT( "detachFromParent.1\n");
[self setParentWindow: nil];
- DBG_PRINT( "detachFromParent.2\n");
- [parent removeChildWindow: self];
+ if(NULL != parent) {
+ DBG_PRINT( "detachFromParent.2\n");
+ [parent removeChildWindow: self];
+ }
DBG_PRINT( "detachFromParent.X\n");
}
@@ -463,15 +479,60 @@ static jmethodID windowRepaintID = NULL;
// NSRect rS = [win convertRectFromScreen: r]; // 10.7
NSPoint oS = [self convertScreenToBase: r.origin];
oS.y = viewFrame.size.height - oS.y; // y-flip
-
return oS;
}
-- (BOOL) canBecomeKeyWindow
+- (BOOL) isMouseInside
{
- // Even if the window is borderless, we still want it to be able
- // to become the key window to receive keyboard events
- return YES;
+ NSView* view = [self contentView];
+ NSRect viewFrame = [view frame];
+ NSPoint l1 = [NSEvent mouseLocation];
+ NSPoint l0 = [self screenPos2NewtClientWinPos: l1];
+ return viewFrame.origin.x <= l0.x && l0.x < (viewFrame.origin.x+viewFrame.size.width) &&
+ viewFrame.origin.y <= l0.y && l0.y < (viewFrame.origin.y+viewFrame.size.height) ;
+}
+
+- (void) setMouseVisible:(BOOL)v hasFocus:(BOOL)focus
+{
+ mouseVisible = v;
+ mouseInside = [self isMouseInside];
+ DBG_PRINT( "setMouseVisible: confined %d, visible %d (current: %d), mouseInside %d, hasFocus %d\n",
+ mouseConfined, mouseVisible, !cursorIsHidden, mouseInside, focus);
+ if(YES == focus && YES == mouseInside) {
+ [self cursorHide: !mouseVisible];
+ }
+}
+
+- (void) cursorHide:(BOOL)v
+{
+ DBG_PRINT( "cursorHide: %d -> %d\n", cursorIsHidden, v);
+ if(v) {
+ if(!cursorIsHidden) {
+ [NSCursor hide];
+ cursorIsHidden = YES;
+ }
+ } else {
+ if(cursorIsHidden) {
+ [NSCursor unhide];
+ cursorIsHidden = NO;
+ }
+ }
+}
+
+- (void) setMouseConfined:(BOOL)v
+{
+ mouseConfined = v;
+ DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible);
+}
+
+- (void) setMousePosition:(NSPoint)p
+{
+ NSScreen* screen = [self screen];
+ NSRect screenRect = [screen frame];
+
+ CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin)
+ CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft);
+ CGEventPost (kCGHIDEventTap, ev);
}
static jint mods2JavaMods(NSUInteger mods)
@@ -538,17 +599,6 @@ static jint mods2JavaMods(NSUInteger mods)
}
}
-- (void) keyDown: (NSEvent*) theEvent
-{
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED];
-}
-
-- (void) keyUp: (NSEvent*) theEvent
-{
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED];
- [self sendKeyEvent: theEvent eventType: EVENT_KEY_TYPED];
-}
-
- (void) sendMouseEvent: (NSEvent*) event eventType: (jint) evType
{
NSView* nsview = [self contentView];
@@ -624,53 +674,100 @@ static jint mods2JavaMods(NSUInteger mods)
}
}
-- (void) setMouseVisible:(BOOL)v
+- (void) focusChanged: (BOOL) gained
{
- mouseVisible = v;
- DBG_PRINT( "setMouseVisible: confined %d, visible %d\n", mouseConfined, mouseVisible);
- if(YES == mouseInside) {
- [self cursorHide: !mouseVisible];
+ DBG_PRINT( "focusChanged: gained %d\n", gained);
+ NSView* nsview = [self contentView];
+ if( ! [nsview isMemberOfClass:[NewtView class]] ) {
+ return;
+ }
+ NewtView* view = (NewtView *) nsview;
+ jobject javaWindowObject = [view getJavaWindowObject];
+ if (javaWindowObject == NULL) {
+ DBG_PRINT("focusChanged: null javaWindowObject\n");
+ return;
+ }
+ int shallBeDetached = 0;
+ JavaVM *jvmHandle = [view getJVMHandle];
+ JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
+ if(NULL==env) {
+ DBG_PRINT("focusChanged: null JNIEnv\n");
+ return;
+ }
+
+ (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
+
+ if (shallBeDetached) {
+ (*jvmHandle)->DetachCurrentThread(jvmHandle);
}
}
-- (void) cursorHide:(BOOL)v
+- (BOOL) becomeFirstResponder
{
- if(v) {
- if(!cursorIsHidden) {
- [NSCursor hide];
- cursorIsHidden = YES;
- }
- } else {
- if(cursorIsHidden) {
- [NSCursor unhide];
- cursorIsHidden = NO;
- }
+ DBG_PRINT( "*************** becomeFirstResponder\n");
+ return [super becomeFirstResponder];
+}
+
+- (BOOL) resignFirstResponder
+{
+ DBG_PRINT( "*************** resignFirstResponder\n");
+ return [super resignFirstResponder];
+}
+
+- (BOOL) canBecomeKeyWindow
+{
+ // Even if the window is borderless, we still want it to be able
+ // to become the key window to receive keyboard events
+ return YES;
+}
+
+- (void) becomeKeyWindow
+{
+ DBG_PRINT( "*************** becomeKeyWindow\n");
+ [super becomeKeyWindow];
+}
+
+- (void) resignKeyWindow
+{
+ DBG_PRINT( "*************** resignKeyWindow: isFullscreen %d\n", (int)isFullscreenWindow);
+ if(!isFullscreenWindow) {
+ [super resignKeyWindow];
}
}
-- (void) setMouseConfined:(BOOL)v
+- (void) windowDidBecomeKey: (NSNotification *) notification
{
- mouseConfined = v;
- DBG_PRINT( "setMouseConfined: confined %d, visible %d\n", mouseConfined, mouseVisible);
+ DBG_PRINT( "*************** windowDidBecomeKey\n");
+ mouseInside = [self isMouseInside];
+ if(YES == mouseInside) {
+ [self cursorHide: !mouseVisible];
+ }
+ [self focusChanged: YES];
}
-- (void) setMousePosition:(NSPoint)p
+- (void) windowDidResignKey: (NSNotification *) notification
{
- NSScreen* screen = [self screen];
- NSRect screenRect = [screen frame];
+ DBG_PRINT( "*************** windowDidResignKey\n");
+ // Implicit mouse exit by OS X
+ [self focusChanged: NO];
+}
- CGPoint pt = { p.x, screenRect.size.height - p.y }; // y-flip (CG is top-left origin)
- CGEventRef ev = CGEventCreateMouseEvent (NULL, kCGEventMouseMoved, pt, kCGMouseButtonLeft);
- CGEventPost (kCGHIDEventTap, ev);
- NSPoint l0 = [NSEvent mouseLocation];
- [self screenPos2NewtClientWinPos: l0];
+- (void) keyDown: (NSEvent*) theEvent
+{
+ [self sendKeyEvent: theEvent eventType: EVENT_KEY_PRESSED];
+}
+
+- (void) keyUp: (NSEvent*) theEvent
+{
+ [self sendKeyEvent: theEvent eventType: EVENT_KEY_RELEASED];
+ [self sendKeyEvent: theEvent eventType: EVENT_KEY_TYPED];
}
- (void) mouseEntered: (NSEvent*) theEvent
{
DBG_PRINT( "mouseEntered: confined %d, visible %d\n", mouseConfined, mouseVisible);
mouseInside = YES;
- [self setMouseVisible: mouseVisible];
+ [self cursorHide: !mouseVisible];
if(NO == mouseConfined) {
[self sendMouseEvent: theEvent eventType: EVENT_MOUSE_ENTERED];
}
@@ -859,68 +956,4 @@ static jint mods2JavaMods(NSUInteger mods)
[pool release];
}
-- (BOOL) becomeFirstResponder
-{
- DBG_PRINT( "*************** becomeFirstResponder\n");
- return [super becomeFirstResponder];
-}
-
-- (BOOL) resignFirstResponder
-{
- DBG_PRINT( "*************** resignFirstResponder\n");
- return [super resignFirstResponder];
-}
-
-- (void) becomeKeyWindow
-{
- DBG_PRINT( "*************** becomeKeyWindow\n");
- [super becomeKeyWindow];
-}
-
-- (void) resignKeyWindow
-{
- DBG_PRINT( "*************** resignKeyWindow\n");
- [super resignKeyWindow];
-}
-
-- (void) windowDidBecomeKey: (NSNotification *) notification
-{
- DBG_PRINT( "*************** windowDidBecomeKey\n");
- [self focusChanged: YES];
-}
-
-- (void) windowDidResignKey: (NSNotification *) notification
-{
- DBG_PRINT( "*************** windowDidResignKey\n");
- [self focusChanged: NO];
-}
-
-- (void) focusChanged: (BOOL) gained
-{
- DBG_PRINT( "focusChanged: gained %d\n", gained);
- NSView* nsview = [self contentView];
- if( ! [nsview isMemberOfClass:[NewtView class]] ) {
- return;
- }
- NewtView* view = (NewtView *) nsview;
- jobject javaWindowObject = [view getJavaWindowObject];
- if (javaWindowObject == NULL) {
- DBG_PRINT("focusChanged: null javaWindowObject\n");
- return;
- }
- int shallBeDetached = 0;
- JavaVM *jvmHandle = [view getJVMHandle];
- JNIEnv* env = NewtCommon_GetJNIEnv(jvmHandle, [view getJVMVersion], &shallBeDetached);
- if(NULL==env) {
- DBG_PRINT("focusChanged: null JNIEnv\n");
- return;
- }
-
- (*env)->CallVoidMethod(env, javaWindowObject, focusChangedID, JNI_FALSE, (gained == YES) ? JNI_TRUE : JNI_FALSE);
-
- if (shallBeDetached) {
- (*jvmHandle)->DetachCurrentThread(jvmHandle);
- }
-}
-
@end
diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c
index 0a7e1cf77..6953140c0 100644
--- a/src/newt/native/X11Window.c
+++ b/src/newt/native/X11Window.c
@@ -169,16 +169,21 @@ static Window NewtWindows_getParent (Display *dpy, Window w) {
}
return 0; // Error
}
-static Status NewtWindows_getParentPosition (Display *dpy, Window w, int *x_return, int *y_return) {
+static void NewtWindows_setCWAbove(Display *dpy, Window w) {
+ XWindowChanges xwc;
+ memset(&xwc, 0, sizeof(XWindowChanges));
+ xwc.stack_mode = Above;
+ XConfigureWindow(dpy, w, CWStackMode, &xwc);
+ XSync(dpy, False);
+}
+static Status NewtWindows_getWindowPositionRelative2Parent (Display *dpy, Window w, int *x_return, int *y_return) {
Window root_return;
unsigned int width_return, height_return;
unsigned int border_width_return;
unsigned int depth_return;
- Window parent = NewtWindows_getParent(dpy, w);
- if(0 != parent) {
- XGetGeometry(dpy, parent, &root_return, x_return, y_return, &width_return,
- &height_return, &border_width_return, &depth_return);
+ if(0 != XGetGeometry(dpy, w, &root_return, x_return, y_return, &width_return,
+ &height_return, &border_width_return, &depth_return)) {
return 1; // OK
}
return 0; // Error
@@ -224,52 +229,6 @@ static Status NewtWindows_getFrameExtends(Display *dpy, Window window, int *left
return 1; // Ok
}
-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
- } else if(0 != NewtWindows_getParentPosition (dpy, window, left, top)) {
- *right = *left; *bottom = *left;
- 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
- }
- return 0; // Error
-}
-
-static void NewtWindows_setCWAbove(Display *dpy, Window w) {
- XWindowChanges xwc;
- memset(&xwc, 0, sizeof(XWindowChanges));
- xwc.stack_mode = Above;
- XConfigureWindow(dpy, w, CWStackMode, &xwc);
- XSync(dpy, False);
-}
-
-static void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean force) {
- XWindowAttributes xwa;
- Window focus_return;
- int revert_to_return;
-
- 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);
-
- if( JNI_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);
- if(xwa.map_state == IsViewable) {
- DBG_PRINT( "X11: XSetInputFocus dpy %p,win %pd\n", dpy, (void*)w);
- XSetInputFocus(dpy, w, RevertToParent, CurrentTime);
- }
- }
- DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force);
- XSync(dpy, False);
-}
#define DECOR_USE_MWM 1 // works for known WMs
// #define DECOR_USE_EWMH 1 // haven't seen this to work (NORMAL->POPUP, never gets undecorated)
@@ -307,6 +266,29 @@ static void NewtWindows_setDecorations (Display *dpy, Window w, Bool decorated)
XSync(dpy, False);
}
+static Bool NewtWindows_hasDecorations (Display *dpy, Window w) {
+ Bool decor = False;
+
+#ifdef DECOR_USE_MWM
+ Atom _MOTIF_WM_HINTS = XInternAtom( dpy, "_MOTIF_WM_HINTS", False );
+ unsigned char *wm_data;
+ Atom wm_type;
+ int wm_format;
+ unsigned long wm_nitems, wm_bytes_after;
+
+ if( Success == XGetWindowProperty(dpy, w, _MOTIF_WM_HINTS, 0, PROP_MWM_HINTS_ELEMENTS, False, AnyPropertyType,
+ &wm_type, &wm_format, &wm_nitems, &wm_bytes_after, &wm_data) ) {
+ if(wm_type != None) {
+ // unsigned long mwmhints[PROP_MWM_HINTS_ELEMENTS] = { MWM_HINTS_DECORATIONS, 0, decorated, 0, 0 }; // flags, functions, decorations, input_mode, status
+ unsigned long *hints = (unsigned long *) wm_data;
+ decor = ( 0 != (hints[0] & MWM_HINTS_DECORATIONS) ) && ( 0 != hints[2] );
+ }
+ }
+#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};
@@ -430,6 +412,56 @@ static Bool NewtWindows_setFullscreenEWMH (Display *dpy, Window root, Window w,
return res;
}
+
+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 void NewtWindows_requestFocus (JNIEnv *env, jobject window, Display *dpy, Window w, jboolean 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);
+
+ if( JNI_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);
+ }
+ }
+ DBG_PRINT( "X11: requestFocus dpy %p,win %p, force %d - FIN\n", dpy, (void*)w, force);
+ XSync(dpy, False);
+}
+
/**
* Window
*/
@@ -601,11 +633,13 @@ JNIEXPORT jlong JNICALL Java_jogamp_newt_driver_x11_X11Window_CreateWindow0
// we can pre-map the window here to be able to gather the insets and position.
{
XEvent event;
- int left, right, top, bottom;
+ int left=0, right=0, top=0, bottom=0;
XMapWindow(dpy, window);
XIfEvent( dpy, &event, WaitForMapNotify, (XPointer) window ); // wait to get proper insets values
+ XSync(dpy, False);
+
// 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);
@@ -683,6 +717,15 @@ static Bool WaitForReparentNotify( Display *dpy, XEvent *event, XPointer arg ) {
}
#endif
+/**
+ * KDE cause lost input focus in fullscreen mode.
+ * Using 'XGrabKeyboard(..)' would prevent the loss,
+ * but also would disable WM task switcher etc.
+ *
+ * #define FS_GRAB_KEYBOARD 1
+ *
+ */
+
/*
* Class: jogamp_newt_driver_x11_X11Window
* Method: reconfigureWindow0
@@ -730,6 +773,17 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
Bool enable = TST_FLAG_CHANGE_FULLSCREEN(flags) ? TST_FLAG_IS_FULLSCREEN(flags) : TST_FLAG_IS_ALWAYSONTOP(flags) ;
if( NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, enable) ) {
NewtDisplay_displayDispatchErrorHandlerEnable(0, env);
+ #ifdef FS_GRAB_KEYBOARD
+ if(TST_FLAG_CHANGE_FULLSCREEN(flags)) {
+ if(TST_FLAG_IS_FULLSCREEN(flags)) {
+ XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ } else {
+ XUngrabKeyboard(dpy, CurrentTime);
+ }
+ } else if(TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags)) {
+ XUngrabKeyboard(dpy, CurrentTime);
+ }
+ #endif
return;
}
}
@@ -744,6 +798,9 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && !TST_FLAG_IS_FULLSCREEN(flags) ) ||
( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && !TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS off
NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, False);
+ #ifdef FS_GRAB_KEYBOARD
+ XUngrabKeyboard(dpy, CurrentTime);
+ #endif
}
if( TST_FLAG_CHANGE_PARENTING(flags) && !TST_FLAG_HAS_PARENT(flags) ) {
@@ -791,6 +848,11 @@ JNIEXPORT void JNICALL Java_jogamp_newt_driver_x11_X11Window_reconfigureWindow0
if( fsEWMHFlags && ( ( TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags) ) ||
( TST_FLAG_CHANGE_ALWAYSONTOP(flags) && TST_FLAG_IS_ALWAYSONTOP(flags) ) ) ) { // FS on
NewtWindows_setFullscreenEWMH(dpy, root, w, fsEWMHFlags, isVisible, True);
+ #ifdef FS_GRAB_KEYBOARD
+ if(TST_FLAG_CHANGE_FULLSCREEN(flags) && TST_FLAG_IS_FULLSCREEN(flags)) {
+ XGrabKeyboard(dpy, w, True, GrabModeAsync, GrabModeAsync, CurrentTime);
+ }
+ #endif
}
NewtDisplay_displayDispatchErrorHandlerEnable(0, env);