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

Java Source Code / Java Documentation
1. JDK Core
2. JDK Modules
3. JDK Modules com.sun
4. JDK Modules com.sun.java
5. JDK Modules Platform
6. JDK Modules sun
7. Open Source Build
8. Open Source Graphic Library
9. Open Source IDE Eclipse
10. Open Source J2EE
11. Open Source JDBC Driver
12. Open Source Library
13. Open Source Library Database
14. Open Source Net
15. Open Source Script
16. Science
17. Security
18. Sevlet Container
19. SUN GlassFish
20. Swing Library
21. Web Services apache cxf 2.0.1
22. Web Services AXIS2
23. XML
Microsoft Office Word 2007 Tutorial
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Java Source Code / Java Documentation » 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:        }
w__w__w___.___ja___v_a_2___s__._c___om_ | Contact Us
Copyright 2003 - 08 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.