0N/A/*
3261N/A * Copyright (c) 1996, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage java.awt;
0N/A
0N/Aimport java.awt.event.InputEvent;
0N/Aimport java.awt.event.MouseEvent;
0N/Aimport java.awt.event.ActionEvent;
0N/Aimport java.awt.event.WindowEvent;
0N/Aimport java.lang.reflect.Method;
0N/Aimport java.security.AccessController;
0N/Aimport sun.security.action.GetPropertyAction;
0N/Aimport sun.awt.AWTAutoShutdown;
0N/Aimport sun.awt.SunToolkit;
4537N/Aimport sun.awt.AppContext;
0N/A
4537N/Aimport java.util.ArrayList;
4537N/Aimport java.util.List;
1696N/Aimport sun.util.logging.PlatformLogger;
0N/A
0N/Aimport sun.awt.dnd.SunDragSourceContextPeer;
617N/Aimport sun.awt.EventQueueDelegate;
0N/A
0N/A/**
0N/A * EventDispatchThread is a package-private AWT class which takes
0N/A * events off the EventQueue and dispatches them to the appropriate
0N/A * AWT components.
0N/A *
0N/A * The Thread starts a "permanent" event pump with a call to
0N/A * pumpEvents(Conditional) in its run() method. Event handlers can choose to
0N/A * block this event pump at any time, but should start a new pump (<b>not</b>
0N/A * a new EventDispatchThread) by again calling pumpEvents(Conditional). This
0N/A * secondary event pump will exit automatically as soon as the Condtional
0N/A * evaluate()s to false and an additional Event is pumped and dispatched.
0N/A *
0N/A * @author Tom Ball
0N/A * @author Amy Fowler
0N/A * @author Fred Ecks
0N/A * @author David Mendenhall
0N/A *
0N/A * @since 1.1
0N/A */
0N/Aclass EventDispatchThread extends Thread {
2518N/A
1696N/A private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
0N/A
0N/A private EventQueue theQueue;
5274N/A private volatile boolean doDispatch = true;
2518N/A
0N/A private static final int ANY_EVENT = -1;
0N/A
4537N/A private ArrayList<EventFilter> eventFilters = new ArrayList<EventFilter>();
0N/A
0N/A EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
0N/A super(group, name);
2518N/A setEventQueue(queue);
0N/A }
0N/A
2518N/A /*
2518N/A * Must be called on EDT only, that's why no synchronization
2518N/A */
0N/A public void stopDispatching() {
2518N/A doDispatch = false;
0N/A }
0N/A
0N/A public void run() {
2518N/A while (true) {
2518N/A try {
2518N/A pumpEvents(new Conditional() {
2518N/A public boolean evaluate() {
2518N/A return true;
2518N/A }
2518N/A });
2518N/A } finally {
5274N/A // 7189350: doDispatch is reset from stopDispatching(),
5274N/A // on InterruptedException, or ThreadDeath. Either way,
5274N/A // this indicates that we must force shutting down.
5274N/A if (getEventQueue().detachDispatchThread(this,
5274N/A !doDispatch || isInterrupted()))
5274N/A {
2518N/A break;
0N/A }
2518N/A }
0N/A }
0N/A }
0N/A
4632N/A // MacOSX change:
4632N/A // This was added because this class (and java.awt.Conditional) are package private.
4632N/A // There are certain instances where classes in other packages need to block the
4632N/A // AWTEventQueue while still allowing it to process events. This uses reflection
4632N/A // to call back into the caller in order to remove dependencies.
4632N/A //
4632N/A // NOTE: This uses reflection in its implementation, so it is not for performance critical code.
4632N/A //
4632N/A // cond is an instance of sun.lwawt.macosx.EventDispatchAccess
4632N/A //
4632N/A private Conditional _macosxGetConditional(final Object cond) {
4632N/A try {
4632N/A return new Conditional() {
4632N/A final Method evaluateMethod = Class.forName("sun.lwawt.macosx.EventDispatchAccess").getMethod("evaluate", null);
4632N/A public boolean evaluate() {
4632N/A try {
4632N/A return ((Boolean)evaluateMethod.invoke(cond, null)).booleanValue();
4632N/A } catch (Exception e) {
4632N/A return false;
4632N/A }
4632N/A }
4632N/A };
4632N/A } catch (Exception e) {
4632N/A return new Conditional() { public boolean evaluate() { return false; } };
4632N/A }
4632N/A }
4632N/A
4632N/A
0N/A void pumpEvents(Conditional cond) {
0N/A pumpEvents(ANY_EVENT, cond);
0N/A }
0N/A
0N/A void pumpEventsForHierarchy(Conditional cond, Component modalComponent) {
0N/A pumpEventsForHierarchy(ANY_EVENT, cond, modalComponent);
0N/A }
0N/A
0N/A void pumpEvents(int id, Conditional cond) {
0N/A pumpEventsForHierarchy(id, cond, null);
0N/A }
0N/A
2695N/A void pumpEventsForHierarchy(int id, Conditional cond, Component modalComponent) {
0N/A pumpEventsForFilter(id, cond, new HierarchyEventFilter(modalComponent));
0N/A }
0N/A
0N/A void pumpEventsForFilter(Conditional cond, EventFilter filter) {
0N/A pumpEventsForFilter(ANY_EVENT, cond, filter);
0N/A }
0N/A
0N/A void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {
0N/A addEventFilter(filter);
2695N/A doDispatch = true;
5274N/A while (doDispatch && !isInterrupted() && cond.evaluate()) {
4537N/A pumpOneEventForFilters(id);
0N/A }
0N/A removeEventFilter(filter);
0N/A }
0N/A
0N/A void addEventFilter(EventFilter filter) {
2695N/A eventLog.finest("adding the event filter: " + filter);
0N/A synchronized (eventFilters) {
0N/A if (!eventFilters.contains(filter)) {
0N/A if (filter instanceof ModalEventFilter) {
0N/A ModalEventFilter newFilter = (ModalEventFilter)filter;
0N/A int k = 0;
0N/A for (k = 0; k < eventFilters.size(); k++) {
0N/A EventFilter f = eventFilters.get(k);
0N/A if (f instanceof ModalEventFilter) {
0N/A ModalEventFilter cf = (ModalEventFilter)f;
0N/A if (cf.compareTo(newFilter) > 0) {
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A eventFilters.add(k, filter);
0N/A } else {
0N/A eventFilters.add(filter);
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A void removeEventFilter(EventFilter filter) {
2695N/A eventLog.finest("removing the event filter: " + filter);
0N/A synchronized (eventFilters) {
2518N/A eventFilters.remove(filter);
0N/A }
0N/A }
0N/A
4537N/A void pumpOneEventForFilters(int id) {
2518N/A AWTEvent event = null;
2518N/A boolean eventOK = false;
0N/A try {
2518N/A EventQueue eq = null;
2518N/A EventQueueDelegate.Delegate delegate = null;
0N/A do {
2518N/A // EventQueue may change during the dispatching
2518N/A eq = getEventQueue();
2518N/A delegate = EventQueueDelegate.getDelegate();
2518N/A
617N/A if (delegate != null && id == ANY_EVENT) {
2518N/A event = delegate.getNextEvent(eq);
617N/A } else {
2518N/A event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id);
617N/A }
0N/A
0N/A eventOK = true;
0N/A synchronized (eventFilters) {
0N/A for (int i = eventFilters.size() - 1; i >= 0; i--) {
0N/A EventFilter f = eventFilters.get(i);
0N/A EventFilter.FilterAction accept = f.acceptEvent(event);
0N/A if (accept == EventFilter.FilterAction.REJECT) {
0N/A eventOK = false;
0N/A break;
0N/A } else if (accept == EventFilter.FilterAction.ACCEPT_IMMEDIATELY) {
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A eventOK = eventOK && SunDragSourceContextPeer.checkEvent(event);
0N/A if (!eventOK) {
0N/A event.consume();
0N/A }
0N/A }
0N/A while (eventOK == false);
0N/A
1696N/A if (eventLog.isLoggable(PlatformLogger.FINEST)) {
1696N/A eventLog.finest("Dispatching: " + event);
0N/A }
0N/A
617N/A Object handle = null;
617N/A if (delegate != null) {
617N/A handle = delegate.beforeDispatch(event);
617N/A }
2518N/A eq.dispatchEvent(event);
617N/A if (delegate != null) {
617N/A delegate.afterDispatch(event, handle);
617N/A }
0N/A }
0N/A catch (ThreadDeath death) {
5274N/A doDispatch = false;
4537N/A throw death;
0N/A }
0N/A catch (InterruptedException interruptedException) {
5274N/A doDispatch = false; // AppContext.dispose() interrupts all
5274N/A // Threads in the AppContext
0N/A }
2518N/A catch (Throwable e) {
869N/A processException(e);
0N/A }
0N/A }
0N/A
869N/A private void processException(Throwable e) {
1696N/A if (eventLog.isLoggable(PlatformLogger.FINE)) {
1696N/A eventLog.fine("Processing exception: " + e);
0N/A }
869N/A getUncaughtExceptionHandler().uncaughtException(this, e);
0N/A }
0N/A
2518N/A public synchronized EventQueue getEventQueue() {
2518N/A return theQueue;
0N/A }
2518N/A public synchronized void setEventQueue(EventQueue eq) {
2518N/A theQueue = eq;
2518N/A }
0N/A
0N/A private static class HierarchyEventFilter implements EventFilter {
0N/A private Component modalComponent;
0N/A public HierarchyEventFilter(Component modalComponent) {
0N/A this.modalComponent = modalComponent;
0N/A }
0N/A public FilterAction acceptEvent(AWTEvent event) {
0N/A if (modalComponent != null) {
0N/A int eventID = event.getID();
0N/A boolean mouseEvent = (eventID >= MouseEvent.MOUSE_FIRST) &&
0N/A (eventID <= MouseEvent.MOUSE_LAST);
0N/A boolean actionEvent = (eventID >= ActionEvent.ACTION_FIRST) &&
0N/A (eventID <= ActionEvent.ACTION_LAST);
0N/A boolean windowClosingEvent = (eventID == WindowEvent.WINDOW_CLOSING);
0N/A /*
0N/A * filter out MouseEvent and ActionEvent that's outside
0N/A * the modalComponent hierarchy.
0N/A * KeyEvent is handled by using enqueueKeyEvent
0N/A * in Dialog.show
0N/A */
0N/A if (Component.isInstanceOf(modalComponent, "javax.swing.JInternalFrame")) {
0N/A /*
0N/A * Modal internal frames are handled separately. If event is
0N/A * for some component from another heavyweight than modalComp,
0N/A * it is accepted. If heavyweight is the same - we still accept
0N/A * event and perform further filtering in LightweightDispatcher
0N/A */
0N/A return windowClosingEvent ? FilterAction.REJECT : FilterAction.ACCEPT;
0N/A }
0N/A if (mouseEvent || actionEvent || windowClosingEvent) {
0N/A Object o = event.getSource();
0N/A if (o instanceof sun.awt.ModalExclude) {
0N/A // Exclude this object from modality and
0N/A // continue to pump it's events.
0N/A return FilterAction.ACCEPT;
0N/A } else if (o instanceof Component) {
0N/A Component c = (Component) o;
0N/A // 5.0u3 modal exclusion
0N/A boolean modalExcluded = false;
0N/A if (modalComponent instanceof Container) {
0N/A while (c != modalComponent && c != null) {
0N/A if ((c instanceof Window) &&
0N/A (sun.awt.SunToolkit.isModalExcluded((Window)c))) {
0N/A // Exclude this window and all its children from
0N/A // modality and continue to pump it's events.
0N/A modalExcluded = true;
0N/A break;
0N/A }
0N/A c = c.getParent();
0N/A }
0N/A }
0N/A if (!modalExcluded && (c != modalComponent)) {
0N/A return FilterAction.REJECT;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A return FilterAction.ACCEPT;
0N/A }
0N/A }
0N/A}