From 0e614cc09e42ce54b50b49e497405f9878cfc455 Mon Sep 17 00:00:00 2001 From: Nikita Tsarev Date: Wed, 14 Jun 2023 17:48:58 +0200 Subject: [PATCH] JBR-5379: Ignore input events only on permament focus loss (cherry picked from commit ca8aebd211ab1a95b5a10724854206cd9bf7bbf7) --- .../sun/lwawt/macosx/CInputMethod.java | 11 ++- .../FocusMoveUncommitedCharactersTest.java | 74 +++++++++++++++++++ .../InputMethodTest/InputMethodTest.java | 11 +-- 3 files changed, 85 insertions(+), 11 deletions(-) create mode 100644 test/jdk/jb/sun/awt/macos/InputMethodTest/FocusMoveUncommitedCharactersTest.java diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java index a4415a7ae126..350633ebaf29 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CInputMethod.java @@ -37,13 +37,10 @@ import java.lang.Character.Subset; import java.lang.reflect.InvocationTargetException; import java.text.AttributedCharacterIterator.Attribute; import java.text.*; -import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.text.JTextComponent; import sun.awt.AWTAccessor; -import sun.awt.AppContext; -import sun.awt.SunToolkit; import sun.awt.im.InputMethodAdapter; import sun.lwawt.*; @@ -54,6 +51,7 @@ public class CInputMethod extends InputMethodAdapter { private volatile Component fAwtFocussedComponent; private LWComponentPeer fAwtFocussedComponentPeer; private boolean isActive; + private boolean isTemporarilyDeactivated; private static Map[] sHighlightStyles; @@ -238,12 +236,13 @@ public class CInputMethod extends InputMethodAdapter { */ public void activate() { isActive = true; - enableListening(true); + isTemporarilyDeactivated = false; } public void deactivate(boolean isTemporary) { isActive = false; + isTemporarilyDeactivated = isTemporary; } /** @@ -287,10 +286,10 @@ public class CInputMethod extends InputMethodAdapter { * to talk to when responding to key events. */ protected void setAWTFocussedComponent(Component component) { - if (component == null || component == fAwtFocussedComponent) { + if ((isTemporarilyDeactivated && component == null) || component == fAwtFocussedComponent) { // Sometimes input happens for the natively unfocused window // (e.g. in case of system emoji picker), - // so we don't reset last focused component on focus lost. + // so we don't reset last focused component on temporary focus lost. return; } diff --git a/test/jdk/jb/sun/awt/macos/InputMethodTest/FocusMoveUncommitedCharactersTest.java b/test/jdk/jb/sun/awt/macos/InputMethodTest/FocusMoveUncommitedCharactersTest.java new file mode 100644 index 000000000000..5694f1c54231 --- /dev/null +++ b/test/jdk/jb/sun/awt/macos/InputMethodTest/FocusMoveUncommitedCharactersTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2000-2023 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. + */ + +/** + * @test + * @summary Regression test for JBR-5379 Last character from Korean input gets inserted once again on click + * @modules java.desktop/sun.lwawt.macosx + * @run main InputMethodTest FocusMoveUncommitedCharactersTest + * @requires (jdk.version.major >= 8 & os.family == "mac") + */ + +import javax.swing.*; + +import java.awt.*; +import java.awt.event.InputEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +import static java.awt.event.KeyEvent.*; + +public class FocusMoveUncommitedCharactersTest implements Runnable { + @Override + public void run() { + var textArea2 = new JTextArea(); + final boolean[] typedEventReceived = {false}; + + textArea2.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + typedEventReceived[0] = true; + } + }); + + InputMethodTest.frame.getContentPane().add(textArea2, BorderLayout.SOUTH); + textArea2.setVisible(true); + + InputMethodTest.layout("com.apple.inputmethod.Korean.2SetKorean"); + InputMethodTest.type(VK_A, 0); + InputMethodTest.type(VK_K, 0); + + var robot = InputMethodTest.robot; + var point = new Point(textArea2.getWidth() / 2, textArea2.getHeight() / 2); + SwingUtilities.convertPointToScreen(point, textArea2); + + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.delay(1000); + + InputMethodTest.expectTrue(!typedEventReceived[0], "Expected no KeyTyped events on the second text area"); + InputMethodTest.expectTrue(textArea2.getText().isEmpty(), "Expected second text area to be empty"); + } +} diff --git a/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java b/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java index 27dc346a19fc..934ab89e9b89 100644 --- a/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java +++ b/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java @@ -35,9 +35,9 @@ import static java.awt.event.KeyEvent.KEY_PRESSED; import static java.awt.event.KeyEvent.KEY_RELEASED; public class InputMethodTest { - private static JFrame frame; - private static JTextArea textArea; - private static Robot robot; + public static JFrame frame; + public static JTextArea textArea; + public static Robot robot; private static String currentTest = ""; private static String currentSection = ""; private static String initialLayout; @@ -47,6 +47,7 @@ public class InputMethodTest { private enum TestCases { DeadKeysTest (new DeadKeysTest()), + FocusMoveUncommitedCharactersTest (new FocusMoveUncommitedCharactersTest()), KeyCodesTest (new KeyCodesTest()), NextAppWinKeyTestDead (new NextAppWinKeyTest(true)), NextAppWinKeyTestNormal (new NextAppWinKeyTest(false)), @@ -106,7 +107,7 @@ public class InputMethodTest { frame = new JFrame("InputMethodTest"); frame.setVisible(true); - frame.setSize(300, 300); + frame.setSize(600, 300); frame.setLocationRelativeTo(null); textArea = new JTextArea(); @@ -128,7 +129,7 @@ public class InputMethodTest { }); frame.setLayout(new BorderLayout()); - frame.getContentPane().add(textArea, BorderLayout.CENTER); + frame.getContentPane().add(textArea, BorderLayout.NORTH); textArea.grabFocus(); try {