8041990: [macosx] Language specific keys does not work in applets when opened outside the browser
authorpchelko
Fri, 06 Jun 2014 14:52:07 +0400
changeset 25133 a327a33a1e0a
parent 25132 a778c3c853bb
child 25134 ee53c90dfeb1
8041990: [macosx] Language specific keys does not work in applets when opened outside the browser Reviewed-by: alexsch, serb
jdk/src/share/classes/java/awt/EventQueue.java
jdk/src/share/classes/java/awt/event/InputMethodEvent.java
jdk/src/share/classes/sun/awt/AWTAccessor.java
jdk/test/java/awt/im/8041990/bug8041990.java
--- a/jdk/src/share/classes/java/awt/EventQueue.java	Fri Jun 06 13:52:49 2014 +0400
+++ b/jdk/src/share/classes/java/awt/EventQueue.java	Fri Jun 06 14:52:07 2014 +0400
@@ -214,6 +214,11 @@
                                             FwDispatcher dispatcher) {
                     eventQueue.setFwDispatcher(dispatcher);
                 }
+
+                @Override
+                public long getMostRecentEventTime(EventQueue eventQueue) {
+                    return eventQueue.getMostRecentEventTimeImpl();
+                }
             });
     }
 
--- a/jdk/src/share/classes/java/awt/event/InputMethodEvent.java	Fri Jun 06 13:52:49 2014 +0400
+++ b/jdk/src/share/classes/java/awt/event/InputMethodEvent.java	Fri Jun 06 14:52:07 2014 +0400
@@ -25,6 +25,10 @@
 
 package java.awt.event;
 
+import sun.awt.AWTAccessor;
+import sun.awt.AppContext;
+import sun.awt.SunToolkit;
+
 import java.awt.AWTEvent;
 import java.awt.Component;
 import java.awt.EventQueue;
@@ -217,8 +221,10 @@
     public InputMethodEvent(Component source, int id,
             AttributedCharacterIterator text, int committedCharacterCount,
             TextHitInfo caret, TextHitInfo visiblePosition) {
-        this(source, id, EventQueue.getMostRecentEventTime(), text,
-             committedCharacterCount, caret, visiblePosition);
+        this(source, id,
+                getMostRecentEventTimeForSource(source),
+                text, committedCharacterCount,
+                caret, visiblePosition);
     }
 
     /**
@@ -258,8 +264,9 @@
      */
     public InputMethodEvent(Component source, int id, TextHitInfo caret,
             TextHitInfo visiblePosition) {
-        this(source, id, EventQueue.getMostRecentEventTime(), null,
-             0, caret, visiblePosition);
+        this(source, id,
+                getMostRecentEventTimeForSource(source),
+                null, 0, caret, visiblePosition);
     }
 
     /**
@@ -411,7 +418,25 @@
     private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
         s.defaultReadObject();
         if (when == 0) {
-            when = EventQueue.getMostRecentEventTime();
+            when = getMostRecentEventTimeForSource(this.source);
         }
     }
+
+    /**
+     * Get the most recent event time in the {@code EventQueue} which the {@code source}
+     * belongs to.
+     *
+     * @param source the source of the event
+     * @exception  IllegalArgumentException  if source is null.
+     * @return most recent event time in the {@code EventQueue}
+     */
+    private static long getMostRecentEventTimeForSource(Object source) {
+        if (source == null) {
+            // throw the IllegalArgumentException to conform to EventObject spec
+            throw new IllegalArgumentException("null source");
+        }
+        AppContext appContext = SunToolkit.targetToAppContext(source);
+        EventQueue eventQueue = SunToolkit.getSystemEventQueueImplPP(appContext);
+        return AWTAccessor.getEventQueueAccessor().getMostRecentEventTime(eventQueue);
+    }
 }
--- a/jdk/src/share/classes/sun/awt/AWTAccessor.java	Fri Jun 06 13:52:49 2014 +0400
+++ b/jdk/src/share/classes/sun/awt/AWTAccessor.java	Fri Jun 06 14:52:07 2014 +0400
@@ -530,7 +530,12 @@
         /**
          * Sets the delegate for the EventQueue used by FX/AWT single threaded mode
          */
-        public void setFwDispatcher(EventQueue eventQueue, FwDispatcher dispatcher);
+        void setFwDispatcher(EventQueue eventQueue, FwDispatcher dispatcher);
+
+        /**
+         * Gets most recent event time in the EventQueue
+         */
+        long getMostRecentEventTime(EventQueue eventQueue);
     }
 
     /*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/awt/im/8041990/bug8041990.java	Fri Jun 06 14:52:07 2014 +0400
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+
+/*
+  @test
+  @bug 8041990
+  @summary Language specific keys does not work in applets when opened outside the browser
+  @author Petr Pchelko
+*/
+
+import sun.awt.SunToolkit;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.InputMethodEvent;
+import java.awt.font.TextHitInfo;
+import java.text.AttributedString;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
+
+public class bug8041990 {
+    private static JFrame frame;
+    private static JComponent component;
+
+    public static void main(String[] args) throws Exception {
+        ThreadGroup stubTG = new ThreadGroup(getRootThreadGroup(), "Stub Thread Group");
+        ThreadGroup swingTG = new ThreadGroup(getRootThreadGroup(), "SwingTG");
+        try {
+            Thread stubThread = new Thread(stubTG, SunToolkit::createNewAppContext);
+            stubThread.start();
+            stubThread.join();
+
+            CountDownLatch startSwingLatch = new CountDownLatch(1);
+            new Thread(swingTG, () -> {
+                SunToolkit.createNewAppContext();
+                SwingUtilities.invokeLater(() -> {
+                    frame = new JFrame();
+                    component = new JLabel("Test Text");
+                    frame.add(component);
+                    frame.setBounds(100, 100, 100, 100);
+                    frame.setVisible(true);
+                    startSwingLatch.countDown();
+                });
+            }).start();
+            startSwingLatch.await();
+
+            AtomicReference<Exception> caughtException = new AtomicReference<>();
+            Thread checkThread = new Thread(getRootThreadGroup(), () -> {
+                try {
+                    // If the bug is present this will throw exception
+                    new InputMethodEvent(component,
+                            InputMethodEvent.CARET_POSITION_CHANGED,
+                            TextHitInfo.leading(0),
+                            TextHitInfo.trailing(0));
+                } catch (Exception e) {
+                    caughtException.set(e);
+                }
+            });
+            checkThread.start();
+            checkThread.join();
+
+            if (caughtException.get() != null) {
+                throw new RuntimeException("Failed. Caught exception!", caughtException.get());
+            }
+        } finally {
+            new Thread(swingTG, () -> SwingUtilities.invokeLater(() -> {
+                if (frame != null) {
+                    frame.dispose();
+                }
+            })).start();
+        }
+    }
+
+    private static ThreadGroup getRootThreadGroup() {
+        ThreadGroup currentTG = Thread.currentThread().getThreadGroup();
+        ThreadGroup parentTG = currentTG.getParent();
+        while (parentTG != null) {
+            currentTG = parentTG;
+            parentTG = currentTG.getParent();
+        }
+        return currentTG;
+    }
+}