--- a/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java Thu Nov 23 23:05:52 2017 -0800
+++ b/src/java.desktop/windows/classes/sun/awt/windows/WInputMethod.java Fri Nov 24 13:18:36 2017 +0530
@@ -498,7 +498,7 @@
// 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; i<clauseBoundary.length-1; i++) {
attrStr.addAttribute(Attribute.INPUT_METHOD_SEGMENT,
--- a/src/java.desktop/windows/native/libawt/windows/awt_InputTextInfor.cpp Thu Nov 23 23:05:52 2017 -0800
+++ b/src/java.desktop/windows/native/libawt/windows/awt_InputTextInfor.cpp Fri Nov 24 13:18:36 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -202,9 +202,15 @@
m_lpClauseW == NULL || m_lpReadClauseW == NULL ||
m_lpClauseW[0] != 0 || m_lpClauseW[m_cClauseW] != (DWORD)m_cStrW ||
m_lpReadClauseW[0] != 0 || m_lpReadClauseW[m_cReadClauseW] != (DWORD)m_cReadStrW) {
- lpBndClauseW = NULL;
- lpReadingClauseW = NULL;
- return 0;
+ // For cases where IMM sends WM_IME_COMPOSITION with both GCS_COMPSTR and GCS_RESULTSTR
+ // The GCS_RESULTSTR part may have Caluse and Reading information which should not be ignored
+ if (NULL == m_pResultTextInfor) {
+ lpBndClauseW = NULL;
+ lpReadingClauseW = NULL;
+ return 0;
+ } else {
+ return m_pResultTextInfor->GetClauseInfor(lpBndClauseW, lpReadingClauseW);
+ }
}
int* bndClauseW = NULL;
@@ -346,10 +352,14 @@
//
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;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/swing/JTextField/JapaneseReadingAttributes/JapaneseReadingAttributes.java Fri Nov 24 13:18:36 2017 +0530
@@ -0,0 +1,295 @@
+/*
+ * 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
+ * @key headful
+ * @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<Integer> keyCodesToUse = new ArrayList<Integer>();
+
+ 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<Integer> 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;
+ }
+}