diff --git a/src/share/classes/java/awt/Dialog.java b/src/share/classes/java/awt/Dialog.java index 71b08d7226d838fc6880ac8fc2f3fd90eda4d4b6..3e2effd1dc059733f7af891f5a03547bc517b1d2 100644 --- a/src/share/classes/java/awt/Dialog.java +++ b/src/share/classes/java/awt/Dialog.java @@ -277,10 +277,8 @@ public class Dialog extends Window { */ String title; - private transient volatile boolean keepBlockingEDT = false; - private transient volatile boolean keepBlockingCT = false; - private transient ModalEventFilter modalFilter; + private transient volatile SecondaryLoop secondaryLoop; /* * Indicates that this dialog is being hidden. This flag is set to true at @@ -1005,12 +1003,6 @@ public class Dialog extends Window { super.setVisible(b); } - /** - * Stores the app context on which event dispatch thread the dialog - * is being shown. Initialized in show(), used in hideAndDisposeHandler() - */ - transient private AppContext showAppContext; - /** * Makes the {@code Dialog} visible. If the dialog and/or its owner * are not yet displayable, both are made displayable. The @@ -1037,39 +1029,18 @@ public class Dialog extends Window { if (!isModal()) { conditionalShow(null, null); } else { - // Set this variable before calling conditionalShow(). That - // way, if the Dialog is hidden right after being shown, we - // won't mistakenly block this thread. - keepBlockingEDT = true; - keepBlockingCT = true; - - // Store the app context on which this dialog is being shown. - // Event dispatch thread of this app context will be sleeping until - // we wake it by any event from hideAndDisposeHandler(). - showAppContext = AppContext.getAppContext(); + AppContext showAppContext = AppContext.getAppContext(); AtomicLong time = new AtomicLong(); Component predictedFocusOwner = null; try { predictedFocusOwner = getMostRecentFocusOwner(); if (conditionalShow(predictedFocusOwner, time)) { - // We have two mechanisms for blocking: 1. If we're on the - // EventDispatchThread, start a new event pump. 2. If we're - // on any other thread, call wait() on the treelock. - modalFilter = ModalEventFilter.createFilterForDialog(this); - - final Runnable pumpEventsForFilter = new Runnable() { - public void run() { - EventDispatchThread dispatchThread = - (EventDispatchThread)Thread.currentThread(); - dispatchThread.pumpEventsForFilter(new Conditional() { - public boolean evaluate() { - synchronized (getTreeLock()) { - return keepBlockingEDT && windowClosingException == null; - } - } - }, modalFilter); + Conditional cond = new Conditional() { + @Override + public boolean evaluate() { + return windowClosingException == null; } }; @@ -1096,44 +1067,10 @@ public class Dialog extends Window { modalityPushed(); try { - if (EventQueue.isDispatchThread()) { - /* - * dispose SequencedEvent we are dispatching on current - * AppContext, to prevent us from hang. - * - */ - // BugId 4531693 (son@sparc.spb.su) - SequencedEvent currentSequencedEvent = KeyboardFocusManager. - getCurrentKeyboardFocusManager().getCurrentSequencedEvent(); - if (currentSequencedEvent != null) { - currentSequencedEvent.dispose(); - } - - /* - * Event processing is done inside doPrivileged block so that - * it wouldn't matter even if user code is on the stack - * Fix for BugId 6300270 - */ - - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { - pumpEventsForFilter.run(); - return null; - } - }); - } else { - synchronized (getTreeLock()) { - Toolkit.getEventQueue().postEvent(new PeerEvent(this, - pumpEventsForFilter, - PeerEvent.PRIORITY_EVENT)); - while (keepBlockingCT && windowClosingException == null) { - try { - getTreeLock().wait(); - } catch (InterruptedException e) { - break; - } - } - } + EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue(); + secondaryLoop = eventQueue.createSecondaryLoop(cond, modalFilter, 5000); + if (!secondaryLoop.enter()) { + secondaryLoop = null; } } finally { modalityPopped(); @@ -1194,18 +1131,11 @@ public class Dialog extends Window { windowClosingException = null; } } - final class WakingRunnable implements Runnable { - public void run() { - synchronized (getTreeLock()) { - keepBlockingCT = false; - getTreeLock().notifyAll(); - } - } - } + private void hideAndDisposePreHandler() { isInHide = true; synchronized (getTreeLock()) { - if (keepBlockingEDT) { + if (secondaryLoop != null) { modalHide(); // dialog can be shown and then disposed before its // modal filter is created @@ -1217,20 +1147,9 @@ public class Dialog extends Window { } } private void hideAndDisposeHandler() { - synchronized (getTreeLock()) { - if (keepBlockingEDT) { - keepBlockingEDT = false; - PeerEvent wakingEvent = new PeerEvent(getToolkit(), new WakingRunnable(), PeerEvent.PRIORITY_EVENT); - AppContext curAppContext = AppContext.getAppContext(); - if (showAppContext != curAppContext) { - // Wake up event dispatch thread on which the dialog was - // initially shown - SunToolkit.postEvent(showAppContext, wakingEvent); - showAppContext = null; - } else { - Toolkit.getEventQueue().postEvent(wakingEvent); - } - } + if (secondaryLoop != null) { + secondaryLoop.exit(); + secondaryLoop = null; } isInHide = false; } diff --git a/src/share/classes/java/awt/EventDispatchThread.java b/src/share/classes/java/awt/EventDispatchThread.java index eed2c16e514281a8c24c6c307bae8bae932db043..b47c3686e81b7110cbe59457531d1960cd7e02cf 100644 --- a/src/share/classes/java/awt/EventDispatchThread.java +++ b/src/share/classes/java/awt/EventDispatchThread.java @@ -113,8 +113,7 @@ class EventDispatchThread extends Thread { pumpEventsForHierarchy(id, cond, null); } - void pumpEventsForHierarchy(int id, Conditional cond, Component modalComponent) - { + void pumpEventsForHierarchy(int id, Conditional cond, Component modalComponent) { pumpEventsForFilter(id, cond, new HierarchyEventFilter(modalComponent)); } @@ -124,6 +123,7 @@ class EventDispatchThread extends Thread { void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) { addEventFilter(filter); + doDispatch = true; while (doDispatch && cond.evaluate()) { if (isInterrupted() || !pumpOneEventForFilters(id)) { doDispatch = false; @@ -133,6 +133,7 @@ class EventDispatchThread extends Thread { } void addEventFilter(EventFilter filter) { + eventLog.finest("adding the event filter: " + filter); synchronized (eventFilters) { if (!eventFilters.contains(filter)) { if (filter instanceof ModalEventFilter) { @@ -156,6 +157,7 @@ class EventDispatchThread extends Thread { } void removeEventFilter(EventFilter filter) { + eventLog.finest("removing the event filter: " + filter); synchronized (eventFilters) { eventFilters.remove(filter); } diff --git a/src/share/classes/java/awt/EventQueue.java b/src/share/classes/java/awt/EventQueue.java index 86c68e8b5c7f353525774a087b4c40fcaee2f86f..ffda53b69e7567f97125195984d830a76beddb7a 100644 --- a/src/share/classes/java/awt/EventQueue.java +++ b/src/share/classes/java/awt/EventQueue.java @@ -883,6 +883,41 @@ public class EventQueue { } } + /** + * Creates a new {@code secondary loop} associated with this + * event queue. Use the {@link SecondaryLoop#enter} and + * {@link SecondaryLoop#exit} methods to start and stop the + * event loop and dispatch the events from this queue. + * + * @return secondaryLoop A new secondary loop object, which can + * be used to launch a new nested event + * loop and dispatch events from this queue + * + * @see SecondaryLoop#enter + * @see SecondaryLoop#exit + * + * @since 1.7 + */ + public SecondaryLoop createSecondaryLoop() { + return createSecondaryLoop(null, null, 0); + } + + SecondaryLoop createSecondaryLoop(Conditional cond, EventFilter filter, long interval) { + pushPopLock.lock(); + try { + if (nextQueue != null) { + // Forward the request to the top of EventQueue stack + return nextQueue.createSecondaryLoop(cond, filter, interval); + } + if (dispatchThread == null) { + initDispatchThread(); + } + return new WaitDispatchSupport(dispatchThread, cond, filter, interval); + } finally { + pushPopLock.unlock(); + } + } + /** * Returns true if the calling thread is * {@link Toolkit#getSystemEventQueue the current AWT EventQueue}'s diff --git a/src/share/classes/java/awt/SecondaryLoop.java b/src/share/classes/java/awt/SecondaryLoop.java new file mode 100644 index 0000000000000000000000000000000000000000..844efc85261547d82facb22bb42075a1e4936658 --- /dev/null +++ b/src/share/classes/java/awt/SecondaryLoop.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2010, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package java.awt; + +/** + * A helper interface to run the nested event loop. + *
+ * Objects that implement this interface are created with the + * {@link EventQueue#createSecondaryLoop} method. The interface + * provides two methods, {@link enter} and {@link exit}, + * which can be used to start and stop the event loop. + *
+ * When the {@link enter} method is called, the current + * thread is blocked until the loop is terminated by the + * {@link exit} method. Also, a new event loop is started + * on the event dispatch thread, which may or may not be + * the current thread. The loop can be terminated on any + * thread by calling its {@link exit} method. After the + * loop is terminated, the {@code SecondaryLoop} object can + * be reused to run a new nested event loop. + *
+ * A typical use case of applying this interface is AWT + * and Swing modal dialogs. When a modal dialog is shown on + * the event dispatch thread, it enters a new secondary loop. + * Later, when the dialog is hidden or disposed, it exits + * the loop, and the thread continues its execution. + *
+ * The following example illustrates a simple use case of + * secondary loops: + * + *
+ * SecondaryLoop loop; + * + * JButton jButton = new JButton("Button"); + * jButton.addActionListener(new ActionListener() { + * {@code @Override} + * public void actionPerformed(ActionEvent e) { + * Toolkit tk = Toolkit.getDefaultToolkit(); + * EventQueue eq = tk.getSystemEventQueue(); + * loop = eq.createSecondaryLoop(); + * + * // Spawn a new thread to do the work + * Thread worker = new WorkerThread(); + * worker.start(); + * + * // Enter the loop to block the current event + * // handler, but leave UI responsive + * if (!loop.enter()) { + * // Report an error + * } + * } + * }); + * + * class WorkerThread extends Thread { + * {@code @Override} + * public void run() { + * // Perform calculations + * doSomethingUseful(); + * + * // Exit the loop + * loop.exit(); + * } + * } + *+ * + * @see Dialog#show + * @see EventQueue#createSecondaryLoop + * @see Toolkit#getSystemEventQueue + * + * @author Anton Tarasov, Artem Ananiev + * + * @since 1.7 + */ +public interface SecondaryLoop { + + /** + * Blocks the execution of the current thread and enters a new + * secondary event loop on the event dispatch thread. + *
+ * This method can be called by any thread including the event + * dispatch thread. This thread will be blocked until the {@link + * exit} method is called or the loop is terminated. A new + * secondary loop will be created on the event dispatch thread + * for dispatching events in either case. + *
+ * This method can only start one new event loop at a time per + * object. If a secondary event loop has already been started + * by this object and is currently still running, this method + * returns {@code false} to indicate that it was not successful + * in starting a new event loop. Otherwise, this method blocks + * the calling thread and later returns {@code true} when the + * new event loop is terminated. At such time, this object can + * again be used to start another new event loop. + * + * @return {@code true} after termination of the secondary loop, + * if the secondary loop was started by this call, + * {@code false} otherwise + */ + public boolean enter(); + + /** + * Unblocks the execution of the thread blocked by the {@link + * enter} method and exits the secondary loop. + *
+ * This method resumes the thread that called the {@link enter} + * method and exits the secondary loop that was created when + * the {@link enter} method was invoked. + *
+ * Note that if any other secondary loop is started while this + * loop is running, the blocked thread will not resume execution + * until the nested loop is terminated. + *
+ * If this secondary loop has not been started with the {@link + * enter} method, or this secondary loop has already finished + * with the {@link exit} method, this method returns {@code + * false}, otherwise {@code true} is returned. + * + * @return {@code true} if this loop was previously started and + * has not yet been finished with the {@link exit} method, + * {@code false} otherwise + */ + public boolean exit(); + +} diff --git a/src/share/classes/java/awt/WaitDispatchSupport.java b/src/share/classes/java/awt/WaitDispatchSupport.java new file mode 100644 index 0000000000000000000000000000000000000000..bf77fa73a62dcc34f8733d3c6d68b460f279d80c --- /dev/null +++ b/src/share/classes/java/awt/WaitDispatchSupport.java @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2010, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +package java.awt; + +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.atomic.AtomicBoolean; + +import java.security.PrivilegedAction; +import java.security.AccessController; + +import sun.awt.PeerEvent; + +import sun.util.logging.PlatformLogger; + +/** + * This utility class is used to suspend execution on a thread + * while still allowing {@code EventDispatchThread} to dispatch events. + * The API methods of the class are thread-safe. + * + * @author Anton Tarasov, Artem Ananiev + * + * @since 1.7 + */ +class WaitDispatchSupport implements SecondaryLoop { + + private final static PlatformLogger log = + PlatformLogger.getLogger("java.awt.event.WaitDispatchSupport"); + + private EventDispatchThread dispatchThread; + private EventFilter filter; + + private volatile Conditional extCondition; + private volatile Conditional condition; + + private long interval; + // Use a shared daemon timer to serve all the WaitDispatchSupports + private static Timer timer; + // When this WDS expires, we cancel the timer task leaving the + // shared timer up and running + private TimerTask timerTask; + + private AtomicBoolean keepBlockingEDT = new AtomicBoolean(false); + private AtomicBoolean keepBlockingCT = new AtomicBoolean(false); + + private static synchronized void initializeTimer() { + if (timer == null) { + timer = new Timer("AWT-WaitDispatchSupport-Timer", true); + } + } + + /** + * Creates a {@code WaitDispatchSupport} instance to + * serve the given event dispatch thread. + * + * @param dispatchThread An event dispatch thread that + * should not stop dispatching events while waiting + * + * @since 1.7 + */ + public WaitDispatchSupport(EventDispatchThread dispatchThread) { + this(dispatchThread, null); + } + + /** + * Creates a {@code WaitDispatchSupport} instance to + * serve the given event dispatch thread. + * + * @param dispatchThread An event dispatch thread that + * should not stop dispatching events while waiting + * @param extCondition A conditional object used to determine + * if the loop should be terminated + * + * @since 1.7 + */ + public WaitDispatchSupport(EventDispatchThread dispatchThread, + Conditional extCond) + { + if (dispatchThread == null) { + throw new IllegalArgumentException("The dispatchThread can not be null"); + } + + this.dispatchThread = dispatchThread; + this.extCondition = extCond; + this.condition = new Conditional() { + @Override + public boolean evaluate() { + if (log.isLoggable(PlatformLogger.FINEST)) { + log.finest("evaluate(): blockingEDT=" + keepBlockingEDT.get() + + ", blockingCT=" + keepBlockingCT.get()); + } + boolean extEvaluate = + (extCondition != null) ? extCondition.evaluate() : true; + if (!keepBlockingEDT.get() || !extEvaluate) { + if (timerTask != null) { + timerTask.cancel(); + timerTask = null; + } + return false; + } + return true; + } + }; + } + + /** + * Creates a {@code WaitDispatchSupport} instance to + * serve the given event dispatch thread. + *
+ * The {@link EventFilter} is set on the {@code dispatchThread} + * while waiting. The filter is removed on completion of the + * waiting process. + *
+ *
+ *
+ * @param dispatchThread An event dispatch thread that
+ * should not stop dispatching events while waiting
+ * @param filter {@code EventFilter} to be set
+ * @param interval A time interval to wait for. Note that
+ * when the waiting process takes place on EDT
+ * there is no guarantee to stop it in the given time
+ *
+ * @since 1.7
+ */
+ public WaitDispatchSupport(EventDispatchThread dispatchThread,
+ Conditional extCondition,
+ EventFilter filter, long interval)
+ {
+ this(dispatchThread, extCondition);
+ this.filter = filter;
+ if (interval < 0) {
+ throw new IllegalArgumentException("The interval value must be >= 0");
+ }
+ this.interval = interval;
+ if (interval != 0) {
+ initializeTimer();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ @Override
+ public boolean enter() {
+ log.fine("enter(): blockingEDT=" + keepBlockingEDT.get() +
+ ", blockingCT=" + keepBlockingCT.get());
+
+ if (!keepBlockingEDT.compareAndSet(false, true)) {
+ log.fine("The secondary loop is already running, aborting");
+ return false;
+ }
+
+ final Runnable run = new Runnable() {
+ public void run() {
+ log.fine("Starting a new event pump");
+ if (filter == null) {
+ dispatchThread.pumpEvents(condition);
+ } else {
+ dispatchThread.pumpEventsForFilter(condition, filter);
+ }
+ }
+ };
+
+ // We have two mechanisms for blocking: if we're on the
+ // dispatch thread, start a new event pump; if we're
+ // on any other thread, call wait() on the treelock
+
+ Thread currentThread = Thread.currentThread();
+ if (currentThread == dispatchThread) {
+ log.finest("On dispatch thread: " + dispatchThread);
+ if (interval != 0) {
+ log.finest("scheduling the timer for " + interval + " ms");
+ timer.schedule(timerTask = new TimerTask() {
+ @Override
+ public void run() {
+ if (keepBlockingEDT.compareAndSet(true, false)) {
+ wakeupEDT();
+ }
+ }
+ }, interval);
+ }
+ // Dispose SequencedEvent we are dispatching on the the current
+ // AppContext, to prevent us from hang - see 4531693 for details
+ SequencedEvent currentSE = KeyboardFocusManager.
+ getCurrentKeyboardFocusManager().getCurrentSequencedEvent();
+ if (currentSE != null) {
+ log.fine("Dispose current SequencedEvent: " + currentSE);
+ currentSE.dispose();
+ }
+ // In case the exit() method is called before starting
+ // new event pump it will post the waking event to EDT.
+ // The event will be handled after the the new event pump
+ // starts. Thus, the enter() method will not hang.
+ //
+ // Event pump should be privileged. See 6300270.
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ run.run();
+ return null;
+ }
+ });
+ } else {
+ log.finest("On non-dispatch thread: " + currentThread);
+ synchronized (getTreeLock()) {
+ if (filter != null) {
+ dispatchThread.addEventFilter(filter);
+ }
+ try {
+ EventQueue eq = dispatchThread.getEventQueue();
+ eq.postEvent(new PeerEvent(this, run, PeerEvent.PRIORITY_EVENT));
+ keepBlockingCT.set(true);
+ if (interval > 0) {
+ long currTime = System.currentTimeMillis();
+ while (keepBlockingCT.get() &&
+ ((extCondition != null) ? extCondition.evaluate() : true) &&
+ (currTime + interval > System.currentTimeMillis()))
+ {
+ getTreeLock().wait(interval);
+ }
+ } else {
+ while (keepBlockingCT.get() &&
+ ((extCondition != null) ? extCondition.evaluate() : true))
+ {
+ getTreeLock().wait();
+ }
+ }
+ log.fine("waitDone " + keepBlockingEDT.get() + " " + keepBlockingCT.get());
+ } catch (InterruptedException e) {
+ log.fine("Exception caught while waiting: " + e);
+ } finally {
+ if (filter != null) {
+ dispatchThread.removeEventFilter(filter);
+ }
+ }
+ // If the waiting process has been stopped because of the
+ // time interval passed or an exception occurred, the state
+ // should be changed
+ keepBlockingEDT.set(false);
+ keepBlockingCT.set(false);
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public boolean exit() {
+ log.fine("exit(): blockingEDT=" + keepBlockingEDT.get() +
+ ", blockingCT=" + keepBlockingCT.get());
+ if (keepBlockingEDT.compareAndSet(true, false)) {
+ wakeupEDT();
+ return true;
+ }
+ return false;
+ }
+
+ private final static Object getTreeLock() {
+ return Component.LOCK;
+ }
+
+ private final Runnable wakingRunnable = new Runnable() {
+ public void run() {
+ log.fine("Wake up EDT");
+ synchronized (getTreeLock()) {
+ keepBlockingCT.set(false);
+ getTreeLock().notifyAll();
+ }
+ log.fine("Wake up EDT done");
+ }
+ };
+
+ private void wakeupEDT() {
+ log.finest("wakeupEDT(): EDT == " + dispatchThread);
+ EventQueue eq = dispatchThread.getEventQueue();
+ eq.postEvent(new PeerEvent(this, wakingRunnable, PeerEvent.PRIORITY_EVENT));
+ }
+}
diff --git a/src/windows/native/sun/windows/awt_MenuItem.cpp b/src/windows/native/sun/windows/awt_MenuItem.cpp
index 67b2fa262a8caf4d866e3df64e20016812be1a88..6ed2a73d6afea7a5c9a2ce33ea595dcb7f361751 100644
--- a/src/windows/native/sun/windows/awt_MenuItem.cpp
+++ b/src/windows/native/sun/windows/awt_MenuItem.cpp
@@ -794,6 +794,11 @@ BOOL AwtMenuItem::IsSeparator() {
jobject jitem = GetTarget(env);
jstring label =
(jstring)(env)->GetObjectField(jitem, AwtMenuItem::labelID);
+ if (label == NULL) {
+ env->DeleteLocalRef(label);
+ env->DeleteLocalRef(jitem);
+ return FALSE; //separator must has '-' as label.
+ }
LPCWSTR labelW = JNU_GetStringPlatformChars(env, label, NULL);
BOOL isSeparator = (labelW && (wcscmp(labelW, L"-") == 0));
JNU_ReleaseStringPlatformChars(env, label, labelW);
diff --git a/src/windows/native/sun/windows/awt_TextComponent.h b/src/windows/native/sun/windows/awt_TextComponent.h
index 3a993742d118206725d8eaae2551103b1b50d436..7581c5c7aae673a8e93850cd607d1fef8257c879 100644
--- a/src/windows/native/sun/windows/awt_TextComponent.h
+++ b/src/windows/native/sun/windows/awt_TextComponent.h
@@ -113,8 +113,6 @@ public:
// Used to prevent untrusted code from synthesizing a WM_PASTE message
// by posting a