7171412: awt Choice doesn't fire ItemStateChange when selecting item after select() call
authorbagiras
Wed, 03 Oct 2012 21:01:47 +0400
changeset 13997 8889b37053e6
parent 13996 e9f4fefc32e1
child 13998 1d391c00b84d
child 14156 1326c5bd5baa
7171412: awt Choice doesn't fire ItemStateChange when selecting item after select() call Reviewed-by: art, denis
jdk/src/macosx/native/sun/awt/InitIDs.m
jdk/src/share/classes/java/awt/Choice.java
jdk/src/solaris/native/sun/awt/initIDs.c
jdk/src/windows/native/sun/windows/awt_Choice.cpp
jdk/src/windows/native/sun/windows/awt_Choice.h
jdk/test/java/awt/Choice/ItemStateChangeTest/ItemStateChangeTest.java
--- 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;
+    }
+}