Mercurial > hg > icedtea7-forest > jdk
changeset 9163:6e0226f8b489
8080729: [macosx] java 7 and 8 JDialogs on multiscreen jump to parent frame on focus
Reviewed-by: ant, denis
author | dmarkov |
---|---|
date | Tue, 17 May 2016 13:12:50 +0300 |
parents | 295b149be8cd |
children | 2cdc473fc6bc |
files | src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java src/macosx/classes/sun/lwawt/macosx/CWarningWindow.java src/macosx/native/sun/awt/AWTWindow.h src/macosx/native/sun/awt/AWTWindow.m test/java/awt/Window/WindowJumpingTest/WindowJumpingTest.java |
diffstat | 5 files changed, 199 insertions(+), 40 deletions(-) [+] |
line wrap: on
line diff
--- a/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Thu Apr 20 23:14:57 2017 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java Tue May 17 13:12:50 2016 +0300 @@ -431,9 +431,6 @@ @Override // PlatformWindow public void dispose() { - if (owner != null) { - CWrapper.NSWindow.removeChildWindow(owner.getNSWindowPtr(), getNSWindowPtr()); - } contentView.dispose(); nativeDispose(getNSWindowPtr()); CPlatformWindow.super.dispose(); @@ -527,25 +524,6 @@ public void setVisible(boolean visible) { final long nsWindowPtr = getNSWindowPtr(); - // Process parent-child relationship when hiding - if (!visible) { - // Unparent my children - for (Window w : target.getOwnedWindows()) { - WindowPeer p = (WindowPeer)w.getPeer(); - if (p instanceof LWWindowPeer) { - CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow(); - if (pw != null && pw.isVisible()) { - CWrapper.NSWindow.removeChildWindow(nsWindowPtr, pw.getNSWindowPtr()); - } - } - } - - // Unparent myself - if (owner != null && owner.isVisible()) { - CWrapper.NSWindow.removeChildWindow(owner.getNSWindowPtr(), nsWindowPtr); - } - } - // Configure stuff updateIconImages(); updateFocusabilityForAutoRequestFocus(false); @@ -609,19 +587,19 @@ // Manage parent-child relationship when showing if (visible) { - // Add myself as a child + // Order myself above my parent if (owner != null && owner.isVisible()) { - CWrapper.NSWindow.addChildWindow(owner.getNSWindowPtr(), nsWindowPtr, CWrapper.NSWindow.NSWindowAbove); + CWrapper.NSWindow.orderWindow(nsWindowPtr, CWrapper.NSWindow.NSWindowAbove, owner.getNSWindowPtr()); applyWindowLevel(target); } - // Add my own children to myself + // Order my own children above myself for (Window w : target.getOwnedWindows()) { WindowPeer p = (WindowPeer)w.getPeer(); if (p instanceof LWWindowPeer) { CPlatformWindow pw = (CPlatformWindow)((LWWindowPeer)p).getPlatformWindow(); if (pw != null && pw.isVisible()) { - CWrapper.NSWindow.addChildWindow(nsWindowPtr, pw.getNSWindowPtr(), CWrapper.NSWindow.NSWindowAbove); + CWrapper.NSWindow.orderWindow(pw.getNSWindowPtr(), CWrapper.NSWindow.NSWindowAbove, nsWindowPtr); pw.applyWindowLevel(w); } } @@ -1050,8 +1028,8 @@ // Order the window to front of the stack of child windows final long nsWindowSelfPtr = getNSWindowPtr(); final long nsWindowOwnerPtr = owner.getNSWindowPtr(); - CWrapper.NSWindow.removeChildWindow(nsWindowOwnerPtr, nsWindowSelfPtr); - CWrapper.NSWindow.addChildWindow(nsWindowOwnerPtr, nsWindowSelfPtr, CWrapper.NSWindow.NSWindowAbove); + CWrapper.NSWindow.orderFront(nsWindowOwnerPtr); + CWrapper.NSWindow.orderWindow(nsWindowSelfPtr, CWrapper.NSWindow.NSWindowAbove, nsWindowOwnerPtr); } applyWindowLevel(target);
--- a/src/macosx/classes/sun/lwawt/macosx/CWarningWindow.java Thu Apr 20 23:14:57 2017 +0100 +++ b/src/macosx/classes/sun/lwawt/macosx/CWarningWindow.java Tue May 17 13:12:50 2016 +0300 @@ -221,15 +221,6 @@ synchronized (lock) { final long nsWindowPtr = getNSWindowPtr(); - // Process parent-child relationship when hiding - if (!visible) { - // Unparent myself - if (owner != null && owner.isVisible()) { - CWrapper.NSWindow.removeChildWindow( - owner.getNSWindowPtr(), nsWindowPtr); - } - } - // Actually show or hide the window if (visible) { CWrapper.NSWindow.orderFront(nsWindowPtr); @@ -241,10 +232,10 @@ // Manage parent-child relationship when showing if (visible) { - // Add myself as a child + // Order myself above my parent if (owner != null && owner.isVisible()) { - CWrapper.NSWindow.addChildWindow(owner.getNSWindowPtr(), - nsWindowPtr, CWrapper.NSWindow.NSWindowAbove); + CWrapper.NSWindow.orderWindow(nsWindowPtr, + CWrapper.NSWindow.NSWindowAbove, owner.getNSWindowPtr()); // do not allow security warning to be obscured by other windows applyWindowLevel(ownerWindow);
--- a/src/macosx/native/sun/awt/AWTWindow.h Thu Apr 20 23:14:57 2017 +0100 +++ b/src/macosx/native/sun/awt/AWTWindow.h Tue May 17 13:12:50 2016 +0300 @@ -47,6 +47,7 @@ NSWindow *nsWindow; AWTWindow *ownerWindow; jint preFullScreenLevel; + BOOL isMinimizing; } // An instance of either AWTWindow_Normal or AWTWindow_Panel @@ -61,6 +62,7 @@ @property (nonatomic) jint styleBits; @property (nonatomic) BOOL isEnabled; @property (nonatomic) jint preFullScreenLevel; +@property (nonatomic) BOOL isMinimizing; - (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)javaPlatformWindow ownerWindow:owner
--- a/src/macosx/native/sun/awt/AWTWindow.m Thu Apr 20 23:14:57 2017 +0100 +++ b/src/macosx/native/sun/awt/AWTWindow.m Tue May 17 13:12:50 2016 +0300 @@ -143,6 +143,7 @@ @synthesize isEnabled; @synthesize ownerWindow; @synthesize preFullScreenLevel; +@synthesize isMinimizing; - (void) updateMinMaxSize:(BOOL)resizable { if (resizable) { @@ -281,6 +282,7 @@ [self.nsWindow release]; // the property retains the object already self.isEnabled = YES; + self.isMinimizing = NO; self.javaPlatformWindow = platformWindow; self.styleBits = bits; self.ownerWindow = owner; @@ -423,6 +425,68 @@ [super dealloc]; } +// Tests wheather the corresponding Java paltform window is visible or not ++ (BOOL) isJavaPlatformWindowVisible:(NSWindow *)window { + BOOL isVisible = NO; + + if ([AWTWindow isAWTWindow:window] && [window delegate] != nil) { + AWTWindow *awtWindow = (AWTWindow *)[window delegate]; + [AWTToolkit eventCountPlusPlus]; + + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject platformWindow = [awtWindow.javaPlatformWindow jObjectWithEnv:env]; + if (platformWindow != NULL) { + static JNF_MEMBER_CACHE(jm_isVisible, jc_CPlatformWindow, "isVisible", "()Z"); + isVisible = JNFCallBooleanMethod(env, platformWindow, jm_isVisible) == JNI_TRUE ? YES : NO; + (*env)->DeleteLocalRef(env, platformWindow); + + } + } + return isVisible; +} + +// Orders window's childs based on the current focus state +- (void) orderChildWindows:(BOOL)focus { +AWT_ASSERT_APPKIT_THREAD; + + if (self.isMinimizing) { + // Do not perform any ordering, if iconify is in progress + return; + } + + NSEnumerator *windowEnumerator = [[NSApp windows]objectEnumerator]; + NSWindow *window; + while ((window = [windowEnumerator nextObject]) != nil) { + if ([AWTWindow isJavaPlatformWindowVisible:window]) { + AWTWindow *awtWindow = (AWTWindow *)[window delegate]; + AWTWindow *owner = awtWindow.ownerWindow; + if (IS(awtWindow.styleBits, ALWAYS_ON_TOP)) { + // Do not order 'always on top' windows + continue; + } + while (awtWindow.ownerWindow != nil) { + if (awtWindow.ownerWindow == self) { + if (focus) { + // Move the childWindow to floating level + // so it will appear in front of its + // parent which owns the focus + [window setLevel:NSFloatingWindowLevel]; + } else { + // Focus owner has changed, move the childWindow + // back to normal window level + [window setLevel:NSNormalWindowLevel]; + } + // The childWindow should be displayed in front of + // its nearest parentWindow + [window orderWindow:NSWindowAbove relativeTo:[owner.nsWindow windowNumber]]; + break; + } + awtWindow = awtWindow.ownerWindow; + } + } + } +} + // NSWindow overrides - (BOOL) canBecomeKeyWindow { AWT_ASSERT_APPKIT_THREAD; @@ -572,6 +636,30 @@ return YES; } +// Hides/shows window's childs during iconify/de-iconify operation +- (void) iconifyChildWindows:(BOOL)iconify { +AWT_ASSERT_APPKIT_THREAD; + + NSEnumerator *windowEnumerator = [[NSApp windows]objectEnumerator]; + NSWindow *window; + while ((window = [windowEnumerator nextObject]) != nil) { + if ([AWTWindow isJavaPlatformWindowVisible:window]) { + AWTWindow *awtWindow = (AWTWindow *)[window delegate]; + while (awtWindow.ownerWindow != nil) { + if (awtWindow.ownerWindow == self) { + if (iconify) { + [window orderOut:window]; + } else { + [window orderFront:window]; + } + break; + } + awtWindow = awtWindow.ownerWindow; + } + } + } +} + - (void) _deliverIconify:(BOOL)iconify { AWT_ASSERT_APPKIT_THREAD; @@ -585,16 +673,28 @@ } } +- (void)windowWillMiniaturize:(NSNotification *)notification { +AWT_ASSERT_APPKIT_THREAD; + + self.isMinimizing = YES; + // Excplicitly make myself a key window to avoid possible + // negative visual effects during iconify operation + [self.nsWindow makeKeyAndOrderFront:self.nsWindow]; + [self iconifyChildWindows:YES]; +} + - (void)windowDidMiniaturize:(NSNotification *)notification { AWT_ASSERT_APPKIT_THREAD; [self _deliverIconify:JNI_TRUE]; + self.isMinimizing = NO; } - (void)windowDidDeminiaturize:(NSNotification *)notification { AWT_ASSERT_APPKIT_THREAD; [self _deliverIconify:JNI_FALSE]; + [self iconifyChildWindows:NO]; } - (void) _deliverWindowFocusEvent:(BOOL)focused oppositeWindow:(AWTWindow *)opposite { @@ -640,6 +740,7 @@ [AWTWindow setLastKeyWindow:nil]; [self _deliverWindowFocusEvent:YES oppositeWindow: opposite]; + [self orderChildWindows:YES]; } - (void) windowDidResignKey: (NSNotification *) notification { @@ -667,6 +768,7 @@ } [self _deliverWindowFocusEvent:NO oppositeWindow: opposite]; + [self orderChildWindows:NO]; } - (void) windowDidBecomeMain: (NSNotification *) notification {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/java/awt/Window/WindowJumpingTest/WindowJumpingTest.java Tue May 17 13:12:50 2016 +0300 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8080729 + * @summary Dialogs on multiscreen jump to parent frame on focus gain + * @author Dmitry Markov + * @library ../../regtesthelpers + * @build Util + * @run main WindowJumpingTest + */ +import java.awt.*; + +import test.java.awt.regtesthelpers.Util; + +public class WindowJumpingTest { + public static void main(String[] args) throws AWTException { + Robot r = Util.createRobot(); + + GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment.getLocalGraphicsEnvironment(); + GraphicsDevice[] graphicsDevices = graphicsEnvironment.getScreenDevices(); + if (graphicsDevices.length < 2) { + System.out.println("This is multi-screen test... Skipping!"); + return; + } + + Frame frame = new Frame("Frame", graphicsDevices[0].getDefaultConfiguration()); + frame.setSize(400, 300); + frame.setVisible(true); + Util.waitForIdle(r); + + Dialog dialog = new Dialog(frame, "Dialog", false, graphicsDevices[1].getDefaultConfiguration()); + dialog.setSize(400, 300); + dialog.setVisible(true); + Util.waitForIdle(r); + + checkGraphicsDevice(frame, graphicsDevices[0]); + checkGraphicsDevice(dialog, graphicsDevices[1]); + + Util.clickOnComp(frame, r); + Util.waitForIdle(r); + + checkGraphicsDevice(frame, graphicsDevices[0]); + checkGraphicsDevice(dialog, graphicsDevices[1]); + + Util.clickOnComp(dialog, r); + Util.waitForIdle(r); + + checkGraphicsDevice(frame, graphicsDevices[0]); + checkGraphicsDevice(dialog, graphicsDevices[1]); + + dialog.dispose(); + frame.dispose(); + } + + private static void checkGraphicsDevice(Window window, GraphicsDevice graphicsDevice) { + GraphicsDevice actualGraphicsDevice = window.getGraphicsConfiguration().getDevice(); + + if (!actualGraphicsDevice.equals(graphicsDevice)) { + System.err.println("Expected screen: " + graphicsDevice); + System.err.println("Actual screen: "+ actualGraphicsDevice); + throw new RuntimeException("Test FAILED: " + window + " is displayed on wrong screen"); + } + } +} +