Source Code Cross Referenced for EventQueue.java in  » 6.0-JDK-Core » AWT » java » awt » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » AWT » java.awt 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001        /*
0002         * Copyright 1996-2007 Sun Microsystems, Inc.  All Rights Reserved.
0003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004         *
0005         * This code is free software; you can redistribute it and/or modify it
0006         * under the terms of the GNU General Public License version 2 only, as
0007         * published by the Free Software Foundation.  Sun designates this
0008         * particular file as subject to the "Classpath" exception as provided
0009         * by Sun in the LICENSE file that accompanied this code.
0010         *
0011         * This code is distributed in the hope that it will be useful, but WITHOUT
0012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014         * version 2 for more details (a copy is included in the LICENSE file that
0015         * accompanied this code).
0016         *
0017         * You should have received a copy of the GNU General Public License version
0018         * 2 along with this work; if not, write to the Free Software Foundation,
0019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020         *
0021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022         * CA 95054 USA or visit www.sun.com if you need additional information or
0023         * have any questions.
0024         */
0025
0026        package java.awt;
0027
0028        import java.awt.event.ActionEvent;
0029        import java.awt.event.FocusEvent;
0030        import java.awt.event.InputEvent;
0031        import java.awt.event.InputMethodEvent;
0032        import java.awt.event.InvocationEvent;
0033        import java.awt.event.KeyEvent;
0034        import java.awt.event.MouseEvent;
0035        import java.awt.event.PaintEvent;
0036        import java.awt.event.WindowEvent;
0037        import java.awt.ActiveEvent;
0038        import java.awt.peer.ComponentPeer;
0039        import java.awt.TrayIcon;
0040        import java.util.EmptyStackException;
0041        import java.lang.ref.WeakReference;
0042        import java.lang.reflect.InvocationTargetException;
0043        import java.security.AccessController;
0044        import java.security.PrivilegedAction;
0045        import sun.awt.PeerEvent;
0046        import sun.awt.SunToolkit;
0047        import sun.awt.AWTAutoShutdown;
0048        import sun.awt.AppContext;
0049
0050        /**
0051         * <code>EventQueue</code> is a platform-independent class
0052         * that queues events, both from the underlying peer classes
0053         * and from trusted application classes.
0054         * <p>
0055         * It encapsulates asynchronous event dispatch machinery which
0056         * extracts events from the queue and dispatches them by calling
0057         * {@link #dispatchEvent(AWTEvent) dispatchEvent(AWTEvent)} method
0058         * on this <code>EventQueue</code> with the event to be dispatched
0059         * as an argument.  The particular behavior of this machinery is
0060         * implementation-dependent.  The only requirements are that events
0061         * which were actually enqueued to this queue (note that events
0062         * being posted to the <code>EventQueue</code> can be coalesced)
0063         * are dispatched:
0064         * <dl>
0065         *   <dt> Sequentially.
0066         *   <dd> That is, it is not permitted that several events from
0067         *        this queue are dispatched simultaneously.
0068         *   <dt> In the same order as they are enqueued.
0069         *   <dd> That is, if <code>AWTEvent</code>&nbsp;A is enqueued
0070         *        to the <code>EventQueue</code> before
0071         *        <code>AWTEvent</code>&nbsp;B then event B will not be
0072         *        dispatched before event A.
0073         * </dl>
0074         * <p>
0075         * Some browsers partition applets in different code bases into 
0076         * separate contexts, and establish walls between these contexts.
0077         * In such a scenario, there will be one <code>EventQueue</code>
0078         * per context. Other browsers place all applets into the same
0079         * context, implying that there will be only a single, global
0080         * <code>EventQueue</code> for all applets. This behavior is
0081         * implementation-dependent.  Consult your browser's documentation
0082         * for more information.
0083         * <p>
0084         * For information on the threading issues of the event dispatch
0085         * machinery, see <a href="doc-files/AWTThreadIssues.html#Autoshutdown"
0086         * >AWT Threading Issues</a>.
0087         *
0088         * @author Thomas Ball
0089         * @author Fred Ecks
0090         * @author David Mendenhall
0091         *
0092         * @version 	1.114, 06/05/07
0093         * @since 	1.1
0094         */
0095        public class EventQueue {
0096
0097            // From Thread.java
0098            private static int threadInitNumber;
0099
0100            private static synchronized int nextThreadNum() {
0101                return threadInitNumber++;
0102            }
0103
0104            private static final int LOW_PRIORITY = 0;
0105            private static final int NORM_PRIORITY = 1;
0106            private static final int HIGH_PRIORITY = 2;
0107            private static final int ULTIMATE_PRIORITY = 3;
0108
0109            private static final int NUM_PRIORITIES = ULTIMATE_PRIORITY + 1;
0110
0111            /*
0112             * We maintain one Queue for each priority that the EventQueue supports.
0113             * That is, the EventQueue object is actually implemented as
0114             * NUM_PRIORITIES queues and all Events on a particular internal Queue
0115             * have identical priority. Events are pulled off the EventQueue starting
0116             * with the Queue of highest priority. We progress in decreasing order
0117             * across all Queues.
0118             */
0119            private Queue[] queues = new Queue[NUM_PRIORITIES];
0120
0121            /*
0122             * The next EventQueue on the stack, or null if this EventQueue is
0123             * on the top of the stack.  If nextQueue is non-null, requests to post
0124             * an event are forwarded to nextQueue.
0125             */
0126            private EventQueue nextQueue;
0127
0128            /*
0129             * The previous EventQueue on the stack, or null if this is the
0130             * "base" EventQueue.
0131             */
0132            private EventQueue previousQueue;
0133
0134            private EventDispatchThread dispatchThread;
0135
0136            private final ThreadGroup threadGroup = Thread.currentThread()
0137                    .getThreadGroup();
0138            private final ClassLoader classLoader = Thread.currentThread()
0139                    .getContextClassLoader();
0140
0141            /*
0142             * Debugging flag -- set true and recompile to enable checking.
0143             */
0144            private final static boolean debug = false;
0145
0146            /*
0147             * The time stamp of the last dispatched InputEvent or ActionEvent.
0148             */
0149            private long mostRecentEventTime = System.currentTimeMillis();
0150
0151            /**
0152             * The modifiers field of the current event, if the current event is an
0153             * InputEvent or ActionEvent.
0154             */
0155            private WeakReference currentEvent;
0156
0157            /*
0158             * Non-zero if a thread is waiting in getNextEvent(int) for an event of
0159             * a particular ID to be posted to the queue.
0160             */
0161            private int waitForID;
0162
0163            private final String name = "AWT-EventQueue-" + nextThreadNum();
0164
0165            public EventQueue() {
0166                for (int i = 0; i < NUM_PRIORITIES; i++) {
0167                    queues[i] = new Queue();
0168                }
0169                /* 
0170                 * NOTE: if you ever have to start the associated event dispatch 
0171                 * thread at this point, be aware of the following problem:
0172                 * If this EventQueue instance is created in 
0173                 * SunToolkit.createNewAppContext() the started dispatch thread
0174                 * may call AppContext.getAppContext() before createNewAppContext()
0175                 * completes thus causing mess in thread group to appcontext mapping.
0176                 */
0177            }
0178
0179            /**
0180             * Posts a 1.1-style event to the <code>EventQueue</code>. 
0181             * If there is an existing event on the queue with the same ID
0182             * and event source, the source <code>Component</code>'s
0183             * <code>coalesceEvents</code> method will be called.
0184             *
0185             * @param theEvent an instance of <code>java.awt.AWTEvent</code>,
0186             *		or a subclass of it
0187             * @throws NullPointerException if <code>theEvent</code> is <code>null</code>
0188             */
0189            public void postEvent(AWTEvent theEvent) {
0190                SunToolkit.flushPendingEvents();
0191                postEventPrivate(theEvent);
0192            }
0193
0194            /**
0195             * Posts a 1.1-style event to the <code>EventQueue</code>.
0196             * If there is an existing event on the queue with the same ID
0197             * and event source, the source <code>Component</code>'s
0198             * <code>coalesceEvents</code> method will be called.
0199             *
0200             * @param theEvent an instance of <code>java.awt.AWTEvent</code>,
0201             * 		or a subclass of it
0202             */
0203            final void postEventPrivate(AWTEvent theEvent) {
0204                theEvent.isPosted = true;
0205                synchronized (this ) {
0206                    if (dispatchThread == null && nextQueue == null) {
0207                        if (theEvent.getSource() == AWTAutoShutdown
0208                                .getInstance()) {
0209                            return;
0210                        } else {
0211                            initDispatchThread();
0212                        }
0213                    }
0214                    if (nextQueue != null) {
0215                        // Forward event to top of EventQueue stack.
0216                        nextQueue.postEventPrivate(theEvent);
0217                        return;
0218                    }
0219                    postEvent(theEvent, getPriority(theEvent));
0220                }
0221            }
0222
0223            private static int getPriority(AWTEvent theEvent) {
0224                if (theEvent instanceof  PeerEvent
0225                        && (((PeerEvent) theEvent).getFlags() & PeerEvent.ULTIMATE_PRIORITY_EVENT) != 0) {
0226                    return ULTIMATE_PRIORITY;
0227                }
0228
0229                if (theEvent instanceof  PeerEvent
0230                        && (((PeerEvent) theEvent).getFlags() & PeerEvent.PRIORITY_EVENT) != 0) {
0231                    return HIGH_PRIORITY;
0232                }
0233
0234                if (theEvent instanceof  PeerEvent
0235                        && (((PeerEvent) theEvent).getFlags() & PeerEvent.LOW_PRIORITY_EVENT) != 0) {
0236                    return LOW_PRIORITY;
0237                }
0238
0239                int id = theEvent.getID();
0240                if (id == PaintEvent.PAINT || id == PaintEvent.UPDATE) {
0241                    return LOW_PRIORITY;
0242                }
0243                return NORM_PRIORITY;
0244            }
0245
0246            /**
0247             * Posts the event to the internal Queue of specified priority,
0248             * coalescing as appropriate.
0249             *
0250             * @param theEvent an instance of <code>java.awt.AWTEvent</code>,
0251             * 		or a subclass of it
0252             * @param priority  the desired priority of the event
0253             */
0254            private void postEvent(AWTEvent theEvent, int priority) {
0255                if (coalesceEvent(theEvent, priority)) {
0256                    return;
0257                }
0258
0259                EventQueueItem newItem = new EventQueueItem(theEvent);
0260
0261                cacheEQItem(newItem);
0262
0263                boolean notifyID = (theEvent.getID() == this .waitForID);
0264
0265                if (queues[priority].head == null) {
0266                    boolean shouldNotify = noEvents();
0267                    queues[priority].head = queues[priority].tail = newItem;
0268
0269                    if (shouldNotify) {
0270                        if (theEvent.getSource() != AWTAutoShutdown
0271                                .getInstance()) {
0272                            AWTAutoShutdown.getInstance().notifyThreadBusy(
0273                                    dispatchThread);
0274                        }
0275                        notifyAll();
0276                    } else if (notifyID) {
0277                        notifyAll();
0278                    }
0279                } else {
0280                    // The event was not coalesced or has non-Component source.
0281                    // Insert it at the end of the appropriate Queue.
0282                    queues[priority].tail.next = newItem;
0283                    queues[priority].tail = newItem;
0284                    if (notifyID) {
0285                        notifyAll();
0286                    }
0287                }
0288            }
0289
0290            private boolean coalescePaintEvent(PaintEvent e) {
0291                ComponentPeer sourcePeer = ((Component) e.getSource()).peer;
0292                if (sourcePeer != null) {
0293                    sourcePeer.coalescePaintEvent(e);
0294                }
0295                EventQueueItem[] cache = ((Component) e.getSource()).eventCache;
0296                if (cache == null) {
0297                    return false;
0298                }
0299                int index = eventToCacheIndex(e);
0300
0301                if (index != -1 && cache[index] != null) {
0302                    PaintEvent merged = mergePaintEvents(e,
0303                            (PaintEvent) cache[index].event);
0304                    if (merged != null) {
0305                        cache[index].event = merged;
0306                        return true;
0307                    }
0308                }
0309                return false;
0310            }
0311
0312            private PaintEvent mergePaintEvents(PaintEvent a, PaintEvent b) {
0313                Rectangle aRect = a.getUpdateRect();
0314                Rectangle bRect = b.getUpdateRect();
0315                if (bRect.contains(aRect)) {
0316                    return b;
0317                }
0318                if (aRect.contains(bRect)) {
0319                    return a;
0320                }
0321                return null;
0322            }
0323
0324            private boolean coalesceMouseEvent(MouseEvent e) {
0325                EventQueueItem[] cache = ((Component) e.getSource()).eventCache;
0326                if (cache == null) {
0327                    return false;
0328                }
0329                int index = eventToCacheIndex(e);
0330                if (index != -1 && cache[index] != null) {
0331                    cache[index].event = e;
0332                    return true;
0333                }
0334                return false;
0335            }
0336
0337            private boolean coalescePeerEvent(PeerEvent e) {
0338                EventQueueItem[] cache = ((Component) e.getSource()).eventCache;
0339                if (cache == null) {
0340                    return false;
0341                }
0342                int index = eventToCacheIndex(e);
0343                if (index != -1 && cache[index] != null) {
0344                    e = e.coalesceEvents((PeerEvent) cache[index].event);
0345                    if (e != null) {
0346                        cache[index].event = e;
0347                        return true;
0348                    } else {
0349                        cache[index] = null;
0350                    }
0351                }
0352                return false;
0353            }
0354
0355            /*                                                                               
0356             * Should avoid of calling this method by any means                            
0357             * as it's working time is dependant on EQ length.                             
0358             * In the wors case this method alone can slow down the entire application     
0359             * 10 times by stalling the Event processing.                                  
0360             * Only here by backward compatibility reasons.                                
0361             */
0362            private boolean coalesceOtherEvent(AWTEvent e, int priority) {
0363                int id = e.getID();
0364                Component source = (Component) e.getSource();
0365                for (EventQueueItem entry = queues[priority].head; entry != null; entry = entry.next) {
0366                    // Give Component.coalesceEvents a chance                              
0367                    if (entry.event.getSource() == source && entry.id == id) {
0368                        AWTEvent coalescedEvent = source.coalesceEvents(
0369                                entry.event, e);
0370                        if (coalescedEvent != null) {
0371                            entry.event = coalescedEvent;
0372                            return true;
0373                        }
0374                    }
0375                }
0376                return false;
0377            }
0378
0379            private boolean coalesceEvent(AWTEvent e, int priority) {
0380                if (!(e.getSource() instanceof  Component)) {
0381                    return false;
0382                }
0383                if (e instanceof  PeerEvent) {
0384                    return coalescePeerEvent((PeerEvent) e);
0385                }
0386                // The worst case                                                          
0387                if (((Component) e.getSource()).isCoalescingEnabled()
0388                        && coalesceOtherEvent(e, priority)) {
0389                    return true;
0390                }
0391                if (e instanceof  PaintEvent) {
0392                    return coalescePaintEvent((PaintEvent) e);
0393                }
0394                if (e instanceof  MouseEvent) {
0395                    return coalesceMouseEvent((MouseEvent) e);
0396                }
0397                return false;
0398            }
0399
0400            private void cacheEQItem(EventQueueItem entry) {
0401                int index = eventToCacheIndex(entry.event);
0402                if (index != -1 && entry.event.getSource() instanceof  Component) {
0403                    Component source = (Component) entry.event.getSource();
0404                    if (source.eventCache == null) {
0405                        source.eventCache = new EventQueueItem[CACHE_LENGTH];
0406                    }
0407                    source.eventCache[index] = entry;
0408                }
0409            }
0410
0411            private void uncacheEQItem(EventQueueItem entry) {
0412                int index = eventToCacheIndex(entry.event);
0413                if (index != -1 && entry.event.getSource() instanceof  Component) {
0414                    Component source = (Component) entry.event.getSource();
0415                    if (source.eventCache == null) {
0416                        return;
0417                    }
0418                    source.eventCache[index] = null;
0419                }
0420            }
0421
0422            private static final int PAINT = 0;
0423            private static final int UPDATE = 1;
0424            private static final int MOVE = 2;
0425            private static final int DRAG = 3;
0426            private static final int PEER = 4;
0427            private static final int CACHE_LENGTH = 5;
0428
0429            private static int eventToCacheIndex(AWTEvent e) {
0430                switch (e.getID()) {
0431                case PaintEvent.PAINT:
0432                    return PAINT;
0433                case PaintEvent.UPDATE:
0434                    return UPDATE;
0435                case MouseEvent.MOUSE_MOVED:
0436                    return MOVE;
0437                case MouseEvent.MOUSE_DRAGGED:
0438                    return DRAG;
0439                default:
0440                    return e instanceof  PeerEvent ? PEER : -1;
0441                }
0442            }
0443
0444            /**
0445             * Returns whether an event is pending on any of the separate
0446             * Queues.
0447             * @return whether an event is pending on any of the separate Queues
0448             */
0449            private boolean noEvents() {
0450                for (int i = 0; i < NUM_PRIORITIES; i++) {
0451                    if (queues[i].head != null) {
0452                        return false;
0453                    }
0454                }
0455
0456                return true;
0457            }
0458
0459            /**
0460             * Removes an event from the <code>EventQueue</code> and
0461             * returns it.  This method will block until an event has
0462             * been posted by another thread.
0463             * @return the next <code>AWTEvent</code>
0464             * @exception InterruptedException 
0465             *            if any thread has interrupted this thread
0466             */
0467            public AWTEvent getNextEvent() throws InterruptedException {
0468                do {
0469                    /*
0470                     * SunToolkit.flushPendingEvents must be called outside
0471                     * of the synchronized block to avoid deadlock when 
0472                     * event queues are nested with push()/pop(). 
0473                     */
0474                    SunToolkit.flushPendingEvents();
0475                    synchronized (this ) {
0476                        for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
0477                            if (queues[i].head != null) {
0478                                EventQueueItem entry = queues[i].head;
0479                                queues[i].head = entry.next;
0480                                if (entry.next == null) {
0481                                    queues[i].tail = null;
0482                                }
0483                                uncacheEQItem(entry);
0484                                return entry.event;
0485                            }
0486                        }
0487                        AWTAutoShutdown.getInstance().notifyThreadFree(
0488                                dispatchThread);
0489                        wait();
0490                    }
0491                } while (true);
0492            }
0493
0494            AWTEvent getNextEvent(int id) throws InterruptedException {
0495                do {
0496                    /*
0497                     * SunToolkit.flushPendingEvents must be called outside
0498                     * of the synchronized block to avoid deadlock when 
0499                     * event queues are nested with push()/pop(). 
0500                     */
0501                    SunToolkit.flushPendingEvents();
0502                    synchronized (this ) {
0503                        for (int i = 0; i < NUM_PRIORITIES; i++) {
0504                            for (EventQueueItem entry = queues[i].head, prev = null; entry != null; prev = entry, entry = entry.next) {
0505                                if (entry.id == id) {
0506                                    if (prev == null) {
0507                                        queues[i].head = entry.next;
0508                                    } else {
0509                                        prev.next = entry.next;
0510                                    }
0511                                    if (queues[i].tail == entry) {
0512                                        queues[i].tail = prev;
0513                                    }
0514                                    uncacheEQItem(entry);
0515                                    return entry.event;
0516                                }
0517                            }
0518                        }
0519                        this .waitForID = id;
0520                        wait();
0521                        this .waitForID = 0;
0522                    }
0523                } while (true);
0524            }
0525
0526            /**
0527             * Returns the first event on the <code>EventQueue</code>
0528             * without removing it.
0529             * @return the first event
0530             */
0531            public synchronized AWTEvent peekEvent() {
0532                for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
0533                    if (queues[i].head != null) {
0534                        return queues[i].head.event;
0535                    }
0536                }
0537
0538                return null;
0539            }
0540
0541            /**
0542             * Returns the first event with the specified id, if any.
0543             * @param id the id of the type of event desired
0544             * @return the first event of the specified id or <code>null</code>
0545             *    if there is no such event
0546             */
0547            public synchronized AWTEvent peekEvent(int id) {
0548                for (int i = NUM_PRIORITIES - 1; i >= 0; i--) {
0549                    EventQueueItem q = queues[i].head;
0550                    for (; q != null; q = q.next) {
0551                        if (q.id == id) {
0552                            return q.event;
0553                        }
0554                    }
0555                }
0556
0557                return null;
0558            }
0559
0560            /**
0561             * Dispatches an event. The manner in which the event is
0562             * dispatched depends upon the type of the event and the
0563             * type of the event's source object:
0564             * <p> </p>
0565             * <table border=1 summary="Event types, source types, and dispatch methods">
0566             * <tr>
0567             *     <th>Event Type</th>
0568             *     <th>Source Type</th> 
0569             *     <th>Dispatched To</th>
0570             * </tr>
0571             * <tr>
0572             *     <td>ActiveEvent</td>
0573             *     <td>Any</td>
0574             *     <td>event.dispatch()</td>
0575             * </tr>
0576             * <tr>
0577             *     <td>Other</td>
0578             *     <td>Component</td>
0579             *     <td>source.dispatchEvent(AWTEvent)</td>
0580             * </tr>
0581             * <tr>
0582             *     <td>Other</td>
0583             *     <td>MenuComponent</td>
0584             *     <td>source.dispatchEvent(AWTEvent)</td>
0585             * </tr>
0586             * <tr>
0587             *     <td>Other</td>
0588             *     <td>Other</td>
0589             *     <td>No action (ignored)</td>
0590             * </tr>
0591             * </table>
0592             * <p> </p>
0593             * @param event an instance of <code>java.awt.AWTEvent</code>,
0594             * 		or a subclass of it
0595             * @throws NullPointerException if <code>event</code> is <code>null</code>
0596             * @since           1.2
0597             */
0598            protected void dispatchEvent(AWTEvent event) {
0599                event.isPosted = true;
0600                Object src = event.getSource();
0601                if (event instanceof  ActiveEvent) {
0602                    // This could become the sole method of dispatching in time.
0603                    setCurrentEventAndMostRecentTimeImpl(event);
0604
0605                    ((ActiveEvent) event).dispatch();
0606                } else if (src instanceof  Component) {
0607                    ((Component) src).dispatchEvent(event);
0608                    event.dispatched();
0609                } else if (src instanceof  MenuComponent) {
0610                    ((MenuComponent) src).dispatchEvent(event);
0611                } else if (src instanceof  TrayIcon) {
0612                    ((TrayIcon) src).dispatchEvent(event);
0613                } else if (src instanceof  AWTAutoShutdown) {
0614                    if (noEvents()) {
0615                        dispatchThread.stopDispatching();
0616                    }
0617                } else {
0618                    System.err.println("unable to dispatch event: " + event);
0619                }
0620            }
0621
0622            /**
0623             * Returns the timestamp of the most recent event that had a timestamp, and
0624             * that was dispatched from the <code>EventQueue</code> associated with the
0625             * calling thread. If an event with a timestamp is currently being
0626             * dispatched, its timestamp will be returned. If no events have yet 
0627             * been dispatched, the EventQueue's initialization time will be 
0628             * returned instead.In the current version of 
0629             * the JDK, only <code>InputEvent</code>s,
0630             * <code>ActionEvent</code>s, and <code>InvocationEvent</code>s have
0631             * timestamps; however, future versions of the JDK may add timestamps to
0632             * additional event types. Note that this method should only be invoked
0633             * from an application's event dispatching thread. If this method is
0634             * invoked from another thread, the current system time (as reported by
0635             * <code>System.currentTimeMillis()</code>) will be returned instead.
0636             *
0637             * @return the timestamp of the last <code>InputEvent</code>,
0638             *         <code>ActionEvent</code>, or <code>InvocationEvent</code> to be
0639             *         dispatched, or <code>System.currentTimeMillis()</code> if this
0640             *         method is invoked on a thread other than an event dispatching
0641             *         thread
0642             * @see java.awt.event.InputEvent#getWhen
0643             * @see java.awt.event.ActionEvent#getWhen
0644             * @see java.awt.event.InvocationEvent#getWhen
0645             *
0646             * @since 1.4
0647             */
0648            public static long getMostRecentEventTime() {
0649                return Toolkit.getEventQueue().getMostRecentEventTimeImpl();
0650            }
0651
0652            private synchronized long getMostRecentEventTimeImpl() {
0653                return (Thread.currentThread() == dispatchThread) ? mostRecentEventTime
0654                        : System.currentTimeMillis();
0655            }
0656
0657            /**
0658             * @return most recent event time on all threads.
0659             */
0660            synchronized long getMostRecentEventTimeEx() {
0661                return mostRecentEventTime;
0662            }
0663
0664            /**
0665             * Returns the the event currently being dispatched by the
0666             * <code>EventQueue</code> associated with the calling thread. This is
0667             * useful if a method needs access to the event, but was not designed to
0668             * receive a reference to it as an argument. Note that this method should
0669             * only be invoked from an application's event dispatching thread. If this
0670             * method is invoked from another thread, null will be returned.
0671             *
0672             * @return the event currently being dispatched, or null if this method is
0673             *         invoked on a thread other than an event dispatching thread
0674             * @since 1.4
0675             */
0676            public static AWTEvent getCurrentEvent() {
0677                return Toolkit.getEventQueue().getCurrentEventImpl();
0678            }
0679
0680            private synchronized AWTEvent getCurrentEventImpl() {
0681                return (Thread.currentThread() == dispatchThread) ? ((AWTEvent) currentEvent
0682                        .get())
0683                        : null;
0684            }
0685
0686            /**
0687             * Replaces the existing <code>EventQueue</code> with the specified one.
0688             * Any pending events are transferred to the new <code>EventQueue</code>
0689             * for processing by it.
0690             *
0691             * @param newEventQueue an <code>EventQueue</code>
0692             *		(or subclass thereof) instance to be use
0693             * @see      java.awt.EventQueue#pop
0694             * @throws NullPointerException if <code>newEventQueue</code> is <code>null</code>
0695             * @since           1.2
0696             */
0697            public synchronized void push(EventQueue newEventQueue) {
0698                if (debug) {
0699                    System.out
0700                            .println("EventQueue.push(" + newEventQueue + ")");
0701                }
0702
0703                if (nextQueue != null) {
0704                    nextQueue.push(newEventQueue);
0705                    return;
0706                }
0707
0708                synchronized (newEventQueue) {
0709                    // Transfer all events forward to new EventQueue.
0710                    while (peekEvent() != null) {
0711                        try {
0712                            newEventQueue.postEventPrivate(getNextEvent());
0713                        } catch (InterruptedException ie) {
0714                            if (debug) {
0715                                System.err.println("interrupted push:");
0716                                ie.printStackTrace(System.err);
0717                            }
0718                        }
0719                    }
0720
0721                    newEventQueue.previousQueue = this ;
0722                }
0723                /* 
0724                 * Stop the event dispatch thread associated with the currently 
0725                 * active event queue, so that after the new queue is pushed
0726                 * on the top this event dispatch thread won't prevent AWT from
0727                 * being automatically shut down.
0728                 * Use stopDispatchingLater() to avoid deadlock: stopDispatching()
0729                 * waits for the dispatch thread to exit, so if the dispatch
0730                 * thread attempts to synchronize on this EventQueue object
0731                 * it will never exit since we already hold this lock.
0732                 */
0733                if (dispatchThread != null) {
0734                    dispatchThread.stopDispatchingLater();
0735                }
0736
0737                nextQueue = newEventQueue;
0738
0739                AppContext appContext = AppContext.getAppContext();
0740                if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this ) {
0741                    appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue);
0742                }
0743            }
0744
0745            /**
0746             * Stops dispatching events using this <code>EventQueue</code>.
0747             * Any pending events are transferred to the previous
0748             * <code>EventQueue</code> for processing.  
0749             * <p>
0750             * Warning: To avoid deadlock, do not declare this method
0751             * synchronized in a subclass.
0752             *
0753             * @exception EmptyStackException if no previous push was made
0754             *	on this <code>EventQueue</code>
0755             * @see      java.awt.EventQueue#push
0756             * @since           1.2
0757             */
0758            protected void pop() throws EmptyStackException {
0759                if (debug) {
0760                    System.out.println("EventQueue.pop(" + this  + ")");
0761                }
0762
0763                // To prevent deadlock, we lock on the previous EventQueue before
0764                // this one.  This uses the same locking order as everything else
0765                // in EventQueue.java, so deadlock isn't possible.
0766                EventQueue prev = previousQueue;
0767                synchronized ((prev != null) ? prev : this ) {
0768                    synchronized (this ) {
0769                        if (nextQueue != null) {
0770                            nextQueue.pop();
0771                            return;
0772                        }
0773                        if (previousQueue == null) {
0774                            throw new EmptyStackException();
0775                        }
0776
0777                        // Transfer all events back to previous EventQueue.
0778                        previousQueue.nextQueue = null;
0779                        while (peekEvent() != null) {
0780                            try {
0781                                previousQueue.postEventPrivate(getNextEvent());
0782                            } catch (InterruptedException ie) {
0783                                if (debug) {
0784                                    System.err.println("interrupted pop:");
0785                                    ie.printStackTrace(System.err);
0786                                }
0787                            }
0788                        }
0789                        AppContext appContext = AppContext.getAppContext();
0790                        if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this ) {
0791                            appContext.put(AppContext.EVENT_QUEUE_KEY,
0792                                    previousQueue);
0793                        }
0794
0795                        previousQueue = null;
0796                    }
0797                }
0798
0799                EventDispatchThread dt = this .dispatchThread;
0800                if (dt != null) {
0801                    dt.stopDispatching(); // Must be done outside synchronized
0802                    // block to avoid possible deadlock
0803                }
0804            }
0805
0806            /**
0807             * Returns true if the calling thread is the current AWT 
0808             * <code>EventQueue</code>'s dispatch thread.  Use this
0809             * call the ensure that a given
0810             * task is being executed (or not being) on the current AWT
0811             * <code>EventDispatchThread</code>.
0812             *
0813             * @return true if running on the current AWT
0814             *  <code>EventQueue</code>'s dispatch thread
0815             * @since           1.2
0816             */
0817            public static boolean isDispatchThread() {
0818                EventQueue eq = Toolkit.getEventQueue();
0819                EventQueue next = eq.nextQueue;
0820                while (next != null) {
0821                    eq = next;
0822                    next = eq.nextQueue;
0823                }
0824                return (Thread.currentThread() == eq.dispatchThread);
0825            }
0826
0827            final void initDispatchThread() {
0828                synchronized (this ) {
0829                    if (dispatchThread == null && !threadGroup.isDestroyed()) {
0830                        dispatchThread = (EventDispatchThread) AccessController
0831                                .doPrivileged(new PrivilegedAction() {
0832                                    public Object run() {
0833                                        EventDispatchThread t = new EventDispatchThread(
0834                                                threadGroup, name,
0835                                                EventQueue.this );
0836                                        t.setContextClassLoader(classLoader);
0837                                        t.setPriority(Thread.NORM_PRIORITY + 1);
0838                                        t.setDaemon(false);
0839                                        return t;
0840                                    }
0841                                });
0842                        AWTAutoShutdown.getInstance().notifyThreadBusy(
0843                                dispatchThread);
0844                        dispatchThread.start();
0845                    }
0846                }
0847            }
0848
0849            final void detachDispatchThread() {
0850                dispatchThread = null;
0851            }
0852
0853            /*
0854             * Gets the <code>EventDispatchThread</code> for this
0855             * <code>EventQueue</code>.
0856             * @return the event dispatch thread associated with this event queue
0857             *         or <code>null</code> if this event queue doesn't have a
0858             *	       working thread associated with it
0859             * @see    java.awt.EventQueue#initDispatchThread
0860             * @see    java.awt.EventQueue#detachDispatchThread
0861             */
0862            final EventDispatchThread getDispatchThread() {
0863                return dispatchThread;
0864            }
0865
0866            /*
0867             * Removes any pending events for the specified source object.
0868             * If removeAllEvents parameter is <code>true</code> then all 
0869             * events for the specified source object are removed, if it 
0870             * is <code>false</code> then <code>SequencedEvent</code>, <code>SentEvent</code>,
0871             * <code>FocusEvent</code>, <code>WindowEvent</code>, <code>KeyEvent</code>,
0872             * and <code>InputMethodEvent</code> are kept in the queue, but all other 
0873             * events are removed.
0874             *
0875             * This method is normally called by the source's 
0876             * <code>removeNotify</code> method.
0877             */
0878            final void removeSourceEvents(Object source, boolean removeAllEvents) {
0879                SunToolkit.flushPendingEvents();
0880                synchronized (this ) {
0881                    for (int i = 0; i < NUM_PRIORITIES; i++) {
0882                        EventQueueItem entry = queues[i].head;
0883                        EventQueueItem prev = null;
0884                        while (entry != null) {
0885                            if ((entry.event.getSource() == source)
0886                                    && (removeAllEvents || !(entry.event instanceof  SequencedEvent
0887                                            || entry.event instanceof  SentEvent
0888                                            || entry.event instanceof  FocusEvent
0889                                            || entry.event instanceof  WindowEvent
0890                                            || entry.event instanceof  KeyEvent || entry.event instanceof  InputMethodEvent))) {
0891                                if (entry.event instanceof  SequencedEvent) {
0892                                    ((SequencedEvent) entry.event).dispose();
0893                                }
0894                                if (entry.event instanceof  SentEvent) {
0895                                    ((SentEvent) entry.event).dispose();
0896                                }
0897                                if (prev == null) {
0898                                    queues[i].head = entry.next;
0899                                } else {
0900                                    prev.next = entry.next;
0901                                }
0902                                uncacheEQItem(entry);
0903                            } else {
0904                                prev = entry;
0905                            }
0906                            entry = entry.next;
0907                        }
0908                        queues[i].tail = prev;
0909                    }
0910                }
0911            }
0912
0913            static void setCurrentEventAndMostRecentTime(AWTEvent e) {
0914                Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e);
0915            }
0916
0917            private synchronized void setCurrentEventAndMostRecentTimeImpl(
0918                    AWTEvent e) {
0919                if (Thread.currentThread() != dispatchThread) {
0920                    return;
0921                }
0922
0923                currentEvent = new WeakReference(e);
0924
0925                // This series of 'instanceof' checks should be replaced with a
0926                // polymorphic type (for example, an interface which declares a
0927                // getWhen() method). However, this would require us to make such
0928                // a type public, or to place it in sun.awt. Both of these approaches
0929                // have been frowned upon. So for now, we hack.
0930                //
0931                // In tiger, we will probably give timestamps to all events, so this
0932                // will no longer be an issue.
0933                long mostRecentEventTime2 = Long.MIN_VALUE;
0934                if (e instanceof  InputEvent) {
0935                    InputEvent ie = (InputEvent) e;
0936                    mostRecentEventTime2 = ie.getWhen();
0937                } else if (e instanceof  InputMethodEvent) {
0938                    InputMethodEvent ime = (InputMethodEvent) e;
0939                    mostRecentEventTime2 = ime.getWhen();
0940                } else if (e instanceof  ActionEvent) {
0941                    ActionEvent ae = (ActionEvent) e;
0942                    mostRecentEventTime2 = ae.getWhen();
0943                } else if (e instanceof  InvocationEvent) {
0944                    InvocationEvent ie = (InvocationEvent) e;
0945                    mostRecentEventTime2 = ie.getWhen();
0946                }
0947                mostRecentEventTime = Math.max(mostRecentEventTime,
0948                        mostRecentEventTime2);
0949            }
0950
0951            /**
0952             * Causes <code>runnable</code> to have its <code>run</code>
0953             * method called in the dispatch thread of 
0954             * {@link Toolkit#getSystemEventQueue the system EventQueue}.
0955             * This will happen after all pending events are processed.
0956             *
0957             * @param runnable  the <code>Runnable</code> whose <code>run</code>
0958             *                  method should be executed
0959             *                  synchronously on the <code>EventQueue</code>
0960             * @see             #invokeAndWait
0961             * @since           1.2
0962             */
0963            public static void invokeLater(Runnable runnable) {
0964                Toolkit.getEventQueue().postEvent(
0965                        new InvocationEvent(Toolkit.getDefaultToolkit(),
0966                                runnable));
0967            }
0968
0969            /**
0970             * Causes <code>runnable</code> to have its <code>run</code>
0971             * method called in the dispatch thread of
0972             * {@link Toolkit#getSystemEventQueue the system EventQueue}.
0973             * This will happen after all pending events are processed.
0974             * The call blocks until this has happened.  This method
0975             * will throw an Error if called from the event dispatcher thread.
0976             *
0977             * @param runnable  the <code>Runnable</code> whose <code>run</code>
0978             *                  method should be executed
0979             *                  synchronously on the <code>EventQueue</code>
0980             * @exception       InterruptedException  if any thread has
0981             *                  interrupted this thread
0982             * @exception       InvocationTargetException  if an throwable is thrown
0983             *                  when running <code>runnable</code>
0984             * @see             #invokeLater
0985             * @since           1.2
0986             */
0987            public static void invokeAndWait(Runnable runnable)
0988                    throws InterruptedException, InvocationTargetException {
0989
0990                if (EventQueue.isDispatchThread()) {
0991                    throw new Error(
0992                            "Cannot call invokeAndWait from the event dispatcher thread");
0993                }
0994
0995                class AWTInvocationLock {
0996                }
0997                Object lock = new AWTInvocationLock();
0998
0999                InvocationEvent event = new InvocationEvent(Toolkit
1000                        .getDefaultToolkit(), runnable, lock, true);
1001
1002                synchronized (lock) {
1003                    Toolkit.getEventQueue().postEvent(event);
1004                    lock.wait();
1005                }
1006
1007                Throwable eventThrowable = event.getThrowable();
1008                if (eventThrowable != null) {
1009                    throw new InvocationTargetException(eventThrowable);
1010                }
1011            }
1012
1013            /*
1014             * Called from PostEventQueue.postEvent to notify that a new event
1015             * appeared. First it proceeds to the EventQueue on the top of the 
1016             * stack, then notifies the associated dispatch thread if it exists 
1017             * or starts a new one otherwise.
1018             */
1019            private void wakeup(boolean isShutdown) {
1020                synchronized (this ) {
1021                    if (nextQueue != null) {
1022                        // Forward call to the top of EventQueue stack.
1023                        nextQueue.wakeup(isShutdown);
1024                    } else if (dispatchThread != null) {
1025                        notifyAll();
1026                    } else if (!isShutdown) {
1027                        initDispatchThread();
1028                    }
1029                }
1030            }
1031        }
1032
1033        /**
1034         * The Queue object holds pointers to the beginning and end of one internal
1035         * queue. An EventQueue object is composed of multiple internal Queues, one
1036         * for each priority supported by the EventQueue. All Events on a particular
1037         * internal Queue have identical priority.
1038         */
1039        class Queue {
1040            EventQueueItem head;
1041            EventQueueItem tail;
1042        }
1043
1044        class EventQueueItem {
1045            AWTEvent event;
1046            int id;
1047            EventQueueItem next;
1048
1049            EventQueueItem(AWTEvent evt) {
1050                event = evt;
1051                id = evt.getID();
1052            }
1053        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.