From e3c2db47271063df070806d233b65c3da7ab10f8 Mon Sep 17 00:00:00 2001 From: ssreedharan Date: Fri, 24 Nov 2017 13:18:36 +0530 Subject: [PATCH] 8176072: READING attributes are not available on TSF Reviewed-by: ssadetsky --- .../classes/sun/awt/windows/WInputMethod.java | 2 +- .../native/sun/windows/awt_InputTextInfor.cpp | 24 +- .../JapaneseReadingAttributes.java | 294 ++++++++++++++++++ 3 files changed, 312 insertions(+), 8 deletions(-) create mode 100644 test/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.java diff --git a/src/windows/classes/sun/awt/windows/WInputMethod.java b/src/windows/classes/sun/awt/windows/WInputMethod.java index de7c478c0..7010f32d8 100644 --- a/src/windows/classes/sun/awt/windows/WInputMethod.java +++ b/src/windows/classes/sun/awt/windows/WInputMethod.java @@ -493,7 +493,7 @@ final class WInputMethod extends InputMethodAdapter // set Clause and Reading Information if (clauseBoundary!=null && clauseReading!=null && clauseReading.length!=0 && clauseBoundary.length==clauseReading.length+1 && - clauseBoundary[0]==0 && clauseBoundary[clauseReading.length]==text.length() ) + clauseBoundary[0]==0 && clauseBoundary[clauseReading.length]<=text.length() ) { for (int i=0; iGetClauseInfor(lpBndClauseW, lpReadingClauseW); + } } int* bndClauseW = NULL; @@ -346,10 +352,14 @@ int AwtInputTextInfor::GetClauseInfor(int*& lpBndClauseW, jstring*& lpReadingCla // int AwtInputTextInfor::GetAttributeInfor(int*& lpBndAttrW, BYTE*& lpValAttrW) { if (m_cStrW == 0 || m_cAttrW != m_cStrW) { - lpBndAttrW = NULL; - lpValAttrW = NULL; + if (NULL == m_pResultTextInfor) { + lpBndAttrW = NULL; + lpValAttrW = NULL; - return 0; + return 0; + } else { + return m_pResultTextInfor->GetAttributeInfor(lpBndAttrW, lpValAttrW); + } } int* bndAttrW = NULL; diff --git a/test/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.java b/test/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.java new file mode 100644 index 000000000..b7164b963 --- /dev/null +++ b/test/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.java @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * 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 + * @bug 8176072 + * @summary Checks whether reading attributes are obtained for Japanese IME + * @requires (os.family == "windows") + * @run main/manual JapaneseReadingAttributes + */ + +/** + * This test requires a manual intervention as the keyboard layout has to be + * changed to Japanese IME. Once the keyboard layout has been selected, click on + * Start Test to start the automated tests. Will run two passes, first with an + * enter key in between to generate the yomigana for the first block of + * characters. The second without the intermediate enter key. Without the fix, + * there will be a mismatch in the reading attributes obtained. + */ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Robot; +import java.awt.event.InputMethodEvent; +import java.awt.event.InputMethodListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; +import java.awt.event.KeyEvent; +import java.text.AttributedCharacterIterator; +import java.util.ArrayList; +import java.util.concurrent.CountDownLatch; +import javax.swing.JLabel; +import javax.swing.JTextField; + +public class JapaneseReadingAttributes { + private static boolean testPassed = false; + private static boolean startTest = false; + + private static JFrame frame = null; + private static JLabel lblTestStatus = null; + private static JTextField textFieldMain = null; + private static JTextField textFieldReading = null; + private static String testResult; + private static String readingPass1; + private static String readingPass2; + + private static final CountDownLatch testStartLatch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + setupUI(); + }); + + testStartLatch.await(); + + if (startTest) { + glyphTest(); + + frame.dispose(); + + if (testPassed) { + System.out.println(testResult); + } else { + throw new RuntimeException(testResult); + } + } else { + throw new RuntimeException("User has not executed the test"); + } + } + + private static void setupUI() { + String description = " 1. Go to \"Language Preferences -> Add a Language" + + "\" and add \"Japanese\"\n" + + " 2. Set current IM to \"Japanese\" \n" + + " 3. Try typing in the text field to ensure" + + " that Japanese IME has been successfully" + + " selected \n" + + " 4. Now click on \"Start Test\" button \n"; + String title = "Reading Attributes test Japanese IME (Windows)"; + + frame = new JFrame(title); + + JPanel mainPanel = new JPanel(new BorderLayout()); + + JPanel textEditPanel = new JPanel(new FlowLayout()); + + textFieldMain = new JTextField(20); + + textFieldReading = new JTextField(20); + textFieldReading.setEditable(false); + + textEditPanel.add(textFieldMain); + textEditPanel.add(textFieldReading); + + mainPanel.add(textEditPanel, BorderLayout.CENTER); + + JTextArea textArea = new JTextArea(description); + textArea.setEditable(false); + final JButton btnStartTest = new JButton("Start Test"); + final JButton btnCancelTest = new JButton("Cancel Test"); + + btnStartTest.addActionListener((e) -> { + btnStartTest.setEnabled(false); + btnCancelTest.setEnabled(false); + startTest = true; + testStartLatch.countDown(); + }); + + btnCancelTest.addActionListener((e) -> { + frame.dispose(); + testStartLatch.countDown(); + }); + mainPanel.add(textArea, BorderLayout.NORTH); + + JPanel buttonPanel = new JPanel(new FlowLayout()); + buttonPanel.add(btnStartTest); + buttonPanel.add(btnCancelTest); + mainPanel.add(buttonPanel, BorderLayout.SOUTH); + + lblTestStatus = new JLabel(""); + lblTestStatus.setMinimumSize(new Dimension(250, 20)); + lblTestStatus.setPreferredSize(new Dimension(250, 20)); + lblTestStatus.setVisible(true); + textEditPanel.add(lblTestStatus); + + frame.add(mainPanel); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + frame.pack(); + frame.setLocationRelativeTo(null); + + frame.addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + testStartLatch.countDown(); + } + @Override + public void windowOpened( WindowEvent e ){ + textFieldMain.requestFocusInWindow(); + } + }); + + textFieldMain.addInputMethodListener(new InputMethodListener() { + @Override + public void caretPositionChanged(InputMethodEvent event) { + } + + @Override + public void inputMethodTextChanged(InputMethodEvent event) { + AttributedCharacterIterator itr = event.getText(); + if (itr != null) { + int toCopy = event.getCommittedCharacterCount(); + if (toCopy > 0) { + itr.first(); + StringBuilder yomigana = new StringBuilder( + textFieldReading.getText()); + while (toCopy-- > 0) { + if (itr.getIndex() == itr.getRunStart( + AttributedCharacterIterator.Attribute.READING)) { + java.text.Annotation annotatedText + = (java.text.Annotation) itr. + getAttribute(AttributedCharacterIterator.Attribute.READING); + yomigana.append(annotatedText.getValue()); + } + itr.next(); + } + textFieldReading.setText(yomigana.toString()); + } + } + } + }); + + frame.setVisible(true); + } + + private static void glyphTest() throws Exception { + Robot robotKeySimulator = new Robot(); + performTasks(robotKeySimulator); + } + + public static void performTasks(Robot robotForKeyInput) throws Exception { + lblTestStatus.setText("Running Tests.."); + robotForKeyInput.setAutoDelay(500); + + ArrayList keyCodesToUse = new ArrayList(); + + keyCodesToUse.add(KeyEvent.VK_A); + keyCodesToUse.add(KeyEvent.VK_B); + keyCodesToUse.add(KeyEvent.VK_E); + keyCodesToUse.add(KeyEvent.VK_SPACE); + keyCodesToUse.add(KeyEvent.VK_SPACE); + keyCodesToUse.add(KeyEvent.VK_ENTER); + keyCodesToUse.add(KeyEvent.VK_S); + keyCodesToUse.add(KeyEvent.VK_I); + keyCodesToUse.add(KeyEvent.VK_N); + keyCodesToUse.add(KeyEvent.VK_Z); + keyCodesToUse.add(KeyEvent.VK_O); + keyCodesToUse.add(KeyEvent.VK_U); + keyCodesToUse.add(KeyEvent.VK_SPACE); + keyCodesToUse.add(KeyEvent.VK_ENTER); + + textFieldMain.requestFocusInWindow(); + + robotForKeyInput.waitForIdle(); + + enterInput(robotForKeyInput, keyCodesToUse); + + SwingUtilities.invokeAndWait(() -> { + readingPass1 = textFieldReading.getText(); + }); + + if (setTaskStatus(readingPass1, 1)) { + keyCodesToUse.remove((Integer) KeyEvent.VK_ENTER); + + enterInput(robotForKeyInput, keyCodesToUse); + + SwingUtilities.invokeAndWait(() -> { + readingPass2 = textFieldReading.getText(); + }); + + if (setTaskStatus(readingPass2, 2)) { + if (readingPass1.equals(readingPass2)) { + testPassed = true; + testResult = "Test Passed : Same reading attribute " + + "obtained from both passes "; + lblTestStatus.setText(testResult); + } else { + testResult = "Test Failed : Reading attribute from Pass 1 <" + + readingPass1 + "> != Reading attribute " + + "from Pass 2 <" + readingPass2 + ">"; + } + } + } + } + + private static void enterInput(Robot robotKeyInput, + ArrayList keyInputs) { + textFieldReading.setText(""); + textFieldMain.setText(""); + + String strKeyInput = "KeyPress=>"; + int nOfKeyInputs = keyInputs.size(); + for (int i = 0; i < nOfKeyInputs; i++) { + int keyToUse = keyInputs.get(i); + robotKeyInput.keyPress(keyToUse); + robotKeyInput.keyRelease(keyToUse); + strKeyInput += (Integer.toHexString(keyToUse)) + ":"; + } + + System.out.println(strKeyInput); + } + + public static boolean setTaskStatus(String readingValue, int passCount) { + boolean status = false; + + if (!readingValue.isEmpty()) { + testResult = "Attribute : " + readingValue + + "read from pass " + Integer.toString(passCount); + status = true; + } else { + testResult = "Failed to read Reading attribute from pass " + + Integer.toString(passCount); + } + + lblTestStatus.setText(testResult); + + return status; + } +} -- GitLab