Compare commits

..

2 Commits
1601 ... 1584

Author SHA1 Message Date
Dmitry Batrak
dec27719cf JBR-3640 java/awt/Modal/ModalFocusTransferTests/FocusTransferDWFAppModalTest.java: window Open button lost focus when it should not
(cherry picked from commit a7d486ca3d)
2021-08-04 13:34:49 +07:00
Artem Bochkarev
c4fb2e5e55 JBR-3342: add npe check
fixed JBR-3342 SIGILL at [libsystem_kernel] __kill NPE/OOME at java.desktop/sun.lwawt.LWComponentPeer.windowToLocal / -[NSApplication(JCEFApplication) _swizzled_sendEvent:]

(cherry picked from commit 37e6e8e616)
2021-08-04 13:34:41 +07:00
9 changed files with 106 additions and 433 deletions

View File

@@ -934,7 +934,7 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(
getTarget(), lightweightChild, temporary,
focusedWindowChangeAllowed, time, cause, true);
focusedWindowChangeAllowed, time, cause, false);
switch (result) {
case LWKeyboardFocusManagerPeer.SNFH_FAILURE:
return false;
@@ -968,22 +968,15 @@ public abstract class LWComponentPeer<T extends Component, D extends JComponent>
return false;
}
boolean res = parentPeer.requestWindowFocus(cause);
// If parent window can be made focused and has been made focused (synchronously)
// then we can proceed with children, otherwise we retreat
if (!res || !parentWindow.isFocused()) {
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
focusLog.fine("request rejected, res= " + res + ", parentWindow.isFocused()=" +
parentWindow.isFocused());
}
return parentPeer.requestWindowFocus(cause, () -> {
LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
return false;
}
}, () -> {
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
Component focusOwner = kfmPeer.getCurrentFocusOwner();
return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
getTarget(), true, cause, focusOwner);
Component focusOwner = kfmPeer.getCurrentFocusOwner();
LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
getTarget(), false, cause, focusOwner);
});
case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
return true;

View File

@@ -61,18 +61,18 @@ public class LWLightweightFramePeer extends LWWindowPeer implements OverrideNati
}
@Override
public boolean requestWindowFocus(FocusEvent.Cause cause) {
public boolean requestWindowFocus(FocusEvent.Cause cause, Runnable r, Runnable lightweightRequest) {
if (!focusAllowedFor()) {
return false;
}
if (getPlatformWindow().rejectFocusRequest(cause)) {
/*if (getPlatformWindow().rejectFocusRequest(cause)) {
return false;
}
}*/
Window opposite = LWKeyboardFocusManagerPeer.getInstance().
getCurrentFocusedWindow();
changeFocusedWindow(true, opposite);
changeFocusedWindow(true, opposite, () -> {});
return true;
}

View File

@@ -290,14 +290,24 @@ public class LWWindowPeer
if (!getTarget().isAutoRequestFocus()) {
return;
} else {
requestWindowFocus(FocusEvent.Cause.ACTIVATION);
requestWindowFocus(FocusEvent.Cause.ACTIVATION, () -> {}, () -> {});
}
// Focus the owner in case this window is focused.
} else if (kfmPeer.getCurrentFocusedWindow() == getTarget()) {
// Transfer focus to the owner.
LWWindowPeer owner = getOwnerFrameDialog(LWWindowPeer.this);
if (owner != null) {
owner.requestWindowFocus(FocusEvent.Cause.ACTIVATION);
Window targetOwner = LWWindowPeer.this.getTarget().getOwner();
while (targetOwner != null && (targetOwner.getOwner() != null && !targetOwner.isFocusableWindow())) {
targetOwner = targetOwner.getOwner();
}
if (targetOwner != null) {
LWWindowPeer owner = (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(targetOwner);
if (owner != null) {
owner.requestWindowFocus(FocusEvent.Cause.ACTIVATION, () -> {}, () -> {});
}
}
}
}
@@ -775,7 +785,7 @@ public class LWWindowPeer
@Override
public void notifyActivation(boolean activation, LWWindowPeer opposite) {
Window oppositeWindow = (opposite == null)? null : opposite.getTarget();
changeFocusedWindow(activation, oppositeWindow);
changeFocusedWindow(activation, oppositeWindow, () -> {});
}
// MouseDown in non-client area
@@ -892,7 +902,7 @@ public class LWWindowPeer
// 2. An active but not focused owner frame/dialog is clicked.
// The mouse event then will trigger a focus request "in window" to the component, so the window
// should gain focus before.
requestWindowFocus(FocusEvent.Cause.MOUSE_EVENT);
requestWindowFocus(FocusEvent.Cause.MOUSE_EVENT, () -> {}, () -> {});
mouseDownTarget[targetIdx] = targetPeer;
} else if (id == MouseEvent.MOUSE_DRAGGED) {
@@ -1248,17 +1258,19 @@ public class LWWindowPeer
* Requests platform to set native focus on a frame/dialog.
* In case of a simple window, triggers appropriate java focus change.
*/
public boolean requestWindowFocus(FocusEvent.Cause cause) {
public boolean requestWindowFocus(FocusEvent.Cause cause, Runnable rejectFocusRequest, Runnable lightweightRequest) {
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
focusLog.fine("requesting native focus to " + this);
}
if (!focusAllowedFor()) {
focusLog.fine("focus is not allowed");
rejectFocusRequest.run();
return false;
}
if (platformWindow.rejectFocusRequest(cause)) {
rejectFocusRequest.run();
return false;
}
@@ -1273,13 +1285,19 @@ public class LWWindowPeer
// In case the toplevel is active but not focused, change focus directly,
// as requesting native focus on it will not have effect.
if (getTarget() == currentActive && !getTarget().hasFocus()) {
changeFocusedWindow(true, opposite);
if (getTarget() == currentActive && !getTarget().isFocused()) {
changeFocusedWindow(true, opposite, lightweightRequest);
return true;
}
return platformWindow.requestWindowFocus();
focusLog.fine("platformWindow.requestWindowFocus()");
boolean requestFocusResult = platformWindow.requestWindowFocus();
if (requestFocusResult) {
lightweightRequest.run();
return true;
}
return false;
}
protected boolean focusAllowedFor() {
@@ -1307,7 +1325,7 @@ public class LWWindowPeer
@Override
public void emulateActivation(boolean activate) {
changeFocusedWindow(activate, null);
changeFocusedWindow(activate, null, () -> {});
}
@SuppressWarnings("deprecation")
@@ -1326,7 +1344,7 @@ public class LWWindowPeer
/*
* Changes focused window on java level.
*/
protected void changeFocusedWindow(boolean becomesFocused, Window opposite) {
protected void changeFocusedWindow(boolean becomesFocused, Window opposite, Runnable lightweightRequestRunnable) {
if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
focusLog.fine((becomesFocused?"gaining":"loosing") + " focus window: " + this);
}
@@ -1365,19 +1383,22 @@ public class LWWindowPeer
}
KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
if (!becomesFocused && kfmPeer.getCurrentFocusedWindow() != getTarget()) {
// late window focus lost event - ingoring
return;
}
kfmPeer.setCurrentFocusedWindow(becomesFocused ? getTarget() : null);
int eventID = becomesFocused ? WindowEvent.WINDOW_GAINED_FOCUS : WindowEvent.WINDOW_LOST_FOCUS;
WindowEvent windowEvent = new TimedWindowEvent(getTarget(), eventID, opposite, System.currentTimeMillis());
SunToolkit.setSystemGenerated(windowEvent);
AWTAccessor.getAWTEventAccessor().setPosted(windowEvent);
PeerEvent pe = new PeerEvent(getTarget(), () -> {
((Component)windowEvent.getSource()).dispatchEvent(windowEvent);
if (becomesFocused) {
lightweightRequestRunnable.run();
}
}, PeerEvent.ULTIMATE_PRIORITY_EVENT);
// TODO: wrap in SequencedEvent
SunToolkit.postPriorityEvent(windowEvent);
postEvent(pe);
}
/*
@@ -1498,4 +1519,4 @@ public class LWWindowPeer
}
return handle[0];
}
}
}

View File

@@ -622,7 +622,7 @@ AWT_ASSERT_APPKIT_THREAD;
AWT_ASSERT_APPKIT_THREAD;
for (NSWindow* window in [NSApp windows]) {
if (window.onActiveSpace && window.mainWindow && [AWTWindow isJavaPlatformWindowVisible:window]) {
if (window.onActiveSpace && [AWTWindow isJavaPlatformWindowVisible:window]) {
AWTWindow *awtWindow = (AWTWindow *)[window delegate];
// there can be only one current blocker per window hierarchy,
// so we're checking just hierarchy root
@@ -635,24 +635,6 @@ AWT_ASSERT_APPKIT_THREAD;
}
}
- (void) processVisibleChildren:(void(^)(AWTWindow*))action {
NSEnumerator *windowEnumerator = [[NSApp windows]objectEnumerator];
NSWindow *window;
while ((window = [windowEnumerator nextObject]) != nil) {
if ([AWTWindow isJavaPlatformWindowVisible:window]) {
AWTWindow *awtWindow = (AWTWindow *)[window delegate];
AWTWindow *parent = awtWindow.ownerWindow;
while (parent != nil) {
if (parent == self) {
action(awtWindow);
break;
}
parent = parent.ownerWindow;
}
}
}
}
// Orders window's childs based on the current focus state
- (void) orderChildWindows:(BOOL)focus {
AWT_ASSERT_APPKIT_THREAD;
@@ -662,28 +644,39 @@ AWT_ASSERT_APPKIT_THREAD;
return;
}
[self processVisibleChildren:^void(AWTWindow* child){
// Do not order 'always on top' windows
if (!IS(child.styleBits, ALWAYS_ON_TOP)) {
NSWindow *window = child.nsWindow;
NSWindow *owner = child.ownerWindow.nsWindow;
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];
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;
}
if (window.onActiveSpace && owner.onActiveSpace) {
// The childWindow should be displayed in front of
// its nearest parentWindow
[window orderWindow:NSWindowAbove relativeTo:[owner windowNumber]];
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];
}
if (window.onActiveSpace && owner.nsWindow.onActiveSpace) {
// The childWindow should be displayed in front of
// its nearest parentWindow
[window orderWindow:NSWindowAbove relativeTo:[owner.nsWindow windowNumber]];
}
break;
}
awtWindow = awtWindow.ownerWindow;
}
}
}];
}
}
// NSWindow overrides
@@ -790,14 +783,24 @@ AWT_ASSERT_APPKIT_THREAD;
- (void) iconifyChildWindows:(BOOL)iconify {
AWT_ASSERT_APPKIT_THREAD;
[self processVisibleChildren:^void(AWTWindow* child){
NSWindow *window = child.nsWindow;
if (iconify) {
[window orderOut:window];
} else {
[window orderFront:window];
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 {
@@ -1000,22 +1003,10 @@ AWT_ASSERT_APPKIT_THREAD;
}
}
// this is required to move owned windows to the full-screen space when owner goes to full-screen mode
- (void)allowMovingChildrenBetweenSpaces:(BOOL)allow {
[self processVisibleChildren:^void(AWTWindow* child){
NSWindow *window = child.nsWindow;
NSWindowCollectionBehavior behavior = window.collectionBehavior;
behavior &= !(NSWindowCollectionBehaviorManaged | NSWindowCollectionBehaviorTransient);
behavior |= allow ? NSWindowCollectionBehaviorTransient : NSWindowCollectionBehaviorManaged;
window.collectionBehavior = behavior;
}];
}
- (void)windowWillEnterFullScreen:(NSNotification *)notification {
self.isEnterFullScreen = YES;
[self allowMovingChildrenBetweenSpaces:YES];
static JNF_MEMBER_CACHE(jm_windowWillEnterFullScreen, jc_CPlatformWindow, "windowWillEnterFullScreen", "()V");
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];
@@ -1028,9 +1019,7 @@ AWT_ASSERT_APPKIT_THREAD;
- (void)windowDidEnterFullScreen:(NSNotification *)notification {
self.isEnterFullScreen = YES;
[self allowMovingChildrenBetweenSpaces:NO];
static JNF_MEMBER_CACHE(jm_windowDidEnterFullScreen, jc_CPlatformWindow, "windowDidEnterFullScreen", "()V");
JNIEnv *env = [ThreadUtilities getJNIEnv];
jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env];

View File

@@ -1,112 +0,0 @@
/*
* Copyright 2021 JetBrains s.r.o.
* 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.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
* @test
* @summary Regression test for JBR-3662 Focus jumps to another project tab after closing modal dialog
* @key headful
*/
public class WrongFrameFocusedOnModalDialogClosing {
private static final CompletableFuture<Boolean> dialogShown = new CompletableFuture<>();
private static CompletableFuture<Boolean> result;
private static Robot robot;
private static JFrame frame1;
private static JFrame frame2;
private static JButton button;
public static void main(String[] args) throws Exception {
robot = new Robot();
try {
SwingUtilities.invokeAndWait(WrongFrameFocusedOnModalDialogClosing::initUI);
robot.delay(1000); // wait for frames to appear
clickOn(button);
dialogShown.get(5, TimeUnit.SECONDS);
if (result.get(5, TimeUnit.SECONDS)) {
throw new RuntimeException("Wrong frame focused");
}
} finally {
SwingUtilities.invokeAndWait(WrongFrameFocusedOnModalDialogClosing::disposeUI);
}
}
private static void initUI() {
frame1 = new JFrame("WFFOMDC 1");
frame1.addWindowFocusListener(new WindowAdapter() {
@Override
public void windowGainedFocus(WindowEvent e) {
if (result != null) result.complete(false);
}
});
button = new JButton("Open dialog");
button.addActionListener(e -> {
JDialog d = new JDialog(frame1, true);
d.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
result = new CompletableFuture<>();
dialogShown.complete(true);
d.dispose();
}
});
d.setVisible(true);
});
frame1.add(button);
frame1.setSize(100, 100);
frame1.setLocation(100, 100);
frame1.setVisible(true);
frame2 = new JFrame("WFFOMDC 2");
frame2.addWindowFocusListener(new WindowAdapter() {
@Override
public void windowGainedFocus(WindowEvent e) {
if (result != null) result.complete(true);
}
});
frame2.setSize(100, 100);
frame2.setLocation(300, 100);
frame2.setVisible(true);
}
private static void disposeUI() {
if (frame1 != null) frame1.dispose();
if (frame2 != null) frame2.dispose();
}
private static void clickAt(int x, int y) {
robot.mouseMove(x, y);
robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
}
private static void clickOn(Component component) {
Point location = component.getLocationOnScreen();
clickAt(location.x + component.getWidth() / 2, location.y + component.getHeight() / 2);
}
}

View File

@@ -1,121 +0,0 @@
/*
* Copyright 2000-2021 JetBrains s.r.o.
* 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.
*/
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.io.File;
import java.nio.file.Files;
/**
* @test
* @summary Regression test for JBR-3671 Window order changes for a background app on macOS desktop space switch
* @key headful
* @requires (os.family == "mac")
*/
public class BackgroundWindowOrderOnSpaceChange {
private static Robot robot;
private static JFrame frame1;
private static JFrame frame2;
private static Process otherProcess;
public static void main(String[] args) throws Exception {
robot = new Robot();
try {
SwingUtilities.invokeAndWait(BackgroundWindowOrderOnSpaceChange::initUI);
launchProcessWithWindow();
switchToNextSpace();
switchToPreviousSpace();
Color color = robot.getPixelColor(400, 400);
if (!Color.green.equals(color)) {
throw new RuntimeException("Frame 1 isn't shown on top. Found color: " + color);
}
}
finally {
SwingUtilities.invokeAndWait(BackgroundWindowOrderOnSpaceChange::disposeUI);
}
}
private static void initUI() {
frame1 = new JFrame("BackgroundWindowOrderOnSpaceChange 1");
frame1.getContentPane().setBackground(Color.green);
frame1.setBounds(100, 100, 400, 400);
frame1.setVisible(true);
frame2 = new JFrame("BackgroundWindowOrderOnSpaceChange 2");
frame2.getContentPane().setBackground(Color.red);
frame2.setBounds(300, 300, 400, 400);
frame2.setVisible(true);
frame1.toFront();
}
private static void disposeUI() {
if (frame1 != null) frame1.dispose();
if (frame2 != null) frame2.dispose();
if (otherProcess != null) otherProcess.destroyForcibly();
}
private static void launchProcessWithWindow() throws Exception {
String javaPath = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java";
File tmpFile = File.createTempFile("BackgroundWindowOrderOnSpaceChange", ".java");
tmpFile.deleteOnExit();
Files.writeString(tmpFile.toPath(), "import javax.swing.*;\n" +
"import java.awt.event.*;\n" +
"\n" +
"public class TestWindow {\n" +
" public static void main(String[] args) {\n" +
" SwingUtilities.invokeLater(() -> {\n" +
" JFrame f = new JFrame(\"BackgroundWindowOrderOnSpaceChange 3\");\n" +
" f.addWindowFocusListener(new WindowAdapter() {\n" +
" @Override\n" +
" public void windowGainedFocus(WindowEvent e) {\n" +
" System.out.println();\n" +
" }\n" +
" });\n" +
" f.setBounds(800, 100, 200, 200);\n" +
" f.setVisible(true);\n" +
" });\n" +
" }\n" +
"}\n");
otherProcess = Runtime.getRuntime().exec(new String[]{javaPath, tmpFile.getAbsolutePath()});
if (otherProcess.getInputStream().read() == -1) {
throw new RuntimeException("Error starting process");
}
}
private static void switchToPreviousSpace() {
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_LEFT);
robot.keyRelease(KeyEvent.VK_LEFT);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.delay(1000); // wait for animation to finish
}
private static void switchToNextSpace() {
robot.keyPress(KeyEvent.VK_CONTROL);
robot.keyPress(KeyEvent.VK_RIGHT);
robot.keyRelease(KeyEvent.VK_RIGHT);
robot.keyRelease(KeyEvent.VK_CONTROL);
robot.delay(1000); // wait for animation to finish
}
}

View File

@@ -1,99 +0,0 @@
/*
* Copyright 2021 JetBrains s.r.o.
* 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.
*/
import com.apple.eawt.Application;
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
/**
* @test
* @summary Regression test for JBR-3666 Child window stays on default space
* when full-screen mode is activated for parent window on macOS
* @key headful
* @requires (os.family == "mac")
* @modules java.desktop/com.apple.eawt
*/
public class FullScreenChildWindowShownBefore {
private static final CompletableFuture<Boolean> dialogShown = new CompletableFuture<>();
private static Robot robot;
private static JFrame frame;
private static JDialog dialog;
public static void main(String[] args) throws Exception {
robot = new Robot();
try {
SwingUtilities.invokeAndWait(FullScreenChildWindowShownBefore::initUI);
dialogShown.get(5, TimeUnit.SECONDS);
SwingUtilities.invokeAndWait(() -> Application.getApplication().requestToggleFullScreen(frame));
robot.delay(1000); // wait for transition to full screen to finish
ensureVisible(frame);
ensureVisible(dialog);
} finally {
SwingUtilities.invokeAndWait(FullScreenChildWindowShownBefore::disposeUI);
}
}
private static void initUI() {
frame = new JFrame("FullScreenChildWindowShownBefore");
frame.getContentPane().setBackground(Color.green);
frame.setSize(100, 100);
frame.setLocation(100, 100);
frame.setVisible(true);
dialog = new JDialog(frame, false);
dialog.getContentPane().setBackground(Color.red);
dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
dialogShown.complete(true);
}
});
dialog.setSize(100, 100);
dialog.setLocation(100, 300);
dialog.setVisible(true);
}
private static void disposeUI() {
if (frame != null) frame.dispose();
}
private static void ensureVisible(Window window) {
Rectangle bounds = window.getBounds();
Insets insets = window.getInsets();
bounds.x += insets.left;
bounds.y += insets.top;
bounds.width -= insets.left + insets.right;
bounds.height -= insets.top + insets.bottom;
Color colorAtCenter = robot.getPixelColor((int) bounds.getCenterX(), (int) bounds.getCenterY());
if (!colorAtCenter.equals(((RootPaneContainer)window).getContentPane().getBackground())) {
throw new RuntimeException(window + " isn't visible: unexpected color " + colorAtCenter);
}
}
}

View File

@@ -1275,5 +1275,6 @@ jb/java/jcef/MouseEventTest.java
jb/java/jcef/MouseEventAfterHideAndShowBrowserTest.java JBR-2750 linux-all
jb/java/awt/event/TouchScreenEvent/TouchScreenEventsTest.java nobug windows-6.1 not supported on Windows 7
jb/java/awt/Focus/ChainOfPopupsFocusTest.java JBR-1518 linux-all
jb/java/awt/Focus/ModalDialogFromMenuTest.java JBR-2768 macosx-all
java/time/tck/java/time/format/TCKDateTimeFormatterBuilder.java JBR-2842 macosx-10.14,macosx-10.15,macosx-10.16

View File

@@ -211,6 +211,7 @@ jb/javax/swing/JDialog/JDialog705.java
jb/javax/swing/JDialog/JDialog741/JDialog741.html nobug macosx-all,linux-all,windows-all
jb/sun/awt/macos/KeyPressAndHoldTest.java nobug macosx-all
jb/sun/lwawt/macosx/NSEvent/nsevent422.sh nobug macosx-all
jb/java/awt/Focus/ModalDialogFromMenuTest.java JBR-2768 macosx-all
jb/java/jcef/MouseEventTest.java JBR-2750 linux-all
jb/java/jcef/MouseEventAfterHideAndShowBrowserTest.java JBR-2750 linux-all