From 0347ac8f0d7c2d0bf25c64635e5a5bfcf88be3e1 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Fri, 29 Jan 2021 14:42:06 +0300 Subject: [PATCH] JBR-1752 Floating windows overlap modal dialogs (cherry picked from commit 0161050077785fb622c6f4f3fae9d8af5e12d770) --- .../sun/lwawt/macosx/CPlatformWindow.java | 5 - .../native/libawt_lwawt/awt/AWTWindow.m | 37 +------- .../awt/Focus/ModalDialogOverSiblingTest.java | 93 +++++++++++++++++++ 3 files changed, 94 insertions(+), 41 deletions(-) create mode 100644 test/jdk/jb/java/awt/Focus/ModalDialogOverSiblingTest.java diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index be36f737027b..33c60b42b0a1 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -1199,11 +1199,6 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo return !peer.isSimpleWindow() && target.getFocusableWindowState(); } - private boolean isBlocked() { - LWWindowPeer blocker = (peer != null) ? peer.getBlocker() : null; - return (blocker != null); - } - /* * An utility method for the support of the auto request focus. * Updates the focusable state of the window under certain diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m index f116af634ebb..e42ec70245dd 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTWindow.m @@ -493,23 +493,6 @@ AWT_ASSERT_APPKIT_THREAD; [super dealloc]; } -// Tests whether window is blocked by modal dialog/window -- (BOOL) isBlocked { - BOOL isBlocked = NO; - - JNIEnv *env = [ThreadUtilities getJNIEnv]; - jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow); - if (platformWindow != NULL) { - GET_CPLATFORM_WINDOW_CLASS_RETURN(isBlocked); - DECLARE_METHOD_RETURN(jm_isBlocked, jc_CPlatformWindow, "isBlocked", "()Z", isBlocked); - isBlocked = (*env)->CallBooleanMethod(env, platformWindow, jm_isBlocked) == JNI_TRUE ? YES : NO; - CHECK_EXCEPTION(); - (*env)->DeleteLocalRef(env, platformWindow); - } - - return isBlocked; -} - // Test whether window is simple window and owned by embedded frame - (BOOL) isSimpleWindowOwnedByEmbeddedFrame { BOOL isSimpleWindowOwnedByEmbeddedFrame = NO; @@ -553,9 +536,8 @@ AWT_ASSERT_APPKIT_THREAD; - (void) orderChildWindows:(BOOL)focus { AWT_ASSERT_APPKIT_THREAD; - if (self.isMinimizing || [self isBlocked]) { + if (self.isMinimizing) { // Do not perform any ordering, if iconify is in progress - // or the window is blocked by a modal window return; } @@ -1000,23 +982,6 @@ AWT_ASSERT_APPKIT_THREAD; - (void)sendEvent:(NSEvent *)event { if ([event type] == NSLeftMouseDown || [event type] == NSRightMouseDown || [event type] == NSOtherMouseDown) { - if ([self isBlocked]) { - // Move parent windows to front and make sure that a child window is displayed - // in front of its nearest parent. - if (self.ownerWindow != nil) { - JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; - jobject platformWindow = (*env)->NewLocalRef(env, self.javaPlatformWindow); - if (platformWindow != NULL) { - GET_CPLATFORM_WINDOW_CLASS(); - DECLARE_METHOD(jm_orderAboveSiblings, jc_CPlatformWindow, "orderAboveSiblings", "()V"); - (*env)->CallVoidMethod(env,platformWindow, jm_orderAboveSiblings); - CHECK_EXCEPTION(); - (*env)->DeleteLocalRef(env, platformWindow); - } - } - [self orderChildWindows:YES]; - } - NSPoint p = [NSEvent mouseLocation]; NSRect frame = [self.nsWindow frame]; NSRect contentRect = [self.nsWindow contentRectForFrameRect:frame]; diff --git a/test/jdk/jb/java/awt/Focus/ModalDialogOverSiblingTest.java b/test/jdk/jb/java/awt/Focus/ModalDialogOverSiblingTest.java new file mode 100644 index 000000000000..8d56afbb86f6 --- /dev/null +++ b/test/jdk/jb/java/awt/Focus/ModalDialogOverSiblingTest.java @@ -0,0 +1,93 @@ +/* + * Copyright 2000-2021 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; +import java.util.concurrent.*; + +/** + * @test + * @summary Regression test for JBR-1752 Floating windows overlap modal dialogs + * @key headful + */ + +public class ModalDialogOverSiblingTest { + private static final CompletableFuture modalDialogButtonClicked = new CompletableFuture<>(); + private static Robot robot; + private static JFrame frame; + private static JButton button1; + private static JButton button2; + private static JButton button3; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + try { + SwingUtilities.invokeAndWait(ModalDialogOverSiblingTest::initUI); + robot.delay(2000); + clickOn(button1); + robot.delay(2000); + clickOn(button2); + robot.delay(2000); + clickOn(button3); + modalDialogButtonClicked.get(5, TimeUnit.SECONDS); + } finally { + SwingUtilities.invokeAndWait(ModalDialogOverSiblingTest::disposeUI); + } + } + + private static void initUI() { + frame = new JFrame("ModalDialogOverSiblingTest"); + frame.setLayout(new FlowLayout()); + button1 = new JButton("Open non-modal dialog"); + button1.addActionListener(e -> { + JDialog dialog = new JDialog(frame, "Non-modal", false); + dialog.setSize(200, 200); + dialog.setLocation(200, 400); + dialog.setVisible(true); + }); + frame.add(button1); + button2 = new JButton("Open modal dialog"); + button2.addActionListener(e -> { + JDialog dialog = new JDialog(frame, "Modal", true); + button3 = new JButton("Button"); + button3.addActionListener(event -> modalDialogButtonClicked.complete(true)); + dialog.add(button3); + dialog.setSize(150, 150); + dialog.setLocation(220, 420); + dialog.setVisible(true); + }); + frame.add(button2); + frame.pack(); + frame.setLocation(200, 200); + frame.setVisible(true); + } + + private static void disposeUI() { + if (frame != null) frame.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); + } +}