Mercurial > hg > icedtea7-forest > jdk
changeset 9171:f2d639848a0e
8169589: [macosx] Activating a JDialog puts to back another dialog
Reviewed-by: anthony, serb
author | dmarkov |
---|---|
date | Fri, 21 Apr 2017 06:21:45 +0100 |
parents | 310499d83a24 |
children | 7cc2d987a269 |
files | src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java src/share/classes/java/awt/Window.java src/share/classes/sun/awt/AWTAccessor.java |
diffstat | 3 files changed, 89 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Mon Jan 09 18:33:02 2017 +0000 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Fri Apr 21 06:21:45 2017 +0100 @@ -31,6 +31,8 @@ import java.awt.peer.WindowPeer; import java.beans.*; import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; @@ -40,6 +42,8 @@ import javax.swing.*; import sun.awt.*; +import sun.awt.AWTAccessor.ComponentAccessor; +import sun.awt.AWTAccessor.WindowAccessor; import sun.java2d.SurfaceData; import sun.java2d.opengl.CGLSurfaceData; import sun.lwawt.*; @@ -1242,37 +1246,89 @@ return true; } - private void orderAboveSiblings() { - if (owner == null) { - return; + private boolean isOneOfOwnersOrSelf(CPlatformWindow window) { + while (window != null) { + if (this == window) { + return true; + } + window = window.owner; } + return false; + } - // NOTE: the logic will fail if we have a hierarchy like: - // visible root owner - // invisible owner - // visible dialog - // However, this is an unlikely scenario for real life apps - if (owner.isVisible()) { - // Recursively pop up the windows from the very bottom so that only - // the very top-most one becomes the main window - owner.orderAboveSiblings(); + private CPlatformWindow getRootOwner() { + CPlatformWindow rootOwner = this; + while (rootOwner.owner != null) { + rootOwner = rootOwner.owner; + } + return rootOwner; + } - // Order the window to front of the stack of child windows - owner.execute(new CFNativeAction() { + private void orderAboveSiblings() { + // Recursively pop up the windows from the very bottom, (i.e. root owner) so that + // the windows are ordered above their nearest owner; ancestors of the window, + // which is going to become 'main window', are placed above their siblings. + CPlatformWindow rootOwner = getRootOwner(); + if (rootOwner.isVisible()) { + rootOwner.execute(new CFNativeAction() { @Override - public void run(final long nsWindowOwnerPtr) { - execute(new CFNativeAction() { - @Override - public void run(long nsWindowSelfPtr) { - CWrapper.NSWindow.orderFront(nsWindowOwnerPtr); - CWrapper.NSWindow.orderWindow(nsWindowSelfPtr, CWrapper.NSWindow.NSWindowAbove, nsWindowOwnerPtr); - } - }); + public void run(long ptr) { + CWrapper.NSWindow.orderFront(ptr); } }); } + final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor(); + orderAboveSiblingsImpl(windowAccessor.getOwnedWindows(rootOwner.target)); + } - applyWindowLevel(target); + private void orderAboveSiblingsImpl(Window[] windows) { + ArrayList<Window> childWindows = new ArrayList<Window>(); + + final ComponentAccessor componentAccessor = AWTAccessor.getComponentAccessor(); + final WindowAccessor windowAccessor = AWTAccessor.getWindowAccessor(); + + // Go through the list of windows and perform ordering. + for (Window w : windows) { + final Object p = componentAccessor.getPeer(w); + if (p instanceof LWWindowPeer) { + final CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow(); + if (pw != null && pw.isVisible()) { + // If the window is one of ancestors of 'main window' or is going to become main by itself, + // the window should be ordered above its siblings; otherwise the window is just ordered + // above its nearest parent. + if (pw.isOneOfOwnersOrSelf(this)) { + pw.execute(new CFNativeAction() { + @Override + public void run(long ptr) { + CWrapper.NSWindow.orderFront(ptr); + } + }); + } else { + pw.owner.execute(new CFNativeAction() { + @Override + public void run(final long ownerPtr) { + pw.execute(new CFNativeAction() { + @Override + public void run(long ptr) { + CWrapper.NSWindow.orderWindow(ptr, CWrapper.NSWindow.NSWindowAbove, ownerPtr); + } + }); + } + }); + } + pw.applyWindowLevel(w); + } + } + // Retrieve the child windows for each window from the list and store them for future use. + // Note: we collect data about child windows even for invisible owners, since they may have + // visible children. + childWindows.addAll(Arrays.asList(windowAccessor.getOwnedWindows(w))); + } + // If some windows, which have just been ordered, have any child windows, let's start new iteration + // and order these child windows. + if (!childWindows.isEmpty()) { + orderAboveSiblingsImpl(childWindows.toArray(new Window[0])); + } } protected void applyWindowLevel(Window target) {
--- a/src/share/classes/java/awt/Window.java Mon Jan 09 18:33:02 2017 +0000 +++ b/src/share/classes/java/awt/Window.java Fri Apr 21 06:21:45 2017 +0100 @@ -4072,6 +4072,10 @@ public void setTrayIconWindow(Window w, boolean isTrayIconWindow) { w.isTrayIconWindow = isTrayIconWindow; } + + public Window[] getOwnedWindows(Window w) { + return w.getOwnedWindows_NoClientCode(); + } }); // WindowAccessor } // static
--- a/src/share/classes/sun/awt/AWTAccessor.java Mon Jan 09 18:33:02 2017 +0000 +++ b/src/share/classes/sun/awt/AWTAccessor.java Fri Apr 21 06:21:45 2017 +0100 @@ -326,6 +326,12 @@ * Marks the specified window as an utility window for TrayIcon. */ void setTrayIconWindow(Window w, boolean isTrayIconWindow); + + /** + * Return an array containing all the windows this + * window currently owns. + */ + Window[] getOwnedWindows(Window w); } /**