aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Tsarev <nikita.tsarev@jetbrains.com>2024-02-14 13:35:21 +0100
committerNikita Tsarev <nikita.tsarev@jetbrains.com>2024-02-14 13:35:21 +0100
commit6c6c95f7f07e6b363a5c70eabdc9397fbbedfb89 (patch)
tree66772ff94f4be83d34d93f3cb69782ef89a47625
parent7756d7a9d2af39d528febac341dba12fb1726a4e (diff)
downloadJetBrainsRuntime-6c6c95f7f07e6b363a5c70eabdc9397fbbedfb89.tar.gz
JBR-6704: Fix extra IME events when a ctrl shortcut causes window focus switch [macOS]
-rw-r--r--src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m23
-rw-r--r--test/jdk/jb/sun/awt/macos/InputMethodTest/CtrlShortcutNewWindowTest.java79
-rw-r--r--test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java5
3 files changed, 104 insertions, 3 deletions
diff --git a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
index aaf766e6e8a..1075fe48568 100644
--- a/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
+++ b/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m
@@ -45,6 +45,9 @@
// keyboard layout
static NSString *kbdLayout;
+// workaround for JBR-6704
+static unichar lastCtrlCombo;
+
@interface AWTView()
@property (retain) CDropTarget *_dropTarget;
@property (retain) CDragSource *_dragSource;
@@ -87,6 +90,7 @@ extern bool isSystemShortcut_NextWindowInApplication(NSUInteger modifiersMask, i
fInputMethodLOCKABLE = NULL;
fKeyEventsNeeded = NO;
fProcessingKeystroke = NO;
+ lastCtrlCombo = 0;
fEnablePressAndHold = shouldUsePressAndHold();
fInPressAndHold = NO;
@@ -365,6 +369,12 @@ static void debugPrintNSEvent(NSEvent* event, const char* comment) {
NSString *eventCharacters = [event characters];
+ if (([event modifierFlags] & NSControlKeyMask) && [eventCharacters length] == 1) {
+ lastCtrlCombo = [eventCharacters characterAtIndex:0];
+ } else {
+ lastCtrlCombo = 0;
+ }
+
// Allow TSM to look at the event and potentially send back NSTextInputClient messages.
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
@@ -1140,6 +1150,14 @@ static jclass jc_CInputMethod = NULL;
fprintf(stderr, "AWTView InputMethod Selector Called : [insertText]: %s\n", [aString UTF8String]);
#endif // IM_DEBUG
+ NSMutableString * useString = [self parseString:aString];
+
+ // See JBR-6704
+ if (lastCtrlCombo && !fProcessingKeystroke && [useString length] == 1 && [useString characterAtIndex:0] == lastCtrlCombo) {
+ lastCtrlCombo = 0;
+ return;
+ }
+
if (fInputMethodLOCKABLE == NULL) {
return;
}
@@ -1152,8 +1170,6 @@ static jclass jc_CInputMethod = NULL;
// text, or 'text in progress'. We also need to send the event if we get an insert text out of the blue!
// (i.e., when the user uses the Character palette or Inkwell), or when the string to insert is a complex
// Unicode value.
-
- NSMutableString * useString = [self parseString:aString];
BOOL usingComplexIM = [self hasMarkedText] || !fProcessingKeystroke;
#ifdef IM_DEBUG
@@ -1162,6 +1178,7 @@ static jclass jc_CInputMethod = NULL;
NSLog(@"insertText kbdlayout %@ ",(NSString *)kbdLayout);
NSLog(@"utf8Length %lu utf16Length %lu", (unsigned long)utf8Length, (unsigned long)utf16Length);
+ NSLog(@"hasMarkedText: %s, fProcessingKeyStroke: %s", [self hasMarkedText] ? "YES" : "NO", fProcessingKeystroke ? "YES" : "NO");
#endif // IM_DEBUG
JNIEnv *env = [ThreadUtilities getJNIEnv];
@@ -1177,7 +1194,7 @@ static jclass jc_CInputMethod = NULL;
if (usingComplexIM) {
DECLARE_METHOD(jm_insertText, jc_CInputMethod, "insertText", "(Ljava/lang/String;)V");
- jstring insertedText = NSStringToJavaString(env, useString);
+ jstring insertedText = NSStringToJavaString(env, useString);
(*env)->CallVoidMethod(env, fInputMethodLOCKABLE, jm_insertText, insertedText);
CHECK_EXCEPTION();
(*env)->DeleteLocalRef(env, insertedText);
diff --git a/test/jdk/jb/sun/awt/macos/InputMethodTest/CtrlShortcutNewWindowTest.java b/test/jdk/jb/sun/awt/macos/InputMethodTest/CtrlShortcutNewWindowTest.java
new file mode 100644
index 00000000000..5d5cbfa40a1
--- /dev/null
+++ b/test/jdk/jb/sun/awt/macos/InputMethodTest/CtrlShortcutNewWindowTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2000-2024 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-6704 Extra IME event fired when pressing a keystroke containing Ctrl and focus moving to a different window
+ * @modules java.desktop/sun.lwawt.macosx
+ * @run main InputMethodTest CtrlShortcutNewWindowTest
+ * @requires (jdk.version.major >= 8 & os.family == "mac")
+ */
+
+import javax.swing.*;
+
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+import static java.awt.event.KeyEvent.*;
+
+public class CtrlShortcutNewWindowTest implements Runnable {
+ @Override
+ public void run() {
+ var frame = new JFrame();
+ frame.setSize(300, 300);
+ frame.setLocation(100, 100);
+ JTextField textField = new JTextField();
+ frame.add(textField);
+ textField.requestFocusInWindow();
+
+ final boolean[] keyPressed = {false};
+
+ InputMethodTest.textArea.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() == VK_BACK_QUOTE && (e.getModifiersEx() & KeyEvent.CTRL_DOWN_MASK) != 0) {
+ keyPressed[0] = true;
+ frame.setVisible(true);
+ }
+ }
+ });
+
+ InputMethodTest.section("Ctrl+Backtick");
+ InputMethodTest.layout("com.apple.keylayout.ABC");
+ InputMethodTest.type(VK_BACK_QUOTE, CTRL_DOWN_MASK);
+ InputMethodTest.delay(500);
+
+ if (!keyPressed[0]) {
+ InputMethodTest.fail("Ctrl+Backtick key combination not detected");
+ }
+
+ if (!textField.getText().isEmpty()) {
+ InputMethodTest.fail("Extra characters in the text field");
+ }
+
+ frame.setVisible(false);
+ frame.dispose();
+ }
+}
diff --git a/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java b/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java
index f23c0e4e019..146fb2e9005 100644
--- a/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java
+++ b/test/jdk/jb/sun/awt/macos/InputMethodTest/InputMethodTest.java
@@ -46,6 +46,7 @@ public class InputMethodTest {
private static final List<KeyEvent> triggeredEvents = new ArrayList<>();
private enum TestCases {
+ CtrlShortcutNewWindowTest (new CtrlShortcutNewWindowTest()),
DeadKeysTest (new DeadKeysTest()),
FocusMoveUncommitedCharactersTest (new FocusMoveUncommitedCharactersTest()),
KeyCodesTest (new KeyCodesTest()),
@@ -332,4 +333,8 @@ public class InputMethodTest {
public static void fail(String comment) {
expectTrue(false, comment);
}
+
+ public static void delay(int millis) {
+ robot.delay(millis);
+ }
}