changeset 7378:f21f2a9ed7df

8046495: KeyEvent can not be accepted in quick mouse clicking Reviewed-by: art, pchelko
author anashaty
date Wed, 30 Jul 2014 13:36:51 +0100
parents 38edb98b7b7f
children 5bccbd93b577
files src/windows/native/sun/windows/awt_Component.cpp src/windows/native/sun/windows/awt_TrayIcon.cpp test/java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java
diffstat 3 files changed, 146 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/src/windows/native/sun/windows/awt_Component.cpp	Fri Jul 25 19:49:06 2014 +0100
+++ b/src/windows/native/sun/windows/awt_Component.cpp	Wed Jul 30 13:36:51 2014 +0100
@@ -2131,19 +2131,7 @@
     }
 
     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;
+        return ::JVM_CurrentTimeMillis(NULL, 0);
     }
 } //TimeHelper
 
@@ -3566,7 +3554,7 @@
 
 
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_PRESSED,
-                             TimeHelper::windowsToUTC(msg.time), jkey, character,
+                             TimeHelper::getMessageTimeUTC(), jkey, character,
                              modifiers, keyLocation, (jlong)wkey, &msg);
 
     // bugid 4724007: Windows does not create a WM_CHAR for the Del key
@@ -3576,7 +3564,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),
+                                 TimeHelper::getMessageTimeUTC(),
                                  java_awt_event_KeyEvent_VK_UNDEFINED,
                                  character, modifiers,
                                  java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0);
@@ -3608,7 +3596,7 @@
     UpdateDynPrimaryKeymap(wkey, jkey, keyLocation, modifiers);
 
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_RELEASED,
-                             TimeHelper::windowsToUTC(msg.time), jkey, character,
+                             TimeHelper::getMessageTimeUTC(), jkey, character,
                              modifiers, keyLocation, (jlong)wkey, &msg);
     return mrConsume;
 }
@@ -3653,7 +3641,7 @@
 
     jint modifiers = GetJavaModifiers();
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
-                             TimeHelper::windowsToUTC(msg.time),
+                             TimeHelper::getMessageTimeUTC(),
                              java_awt_event_KeyEvent_VK_UNDEFINED,
                              unicodeChar, modifiers,
                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
@@ -3722,7 +3710,7 @@
     InitMessage(&msg, message, character,
                               MAKELPARAM(repCnt, flags));
     SendKeyEventToFocusOwner(java_awt_event_KeyEvent_KEY_TYPED,
-                             TimeHelper::windowsToUTC(msg.time),
+                             TimeHelper::getMessageTimeUTC(),
                              java_awt_event_KeyEvent_VK_UNDEFINED,
                              unicodeChar, modifiers,
                              java_awt_event_KeyEvent_KEY_LOCATION_UNKNOWN, (jlong)0,
--- a/src/windows/native/sun/windows/awt_TrayIcon.cpp	Fri Jul 25 19:49:06 2014 +0100
+++ b/src/windows/native/sun/windows/awt_TrayIcon.cpp	Wed Jul 30 13:36:51 2014 +0100
@@ -325,7 +325,7 @@
 
 MsgRouting AwtTrayIcon::WmMouseDown(UINT flags, int x, int y, int button)
 {
-    jlong now = TimeHelper::windowsToUTC(::GetTickCount());
+    jlong now = TimeHelper::getMessageTimeUTC();
     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, TimeHelper::getMessageTimeUTC(),
                    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(),
+                       TimeHelper::getMessageTimeUTC(), 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, TimeHelper::getMessageTimeUTC(), 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, TimeHelper::getMessageTimeUTC(),
                         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 = TimeHelper::getMessageTimeUTC();
 
     // 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, TimeHelper::getMessageTimeUTC(),
                         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, TimeHelper::getMessageTimeUTC(),
                         AwtComponent::GetJavaModifiers(), &msg);
     }
     return mrConsume;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java	Wed Jul 30 13:36:51 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();
+        }
+    }
+}