42 import sun.awt.AWTAutoShutdown; |
42 import sun.awt.AWTAutoShutdown; |
43 import sun.awt.PeerEvent; |
43 import sun.awt.PeerEvent; |
44 import sun.awt.SunToolkit; |
44 import sun.awt.SunToolkit; |
45 import sun.awt.EventQueueItem; |
45 import sun.awt.EventQueueItem; |
46 import sun.awt.AWTAccessor; |
46 import sun.awt.AWTAccessor; |
|
47 |
|
48 import java.util.concurrent.locks.Condition; |
|
49 import java.util.concurrent.locks.Lock; |
47 |
50 |
48 /** |
51 /** |
49 * <code>EventQueue</code> is a platform-independent class |
52 * <code>EventQueue</code> is a platform-independent class |
50 * that queues events, both from the underlying peer classes |
53 * that queues events, both from the underlying peer classes |
51 * and from trusted application classes. |
54 * and from trusted application classes. |
125 * The previous EventQueue on the stack, or null if this is the |
128 * The previous EventQueue on the stack, or null if this is the |
126 * "base" EventQueue. |
129 * "base" EventQueue. |
127 */ |
130 */ |
128 private EventQueue previousQueue; |
131 private EventQueue previousQueue; |
129 |
132 |
|
133 /* |
|
134 * A single lock to synchronize the push()/pop() and related operations with |
|
135 * all the EventQueues from the AppContext. Synchronization on any particular |
|
136 * event queue(s) is not enough: we should lock the whole stack. |
|
137 */ |
|
138 private final Lock pushPopLock; |
|
139 private final Condition pushPopCond; |
|
140 |
130 private EventDispatchThread dispatchThread; |
141 private EventDispatchThread dispatchThread; |
131 |
142 |
132 private final ThreadGroup threadGroup = |
143 private final ThreadGroup threadGroup = |
133 Thread.currentThread().getThreadGroup(); |
144 Thread.currentThread().getThreadGroup(); |
134 private final ClassLoader classLoader = |
145 private final ClassLoader classLoader = |
156 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue"); |
167 private static final PlatformLogger eventLog = PlatformLogger.getLogger("java.awt.event.EventQueue"); |
157 |
168 |
158 static { |
169 static { |
159 AWTAccessor.setEventQueueAccessor( |
170 AWTAccessor.setEventQueueAccessor( |
160 new AWTAccessor.EventQueueAccessor() { |
171 new AWTAccessor.EventQueueAccessor() { |
161 public EventQueue getNextQueue(EventQueue eventQueue) { |
|
162 return eventQueue.nextQueue; |
|
163 } |
|
164 public Thread getDispatchThread(EventQueue eventQueue) { |
172 public Thread getDispatchThread(EventQueue eventQueue) { |
165 return eventQueue.dispatchThread; |
173 return eventQueue.getDispatchThread(); |
|
174 } |
|
175 public boolean isDispatchThreadImpl(EventQueue eventQueue) { |
|
176 return eventQueue.isDispatchThreadImpl(); |
166 } |
177 } |
167 }); |
178 }); |
168 } |
179 } |
169 |
180 |
170 public EventQueue() { |
181 public EventQueue() { |
177 * If this EventQueue instance is created in |
188 * If this EventQueue instance is created in |
178 * SunToolkit.createNewAppContext() the started dispatch thread |
189 * SunToolkit.createNewAppContext() the started dispatch thread |
179 * may call AppContext.getAppContext() before createNewAppContext() |
190 * may call AppContext.getAppContext() before createNewAppContext() |
180 * completes thus causing mess in thread group to appcontext mapping. |
191 * completes thus causing mess in thread group to appcontext mapping. |
181 */ |
192 */ |
|
193 |
|
194 pushPopLock = (Lock)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_LOCK_KEY); |
|
195 pushPopCond = (Condition)AppContext.getAppContext().get(AppContext.EVENT_QUEUE_COND_KEY); |
182 } |
196 } |
183 |
197 |
184 /** |
198 /** |
185 * Posts a 1.1-style event to the <code>EventQueue</code>. |
199 * Posts a 1.1-style event to the <code>EventQueue</code>. |
186 * If there is an existing event on the queue with the same ID |
200 * If there is an existing event on the queue with the same ID |
205 * @param theEvent an instance of <code>java.awt.AWTEvent</code>, |
219 * @param theEvent an instance of <code>java.awt.AWTEvent</code>, |
206 * or a subclass of it |
220 * or a subclass of it |
207 */ |
221 */ |
208 final void postEventPrivate(AWTEvent theEvent) { |
222 final void postEventPrivate(AWTEvent theEvent) { |
209 theEvent.isPosted = true; |
223 theEvent.isPosted = true; |
210 synchronized(this) { |
224 pushPopLock.lock(); |
|
225 try { |
211 if (dispatchThread == null && nextQueue == null) { |
226 if (dispatchThread == null && nextQueue == null) { |
212 if (theEvent.getSource() == AWTAutoShutdown.getInstance()) { |
227 if (theEvent.getSource() == AWTAutoShutdown.getInstance()) { |
213 return; |
228 return; |
214 } else { |
229 } else { |
215 initDispatchThread(); |
230 initDispatchThread(); |
278 |
295 |
279 if (shouldNotify) { |
296 if (shouldNotify) { |
280 if (theEvent.getSource() != AWTAutoShutdown.getInstance()) { |
297 if (theEvent.getSource() != AWTAutoShutdown.getInstance()) { |
281 AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread); |
298 AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread); |
282 } |
299 } |
283 notifyAll(); |
300 pushPopCond.signalAll(); |
284 } else if (notifyID) { |
301 } else if (notifyID) { |
285 notifyAll(); |
302 pushPopCond.signalAll(); |
286 } |
303 } |
287 } else { |
304 } else { |
288 // The event was not coalesced or has non-Component source. |
305 // The event was not coalesced or has non-Component source. |
289 // Insert it at the end of the appropriate Queue. |
306 // Insert it at the end of the appropriate Queue. |
290 queues[priority].tail.next = newItem; |
307 queues[priority].tail.next = newItem; |
291 queues[priority].tail = newItem; |
308 queues[priority].tail = newItem; |
292 if (notifyID) { |
309 if (notifyID) { |
293 notifyAll(); |
310 pushPopCond.signalAll(); |
294 } |
311 } |
295 } |
312 } |
296 } |
313 } |
297 |
314 |
298 private boolean coalescePaintEvent(PaintEvent e) { |
315 private boolean coalescePaintEvent(PaintEvent e) { |
480 * SunToolkit.flushPendingEvents must be called outside |
497 * SunToolkit.flushPendingEvents must be called outside |
481 * of the synchronized block to avoid deadlock when |
498 * of the synchronized block to avoid deadlock when |
482 * event queues are nested with push()/pop(). |
499 * event queues are nested with push()/pop(). |
483 */ |
500 */ |
484 SunToolkit.flushPendingEvents(); |
501 SunToolkit.flushPendingEvents(); |
485 synchronized (this) { |
502 pushPopLock.lock(); |
|
503 try { |
486 for (int i = NUM_PRIORITIES - 1; i >= 0; i--) { |
504 for (int i = NUM_PRIORITIES - 1; i >= 0; i--) { |
487 if (queues[i].head != null) { |
505 if (queues[i].head != null) { |
488 EventQueueItem entry = queues[i].head; |
506 EventQueueItem entry = queues[i].head; |
489 queues[i].head = entry.next; |
507 queues[i].head = entry.next; |
490 if (entry.next == null) { |
508 if (entry.next == null) { |
506 * SunToolkit.flushPendingEvents must be called outside |
526 * SunToolkit.flushPendingEvents must be called outside |
507 * of the synchronized block to avoid deadlock when |
527 * of the synchronized block to avoid deadlock when |
508 * event queues are nested with push()/pop(). |
528 * event queues are nested with push()/pop(). |
509 */ |
529 */ |
510 SunToolkit.flushPendingEvents(); |
530 SunToolkit.flushPendingEvents(); |
511 synchronized (this) { |
531 pushPopLock.lock(); |
|
532 try { |
512 for (int i = 0; i < NUM_PRIORITIES; i++) { |
533 for (int i = 0; i < NUM_PRIORITIES; i++) { |
513 for (EventQueueItem entry = queues[i].head, prev = null; |
534 for (EventQueueItem entry = queues[i].head, prev = null; |
514 entry != null; prev = entry, entry = entry.next) |
535 entry != null; prev = entry, entry = entry.next) |
515 { |
536 { |
516 if (entry.event.getID() == id) { |
537 if (entry.event.getID() == id) { |
525 uncacheEQItem(entry); |
546 uncacheEQItem(entry); |
526 return entry.event; |
547 return entry.event; |
527 } |
548 } |
528 } |
549 } |
529 } |
550 } |
530 this.waitForID = id; |
551 waitForID = id; |
531 wait(); |
552 pushPopCond.await(); |
532 this.waitForID = 0; |
553 waitForID = 0; |
|
554 } finally { |
|
555 pushPopLock.unlock(); |
533 } |
556 } |
534 } while(true); |
557 } while(true); |
535 } |
558 } |
536 |
559 |
537 /** |
560 /** |
538 * Returns the first event on the <code>EventQueue</code> |
561 * Returns the first event on the <code>EventQueue</code> |
539 * without removing it. |
562 * without removing it. |
540 * @return the first event |
563 * @return the first event |
541 */ |
564 */ |
542 public synchronized AWTEvent peekEvent() { |
565 public AWTEvent peekEvent() { |
543 for (int i = NUM_PRIORITIES - 1; i >= 0; i--) { |
566 pushPopLock.lock(); |
544 if (queues[i].head != null) { |
567 try { |
545 return queues[i].head.event; |
568 for (int i = NUM_PRIORITIES - 1; i >= 0; i--) { |
546 } |
569 if (queues[i].head != null) { |
|
570 return queues[i].head.event; |
|
571 } |
|
572 } |
|
573 } finally { |
|
574 pushPopLock.unlock(); |
547 } |
575 } |
548 |
576 |
549 return null; |
577 return null; |
550 } |
578 } |
551 |
579 |
553 * Returns the first event with the specified id, if any. |
581 * Returns the first event with the specified id, if any. |
554 * @param id the id of the type of event desired |
582 * @param id the id of the type of event desired |
555 * @return the first event of the specified id or <code>null</code> |
583 * @return the first event of the specified id or <code>null</code> |
556 * if there is no such event |
584 * if there is no such event |
557 */ |
585 */ |
558 public synchronized AWTEvent peekEvent(int id) { |
586 public AWTEvent peekEvent(int id) { |
559 for (int i = NUM_PRIORITIES - 1; i >= 0; i--) { |
587 pushPopLock.lock(); |
560 EventQueueItem q = queues[i].head; |
588 try { |
561 for (; q != null; q = q.next) { |
589 for (int i = NUM_PRIORITIES - 1; i >= 0; i--) { |
562 if (q.event.getID() == id) { |
590 EventQueueItem q = queues[i].head; |
563 return q.event; |
591 for (; q != null; q = q.next) { |
564 } |
592 if (q.event.getID() == id) { |
565 } |
593 return q.event; |
|
594 } |
|
595 } |
|
596 } |
|
597 } finally { |
|
598 pushPopLock.unlock(); |
566 } |
599 } |
567 |
600 |
568 return null; |
601 return null; |
569 } |
602 } |
570 |
603 |
659 * @since 1.4 |
692 * @since 1.4 |
660 */ |
693 */ |
661 public static long getMostRecentEventTime() { |
694 public static long getMostRecentEventTime() { |
662 return Toolkit.getEventQueue().getMostRecentEventTimeImpl(); |
695 return Toolkit.getEventQueue().getMostRecentEventTimeImpl(); |
663 } |
696 } |
664 private synchronized long getMostRecentEventTimeImpl() { |
697 private long getMostRecentEventTimeImpl() { |
665 return (Thread.currentThread() == dispatchThread) |
698 pushPopLock.lock(); |
666 ? mostRecentEventTime |
699 try { |
667 : System.currentTimeMillis(); |
700 return (Thread.currentThread() == dispatchThread) |
|
701 ? mostRecentEventTime |
|
702 : System.currentTimeMillis(); |
|
703 } finally { |
|
704 pushPopLock.unlock(); |
|
705 } |
668 } |
706 } |
669 |
707 |
670 /** |
708 /** |
671 * @return most recent event time on all threads. |
709 * @return most recent event time on all threads. |
672 */ |
710 */ |
673 synchronized long getMostRecentEventTimeEx() { |
711 long getMostRecentEventTimeEx() { |
674 return mostRecentEventTime; |
712 pushPopLock.lock(); |
|
713 try { |
|
714 return mostRecentEventTime; |
|
715 } finally { |
|
716 pushPopLock.unlock(); |
|
717 } |
675 } |
718 } |
676 |
719 |
677 /** |
720 /** |
678 * Returns the the event currently being dispatched by the |
721 * Returns the the event currently being dispatched by the |
679 * <code>EventQueue</code> associated with the calling thread. This is |
722 * <code>EventQueue</code> associated with the calling thread. This is |
687 * @since 1.4 |
730 * @since 1.4 |
688 */ |
731 */ |
689 public static AWTEvent getCurrentEvent() { |
732 public static AWTEvent getCurrentEvent() { |
690 return Toolkit.getEventQueue().getCurrentEventImpl(); |
733 return Toolkit.getEventQueue().getCurrentEventImpl(); |
691 } |
734 } |
692 private synchronized AWTEvent getCurrentEventImpl() { |
735 private AWTEvent getCurrentEventImpl() { |
693 return (Thread.currentThread() == dispatchThread) |
736 pushPopLock.lock(); |
694 ? ((AWTEvent)currentEvent.get()) |
737 try { |
695 : null; |
738 return (Thread.currentThread() == dispatchThread) |
|
739 ? ((AWTEvent)currentEvent.get()) |
|
740 : null; |
|
741 } finally { |
|
742 pushPopLock.unlock(); |
|
743 } |
696 } |
744 } |
697 |
745 |
698 /** |
746 /** |
699 * Replaces the existing <code>EventQueue</code> with the specified one. |
747 * Replaces the existing <code>EventQueue</code> with the specified one. |
700 * Any pending events are transferred to the new <code>EventQueue</code> |
748 * Any pending events are transferred to the new <code>EventQueue</code> |
704 * (or subclass thereof) instance to be use |
752 * (or subclass thereof) instance to be use |
705 * @see java.awt.EventQueue#pop |
753 * @see java.awt.EventQueue#pop |
706 * @throws NullPointerException if <code>newEventQueue</code> is <code>null</code> |
754 * @throws NullPointerException if <code>newEventQueue</code> is <code>null</code> |
707 * @since 1.2 |
755 * @since 1.2 |
708 */ |
756 */ |
709 public synchronized void push(EventQueue newEventQueue) { |
757 public void push(EventQueue newEventQueue) { |
710 if (eventLog.isLoggable(PlatformLogger.FINE)) { |
758 if (eventLog.isLoggable(PlatformLogger.FINE)) { |
711 eventLog.fine("EventQueue.push(" + newEventQueue + ")"); |
759 eventLog.fine("EventQueue.push(" + newEventQueue + ")"); |
712 } |
760 } |
713 |
761 |
714 if (nextQueue != null) { |
762 pushPopLock.lock(); |
715 nextQueue.push(newEventQueue); |
763 try { |
716 return; |
764 EventQueue toPush = this; |
717 } |
765 while (toPush.nextQueue != null) { |
718 |
766 toPush = toPush.nextQueue; |
719 synchronized (newEventQueue) { |
767 } |
|
768 |
720 // Transfer all events forward to new EventQueue. |
769 // Transfer all events forward to new EventQueue. |
721 while (peekEvent() != null) { |
770 while (toPush.peekEvent() != null) { |
722 try { |
771 try { |
723 newEventQueue.postEventPrivate(getNextEvent()); |
772 newEventQueue.postEventPrivate(toPush.getNextEvent()); |
724 } catch (InterruptedException ie) { |
773 } catch (InterruptedException ie) { |
725 if (eventLog.isLoggable(PlatformLogger.FINE)) { |
774 if (eventLog.isLoggable(PlatformLogger.FINE)) { |
726 eventLog.fine("Interrupted push", ie); |
775 eventLog.fine("Interrupted push", ie); |
727 } |
776 } |
728 } |
777 } |
729 } |
778 } |
730 |
779 |
731 newEventQueue.previousQueue = this; |
780 newEventQueue.previousQueue = toPush; |
732 } |
781 |
733 /* |
782 /* |
734 * Stop the event dispatch thread associated with the currently |
783 * Stop the event dispatch thread associated with the currently |
735 * active event queue, so that after the new queue is pushed |
784 * active event queue, so that after the new queue is pushed |
736 * on the top this event dispatch thread won't prevent AWT from |
785 * on the top this event dispatch thread won't prevent AWT from |
737 * being automatically shut down. |
786 * being automatically shut down. |
738 * Use stopDispatchingLater() to avoid deadlock: stopDispatching() |
787 * Use stopDispatchingLater() to avoid deadlock: stopDispatching() |
739 * waits for the dispatch thread to exit, so if the dispatch |
788 * waits for the dispatch thread to exit, which in turn waits |
740 * thread attempts to synchronize on this EventQueue object |
789 * for the lock in EQ.detachDispatchThread(), which is hold by |
741 * it will never exit since we already hold this lock. |
790 * this method. |
742 */ |
791 */ |
743 if (dispatchThread != null) { |
792 if (toPush.dispatchThread != null) { |
744 dispatchThread.stopDispatchingLater(); |
793 toPush.dispatchThread.stopDispatchingLater(); |
745 } |
794 } |
746 |
795 |
747 nextQueue = newEventQueue; |
796 toPush.nextQueue = newEventQueue; |
748 |
797 |
749 AppContext appContext = AppContext.getAppContext(); |
798 AppContext appContext = AppContext.getAppContext(); |
750 if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) { |
799 if (appContext.get(AppContext.EVENT_QUEUE_KEY) == toPush) { |
751 appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue); |
800 appContext.put(AppContext.EVENT_QUEUE_KEY, newEventQueue); |
|
801 } |
|
802 } finally { |
|
803 pushPopLock.unlock(); |
752 } |
804 } |
753 } |
805 } |
754 |
806 |
755 /** |
807 /** |
756 * Stops dispatching events using this <code>EventQueue</code>. |
808 * Stops dispatching events using this <code>EventQueue</code>. |
768 protected void pop() throws EmptyStackException { |
820 protected void pop() throws EmptyStackException { |
769 if (eventLog.isLoggable(PlatformLogger.FINE)) { |
821 if (eventLog.isLoggable(PlatformLogger.FINE)) { |
770 eventLog.fine("EventQueue.pop(" + this + ")"); |
822 eventLog.fine("EventQueue.pop(" + this + ")"); |
771 } |
823 } |
772 |
824 |
773 // To prevent deadlock, we lock on the previous EventQueue before |
825 EventDispatchThread dt = null; |
774 // this one. This uses the same locking order as everything else |
826 pushPopLock.lock(); |
775 // in EventQueue.java, so deadlock isn't possible. |
827 try { |
776 EventQueue prev = previousQueue; |
828 EventQueue toPop = this; |
777 synchronized ((prev != null) ? prev : this) { |
829 while (toPop.nextQueue != null) { |
778 synchronized(this) { |
830 toPop = toPop.nextQueue; |
779 if (nextQueue != null) { |
831 } |
780 nextQueue.pop(); |
832 EventQueue prev = toPop.previousQueue; |
781 return; |
833 if (prev == null) { |
782 } |
|
783 if (previousQueue == null) { |
|
784 throw new EmptyStackException(); |
834 throw new EmptyStackException(); |
785 } |
835 } |
|
836 toPop.previousQueue = null; |
786 |
837 |
787 // Transfer all events back to previous EventQueue. |
838 // Transfer all events back to previous EventQueue. |
788 previousQueue.nextQueue = null; |
839 prev.nextQueue = null; |
789 while (peekEvent() != null) { |
840 while (toPop.peekEvent() != null) { |
790 try { |
841 try { |
791 previousQueue.postEventPrivate(getNextEvent()); |
842 prev.postEventPrivate(toPop.getNextEvent()); |
792 } catch (InterruptedException ie) { |
843 } catch (InterruptedException ie) { |
793 if (eventLog.isLoggable(PlatformLogger.FINE)) { |
844 if (eventLog.isLoggable(PlatformLogger.FINE)) { |
794 eventLog.fine("Interrupted pop", ie); |
845 eventLog.fine("Interrupted pop", ie); |
795 } |
846 } |
796 } |
847 } |
797 } |
848 } |
798 AppContext appContext = AppContext.getAppContext(); |
849 AppContext appContext = AppContext.getAppContext(); |
799 if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) { |
850 if (appContext.get(AppContext.EVENT_QUEUE_KEY) == this) { |
800 appContext.put(AppContext.EVENT_QUEUE_KEY, previousQueue); |
851 appContext.put(AppContext.EVENT_QUEUE_KEY, prev); |
801 } |
852 } |
802 |
853 |
803 previousQueue = null; |
854 dt = toPop.dispatchThread; |
804 } |
855 } finally { |
805 } |
856 pushPopLock.unlock(); |
806 |
857 } |
807 EventDispatchThread dt = this.dispatchThread; |
858 |
808 if (dt != null) { |
859 if (dt != null) { |
809 dt.stopDispatching(); // Must be done outside synchronized |
860 dt.stopDispatching(); // Must be done outside synchronized |
810 // block to avoid possible deadlock |
861 // block to avoid possible deadlock |
811 } |
862 } |
812 } |
863 } |
831 * @see Toolkit#getSystemEventQueue |
882 * @see Toolkit#getSystemEventQueue |
832 * @since 1.2 |
883 * @since 1.2 |
833 */ |
884 */ |
834 public static boolean isDispatchThread() { |
885 public static boolean isDispatchThread() { |
835 EventQueue eq = Toolkit.getEventQueue(); |
886 EventQueue eq = Toolkit.getEventQueue(); |
836 EventQueue next = eq.nextQueue; |
887 return eq.isDispatchThreadImpl(); |
837 while (next != null) { |
888 } |
838 eq = next; |
889 |
839 next = eq.nextQueue; |
890 final boolean isDispatchThreadImpl() { |
840 } |
891 EventQueue eq = this; |
841 return (Thread.currentThread() == eq.dispatchThread); |
892 pushPopLock.lock(); |
|
893 try { |
|
894 EventQueue next = eq.nextQueue; |
|
895 while (next != null) { |
|
896 eq = next; |
|
897 next = eq.nextQueue; |
|
898 } |
|
899 return (Thread.currentThread() == eq.dispatchThread); |
|
900 } finally { |
|
901 pushPopLock.unlock(); |
|
902 } |
842 } |
903 } |
843 |
904 |
844 final void initDispatchThread() { |
905 final void initDispatchThread() { |
845 synchronized (this) { |
906 pushPopLock.lock(); |
|
907 try { |
846 AppContext appContext = AppContext.getAppContext(); |
908 AppContext appContext = AppContext.getAppContext(); |
847 if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) { |
909 if (dispatchThread == null && !threadGroup.isDestroyed() && !appContext.isDisposed()) { |
848 dispatchThread = (EventDispatchThread) |
910 dispatchThread = (EventDispatchThread) |
849 AccessController.doPrivileged(new PrivilegedAction() { |
911 AccessController.doPrivileged(new PrivilegedAction() { |
850 public Object run() { |
912 public Object run() { |
859 } |
921 } |
860 }); |
922 }); |
861 AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread); |
923 AWTAutoShutdown.getInstance().notifyThreadBusy(dispatchThread); |
862 dispatchThread.start(); |
924 dispatchThread.start(); |
863 } |
925 } |
864 } |
926 } finally { |
865 } |
927 pushPopLock.unlock(); |
866 |
928 } |
867 final void detachDispatchThread() { |
929 } |
868 dispatchThread = null; |
930 |
|
931 final void detachDispatchThread(EventDispatchThread edt, boolean restart) { |
|
932 /* |
|
933 * This synchronized block is to secure that the event dispatch |
|
934 * thread won't die in the middle of posting a new event to the |
|
935 * associated event queue. It is important because we notify |
|
936 * that the event dispatch thread is busy after posting a new event |
|
937 * to its queue, so the EventQueue.dispatchThread reference must |
|
938 * be valid at that point. |
|
939 */ |
|
940 pushPopLock.lock(); |
|
941 try { |
|
942 EventDispatchThread oldDispatchThread = dispatchThread; |
|
943 if (dispatchThread == edt) { |
|
944 dispatchThread = null; |
|
945 } |
|
946 if (restart) { |
|
947 /* |
|
948 * Event dispatch thread dies in case of an uncaught exception. |
|
949 * A new event dispatch thread for this queue will be started |
|
950 * only if a new event is posted to it. In case if no more |
|
951 * events are posted after this thread died all events that |
|
952 * currently are in the queue will never be dispatched. |
|
953 * |
|
954 * Fix for 4648733. Check both the associated java event |
|
955 * queue and the PostEventQueue. |
|
956 */ |
|
957 if ((peekEvent() != null) || !SunToolkit.isPostEventQueueEmpty()) { |
|
958 initDispatchThread(); |
|
959 } |
|
960 AWTAutoShutdown.getInstance().notifyThreadFree(oldDispatchThread); |
|
961 } |
|
962 } finally { |
|
963 pushPopLock.unlock(); |
|
964 } |
869 } |
965 } |
870 |
966 |
871 /* |
967 /* |
872 * Gets the <code>EventDispatchThread</code> for this |
968 * Gets the <code>EventDispatchThread</code> for this |
873 * <code>EventQueue</code>. |
969 * <code>EventQueue</code>. |
876 * working thread associated with it |
972 * working thread associated with it |
877 * @see java.awt.EventQueue#initDispatchThread |
973 * @see java.awt.EventQueue#initDispatchThread |
878 * @see java.awt.EventQueue#detachDispatchThread |
974 * @see java.awt.EventQueue#detachDispatchThread |
879 */ |
975 */ |
880 final EventDispatchThread getDispatchThread() { |
976 final EventDispatchThread getDispatchThread() { |
881 return dispatchThread; |
977 pushPopLock.lock(); |
|
978 try { |
|
979 return dispatchThread; |
|
980 } finally { |
|
981 pushPopLock.unlock(); |
|
982 } |
882 } |
983 } |
883 |
984 |
884 /* |
985 /* |
885 * Removes any pending events for the specified source object. |
986 * Removes any pending events for the specified source object. |
886 * If removeAllEvents parameter is <code>true</code> then all |
987 * If removeAllEvents parameter is <code>true</code> then all |
893 * This method is normally called by the source's |
994 * This method is normally called by the source's |
894 * <code>removeNotify</code> method. |
995 * <code>removeNotify</code> method. |
895 */ |
996 */ |
896 final void removeSourceEvents(Object source, boolean removeAllEvents) { |
997 final void removeSourceEvents(Object source, boolean removeAllEvents) { |
897 SunToolkit.flushPendingEvents(); |
998 SunToolkit.flushPendingEvents(); |
898 synchronized (this) { |
999 pushPopLock.lock(); |
|
1000 try { |
899 for (int i = 0; i < NUM_PRIORITIES; i++) { |
1001 for (int i = 0; i < NUM_PRIORITIES; i++) { |
900 EventQueueItem entry = queues[i].head; |
1002 EventQueueItem entry = queues[i].head; |
901 EventQueueItem prev = null; |
1003 EventQueueItem prev = null; |
902 while (entry != null) { |
1004 while (entry != null) { |
903 if ((entry.event.getSource() == source) |
1005 if ((entry.event.getSource() == source) |
926 } |
1028 } |
927 entry = entry.next; |
1029 entry = entry.next; |
928 } |
1030 } |
929 queues[i].tail = prev; |
1031 queues[i].tail = prev; |
930 } |
1032 } |
|
1033 } finally { |
|
1034 pushPopLock.unlock(); |
931 } |
1035 } |
932 } |
1036 } |
933 |
1037 |
934 static void setCurrentEventAndMostRecentTime(AWTEvent e) { |
1038 static void setCurrentEventAndMostRecentTime(AWTEvent e) { |
935 Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e); |
1039 Toolkit.getEventQueue().setCurrentEventAndMostRecentTimeImpl(e); |
936 } |
1040 } |
937 private synchronized void setCurrentEventAndMostRecentTimeImpl(AWTEvent e) |
1041 private void setCurrentEventAndMostRecentTimeImpl(AWTEvent e) { |
938 { |
1042 pushPopLock.lock(); |
939 if (Thread.currentThread() != dispatchThread) { |
1043 try { |
940 return; |
1044 if (Thread.currentThread() != dispatchThread) { |
941 } |
1045 return; |
942 |
1046 } |
943 currentEvent = new WeakReference(e); |
1047 |
944 |
1048 currentEvent = new WeakReference(e); |
945 // This series of 'instanceof' checks should be replaced with a |
1049 |
946 // polymorphic type (for example, an interface which declares a |
1050 // This series of 'instanceof' checks should be replaced with a |
947 // getWhen() method). However, this would require us to make such |
1051 // polymorphic type (for example, an interface which declares a |
948 // a type public, or to place it in sun.awt. Both of these approaches |
1052 // getWhen() method). However, this would require us to make such |
949 // have been frowned upon. So for now, we hack. |
1053 // a type public, or to place it in sun.awt. Both of these approaches |
950 // |
1054 // have been frowned upon. So for now, we hack. |
951 // In tiger, we will probably give timestamps to all events, so this |
1055 // |
952 // will no longer be an issue. |
1056 // In tiger, we will probably give timestamps to all events, so this |
953 long mostRecentEventTime2 = Long.MIN_VALUE; |
1057 // will no longer be an issue. |
954 if (e instanceof InputEvent) { |
1058 long mostRecentEventTime2 = Long.MIN_VALUE; |
955 InputEvent ie = (InputEvent)e; |
1059 if (e instanceof InputEvent) { |
956 mostRecentEventTime2 = ie.getWhen(); |
1060 InputEvent ie = (InputEvent)e; |
957 } else if (e instanceof InputMethodEvent) { |
1061 mostRecentEventTime2 = ie.getWhen(); |
958 InputMethodEvent ime = (InputMethodEvent)e; |
1062 } else if (e instanceof InputMethodEvent) { |
959 mostRecentEventTime2 = ime.getWhen(); |
1063 InputMethodEvent ime = (InputMethodEvent)e; |
960 } else if (e instanceof ActionEvent) { |
1064 mostRecentEventTime2 = ime.getWhen(); |
961 ActionEvent ae = (ActionEvent)e; |
1065 } else if (e instanceof ActionEvent) { |
962 mostRecentEventTime2 = ae.getWhen(); |
1066 ActionEvent ae = (ActionEvent)e; |
963 } else if (e instanceof InvocationEvent) { |
1067 mostRecentEventTime2 = ae.getWhen(); |
964 InvocationEvent ie = (InvocationEvent)e; |
1068 } else if (e instanceof InvocationEvent) { |
965 mostRecentEventTime2 = ie.getWhen(); |
1069 InvocationEvent ie = (InvocationEvent)e; |
966 } |
1070 mostRecentEventTime2 = ie.getWhen(); |
967 mostRecentEventTime = Math.max(mostRecentEventTime, mostRecentEventTime2); |
1071 } |
|
1072 mostRecentEventTime = Math.max(mostRecentEventTime, mostRecentEventTime2); |
|
1073 } finally { |
|
1074 pushPopLock.unlock(); |
|
1075 } |
968 } |
1076 } |
969 |
1077 |
970 /** |
1078 /** |
971 * Causes <code>runnable</code> to have its <code>run</code> |
1079 * Causes <code>runnable</code> to have its <code>run</code> |
972 * method called in the {@link #isDispatchThread dispatch thread} of |
1080 * method called in the {@link #isDispatchThread dispatch thread} of |
1043 * appeared. First it proceeds to the EventQueue on the top of the |
1151 * appeared. First it proceeds to the EventQueue on the top of the |
1044 * stack, then notifies the associated dispatch thread if it exists |
1152 * stack, then notifies the associated dispatch thread if it exists |
1045 * or starts a new one otherwise. |
1153 * or starts a new one otherwise. |
1046 */ |
1154 */ |
1047 private void wakeup(boolean isShutdown) { |
1155 private void wakeup(boolean isShutdown) { |
1048 synchronized(this) { |
1156 pushPopLock.lock(); |
|
1157 try { |
1049 if (nextQueue != null) { |
1158 if (nextQueue != null) { |
1050 // Forward call to the top of EventQueue stack. |
1159 // Forward call to the top of EventQueue stack. |
1051 nextQueue.wakeup(isShutdown); |
1160 nextQueue.wakeup(isShutdown); |
1052 } else if (dispatchThread != null) { |
1161 } else if (dispatchThread != null) { |
1053 notifyAll(); |
1162 pushPopCond.signalAll(); |
1054 } else if (!isShutdown) { |
1163 } else if (!isShutdown) { |
1055 initDispatchThread(); |
1164 initDispatchThread(); |
1056 } |
1165 } |
|
1166 } finally { |
|
1167 pushPopLock.unlock(); |
1057 } |
1168 } |
1058 } |
1169 } |
1059 } |
1170 } |
1060 |
1171 |
1061 /** |
1172 /** |