7171412: awt Choice doesn't fire ItemStateChange when selecting item after select() call
Reviewed-by: art, denis
--- a/jdk/src/macosx/native/sun/awt/InitIDs.m Fri Sep 28 10:54:12 2012 -0700
+++ b/jdk/src/macosx/native/sun/awt/InitIDs.m Wed Oct 03 21:01:47 2012 +0400
@@ -47,7 +47,10 @@
{
}
-
+JNIEXPORT void JNICALL Java_java_awt_Choice_initIDs
+(JNIEnv *env, jclass cls)
+{
+}
JNIEXPORT void JNICALL Java_java_awt_Color_initIDs
(JNIEnv *env, jclass cls)
--- a/jdk/src/share/classes/java/awt/Choice.java Fri Sep 28 10:54:12 2012 -0700
+++ b/jdk/src/share/classes/java/awt/Choice.java Wed Oct 03 21:01:47 2012 +0400
@@ -104,7 +104,16 @@
/*
* JDK 1.1 serialVersionUID
*/
- private static final long serialVersionUID = -4075310674757313071L;
+ private static final long serialVersionUID = -4075310674757313071L;
+
+ static {
+ /* ensure that the necessary native libraries are loaded */
+ Toolkit.loadLibraries();
+ /* initialize JNI field and method ids */
+ if (!GraphicsEnvironment.isHeadless()) {
+ initIDs();
+ }
+ }
/**
* Creates a new choice menu. The menu initially has no items in it.
@@ -711,6 +720,10 @@
}
}
+ /**
+ * Initialize JNI field and method IDs
+ */
+ private static native void initIDs();
/////////////////
// Accessibility support
--- a/jdk/src/solaris/native/sun/awt/initIDs.c Fri Sep 28 10:54:12 2012 -0700
+++ b/jdk/src/solaris/native/sun/awt/initIDs.c Wed Oct 03 21:01:47 2012 +0400
@@ -89,6 +89,12 @@
}
JNIEXPORT void JNICALL
+Java_java_awt_Choice_initIDs
+ (JNIEnv *env, jclass clazz)
+{
+}
+
+JNIEXPORT void JNICALL
Java_java_awt_Dimension_initIDs
(JNIEnv *env, jclass clazz)
{
--- a/jdk/src/windows/native/sun/windows/awt_Choice.cpp Fri Sep 28 10:54:12 2012 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Choice.cpp Wed Oct 03 21:01:47 2012 +0400
@@ -79,6 +79,10 @@
static const UINT MINIMUM_NUMBER_OF_VISIBLE_ITEMS = 8;
+namespace {
+ jfieldID selectedIndexID;
+}
+
/*************************************************************************
* AwtChoice class methods
*/
@@ -86,7 +90,6 @@
AwtChoice::AwtChoice() {
m_hList = NULL;
m_listDefWindowProc = NULL;
- m_selectedItem = -1;
}
LPCTSTR AwtChoice::GetClassName() {
@@ -102,7 +105,6 @@
AwtChoice* AwtChoice::Create(jobject peer, jobject parent) {
-
JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
jobject target = NULL;
@@ -438,10 +440,14 @@
MsgRouting AwtChoice::WmNotify(UINT notifyCode)
{
if (notifyCode == CBN_SELCHANGE) {
- int selectedItem = (int)SendMessage(CB_GETCURSEL);
- if (selectedItem != CB_ERR && m_selectedItem != selectedItem){
- m_selectedItem = selectedItem;
- DoCallback("handleAction", "(I)V", selectedItem);
+ int selectedIndex = (int)SendMessage(CB_GETCURSEL);
+
+ JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
+ jobject target = GetTarget(env);
+ int previousIndex = env->GetIntField(target, selectedIndexID);
+
+ if (selectedIndex != CB_ERR && selectedIndex != previousIndex){
+ DoCallback("handleAction", "(I)V", selectedIndex);
}
} else if (notifyCode == CBN_DROPDOWN) {
@@ -695,6 +701,15 @@
extern "C" {
+JNIEXPORT void JNICALL
+Java_java_awt_Choice_initIDs(JNIEnv *env, jclass cls)
+{
+ TRY;
+ selectedIndexID = env->GetFieldID(cls, "selectedIndex", "I");
+ DASSERT(selectedIndexID);
+ CATCH_BAD_ALLOC;
+}
+
/*
* Class: sun_awt_windows_WChoicePeer
* Method: select
--- a/jdk/src/windows/native/sun/windows/awt_Choice.h Fri Sep 28 10:54:12 2012 -0700
+++ b/jdk/src/windows/native/sun/windows/awt_Choice.h Wed Oct 03 21:01:47 2012 +0400
@@ -94,7 +94,6 @@
static BOOL sm_isMouseMoveInList;
HWND m_hList;
WNDPROC m_listDefWindowProc;
- int m_selectedItem;
static LRESULT CALLBACK ListWindowProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam);
};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/Choice/ItemStateChangeTest/ItemStateChangeTest.java Wed Oct 03 21:01:47 2012 +0400
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2012, 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 7171412
+ @summary awt Choice doesn't fire ItemStateChange when selecting item after select() call
+ @author Oleg Pekhovskiy: area=awt-choice
+ @library ../../regtesthelpers
+ @build Util
+ @run main ItemStateChangeTest
+*/
+
+import test.java.awt.regtesthelpers.Util;
+
+import java.awt.*;
+import java.awt.event.*;
+import sun.awt.OSInfo;
+
+public class ItemStateChangeTest extends Frame {
+
+ int events = 0;
+
+ public static void main(String args[]) {
+ new ItemStateChangeTest();
+ }
+
+ public ItemStateChangeTest() {
+
+ if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) {
+ return;
+ }
+
+ try {
+
+ final Robot robot = new Robot();
+ robot.setAutoDelay(20);
+ Util.waitForIdle(robot);
+
+ addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(WindowEvent e) {
+ System.exit(0);
+ }
+ });
+
+ final Choice choice = new Choice();
+ choice.add("A");
+ choice.add("B");
+ choice.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ ++events;
+ }
+ });
+
+ add(choice);
+ setSize(200, 150);
+ setVisible(true);
+ toFront();
+
+ // choose B
+ int y = chooseB(choice, robot, 16);
+
+ // reset to A
+ choice.select(0);
+ robot.delay(20);
+ Util.waitForIdle(robot);
+
+ // choose B again
+ chooseB(choice, robot, y);
+
+ if (events == 2) {
+ System.out.println("Test passed!");
+ }
+ else {
+ throw new RuntimeException("Test failed!");
+ }
+
+ }
+ catch (AWTException e) {
+ throw new RuntimeException("Test failed!");
+ }
+ }
+
+ final int chooseB(Choice choice, Robot robot, int y) {
+ while (true) {
+ // show drop-down list
+ Util.clickOnComp(choice, robot);
+ Util.waitForIdle(robot);
+ Point pt = choice.getLocationOnScreen();
+ Dimension size = choice.getSize();
+ // try to click B item
+ robot.mouseMove(pt.x + size.width / 2, pt.y + size.height + y);
+ Util.waitForIdle(robot);
+ robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
+ Util.waitForIdle(robot);
+ robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);
+ Util.waitForIdle(robot);
+ if (choice.getSelectedIndex() == 1) {
+ break;
+ }
+ // if it's not B, position cursor lower by 2 pixels and try again
+ y += 2;
+ }
+ return y;
+ }
+}