Path: blob/master/src/java.desktop/share/classes/java/awt/EventDispatchThread.java
41152 views
/*1* Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package java.awt;2627import java.awt.event.MouseEvent;28import java.awt.event.ActionEvent;29import java.awt.event.WindowEvent;3031import java.util.ArrayList;3233import sun.util.logging.PlatformLogger;3435import sun.awt.dnd.SunDragSourceContextPeer;3637/**38* EventDispatchThread is a package-private AWT class which takes39* events off the EventQueue and dispatches them to the appropriate40* AWT components.41*42* The Thread starts a "permanent" event pump with a call to43* pumpEvents(Conditional) in its run() method. Event handlers can choose to44* block this event pump at any time, but should start a new pump (<b>not</b>45* a new EventDispatchThread) by again calling pumpEvents(Conditional). This46* secondary event pump will exit automatically as soon as the Conditional47* evaluate()s to false and an additional Event is pumped and dispatched.48*49* @author Tom Ball50* @author Amy Fowler51* @author Fred Ecks52* @author David Mendenhall53*54* @since 1.155*/56class EventDispatchThread extends Thread {5758private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");5960private EventQueue theQueue;61private volatile boolean doDispatch = true;6263private static final int ANY_EVENT = -1;6465private ArrayList<EventFilter> eventFilters = new ArrayList<EventFilter>();6667/**68* Must always call 5 args super-class constructor passing false69* to indicate not to inherit locals.70*/71private EventDispatchThread() {72throw new UnsupportedOperationException("Must erase locals");73}7475EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {76super(group, null, name, 0, false);77setEventQueue(queue);78}7980/*81* Must be called on EDT only, that's why no synchronization82*/83public void stopDispatching() {84doDispatch = false;85}8687public void run() {88try {89pumpEvents(new Conditional() {90public boolean evaluate() {91return true;92}93});94} finally {95getEventQueue().detachDispatchThread(this);96}97}9899void pumpEvents(Conditional cond) {100pumpEvents(ANY_EVENT, cond);101}102103void pumpEventsForHierarchy(Conditional cond, Component modalComponent) {104pumpEventsForHierarchy(ANY_EVENT, cond, modalComponent);105}106107void pumpEvents(int id, Conditional cond) {108pumpEventsForHierarchy(id, cond, null);109}110111void pumpEventsForHierarchy(int id, Conditional cond, Component modalComponent) {112pumpEventsForFilter(id, cond, new HierarchyEventFilter(modalComponent));113}114115void pumpEventsForFilter(Conditional cond, EventFilter filter) {116pumpEventsForFilter(ANY_EVENT, cond, filter);117}118119void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {120addEventFilter(filter);121doDispatch = true;122while (doDispatch && !isInterrupted() && cond.evaluate()) {123pumpOneEventForFilters(id);124}125removeEventFilter(filter);126}127128void addEventFilter(EventFilter filter) {129if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {130eventLog.finest("adding the event filter: " + filter);131}132synchronized (eventFilters) {133if (!eventFilters.contains(filter)) {134if (filter instanceof ModalEventFilter) {135ModalEventFilter newFilter = (ModalEventFilter)filter;136int k = 0;137for (k = 0; k < eventFilters.size(); k++) {138EventFilter f = eventFilters.get(k);139if (f instanceof ModalEventFilter) {140ModalEventFilter cf = (ModalEventFilter)f;141if (cf.compareTo(newFilter) > 0) {142break;143}144}145}146eventFilters.add(k, filter);147} else {148eventFilters.add(filter);149}150}151}152}153154void removeEventFilter(EventFilter filter) {155if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {156eventLog.finest("removing the event filter: " + filter);157}158synchronized (eventFilters) {159eventFilters.remove(filter);160}161}162163boolean filterAndCheckEvent(AWTEvent event) {164boolean eventOK = true;165synchronized (eventFilters) {166for (int i = eventFilters.size() - 1; i >= 0; i--) {167EventFilter f = eventFilters.get(i);168EventFilter.FilterAction accept = f.acceptEvent(event);169if (accept == EventFilter.FilterAction.REJECT) {170eventOK = false;171break;172} else if (accept == EventFilter.FilterAction.ACCEPT_IMMEDIATELY) {173break;174}175}176}177return eventOK && SunDragSourceContextPeer.checkEvent(event);178}179180void pumpOneEventForFilters(int id) {181AWTEvent event = null;182boolean eventOK = false;183try {184EventQueue eq = null;185do {186// EventQueue may change during the dispatching187eq = getEventQueue();188189event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id);190191eventOK = filterAndCheckEvent(event);192if (!eventOK) {193event.consume();194}195}196while (eventOK == false);197198if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {199eventLog.finest("Dispatching: " + event);200}201202eq.dispatchEvent(event);203}204catch (ThreadDeath death) {205doDispatch = false;206throw death;207}208catch (InterruptedException interruptedException) {209doDispatch = false; // AppContext.dispose() interrupts all210// Threads in the AppContext211}212catch (Throwable e) {213processException(e);214}215}216217private void processException(Throwable e) {218if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {219eventLog.fine("Processing exception: " + e);220}221getUncaughtExceptionHandler().uncaughtException(this, e);222}223224public synchronized EventQueue getEventQueue() {225return theQueue;226}227public synchronized void setEventQueue(EventQueue eq) {228theQueue = eq;229}230231private static class HierarchyEventFilter implements EventFilter {232private Component modalComponent;233public HierarchyEventFilter(Component modalComponent) {234this.modalComponent = modalComponent;235}236public FilterAction acceptEvent(AWTEvent event) {237if (modalComponent != null) {238int eventID = event.getID();239boolean mouseEvent = (eventID >= MouseEvent.MOUSE_FIRST) &&240(eventID <= MouseEvent.MOUSE_LAST);241boolean actionEvent = (eventID >= ActionEvent.ACTION_FIRST) &&242(eventID <= ActionEvent.ACTION_LAST);243boolean windowClosingEvent = (eventID == WindowEvent.WINDOW_CLOSING);244/*245* filter out MouseEvent and ActionEvent that's outside246* the modalComponent hierarchy.247* KeyEvent is handled by using enqueueKeyEvent248* in Dialog.show249*/250if (Component.isInstanceOf(modalComponent, "javax.swing.JInternalFrame")) {251/*252* Modal internal frames are handled separately. If event is253* for some component from another heavyweight than modalComp,254* it is accepted. If heavyweight is the same - we still accept255* event and perform further filtering in LightweightDispatcher256*/257return windowClosingEvent ? FilterAction.REJECT : FilterAction.ACCEPT;258}259if (mouseEvent || actionEvent || windowClosingEvent) {260Object o = event.getSource();261if (o instanceof sun.awt.ModalExclude) {262// Exclude this object from modality and263// continue to pump it's events.264return FilterAction.ACCEPT;265} else if (o instanceof Component) {266Component c = (Component) o;267// 5.0u3 modal exclusion268boolean modalExcluded = false;269if (modalComponent instanceof Container) {270while (c != modalComponent && c != null) {271if ((c instanceof Window) &&272(sun.awt.SunToolkit.isModalExcluded((Window)c))) {273// Exclude this window and all its children from274// modality and continue to pump it's events.275modalExcluded = true;276break;277}278c = c.getParent();279}280}281if (!modalExcluded && (c != modalComponent)) {282return FilterAction.REJECT;283}284}285}286}287return FilterAction.ACCEPT;288}289}290}291292293