From a4b16ad544f3f7872f15e52d7ada7dc1e506d333 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Wed, 7 Jul 2010 15:02:13 +0200 Subject: GLAutoDrawable: setAnimator/getAnimator/invoke/display changes; NEWT: Adding native repaint; Fix reparent/fullscreen New: NEWT Native Repaint ========================= Support for native repaint, which shall call display() in case no animator is running. GLAutoDrawable invoke(GLRunnable) impl. handles case if invoked on animator thread, or no animator thread is running (issueing a display() call). The impl resides in GLDrawableHelper. The Animator un-/registers itself at the GLAutoDrawable via setAnimator. New: NEWT AWT/NEWT Parenting Focus Handling ============================================ Introducing Window.FocusRunnable, to be registered at the NEWT Window, which will be executed before the native focus claim. Window.FocusRunnable's run method returns a boolean, which determines whether the native implementation shall proceed claiming the native focus. This API focus hook is necessary to allow an optional underlying windowing toolkit, ie AWT (see usage NewtCanvasAWT), to make the focus traversal transparent. Fix: GLEventListener / GLDrawableHelper ======================================== GLEventListener's init() and glViewport()/reshape() method must be called before the 1st display() and after a dispose() call. It could miss the 1st display() call if added after the setVisible(true) call - due to the native repainting. The impl resides in GLDrawableHelper. Fix: Misc NEWT ============== Window reparent issues a resize() and display() call, if it is visible. native Window uses direct send.*Event for input events (again), instead of enqueueing it for performance. Window impl all status change native event Java callbacks, instead of having duplicated code in all implementations. Fullscreen, reposition at zero. Reparent/Fullscreen repaint if visible. Native reparent/fullscreen, fix glitches on Windows (visibility while reparenting) --- .../classes/com/jogamp/newt/OffscreenWindow.java | 3 +- src/newt/classes/com/jogamp/newt/Window.java | 46 ++++++- .../classes/com/jogamp/newt/awt/NewtCanvasAWT.java | 149 ++++++++++----------- .../newt/event/awt/AWTParentWindowAdapter.java | 1 - .../com/jogamp/newt/impl/awt/AWTWindow.java | 3 +- .../com/jogamp/newt/impl/intel/gdl/Window.java | 3 +- .../com/jogamp/newt/impl/macosx/MacDisplay.java | 6 +- .../com/jogamp/newt/impl/macosx/MacWindow.java | 3 +- .../newt/impl/opengl/broadcom/egl/Window.java | 3 +- .../com/jogamp/newt/impl/opengl/kd/KDWindow.java | 3 +- .../jogamp/newt/impl/windows/WindowsWindow.java | 7 +- .../com/jogamp/newt/impl/x11/X11Window.java | 3 +- .../classes/com/jogamp/newt/opengl/GLWindow.java | 6 +- src/newt/native/WindowsWindow.c | 103 +++++++------- src/newt/native/X11Window.c | 55 ++++++-- 15 files changed, 223 insertions(+), 171 deletions(-) (limited to 'src/newt') diff --git a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java index 0f75fbfa9..e85714d4f 100644 --- a/src/newt/classes/com/jogamp/newt/OffscreenWindow.java +++ b/src/newt/classes/com/jogamp/newt/OffscreenWindow.java @@ -107,9 +107,8 @@ public class OffscreenWindow extends Window implements SurfaceChangeable { // nop return false; } - protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + protected void setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { shouldNotCallThis(); - return false; } } diff --git a/src/newt/classes/com/jogamp/newt/Window.java b/src/newt/classes/com/jogamp/newt/Window.java index 0cd5b31bc..9c724314e 100755 --- a/src/newt/classes/com/jogamp/newt/Window.java +++ b/src/newt/classes/com/jogamp/newt/Window.java @@ -303,6 +303,30 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer } protected void requestFocusImpl() {} + /** + * May set to a {@link FocusRunnable}, {@link FocusRunnable#run()} before Newt requests the native focus. + * This allows notifying a covered window toolkit like AWT that the focus is requested, + * hence focus traversal can be made transparent. + */ + public void setFocusAction(FocusRunnable focusAction) { + this.focusAction = focusAction; + } + protected boolean focusAction() { + if(null!=focusAction) { + return focusAction.run(); + } + return false; + } + protected FocusRunnable focusAction = null; + + public static interface FocusRunnable { + /** + * @return false if NEWT shall proceed requesting the focus, + * true if NEWT shall not request the focus. + */ + public boolean run(); + } + // // NativeWindow impl // @@ -888,22 +912,31 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer w = screen.getWidth(); h = screen.getHeight(); } else { - x = nfs_x; - y = nfs_y; + if(0!=parentWindowHandle) { + x=0; + y=0; + } else { + x = nfs_x; + y = nfs_y; + } w = nfs_width; h = nfs_height; } if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { System.out.println("X11Window fs: "+fullscreen+" "+x+"/"+y+" "+w+"x"+h+", "+isUndecorated()); } - this.fullscreen = setFullscreenImpl(fullscreen, x, y, w, h); + this.fullscreen = fullscreen; + setFullscreenImpl(fullscreen, x, y, w, h); } - return this.fullscreen; } finally { windowUnlock(); } + if( isVisible() ) { + windowRepaint(0, 0, getWidth(), getHeight()); + } + return this.fullscreen; } - protected abstract boolean setFullscreenImpl(boolean fullscreen, int x, int y, int widht, int height); + protected abstract void setFullscreenImpl(boolean fullscreen, int x, int y, int widht, int height); // // Child Window Management @@ -1495,6 +1528,9 @@ public abstract class Window implements NativeWindow, NEWTEventConsumer invalidate(); } + public boolean getPropagateRepaint() { + return propagateRepaint; + } public void setPropagateRepaint(boolean v) { propagateRepaint = v; } diff --git a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java index b2dd719bc..6fd924e66 100644 --- a/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java +++ b/src/newt/classes/com/jogamp/newt/awt/NewtCanvasAWT.java @@ -36,10 +36,11 @@ import java.lang.reflect.*; import java.security.*; import java.awt.Button; -import java.awt.Frame; import java.awt.Canvas; +import java.awt.Component; +import java.awt.EventQueue; +import java.awt.Frame; import java.awt.Graphics; -import java.awt.KeyboardFocusManager; import javax.media.nativewindow.*; @@ -59,7 +60,6 @@ public class NewtCanvasAWT extends java.awt.Canvas { NativeWindow parent = null; Window newtChild = null; AWTAdapter awtAdapter = null; - boolean hasSwingContainer = false; /** * Instantiates a NewtCanvas without a NEWT child.
@@ -75,84 +75,39 @@ public class NewtCanvasAWT extends java.awt.Canvas { super(); setNEWTChild(child); } - - class UnfocusRunnable implements Runnable { - boolean focusTraversed = false; - public void run() { - KeyboardFocusManager focusManager = - KeyboardFocusManager.getCurrentKeyboardFocusManager(); - java.awt.Component comp1 = focusManager.getPermanentFocusOwner(); - java.awt.Component comp2 = focusManager.getFocusOwner(); - if(DEBUG_IMPLEMENTATION) { - System.out.println("AWT Unfocus: traversed "+focusTraversed+" (1)"); - System.out.println("PRE PermenetFocusOwner: "+comp1); - System.out.println("PRE FocusOwner: "+comp2); - } - if(null!=comp1) { - if(!focusTraversed && null==comp2) { - comp1.requestFocus(); - focusTraversed=true; - if(DEBUG_IMPLEMENTATION) { - System.out.println("AWT Unfocus: traversed "+focusTraversed+" (*)"); - } - } else { - focusTraversed=false; - } - - if(DEBUG_IMPLEMENTATION) { - comp1 = focusManager.getPermanentFocusOwner(); - comp2 = focusManager.getFocusOwner(); - System.out.println("MID PermenetFocusOwner: "+comp1); - System.out.println("MID FocusOwner: "+comp2); - } - focusManager.clearGlobalFocusOwner(); + class FocusAction implements Window.FocusRunnable { + public boolean run() { + if ( EventQueue.isDispatchThread() ) { + focusActionImpl.run(); + } else { + try { + EventQueue.invokeAndWait(focusActionImpl); + } catch (Exception e) { + throw new NativeWindowException(e); + } + } + return focusActionImpl.result; + } + class FocusActionImpl implements Runnable { + public final boolean result = false; // NEWT shall always proceed requesting the native focus + public void run() { if(DEBUG_IMPLEMENTATION) { - comp1 = focusManager.getPermanentFocusOwner(); - comp2 = focusManager.getFocusOwner(); - System.out.println("POST PermenetFocusOwner: "+comp1); - System.out.println("POST FocusOwner: "+comp2); - } - - if(focusTraversed && null!=newtChild) { - newtChild.requestFocus(); + System.out.println("FocusActionImpl.run() "+Window.getThreadName()); } + NewtCanvasAWT.this.requestFocusAWT(); } } + FocusActionImpl focusActionImpl = new FocusActionImpl(); } - UnfocusRunnable unfocusRunnable = new UnfocusRunnable(); + FocusAction focusAction = new FocusAction(); - class FocusListener extends WindowAdapter { - public synchronized void windowGainedFocus(WindowEvent e) { - if(DEBUG_IMPLEMENTATION) { - System.out.println("NewtCanvasAWT focus on: AWT focus "+ NewtCanvasAWT.this.hasFocus()+ - ", focusable "+NewtCanvasAWT.this.isFocusable()+", onEDT "+hasSwingContainer); - } - if(hasSwingContainer) { - java.awt.EventQueue.invokeLater(unfocusRunnable); - } else { - unfocusRunnable.run(); - } - } - public synchronized void windowLostFocus(WindowEvent e) { - if(DEBUG_IMPLEMENTATION) { - System.out.println("NewtCanvasAWT focus off: AWT focus "+ NewtCanvasAWT.this.hasFocus()); - } - } - } - FocusListener focusListener = new FocusListener(); - /** sets a new NEWT child, provoking reparenting on the NEWT level. */ public NewtCanvasAWT setNEWTChild(Window child) { if(newtChild!=child) { - if(null!=newtChild) { - newtChild.removeWindowListener(focusListener); - } newtChild = child; - if(null!=newtChild) { - newtChild.addWindowListener(focusListener); - } + newtChild.setFocusAction(focusAction); if(null!=parent) { java.awt.Container cont = getContainer(this); // reparent right away, addNotify has been called already @@ -181,16 +136,6 @@ public class NewtCanvasAWT extends java.awt.Canvas { } } - static boolean hasSwingContainer(java.awt.Component comp) { - while( null != comp ) { - if( comp instanceof javax.swing.JComponent ) { - return true; - } - comp = comp.getParent(); - } - return false; - } - static java.awt.Container getContainer(java.awt.Component comp) { while( null != comp ) { if( comp instanceof java.awt.Container ) { @@ -204,13 +149,12 @@ public class NewtCanvasAWT extends java.awt.Canvas { public void addNotify() { super.addNotify(); disableBackgroundErase(); - hasSwingContainer = hasSwingContainer(this); java.awt.Container cont = getContainer(this); if(DEBUG_IMPLEMENTATION) { // if ( isShowing() == false ) -> Container was not visible yet. // if ( isShowing() == true ) -> Container is already visible. System.err.println("NewtCanvasAWT.addNotify: "+newtChild+", "+this+", visible "+isVisible()+", showing "+isShowing()+ - ", displayable "+isDisplayable()+", swingContainer "+hasSwingContainer+" -> "+cont); + ", displayable "+isDisplayable()+" -> "+cont); } reparentWindow(true, cont); } @@ -269,6 +213,49 @@ public class NewtCanvasAWT extends java.awt.Canvas { } } + void requestFocusAWT() { + super.requestFocus(); + } + + public void requestFocus() { + super.requestFocus(); + if(null!=newtChild) { + newtChild.setFocusAction(null); + newtChild.requestFocus(); + newtChild.setFocusAction(focusAction); + } + } + + public boolean requestFocus(boolean temporary) { + boolean res = super.requestFocus(temporary); + if(res && null!=newtChild) { + newtChild.setFocusAction(null); + newtChild.requestFocus(); + newtChild.setFocusAction(focusAction); + } + return res; + } + + public boolean requestFocusInWindow() { + boolean res = super.requestFocusInWindow(); + if(res && null!=newtChild) { + newtChild.setFocusAction(null); + newtChild.requestFocus(); + newtChild.setFocusAction(focusAction); + } + return res; + } + + public boolean requestFocusInWindow(boolean temporary) { + boolean res = super.requestFocusInWindow(temporary); + if(res && null!=newtChild) { + newtChild.setFocusAction(null); + newtChild.requestFocus(); + newtChild.setFocusAction(focusAction); + } + return res; + } + // Disables the AWT's erasing of this Canvas's background on Windows // in Java SE 6. This internal API is not available in previous // releases, but the system property diff --git a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java index 43087289a..9f0944ea0 100644 --- a/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java +++ b/src/newt/classes/com/jogamp/newt/event/awt/AWTParentWindowAdapter.java @@ -57,7 +57,6 @@ public class AWTParentWindowAdapter if(DEBUG_IMPLEMENTATION) { System.out.println("AWT: focusGained: START "+ e.getComponent()); } - newtWindow.requestFocus(); } public void focusLost(java.awt.event.FocusEvent e) { diff --git a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java index 6f936d2c6..56e5a4240 100644 --- a/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/awt/AWTWindow.java @@ -240,7 +240,7 @@ public class AWTWindow extends Window { } } - protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + protected void setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { /** An AWT event on setSize() would bring us in a deadlock situation, hence invokeLater() */ runOnEDT(false, new Runnable() { public void run() { @@ -257,7 +257,6 @@ public class AWTWindow extends Window { container.setSize(w, h); } }); - return fullscreen; } public Object getWrappedWindow() { diff --git a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java index 1b8a62a9c..14621807a 100644 --- a/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/intel/gdl/Window.java @@ -109,11 +109,10 @@ public class Window extends com.jogamp.newt.Window { } } - protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + protected void setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { if(0!=surfaceHandle) { SetBounds0(surfaceHandle, screen.getWidth(), screen.getHeight(), x, y, w, h); } - return fullscreen; } protected void requestFocusImpl() { diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java index 0fde19cd4..699b675dd 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacDisplay.java @@ -99,17 +99,15 @@ public class MacDisplay extends Display { if(wait) { ReflectionUtil.callStaticMethod( "java.awt.EventQueue", - cl, "invokeAndWait", new Class[] { java.lang.Runnable.class }, - new Object[] { r } ); + new Object[] { r }, cl ); } else { ReflectionUtil.callStaticMethod( "java.awt.EventQueue", - cl, "invokeLater", new Class[] { java.lang.Runnable.class }, - new Object[] { r } ); + new Object[] { r }, cl ); } } catch (Exception e) { throw new NativeWindowException(e); diff --git a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java index 9f47aa49f..8f5041253 100755 --- a/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/macosx/MacWindow.java @@ -280,7 +280,7 @@ public class MacWindow extends Window { } } - protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + protected void setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { nsViewLock.lock(); try { if(DEBUG_IMPLEMENTATION || DEBUG_WINDOW_EVENT) { @@ -293,7 +293,6 @@ public class MacWindow extends Window { } finally { nsViewLock.unlock(); } - return fullscreen; } private void insetsChanged(int left, int top, int right, int bottom) { diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java index 7d3a0ac8c..ca06699f5 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/broadcom/egl/Window.java @@ -87,10 +87,9 @@ public class Window extends com.jogamp.newt.Window { System.err.println("BCEGL Window.setPositionImpl n/a in BroadcomEGL"); } - protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + protected void setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { // n/a in BroadcomEGL System.err.println("setFullscreen n/a in BroadcomEGL"); - return false; } public boolean surfaceSwap() { diff --git a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java index 0c7254376..2f534548b 100755 --- a/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/opengl/kd/KDWindow.java @@ -100,14 +100,13 @@ public class KDWindow extends Window { System.err.println("setPosition n/a in KD"); } - protected boolean setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { + protected void setFullscreenImpl(final boolean fullscreen, final int x, final int y, final int w, final int h) { if(0!=eglWindowHandle) { setFullScreen0(eglWindowHandle, fullscreen); if(!fullscreen) { setSize0(eglWindowHandle, w, h); } } - return true; } //---------------------------------------------------------------------- diff --git a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java index 47f79f46a..69cd62201 100755 --- a/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java +++ b/src/newt/classes/com/jogamp/newt/impl/windows/WindowsWindow.java @@ -162,9 +162,8 @@ public class WindowsWindow extends Window { setPosition0(parentWindowHandle, windowHandle, x , y /*, width, height*/); } - protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + protected void setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { setFullscreen0(fullscreen?0:parentWindowHandle, windowHandle, x, y, w, h, isUndecorated(fullscreen)); - return fullscreen; } protected boolean reparentWindowImpl() { @@ -176,7 +175,7 @@ public class WindowsWindow extends Window { protected void requestFocusImpl() { if (windowHandle != 0L) { - requestFocus0(fullscreen?0:parentWindowHandle, windowHandle); + requestFocus0(windowHandle); } } @@ -207,7 +206,7 @@ public class WindowsWindow extends Window { private native void setFullscreen0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated); private native void reparentWindow0(long parentWindowHandle, long windowHandle, int x, int y, int width, int height, boolean isUndecorated); private static native void setTitle0(long windowHandle, String title); - private static native void requestFocus0(long parentWindowHandle, long windowHandle); + private native void requestFocus0(long windowHandle); private void insetsChanged(int left, int top, int right, int bottom) { if (left != -1 && top != -1 && right != -1 && bottom != -1) { diff --git a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java index 6890b29fa..7a770f770 100755 --- a/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java +++ b/src/newt/classes/com/jogamp/newt/impl/x11/X11Window.java @@ -102,10 +102,9 @@ public class X11Window extends Window { setPosition0(parentWindowHandle, getDisplayHandle(), windowHandle, x, y); } - protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + protected void setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { setPosSizeDecor0(fullscreen?0:parentWindowHandle, getDisplayHandle(), getScreenIndex(), windowHandle, x, y, w, h, isUndecorated(fullscreen), isVisible()); - return fullscreen; } protected boolean reparentWindowImpl() { diff --git a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java index e66ed1e34..99b4314a3 100644 --- a/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java +++ b/src/newt/classes/com/jogamp/newt/opengl/GLWindow.java @@ -305,6 +305,9 @@ public class GLWindow extends Window implements GLAutoDrawable { public void requestFocus() { window.requestFocus(); } + public void setFocusAction(FocusRunnable focusAction) { + window.setFocusAction(focusAction); + } public Insets getInsets() { return window.getInsets(); @@ -327,9 +330,8 @@ public class GLWindow extends Window implements GLAutoDrawable { public boolean setFullscreen(boolean fullscreen) { return window.setFullscreen(fullscreen); } - protected boolean setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { + protected void setFullscreenImpl(boolean fullscreen, int x, int y, int w, int h) { shouldNotCallThis(); - return false; } public boolean isVisible() { diff --git a/src/newt/native/WindowsWindow.c b/src/newt/native/WindowsWindow.c index a1dab2678..cda6a4086 100755 --- a/src/newt/native/WindowsWindow.c +++ b/src/newt/native/WindowsWindow.c @@ -119,6 +119,7 @@ static jmethodID windowDestroyedID = NULL; static jmethodID windowRepaintID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID sendKeyEventID = NULL; +static jmethodID focusActionID = NULL; static RECT* UpdateInsets(JNIEnv *env, HWND hwnd, jobject window); @@ -596,23 +597,27 @@ static int WmKeyUp(JNIEnv *env, jobject window, UINT wkey, UINT repCnt, return 0; } -static void NewtWindows_requestFocus (HWND hwnd, BOOL topLevel, BOOL reparented) { - DBG_PRINT("*** WindowsWindow: requestFocus.0 window %p\n", (void*)hwnd); - if (IsWindow(hwnd)) { - UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; - if(reparented) { - flags |= SWP_FRAMECHANGED; - } - SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags); - DBG_PRINT("*** WindowsWindow: requestFocus.1\n"); - SetForegroundWindow(hwnd); // Slightly Higher Priority - DBG_PRINT("*** WindowsWindow: requestFocus.2\n"); - SetFocus(hwnd);// Sets Keyboard Focus To TheWindow - DBG_PRINT("*** WindowsWindow: requestFocus.3\n"); - if(topLevel) { - SetActiveWindow(hwnd); +static void NewtWindows_requestFocus (JNIEnv *env, jobject window, HWND hwnd, BOOL reparented) { + HWND pHwnd = GetParent(hwnd); + HWND current = GetFocus(); + DBG_PRINT("*** WindowsWindow: requestFocus.0 parent %p, window %p, isCurrent %d\n", + (void*) pHwnd, (void*)hwnd, current==hwnd); + if(reparented || current!=hwnd) { + if( JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { + UINT flags = SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE; + if(reparented) { + flags |= SWP_FRAMECHANGED; + } + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, flags); + SetForegroundWindow(hwnd); // Slightly Higher Priority + SetFocus(hwnd);// Sets Keyboard Focus To Window + if(NULL!=pHwnd) { + SetActiveWindow(hwnd); + } + DBG_PRINT("*** WindowsWindow: requestFocus.X1\n"); + } else { + DBG_PRINT("*** WindowsWindow: requestFocus.X0\n"); } - DBG_PRINT("*** WindowsWindow: requestFocus.X\n"); } } @@ -800,7 +805,8 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, case WM_LBUTTONDOWN: - NewtWindows_requestFocus ( wnd, FALSE, FALSE ); // request focus on this window, if not already .. + DBG_PRINT("*** WindowsWindow: LBUTTONDOWN\n"); + NewtWindows_requestFocus ( env, window, wnd, FALSE ); // request focus on this window, if not already .. (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, GetModifiers(), @@ -819,7 +825,8 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, break; case WM_MBUTTONDOWN: - NewtWindows_requestFocus ( wnd, FALSE, FALSE ); // request focus on this window, if not already .. + DBG_PRINT("*** WindowsWindow: MBUTTONDOWN\n"); + NewtWindows_requestFocus ( env, window, wnd, FALSE ); // request focus on this window, if not already .. (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, GetModifiers(), @@ -838,7 +845,8 @@ static LRESULT CALLBACK wndProc(HWND wnd, UINT message, break; case WM_RBUTTONDOWN: - NewtWindows_requestFocus ( wnd, FALSE, FALSE ); // request focus on this window, if not already .. + DBG_PRINT("*** WindowsWindow: RBUTTONDOWN\n"); + NewtWindows_requestFocus ( env, window, wnd, FALSE ); // request focus on this window, if not already .. (*env)->CallVoidMethod(env, window, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, GetModifiers(), @@ -1069,6 +1077,8 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_initI windowRepaintID = (*env)->GetMethodID(env, clazz, "windowRepaint", "(IIII)V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z"); + if (insetsChangedID == NULL || sizeChangedID == NULL || positionChangedID == NULL || @@ -1078,7 +1088,8 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_initI windowDestroyedID == NULL || windowRepaintID == NULL || sendMouseEventID == NULL || - sendKeyEventID == NULL) + sendKeyEventID == NULL || + focusActionID == NULL) { return JNI_FALSE; } @@ -1148,13 +1159,6 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_CreateWi #endif UpdateInsets(env, window, obj); - - ShowWindow(window, SW_SHOWNORMAL); - if(NULL!=parentWindow) { - NewtWindows_requestFocus ( window, FALSE, FALSE ); // request focus on this window, if not already .. - } /* else { - // top level already capable of receiving [keyboard] events - } */ } #ifdef UNICODE @@ -1224,13 +1228,13 @@ JNIEXPORT jlong JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_MonitorF JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setVisible0 (JNIEnv *_env, jclass clazz, jlong window, jboolean visible) { - HWND hWnd = (HWND) (intptr_t) window; - DBG_PRINT("*** WindowsWindow: setVisible window %p, visible: %d\n", hWnd, (int)visible); + HWND hwnd = (HWND) (intptr_t) window; + DBG_PRINT("*** WindowsWindow: setVisible window %p, visible: %d\n", hwnd, (int)visible); if (visible) { - SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE); - ShowWindow(hWnd, SW_SHOW); + SetWindowPos(hwnd, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOSIZE | SWP_NOMOVE); + ShowWindow(hwnd, SW_SHOW); } else { - ShowWindow(hWnd, SW_HIDE); + ShowWindow(hwnd, SW_HIDE); } } @@ -1301,14 +1305,14 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setPositi } } -static void NewtWindows_reparentWindow(HWND hwndP, HWND hwnd, jint x, jint y, jint width, jint height, jboolean bIsUndecorated) +static void NewtWindows_reparentWindow(JNIEnv *env, jobject obj, HWND hwndP, HWND hwnd, BOOL visible, + jint x, jint y, jint width, jint height, jboolean bIsUndecorated) { UINT flags; HWND hWndInsertAfter; DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN ; - BOOL isVisible = IsWindowVisible(hwnd); - DBG_PRINT("*** WindowsWindow: reparentWindow.1 parent %p, window %p, %d/%d %dx%d undeco %d visible %d\n", (void*)hwndP, (void*)hwnd, x, y, width, height, bIsUndecorated, isVisible); + DBG_PRINT("*** WindowsWindow: reparentWindow.1 parent %p, window %p, %d/%d %dx%d undeco %d\n", (void*)hwndP, (void*)hwnd, x, y, width, height, bIsUndecorated); if (!IsWindow(hwnd)) { DBG_PRINT("*** WindowsWindow: reparentWindow failure: Passed window %p is invalid\n", (void*)hwnd); return; @@ -1318,8 +1322,8 @@ static void NewtWindows_reparentWindow(HWND hwndP, HWND hwnd, jint x, jint y, ji return; } - if (isVisible) { - windowStyle |= WS_VISIBLE; + if(visible) { + windowStyle |= WS_VISIBLE ; } // order of call sequence: (MS documentation) @@ -1346,10 +1350,6 @@ static void NewtWindows_reparentWindow(HWND hwndP, HWND hwnd, jint x, jint y, ji DBG_PRINT("*** WindowsWindow: reparentWindow.4\n"); } - if(isVisible) { - NewtWindows_requestFocus ( hwnd, ( NULL == hwndP ) ? TRUE : FALSE, TRUE ); - } - DBG_PRINT("*** WindowsWindow: reparentWindow.X\n"); } @@ -1365,13 +1365,12 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc HWND hwndP = (HWND) (intptr_t) parent; HWND hwnd = (HWND) (intptr_t) window; HWND hWndInsertAfter; - DWORD windowStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE; BOOL isVisible = IsWindowVisible(hwnd); DBG_PRINT("*** WindowsWindow: setFullscreen.1 parent %p, window %p, %d/%d %dx%d undeco %d visible\n", parent, window, x, y, width, height, bIsUndecorated, isVisible); - NewtWindows_reparentWindow(hwndP, hwnd, x, y, width, height, bIsUndecorated); + NewtWindows_reparentWindow(env, obj, hwndP, hwnd, FALSE, x, y, width, height, bIsUndecorated); if ( NULL == hwndP ) { flags = SWP_SHOWWINDOW; @@ -1380,9 +1379,12 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setFullsc flags = SWP_NOACTIVATE | SWP_NOZORDER; hWndInsertAfter = 0; } - SetWindowPos(hwnd, hWndInsertAfter, x, y, width, height, flags); + if(isVisible) { + NewtWindows_requestFocus ( env, obj, hwnd, TRUE ); // request focus on this window, if not already .. + } + DBG_PRINT("*** WindowsWindow: setFullscreen.X\n"); (*env)->CallVoidMethod(env, obj, sizeChangedID, (jint) width, (jint) height); // resize necessary .. } @@ -1397,8 +1399,14 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_reparentW { HWND hwndP = (HWND) (intptr_t) parent; HWND hwnd = (HWND) (intptr_t) window; + BOOL isVisible = IsWindowVisible(hwnd); + + NewtWindows_reparentWindow(env, obj, hwndP, hwnd, FALSE, x, y, width, height, bIsUndecorated); + + if(isVisible) { + NewtWindows_requestFocus ( env, obj, hwnd, TRUE ); // request focus on this window, if not already .. + } - NewtWindows_reparentWindow(hwndP, hwnd, x, y, width, height, bIsUndecorated); } /* @@ -1425,8 +1433,9 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_setTitle0 * Signature: (J)V */ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_windows_WindowsWindow_requestFocus0 - (JNIEnv *env, jclass clazz, jlong parent, jlong window) + (JNIEnv *env, jobject obj, jlong window) { - NewtWindows_requestFocus ( (HWND) (intptr_t) window, (0 == parent) ? TRUE : FALSE, FALSE ) ; + DBG_PRINT("*** WindowsWindow: RequestFocus0\n"); + NewtWindows_requestFocus ( env, obj, (HWND) (intptr_t) window, FALSE ) ; } diff --git a/src/newt/native/X11Window.c b/src/newt/native/X11Window.c index dbf833633..60caab662 100755 --- a/src/newt/native/X11Window.c +++ b/src/newt/native/X11Window.c @@ -161,6 +161,7 @@ static jmethodID windowRepaintID = NULL; static jmethodID windowCreatedID = NULL; static jmethodID sendMouseEventID = NULL; static jmethodID sendKeyEventID = NULL; +static jmethodID focusActionID = NULL; static jmethodID displayCompletedID = NULL; @@ -372,18 +373,42 @@ static jobject getJavaWindowProperty(JNIEnv *env, Display *dpy, Window window, j return jwindow; } -static void NewtWindows_requestFocus0 (Display *dpy, Window w, XWindowAttributes *xwa) { - // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable - if(xwa->map_state == IsViewable) { - XSetInputFocus(dpy, w, RevertToParent, CurrentTime); +/** +static Window NewtWindows_getParent (Display *dpy, Window w) { + Window root_return=0; + Window parent_return=0; + Window *children_return=NULL; + unsigned int nchildren_return=0; + + Status res = XQueryTree(dpy, w, &root_return, &parent_return, &children_return, &nchildren_return); + if(NULL!=children_return) { + XFree(children_return); + } + if(0!=res) { + return parent_return; + } + return 0; +} */ + +static void NewtWindows_requestFocus0 (JNIEnv *env, jobject window, Display *dpy, Window w, XWindowAttributes *xwa) { + Window focus_return; + int revert_to_return; + XGetInputFocus(dpy, &focus_return, &revert_to_return); + if(focus_return!=w) { + // Avoid 'BadMatch' errors from XSetInputFocus, ie if window is not viewable + if( JNI_FALSE == (*env)->CallBooleanMethod(env, window, focusActionID) ) { + if(xwa->map_state == IsViewable) { + XSetInputFocus(dpy, w, RevertToParent, CurrentTime); + } + } } } -static void NewtWindows_requestFocus1 (Display *dpy, Window w) { +static void NewtWindows_requestFocus1 (JNIEnv *env, jobject window, Display *dpy, Window w) { XWindowAttributes xwa; XGetWindowAttributes(dpy, w, &xwa); - NewtWindows_requestFocus0 (dpy, w, &xwa); + NewtWindows_requestFocus0 (env, window, dpy, w, &xwa); XSync(dpy, False); } @@ -505,7 +530,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Display_DispatchMessages switch(evt.type) { case ButtonPress: - NewtWindows_requestFocus1 ( dpy, evt.xany.window ); + NewtWindows_requestFocus1 ( env, jwindow, dpy, evt.xany.window ); (*env)->CallVoidMethod(env, jwindow, sendMouseEventID, (jint) EVENT_MOUSE_PRESSED, (jint) evt.xbutton.state, @@ -674,6 +699,7 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 windowCreatedID = (*env)->GetMethodID(env, clazz, "windowCreated", "(J)V"); sendMouseEventID = (*env)->GetMethodID(env, clazz, "sendMouseEvent", "(IIIIII)V"); sendKeyEventID = (*env)->GetMethodID(env, clazz, "sendKeyEvent", "(IIIC)V"); + focusActionID = (*env)->GetMethodID(env, clazz, "focusAction", "()Z"); if (sizeChangedID == NULL || positionChangedID == NULL || @@ -684,7 +710,8 @@ JNIEXPORT jboolean JNICALL Java_com_jogamp_newt_impl_x11_X11Window_initIDs0 windowRepaintID == NULL || windowCreatedID == NULL || sendMouseEventID == NULL || - sendKeyEventID == NULL) { + sendKeyEventID == NULL || + focusActionID == NULL) { return JNI_FALSE; } return JNI_TRUE; @@ -941,7 +968,9 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosition0 } static void NewtWindows_reparentWindow - (Display * dpy, Screen * scrn, Window w, XWindowAttributes *xwa, jlong jparent, jint x, jint y, jboolean undecorated, jboolean isVisible) + (JNIEnv *env, jobject obj, + Display * dpy, Screen * scrn, Window w, XWindowAttributes *xwa, jlong jparent, + jint x, jint y, jboolean undecorated, jboolean isVisible) { Window parent = (0!=jparent)?(Window)jparent:XRootWindowOfScreen(scrn); @@ -990,7 +1019,7 @@ static void NewtWindows_reparentWindow XSync(dpy, False); */ if(JNI_TRUE == isVisible) { - NewtWindows_requestFocus0 ( dpy, w, xwa ); + NewtWindows_requestFocus0 ( env, obj, dpy, w, xwa ); XSync(dpy, False); } @@ -1023,7 +1052,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_setPosSizeDecor0 XSync(dpy, False); XGetWindowAttributes(dpy, w, &xwa); - NewtWindows_reparentWindow(dpy, scrn, w, &xwa, jparent, x, y, undecorated, isVisible); + NewtWindows_reparentWindow(env, obj, dpy, scrn, w, &xwa, jparent, x, y, undecorated, isVisible); XSync(dpy, False); memset(&xwc, 0, sizeof(XWindowChanges)); @@ -1058,7 +1087,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reparentWindow0 XSync(dpy, False); XGetWindowAttributes(dpy, w, &xwa); - NewtWindows_reparentWindow(dpy, scrn, w, &xwa, jparent, x, y, undecorated, isVisible); + NewtWindows_reparentWindow(env, obj, dpy, scrn, w, &xwa, jparent, x, y, undecorated, isVisible); XSync(dpy, False); DBG_PRINT( "X11: reparentWindow0 X\n"); @@ -1072,7 +1101,7 @@ JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_reparentWindow0 JNIEXPORT void JNICALL Java_com_jogamp_newt_impl_x11_X11Window_requestFocus0 (JNIEnv *env, jobject obj, jlong display, jlong window) { - NewtWindows_requestFocus1 ( (Display *) (intptr_t) display, (Window)window ) ; + NewtWindows_requestFocus1 ( env, obj, (Display *) (intptr_t) display, (Window)window ) ; } /* -- cgit v1.2.3