1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17/**
18 * @author Michael Danilov, Pavel Dolgov
19 * @version $Revision$
20 */
21package java.awt;
22
23import org.apache.harmony.awt.wtk.NativeEvent;
24import org.apache.harmony.awt.wtk.NativeEventQueue;
25
26class EventDispatchThread extends Thread  {
27
28    private static final class MarkerEvent extends AWTEvent {
29        MarkerEvent(Object source, int id) {
30            super(source, id);
31        }
32    }
33
34    final Dispatcher dispatcher;
35    final Toolkit toolkit;
36    private NativeEventQueue nativeQueue;
37
38    protected volatile boolean shutdownPending = false;
39
40    /**
41     * Initialise and run the main event loop
42     */
43    @Override
44    public void run() {
45        nativeQueue = toolkit.getNativeEventQueue();
46
47        try {
48            runModalLoop(null);
49        } finally {
50            toolkit.shutdownWatchdog.forceShutdown();
51        }
52    }
53
54    void runModalLoop(ModalContext context) {
55        long lastPaintTime = System.currentTimeMillis();
56        while (!shutdownPending && (context == null || context.isModalLoopRunning())) {
57            try {
58            EventQueue eventQueue = toolkit.getSystemEventQueueImpl();
59
60            NativeEvent ne = nativeQueue.getNextEvent();
61            if (ne != null) {
62                dispatcher.onEvent(ne);
63                MarkerEvent marker = new MarkerEvent(this, 0);
64                eventQueue.postEvent(marker);
65                for (AWTEvent ae = eventQueue.getNextEventNoWait();
66                        (ae != null) && (ae != marker);
67                        ae = eventQueue.getNextEventNoWait()) {
68                    eventQueue.dispatchEvent(ae);
69                }
70            } else {
71                toolkit.shutdownWatchdog.setNativeQueueEmpty(true);
72                AWTEvent ae = eventQueue.getNextEventNoWait();
73                if (ae != null) {
74                    eventQueue.dispatchEvent(ae);
75                    long curTime = System.currentTimeMillis();
76                    if (curTime - lastPaintTime > 10) {
77                        toolkit.onQueueEmpty();
78                        lastPaintTime = System.currentTimeMillis();
79                    }
80                } else {
81                    toolkit.shutdownWatchdog.setAwtQueueEmpty(true);
82                    toolkit.onQueueEmpty();
83                    lastPaintTime = System.currentTimeMillis();
84                    waitForAnyEvent();
85                }
86            }
87            } catch (Throwable t) {
88                // TODO: Exception handler should be implemented
89                // t.printStackTrace();
90            }
91        }
92    }
93
94    private void waitForAnyEvent() {
95        EventQueue eventQueue = toolkit.getSystemEventQueueImpl();
96        if (!eventQueue.isEmpty() || !nativeQueue.isEmpty()) {
97            return;
98        }
99        Object eventMonitor = nativeQueue.getEventMonitor();
100        synchronized(eventMonitor) {
101            try {
102                eventMonitor.wait();
103            } catch (InterruptedException e) {}
104        }
105    }
106
107    void shutdown() {
108        shutdownPending = true;
109    }
110
111    EventDispatchThread(Toolkit toolkit, Dispatcher dispatcher ) {
112        this.toolkit = toolkit;
113        this.dispatcher = dispatcher;
114        setName("AWT-EventDispatchThread"); //$NON-NLS-1$
115        setDaemon(true);
116    }
117
118}
119