mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-10 16:03:16 +00:00
8080729: [macosx] java 7 and 8 JDialogs on multiscreen jump to parent frame on focus
Reviewed-by: ant, denis
This commit is contained in:
parent
7a40b8d5f7
commit
e28bb07a3d
@ -430,9 +430,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
|
||||
@Override // PlatformWindow
|
||||
public void dispose() {
|
||||
if (owner != null) {
|
||||
CWrapper.NSWindow.removeChildWindow(owner.getNSWindowPtr(), getNSWindowPtr());
|
||||
}
|
||||
contentView.dispose();
|
||||
nativeDispose(getNSWindowPtr());
|
||||
CPlatformWindow.super.dispose();
|
||||
@ -527,26 +524,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
public void setVisible(boolean visible) {
|
||||
final long nsWindowPtr = getNSWindowPtr();
|
||||
|
||||
// Process parent-child relationship when hiding
|
||||
final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
|
||||
if (!visible) {
|
||||
// Unparent my children
|
||||
for (Window w : target.getOwnedWindows()) {
|
||||
WindowPeer p = acc.getPeer(w);
|
||||
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);
|
||||
@ -619,20 +596,22 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
updateFocusabilityForAutoRequestFocus(true);
|
||||
|
||||
// Manage parent-child relationship when showing
|
||||
final ComponentAccessor acc = AWTAccessor.getComponentAccessor();
|
||||
|
||||
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()) {
|
||||
final Object p = acc.getPeer(w);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -1052,8 +1031,8 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo
|
||||
// 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);
|
||||
|
||||
@ -206,15 +206,6 @@ public final class CWarningWindow extends CPlatformWindow
|
||||
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);
|
||||
@ -226,10 +217,10 @@ public final class CWarningWindow extends CPlatformWindow
|
||||
|
||||
// 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);
|
||||
|
||||
@ -46,6 +46,7 @@
|
||||
AWTWindow *ownerWindow;
|
||||
jint preFullScreenLevel;
|
||||
NSRect standardFrame;
|
||||
BOOL isMinimizing;
|
||||
}
|
||||
|
||||
// An instance of either AWTWindow_Normal or AWTWindow_Panel
|
||||
@ -60,6 +61,7 @@
|
||||
@property (nonatomic) BOOL isEnabled;
|
||||
@property (nonatomic) jint preFullScreenLevel;
|
||||
@property (nonatomic) NSRect standardFrame;
|
||||
@property (nonatomic) BOOL isMinimizing;
|
||||
|
||||
- (id) initWithPlatformWindow:(JNFWeakJObjectWrapper *)javaPlatformWindow
|
||||
ownerWindow:owner
|
||||
|
||||
@ -180,6 +180,7 @@ AWT_NS_WINDOW_IMPLEMENTATION
|
||||
@synthesize ownerWindow;
|
||||
@synthesize preFullScreenLevel;
|
||||
@synthesize standardFrame;
|
||||
@synthesize isMinimizing;
|
||||
|
||||
- (void) updateMinMaxSize:(BOOL)resizable {
|
||||
if (resizable) {
|
||||
@ -304,6 +305,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
[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 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
[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;
|
||||
@ -511,6 +575,30 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
return [self standardFrame];
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
@ -524,16 +612,28 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
}
|
||||
}
|
||||
|
||||
- (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 {
|
||||
@ -579,6 +679,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
[AWTWindow setLastKeyWindow:nil];
|
||||
|
||||
[self _deliverWindowFocusEvent:YES oppositeWindow: opposite];
|
||||
[self orderChildWindows:YES];
|
||||
}
|
||||
|
||||
- (void) windowDidResignKey: (NSNotification *) notification {
|
||||
@ -606,6 +707,7 @@ AWT_ASSERT_APPKIT_THREAD;
|
||||
}
|
||||
|
||||
[self _deliverWindowFocusEvent:NO oppositeWindow: opposite];
|
||||
[self orderChildWindows:NO];
|
||||
}
|
||||
|
||||
- (void) windowDidBecomeMain: (NSNotification *) notification {
|
||||
|
||||
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user