JBR-5379: Ignore input events only on permament focus loss

(cherry picked from commit ca8aebd211)
This commit is contained in:
Nikita Tsarev
2023-06-14 17:48:58 +02:00
committed by jbrbot
parent 80afe45c93
commit 0e614cc09e
3 changed files with 85 additions and 11 deletions

View File

@@ -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<TextAttribute, Integer>[] 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;
}

View File

@@ -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");
}
}

View File

@@ -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 {