8046495: KeyEvent can not be accepted in quick mouse clicking
authoranashaty
Thu, 24 Jul 2014 16:06:49 +0100
changeset 26005 25124e230434
parent 26004 7507a1b93f67
child 26006 da0572ecab20
8046495: KeyEvent can not be accepted in quick mouse clicking Reviewed-by: art, pchelko
jdk/src/windows/native/sun/windows/awt_Button.cpp
jdk/src/windows/native/sun/windows/awt_Component.cpp
jdk/src/windows/native/sun/windows/awt_Component.h
jdk/src/windows/native/sun/windows/awt_List.cpp
jdk/src/windows/native/sun/windows/awt_MenuItem.cpp
jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp
jdk/src/windows/native/sun/windows/awt_Window.cpp
jdk/test/java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java
--- a/jdk/src/windows/native/sun/windows/awt_Button.cpp	Thu Jul 24 17:36:56 2014 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Button.cpp	Thu Jul 24 16:06:49 2014 +0100
@@ -186,7 +186,7 @@
 void
 AwtButton::NotifyListeners()
 {
-    DoCallback("handleAction", "(JI)V", TimeHelper::getMessageTimeUTC(),
+    DoCallback("handleAction", "(JI)V", ::JVM_CurrentTimeMillis(NULL, 0),
                (jint)AwtComponent::GetJavaModifiers());
 }
 
--- a/jdk/src/windows/native/sun/windows/awt_Component.cpp	Thu Jul 24 17:36:56 2014 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.cpp	Thu Jul 24 16:06:49 2014 +0100
@@ -2125,37 +2125,6 @@
     return mrDoDefault;
 }
 
-namespace TimeHelper {
-    // Sometimes the message belongs to another event queue and
-    // GetMessageTime() may return wrong non-zero value (the case is
-    // the TrayIcon peer). Using TimeHelper::windowsToUTC(::GetTickCount())
-    // could help there.
-    static DWORD getMessageTimeWindows(){
-        DWORD time = ::GetMessageTime();
-        // The following 'if' seems to be a unneeded hack.
-        // Consider removing it.
-        if (time == 0) {
-            time = ::GetTickCount();
-        }
-        return time;
-    }
-
-    jlong getMessageTimeUTC() {
-        return windowsToUTC(getMessageTimeWindows());
-    }
-
-    // If calling order of GetTickCount and JVM_CurrentTimeMillis
-    // is swapped, it would sometimes give different result.
-    // Anyway, we would not always have determinism
-    // and sortedness of time conversion here (due to Windows's
-    // timers peculiarities). Having some euristic algorithm might
-    // help here.
-    jlong windowsToUTC(DWORD windowsTime) {
-        jlong offset = ::GetTickCount() - windowsTime;
-        jlong jvm_time = ::JVM_CurrentTimeMillis(NULL, 0);
-        return jvm_time - offset;
-    }
-} //TimeHelper
 
 MsgRouting AwtComponent::WmPaint(HDC)
 {
@@ -2253,7 +2222,7 @@
 MsgRouting AwtComponent::WmMouseEnter(UINT flags, int x, int y)
 {
     SendMouseEvent(java_awt_event_MouseEvent_MOUSE_ENTERED,
-                   TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(), 0, JNI_FALSE);
+                   ::JVM_CurrentTimeMillis(NULL, 0), x, y, GetJavaModifiers(), 0, JNI_FALSE);
     if ((flags & ALL_MK_BUTTONS) == 0) {
         AwtCursor::UpdateCursor(this);
     }
@@ -2288,7 +2257,7 @@
     msg->message = message;
     msg->wParam = wParam;
     msg->lParam = lParam;
-    msg->time = TimeHelper::getMessageTimeWindows();
+    msg->time = ::GetMessageTime();
     msg->pt.x = x;
     msg->pt.y = y;
 }
@@ -2327,7 +2296,7 @@
 
 MsgRouting AwtComponent::WmMouseDown(UINT flags, int x, int y, int button)
 {
-    jlong now = TimeHelper::getMessageTimeUTC();
+    jlong now = ::JVM_CurrentTimeMillis(NULL, 0);
 
     if (lastClickWnd == this &&
         lastButton == button &&
@@ -2392,7 +2361,7 @@
     MSG msg;
     InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
 
-    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, TimeHelper::getMessageTimeUTC(),
+    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, ::JVM_CurrentTimeMillis(NULL, 0),
                    x, y, GetJavaModifiers(), clickCount,
                    (GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
                     TRUE : FALSE), GetButton(button), &msg);
@@ -2403,7 +2372,7 @@
      */
     if ((m_mouseButtonClickAllowed & GetButtonMK(button)) != 0) { //CLICK allowed
         SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
-                       TimeHelper::getMessageTimeUTC(), x, y, GetJavaModifiers(),
+                       ::JVM_CurrentTimeMillis(NULL, 0), x, y, GetJavaModifiers(),
                        clickCount, JNI_FALSE, GetButton(button));
     }
     // Exclude button from allowed to generate CLICK messages
@@ -2452,7 +2421,7 @@
             // This is a partial backout of 5039416 fix.
             MSG msg;
             InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
-            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, TimeHelper::getMessageTimeUTC(), x, y,
+            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_DRAGGED, ::JVM_CurrentTimeMillis(NULL, 0), x, y,
                            GetJavaModifiers(), 0, JNI_FALSE,
                            java_awt_event_MouseEvent_NOBUTTON, &msg);
             //dragging means no more CLICKs until next WM_MOUSE_DOWN/WM_MOUSE_UP message sequence
@@ -2460,7 +2429,7 @@
         } else {
             MSG msg;
             InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
-            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::getMessageTimeUTC(), x, y,
+            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, ::JVM_CurrentTimeMillis(NULL, 0), x, y,
                            GetJavaModifiers(), 0, JNI_FALSE,
                            java_awt_event_MouseEvent_NOBUTTON, &msg);
         }
@@ -2471,7 +2440,7 @@
 
 MsgRouting AwtComponent::WmMouseExit(UINT flags, int x, int y)
 {
-    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_EXITED, TimeHelper::getMessageTimeUTC(), x,
+    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_EXITED, ::JVM_CurrentTimeMillis(NULL, 0), x,
                    y, GetJavaModifiers(), 0, JNI_FALSE);
     sm_cursorOn = NULL;
     return mrConsume;   /* Don't pass our synthetic event on! */
@@ -2523,7 +2492,7 @@
 
     DTRACE_PRINTLN("calling SendMouseWheelEvent");
 
-    SendMouseWheelEvent(java_awt_event_MouseEvent_MOUSE_WHEEL, TimeHelper::getMessageTimeUTC(),
+    SendMouseWheelEvent(java_awt_event_MouseEvent_MOUSE_WHEEL, ::JVM_CurrentTimeMillis(NULL, 0),
                         eventPt.x, eventPt.y, GetJavaModifiers(), 0, 0, scrollType,
                         scrollLines, roundedWheelRotation, preciseWheelRotation, &msg);
 
@@ -3578,7 +3547,7 @@
 
 
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
-                             TimeHelper::windowsToUTC(msg.time), jkey, character,
+                             ::JVM_CurrentTimeMillis(NULL, 0), jkey, character,
                              modifiers, keyLocation, (jlong)wkey, &msg);
 
     // bugid 4724007: Windows does not create a WM_CHAR for the Del key
@@ -3588,7 +3557,7 @@
     // for Java - we don't want Windows trying to process it).
     if (jkey == java_awt_event_KeyEvent_VK_DELETE) {
         SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
-                                 TimeHelper::windowsToUTC(msg.time),
+                                 ::JVM_CurrentTimeMillis(NULL, 0),
                                  java_awt_event_KeyEvent_VK_UNDEFINED,
                                  character, modifiers,
                                  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
@@ -3620,7 +3589,7 @@
     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
 
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
-                             TimeHelper::windowsToUTC(msg.time), jkey, character,
+                             ::JVM_CurrentTimeMillis(NULL, 0), jkey, character,
                              modifiers, keyLocation, (jlong)wkey, &msg);
     return mrConsume;
 }
@@ -3665,7 +3634,7 @@
 
     jint modifiers = GetJavaModifiers();
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
-                             TimeHelper::windowsToUTC(msg.time),
+                             ::JVM_CurrentTimeMillis(NULL, 0),
                              java_awt_event_KeyEvent_VK_UNDEFINED,
                              unicodeChar, modifiers,
                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
@@ -3734,7 +3703,7 @@
     InitMessage(&msg, message, character,
                               MAKELPARAM(repCnt, flags));
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
-                             TimeHelper::windowsToUTC(msg.time),
+                             ::JVM_CurrentTimeMillis(NULL, 0),
                              java_awt_event_KeyEvent_VK_UNDEFINED,
                              unicodeChar, modifiers,
                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
@@ -4020,7 +3989,7 @@
     }
 
     // call m_InputMethod.sendInputMethod()
-    env->CallVoidMethod(m_InputMethod, sendIMEventMid, id, TimeHelper::getMessageTimeUTC(),
+    env->CallVoidMethod(m_InputMethod, sendIMEventMid, id, ::JVM_CurrentTimeMillis(NULL, 0),
                         text, clauseBoundary, clauseReading, attrBoundary,
                         attrValue, commitedTextLength, caretPos, visiblePos);
     if (safe_ExceptionOccurred(env))   env->ExceptionDescribe();
--- a/jdk/src/windows/native/sun/windows/awt_Component.h	Thu Jul 24 17:36:56 2014 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Component.h	Thu Jul 24 16:06:49 2014 +0100
@@ -908,11 +908,6 @@
 void ReleaseDCList(HWND hwnd, DCList &list);
 void MoveDCToPassiveList(HDC hDC);
 
-namespace TimeHelper{
-    jlong getMessageTimeUTC();
-    jlong windowsToUTC(DWORD event_offset);
-}
-
 #include "ObjectList.h"
 
 #endif /* AWT_COMPONENT_H */
--- a/jdk/src/windows/native/sun/windows/awt_List.cpp	Thu Jul 24 17:36:56 2014 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_List.cpp	Thu Jul 24 16:06:49 2014 +0100
@@ -535,7 +535,7 @@
             }
             else if (notifyCode == LBN_DBLCLK) {
                 DoCallback("handleAction", "(IJI)V", nCurrentSelection,
-                           TimeHelper::getMessageTimeUTC(),
+                           ::JVM_CurrentTimeMillis(NULL, 0),
                            (jint)AwtComponent::GetJavaModifiers());
             }
         }
--- a/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp	Thu Jul 24 17:36:56 2014 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_MenuItem.cpp	Thu Jul 24 16:06:49 2014 +0100
@@ -665,7 +665,7 @@
         DASSERT(nState != 0xFFFFFFFF);
         DoCallback("handleAction", "(Z)V", ((nState & MF_CHECKED) == 0));
     } else {
-        DoCallback("handleAction", "(JI)V", TimeHelper::getMessageTimeUTC(),
+        DoCallback("handleAction", "(JI)V", ::JVM_CurrentTimeMillis(NULL, 0),
                    (jint)AwtComponent::GetJavaModifiers());
     }
 }
--- a/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp	Thu Jul 24 17:36:56 2014 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_TrayIcon.cpp	Thu Jul 24 16:06:49 2014 +0100
@@ -325,7 +325,7 @@
 
 MsgRouting AwtTrayIcon::WmMouseDown(UINT flags, int x, int y, int button)
 {
-    jlong now = TimeHelper::windowsToUTC(::GetTickCount());
+    jlong now = ::JVM_CurrentTimeMillis(NULL, 0);
     jint javaModif = AwtComponent::GetJavaModifiers();
 
     if (lastClickTrIc == this &&
@@ -361,14 +361,14 @@
     MSG msg;
     AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
 
-    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, TimeHelper::windowsToUTC(::GetTickCount()),
+    SendMouseEvent(java_awt_event_MouseEvent_MOUSE_RELEASED, ::JVM_CurrentTimeMillis(NULL, 0),
                    x, y, AwtComponent::GetJavaModifiers(), clickCount,
                    (AwtComponent::GetButton(button) == java_awt_event_MouseEvent_BUTTON3 ?
                     TRUE : FALSE), AwtComponent::GetButton(button), &msg);
 
     if ((m_mouseButtonClickAllowed & AwtComponent::GetButtonMK(button)) != 0) { // No up-button in the drag-state
         SendMouseEvent(java_awt_event_MouseEvent_MOUSE_CLICKED,
-                       TimeHelper::windowsToUTC(::GetTickCount()), x, y, AwtComponent::GetJavaModifiers(),
+                       ::JVM_CurrentTimeMillis(NULL, 0), x, y, AwtComponent::GetJavaModifiers(),
                        clickCount, JNI_FALSE, AwtComponent::GetButton(button));
     }
     m_mouseButtonClickAllowed &= ~AwtComponent::GetButtonMK(button); // Exclude the up-button from the drag-state
@@ -395,7 +395,7 @@
         if ((flags & ALL_MK_BUTTONS) != 0) {
             m_mouseButtonClickAllowed = 0;
         } else {
-            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, TimeHelper::windowsToUTC(::GetTickCount()), x, y,
+            SendMouseEvent(java_awt_event_MouseEvent_MOUSE_MOVED, ::JVM_CurrentTimeMillis(NULL, 0), x, y,
                            AwtComponent::GetJavaModifiers(), 0, JNI_FALSE,
                            java_awt_event_MouseEvent_NOBUTTON, &msg);
         }
@@ -408,7 +408,7 @@
     if (AwtComponent::GetJavaModifiers() & java_awt_event_InputEvent_BUTTON1_DOWN_MASK) {
         MSG msg;
         AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
-        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::windowsToUTC(::GetTickCount()),
+        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0),
                         AwtComponent::GetJavaModifiers(), &msg);
     }
     return mrConsume;
@@ -417,14 +417,14 @@
 MsgRouting AwtTrayIcon::WmKeySelect(UINT flags, int x, int y)
 {
     static jlong lastKeySelectTime = 0;
-    jlong now = TimeHelper::windowsToUTC(::GetTickCount());
+    jlong now = ::JVM_CurrentTimeMillis(NULL, 0);
 
     // If a user selects a notify icon with the ENTER key,
     // Shell 5.0 sends double NIN_KEYSELECT notification.
     if (lastKeySelectTime != now) {
         MSG msg;
         AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
-        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::windowsToUTC(::GetTickCount()),
+        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0),
                         AwtComponent::GetJavaModifiers(), &msg);
     }
     lastKeySelectTime = now;
@@ -441,7 +441,7 @@
     if (clickCount == 2) {
         MSG msg;
         AwtComponent::InitMessage(&msg, lastMessage, flags, MAKELPARAM(x, y), x, y);
-        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, TimeHelper::windowsToUTC(::GetTickCount()),
+        SendActionEvent(java_awt_event_ActionEvent_ACTION_PERFORMED, ::JVM_CurrentTimeMillis(NULL, 0),
                         AwtComponent::GetJavaModifiers(), &msg);
     }
     return mrConsume;
--- a/jdk/src/windows/native/sun/windows/awt_Window.cpp	Thu Jul 24 17:36:56 2014 +0400
+++ b/jdk/src/windows/native/sun/windows/awt_Window.cpp	Thu Jul 24 16:06:49 2014 +0100
@@ -1552,7 +1552,7 @@
         }
     }
     jobject event = env->NewObject(wClassEvent, wEventInitMID, target, id,
-                                   jOpposite, oldState, newState, TimeHelper::getMessageTimeUTC());
+                                   jOpposite, oldState, newState, ::JVM_CurrentTimeMillis(NULL, 0));
     DASSERT(!safe_ExceptionOccurred(env));
     DASSERT(event != NULL);
     if (jOpposite != NULL) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java	Thu Jul 24 16:06:49 2014 +0100
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2014, 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.
+ */
+
+import sun.awt.SunToolkit;
+
+import java.awt.*;
+import java.awt.event.AWTEventListener;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+
+/*
+ * @test
+ * @bug 8046495
+ * @summary Verifies that mouse/key events has always increasing 'when' timestamps
+ * @author Anton Nashatyrev
+ * @run main EventWhenTest
+ */
+public class EventWhenTest {
+
+    private static volatile int eventsCount = 0;
+    private static volatile boolean failed = false;
+
+    static {
+        Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
+            long lastWhen = 0;
+
+            @Override
+            public void eventDispatched(AWTEvent event) {
+                long curWhen;
+                if (event instanceof KeyEvent) {
+                    curWhen = ((KeyEvent) event).getWhen();
+                } else if (event instanceof MouseEvent) {
+                    curWhen = ((MouseEvent) event).getWhen();
+                } else {
+                    return;
+                }
+
+                eventsCount++;
+
+                if (curWhen < lastWhen) {
+                    System.err.println("FAILED: " + curWhen + " < " + lastWhen +
+                        " for " + event);
+                    failed = true;
+                } else {
+                    lastWhen = curWhen;
+                }
+            }
+        }, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK);
+    }
+
+    public static void main(String[] args) throws Exception {
+
+        SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
+        Frame frame = new Frame();
+
+        try {
+            Button b = new Button("Button");
+            frame.setBounds(300, 300, 300, 300);
+            frame.add(b);
+            frame.setVisible(true);
+            toolkit.realSync();
+
+            Robot robot = new Robot();
+            robot.mouseMove((int)frame.getLocationOnScreen().getX() + 150,
+                    (int)frame.getLocationOnScreen().getY() + 150);
+
+            eventsCount = 0;
+            System.out.println("Clicking mouse...");
+            for (int i = 0; i < 300 && !failed; i++) {
+                robot.mousePress(InputEvent.BUTTON1_MASK);
+                robot.mouseRelease(InputEvent.BUTTON1_MASK);
+                Thread.sleep(10);
+                b.setLabel("Click: " + i);
+            }
+
+            if (eventsCount == 0) {
+                throw new RuntimeException("No events were received");
+            }
+
+            if (failed) {
+                throw new RuntimeException("Test failed.");
+            }
+            System.out.println("Clicking mouse done: " + eventsCount + " events.");
+
+            b.requestFocusInWindow();
+            toolkit.realSync();
+
+            eventsCount = 0;
+            System.out.println("Typing a key...");
+            for (int i = 0; i < 300 && !failed; i++) {
+                robot.keyPress(KeyEvent.VK_A);
+                robot.keyRelease(KeyEvent.VK_A);
+                Thread.sleep(10);
+                b.setLabel("Type: " + i);
+            }
+            System.out.println("Key typing done: " + eventsCount + " events.");
+
+            if (eventsCount == 0) {
+                throw new RuntimeException("No events were received");
+            }
+
+            if (failed) {
+                throw new RuntimeException("Test failed.");
+            }
+
+            System.out.println("Success!");
+        } finally {
+            frame.dispose();
+        }
+    }
+}