blob: d4bead313602d3d7805795b8af74a4a6ec546dd1 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
Sergey Bylokhov33c5b922015-06-29 01:27:08 +03002 * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
J. Duke319a3b92007-12-01 00:00:00 +00003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07007 * published by the Free Software Foundation. Oracle designates this
J. Duke319a3b92007-12-01 00:00:00 +00008 * particular file as subject to the "Classpath" exception as provided
Kelly O'Hairfe008ae2010-05-25 15:58:33 -07009 * by Oracle in the LICENSE file that accompanied this code.
J. Duke319a3b92007-12-01 00:00:00 +000010 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
Kelly O'Hairfe008ae2010-05-25 15:58:33 -070021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
J. Duke319a3b92007-12-01 00:00:00 +000024 */
25
26package java.awt;
27
J. Duke319a3b92007-12-01 00:00:00 +000028import java.awt.event.MouseEvent;
29import java.awt.event.ActionEvent;
30import java.awt.event.WindowEvent;
J. Duke319a3b92007-12-01 00:00:00 +000031
Clemens Eisserer20558b32011-09-26 17:59:52 +040032import java.util.ArrayList;
Sergey Bylokhov78119062015-04-03 17:17:36 +030033
Mandy Chungfc0fc962009-09-29 16:03:03 -070034import sun.util.logging.PlatformLogger;
J. Duke319a3b92007-12-01 00:00:00 +000035
36import sun.awt.dnd.SunDragSourceContextPeer;
37
38/**
39 * EventDispatchThread is a package-private AWT class which takes
40 * events off the EventQueue and dispatches them to the appropriate
41 * AWT components.
42 *
43 * The Thread starts a "permanent" event pump with a call to
44 * pumpEvents(Conditional) in its run() method. Event handlers can choose to
45 * block this event pump at any time, but should start a new pump (<b>not</b>
46 * a new EventDispatchThread) by again calling pumpEvents(Conditional). This
Pavel Rappo8be77ee2014-09-17 16:14:12 +040047 * secondary event pump will exit automatically as soon as the Conditional
J. Duke319a3b92007-12-01 00:00:00 +000048 * evaluate()s to false and an additional Event is pumped and dispatched.
49 *
50 * @author Tom Ball
51 * @author Amy Fowler
52 * @author Fred Ecks
53 * @author David Mendenhall
54 *
55 * @since 1.1
56 */
Phil Race01b34482016-04-04 14:22:07 -070057class EventDispatchThread extends Thread {
Artem Ananiev983ec862010-07-06 17:59:56 +040058
Mandy Chungfc0fc962009-09-29 16:03:03 -070059 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventDispatchThread");
J. Duke319a3b92007-12-01 00:00:00 +000060
61 private EventQueue theQueue;
Oleg Pekhovskiyf888e842013-10-16 19:02:10 +040062 private volatile boolean doDispatch = true;
Artem Ananiev983ec862010-07-06 17:59:56 +040063
J. Duke319a3b92007-12-01 00:00:00 +000064 private static final int ANY_EVENT = -1;
65
Clemens Eisserer20558b32011-09-26 17:59:52 +040066 private ArrayList<EventFilter> eventFilters = new ArrayList<EventFilter>();
J. Duke319a3b92007-12-01 00:00:00 +000067
Phil Race01b34482016-04-04 14:22:07 -070068 /**
69 * Must always call 5 args super-class constructor passing false
70 * to indicate not to inherit locals.
71 */
72 private EventDispatchThread() {
73 throw new UnsupportedOperationException("Must erase locals");
74 }
75
J. Duke319a3b92007-12-01 00:00:00 +000076 EventDispatchThread(ThreadGroup group, String name, EventQueue queue) {
Phil Race01b34482016-04-04 14:22:07 -070077 super(group, null, name, 0, false);
Artem Ananiev983ec862010-07-06 17:59:56 +040078 setEventQueue(queue);
J. Duke319a3b92007-12-01 00:00:00 +000079 }
80
Artem Ananiev983ec862010-07-06 17:59:56 +040081 /*
82 * Must be called on EDT only, that's why no synchronization
83 */
J. Duke319a3b92007-12-01 00:00:00 +000084 public void stopDispatching() {
Artem Ananiev983ec862010-07-06 17:59:56 +040085 doDispatch = false;
J. Duke319a3b92007-12-01 00:00:00 +000086 }
87
88 public void run() {
Oleg Pekhovskiyf888e842013-10-16 19:02:10 +040089 try {
90 pumpEvents(new Conditional() {
91 public boolean evaluate() {
92 return true;
J. Duke319a3b92007-12-01 00:00:00 +000093 }
Oleg Pekhovskiyf888e842013-10-16 19:02:10 +040094 });
95 } finally {
96 getEventQueue().detachDispatchThread(this);
J. Duke319a3b92007-12-01 00:00:00 +000097 }
98 }
99
100 void pumpEvents(Conditional cond) {
101 pumpEvents(ANY_EVENT, cond);
102 }
103
104 void pumpEventsForHierarchy(Conditional cond, Component modalComponent) {
105 pumpEventsForHierarchy(ANY_EVENT, cond, modalComponent);
106 }
107
108 void pumpEvents(int id, Conditional cond) {
109 pumpEventsForHierarchy(id, cond, null);
110 }
111
Artem Ananiev28253f92010-08-24 12:54:46 +0400112 void pumpEventsForHierarchy(int id, Conditional cond, Component modalComponent) {
J. Duke319a3b92007-12-01 00:00:00 +0000113 pumpEventsForFilter(id, cond, new HierarchyEventFilter(modalComponent));
114 }
115
116 void pumpEventsForFilter(Conditional cond, EventFilter filter) {
117 pumpEventsForFilter(ANY_EVENT, cond, filter);
118 }
119
120 void pumpEventsForFilter(int id, Conditional cond, EventFilter filter) {
121 addEventFilter(filter);
Artem Ananiev28253f92010-08-24 12:54:46 +0400122 doDispatch = true;
Oleg Pekhovskiyf888e842013-10-16 19:02:10 +0400123 while (doDispatch && !isInterrupted() && cond.evaluate()) {
Clemens Eisserer20558b32011-09-26 17:59:52 +0400124 pumpOneEventForFilters(id);
J. Duke319a3b92007-12-01 00:00:00 +0000125 }
126 removeEventFilter(filter);
127 }
128
129 void addEventFilter(EventFilter filter) {
Chris Hegartya2e706f2013-06-17 14:09:25 +0100130 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
Laurent Bourges2e5ce052013-04-12 14:33:38 +0400131 eventLog.finest("adding the event filter: " + filter);
132 }
J. Duke319a3b92007-12-01 00:00:00 +0000133 synchronized (eventFilters) {
134 if (!eventFilters.contains(filter)) {
135 if (filter instanceof ModalEventFilter) {
136 ModalEventFilter newFilter = (ModalEventFilter)filter;
137 int k = 0;
138 for (k = 0; k < eventFilters.size(); k++) {
139 EventFilter f = eventFilters.get(k);
140 if (f instanceof ModalEventFilter) {
141 ModalEventFilter cf = (ModalEventFilter)f;
142 if (cf.compareTo(newFilter) > 0) {
143 break;
144 }
145 }
146 }
147 eventFilters.add(k, filter);
J. Duke319a3b92007-12-01 00:00:00 +0000148 } else {
149 eventFilters.add(filter);
150 }
151 }
152 }
153 }
154
155 void removeEventFilter(EventFilter filter) {
Chris Hegartya2e706f2013-06-17 14:09:25 +0100156 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
Laurent Bourges2e5ce052013-04-12 14:33:38 +0400157 eventLog.finest("removing the event filter: " + filter);
158 }
J. Duke319a3b92007-12-01 00:00:00 +0000159 synchronized (eventFilters) {
Artem Ananiev983ec862010-07-06 17:59:56 +0400160 eventFilters.remove(filter);
J. Duke319a3b92007-12-01 00:00:00 +0000161 }
162 }
163
Clemens Eisserer20558b32011-09-26 17:59:52 +0400164 void pumpOneEventForFilters(int id) {
Artem Ananiev983ec862010-07-06 17:59:56 +0400165 AWTEvent event = null;
166 boolean eventOK = false;
J. Duke319a3b92007-12-01 00:00:00 +0000167 try {
Artem Ananiev983ec862010-07-06 17:59:56 +0400168 EventQueue eq = null;
J. Duke319a3b92007-12-01 00:00:00 +0000169 do {
Artem Ananiev983ec862010-07-06 17:59:56 +0400170 // EventQueue may change during the dispatching
171 eq = getEventQueue();
Artem Ananiev983ec862010-07-06 17:59:56 +0400172
Petr Pchelko22b836a2014-06-23 22:15:09 +0400173 event = (id == ANY_EVENT) ? eq.getNextEvent() : eq.getNextEvent(id);
J. Duke319a3b92007-12-01 00:00:00 +0000174
175 eventOK = true;
176 synchronized (eventFilters) {
177 for (int i = eventFilters.size() - 1; i >= 0; i--) {
178 EventFilter f = eventFilters.get(i);
179 EventFilter.FilterAction accept = f.acceptEvent(event);
180 if (accept == EventFilter.FilterAction.REJECT) {
181 eventOK = false;
182 break;
183 } else if (accept == EventFilter.FilterAction.ACCEPT_IMMEDIATELY) {
184 break;
185 }
186 }
187 }
188 eventOK = eventOK && SunDragSourceContextPeer.checkEvent(event);
189 if (!eventOK) {
190 event.consume();
191 }
192 }
193 while (eventOK == false);
194
Chris Hegartya2e706f2013-06-17 14:09:25 +0100195 if (eventLog.isLoggable(PlatformLogger.Level.FINEST)) {
Mandy Chungfc0fc962009-09-29 16:03:03 -0700196 eventLog.finest("Dispatching: " + event);
J. Duke319a3b92007-12-01 00:00:00 +0000197 }
198
Artem Ananiev983ec862010-07-06 17:59:56 +0400199 eq.dispatchEvent(event);
J. Duke319a3b92007-12-01 00:00:00 +0000200 }
201 catch (ThreadDeath death) {
Oleg Pekhovskiyf888e842013-10-16 19:02:10 +0400202 doDispatch = false;
Clemens Eisserer20558b32011-09-26 17:59:52 +0400203 throw death;
J. Duke319a3b92007-12-01 00:00:00 +0000204 }
205 catch (InterruptedException interruptedException) {
Oleg Pekhovskiyf888e842013-10-16 19:02:10 +0400206 doDispatch = false; // AppContext.dispose() interrupts all
207 // Threads in the AppContext
J. Duke319a3b92007-12-01 00:00:00 +0000208 }
Artem Ananiev983ec862010-07-06 17:59:56 +0400209 catch (Throwable e) {
Artem Ananiev6b814bb2008-09-11 10:38:00 +0400210 processException(e);
J. Duke319a3b92007-12-01 00:00:00 +0000211 }
J. Duke319a3b92007-12-01 00:00:00 +0000212 }
213
Artem Ananiev6b814bb2008-09-11 10:38:00 +0400214 private void processException(Throwable e) {
Chris Hegartya2e706f2013-06-17 14:09:25 +0100215 if (eventLog.isLoggable(PlatformLogger.Level.FINE)) {
Mandy Chungfc0fc962009-09-29 16:03:03 -0700216 eventLog.fine("Processing exception: " + e);
J. Duke319a3b92007-12-01 00:00:00 +0000217 }
Artem Ananiev6b814bb2008-09-11 10:38:00 +0400218 getUncaughtExceptionHandler().uncaughtException(this, e);
J. Duke319a3b92007-12-01 00:00:00 +0000219 }
220
Artem Ananiev983ec862010-07-06 17:59:56 +0400221 public synchronized EventQueue getEventQueue() {
222 return theQueue;
J. Duke319a3b92007-12-01 00:00:00 +0000223 }
Artem Ananiev983ec862010-07-06 17:59:56 +0400224 public synchronized void setEventQueue(EventQueue eq) {
225 theQueue = eq;
226 }
J. Duke319a3b92007-12-01 00:00:00 +0000227
228 private static class HierarchyEventFilter implements EventFilter {
229 private Component modalComponent;
230 public HierarchyEventFilter(Component modalComponent) {
231 this.modalComponent = modalComponent;
232 }
233 public FilterAction acceptEvent(AWTEvent event) {
234 if (modalComponent != null) {
235 int eventID = event.getID();
236 boolean mouseEvent = (eventID >= MouseEvent.MOUSE_FIRST) &&
237 (eventID <= MouseEvent.MOUSE_LAST);
238 boolean actionEvent = (eventID >= ActionEvent.ACTION_FIRST) &&
239 (eventID <= ActionEvent.ACTION_LAST);
240 boolean windowClosingEvent = (eventID == WindowEvent.WINDOW_CLOSING);
241 /*
242 * filter out MouseEvent and ActionEvent that's outside
243 * the modalComponent hierarchy.
244 * KeyEvent is handled by using enqueueKeyEvent
245 * in Dialog.show
246 */
247 if (Component.isInstanceOf(modalComponent, "javax.swing.JInternalFrame")) {
248 /*
249 * Modal internal frames are handled separately. If event is
250 * for some component from another heavyweight than modalComp,
251 * it is accepted. If heavyweight is the same - we still accept
252 * event and perform further filtering in LightweightDispatcher
253 */
254 return windowClosingEvent ? FilterAction.REJECT : FilterAction.ACCEPT;
255 }
256 if (mouseEvent || actionEvent || windowClosingEvent) {
257 Object o = event.getSource();
258 if (o instanceof sun.awt.ModalExclude) {
259 // Exclude this object from modality and
260 // continue to pump it's events.
261 return FilterAction.ACCEPT;
262 } else if (o instanceof Component) {
263 Component c = (Component) o;
264 // 5.0u3 modal exclusion
265 boolean modalExcluded = false;
266 if (modalComponent instanceof Container) {
267 while (c != modalComponent && c != null) {
268 if ((c instanceof Window) &&
269 (sun.awt.SunToolkit.isModalExcluded((Window)c))) {
270 // Exclude this window and all its children from
271 // modality and continue to pump it's events.
272 modalExcluded = true;
273 break;
274 }
275 c = c.getParent();
276 }
277 }
278 if (!modalExcluded && (c != modalComponent)) {
279 return FilterAction.REJECT;
280 }
281 }
282 }
283 }
284 return FilterAction.ACCEPT;
285 }
286 }
287}