--- old/src/share/classes/java/awt/EventQueue.java 2014-06-06 14:42:27.000000000 +0400 +++ new/src/share/classes/java/awt/EventQueue.java 2014-06-06 14:42:26.000000000 +0400 @@ -214,6 +214,11 @@ FwDispatcher dispatcher) { eventQueue.setFwDispatcher(dispatcher); } + + @Override + public long getMostRecentEventTime(EventQueue eventQueue) { + return eventQueue.getMostRecentEventTimeImpl(); + } }); } --- old/src/share/classes/java/awt/event/InputMethodEvent.java 2014-06-06 14:42:27.000000000 +0400 +++ new/src/share/classes/java/awt/event/InputMethodEvent.java 2014-06-06 14:42:27.000000000 +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); } } --- old/src/share/classes/sun/awt/AWTAccessor.java 2014-06-06 14:42:28.000000000 +0400 +++ new/src/share/classes/sun/awt/AWTAccessor.java 2014-06-06 14:42:28.000000000 +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 2014-06-06 14:42:29.000000000 +0400 +++ new/test/java/awt/im/8041990/bug8041990.java 2014-06-06 14:42:29.000000000 +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 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; + } +}