OSDN Git Service

libjava/
[pf3gnuchains/gcc-fork.git] / libjava / classpath / gnu / java / awt / peer / gtk / GtkMainThread.java
1 /* GtkMainThread.java -- Wrapper for the GTK main thread, and some utilities.
2    Copyright (C) 2006  Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38
39 package gnu.java.awt.peer.gtk;
40
41 import gnu.java.awt.peer.NativeEventLoopRunningEvent;
42
43 /**
44  * The Java thread representing the native GTK main loop, that is,
45  * GtkMainThread.mainThread, terminates when GtkToolkit.gtkMain()
46  * returns.  That happens in response to the last window peer being
47  * disposed (see GtkWindowPeer.dispose).
48  *
49  * When GtkMainThread.destroyWindow is called for the last window, it
50  * in turn calls GtkMainThread.endMainThread, which calls gtk_quit.
51  * gtk_quit signals gtk_main to return, which causes GtkMainThread.run
52  * to return.
53  *
54  * There should only be one native GTK main loop running at any given
55  * time.  In order to safely start and stop the GTK main loop, we use
56  * a running flag and corresponding runningLock.  startMainThread will
57  * not return until the native GTK main loop has started, as confirmed
58  * by the native set_running_flag callback setting the running flag to
59  * true.  Without this protection, gtk_quit could be called before the
60  * main loop has actually started, which causes GTK assertion
61  * failures.  Likewise endMainThread will not return until the native
62  * GTK main loop has ended.
63  *
64  * post_running_flag_callback is called during gtk_main initialization
65  * and no window can be created before startMainThread returns.  This
66  * ensures that calling post_running_flag_callback is the first action
67  * taken by the native GTK main loop.
68  *
69  * GtkMainThread.mainThread is started when the window count goes from
70  * zero to one.
71  *
72  * GtkMainThread keeps the AWT event queue informed of its status by
73  * posting NativeEventLoopRunningEvents.  The AWT event queue uses
74  * this status to determine whether or not the AWT exit conditions
75  * have been met (see EventQueue.isShutdown).
76  */
77 public class GtkMainThread extends Thread
78 {
79   /** Count of the number of open windows */
80   private static int numberOfWindows = 0;
81
82   /** Lock for the above */
83   private static Object nWindowsLock = new Object();
84
85   /** Indicates whether or not the GTK main loop is running. */
86   private static boolean running = false;
87
88   /** Lock for the above. */
89   private static Object runningLock = new Object();
90
91   /** The main thread instance (singleton) */
92   public static GtkMainThread mainThread;
93
94   /** Constructs a main thread */
95   private GtkMainThread()
96   {
97     super("GTK main thread");
98   }
99
100   public void run ()
101   {
102     GtkToolkit.gtkMain ();
103   }
104
105   private static void setRunning(boolean running)
106   {
107     synchronized (runningLock)
108       {
109         GtkMainThread.running = running;
110         runningLock.notifyAll();
111       }
112   }
113
114   private static void startMainThread()
115   {
116     synchronized (runningLock)
117       {
118         if (!running)
119           {
120             mainThread = new GtkMainThread();
121             mainThread.start();
122
123             while (!running)
124               {
125                 try
126                   {
127                     runningLock.wait();
128                   }
129                 catch (InterruptedException e)
130                   {
131                     System.err.println ("GtkMainThread.startMainThread:"
132                                         + " interrupted while waiting "
133                                         + " for GTK main loop to start");
134                   }
135               }
136             GtkGenericPeer.q()
137               .postEvent(new NativeEventLoopRunningEvent(Boolean.TRUE));
138           }
139       }
140   }
141
142   private static void endMainThread()
143   {
144     synchronized (runningLock)
145       {
146         if (running)
147           {
148             GtkToolkit.gtkQuit();
149
150             while (running)
151               {
152                 try
153                   {
154                     runningLock.wait();
155                   }
156                 catch (InterruptedException e)
157                   {
158                     System.err.println ("GtkMainThread.endMainThread:"
159                                         + " interrupted while waiting "
160                                         + " for GTK main loop to stop");
161                   }
162               }
163             GtkGenericPeer.q()
164               .postEvent(new NativeEventLoopRunningEvent(Boolean.FALSE));
165             }
166       }
167   }
168
169   public static void createWindow()
170   {
171     synchronized (nWindowsLock)
172       {
173         if (numberOfWindows == 0)
174           startMainThread();
175         numberOfWindows++;
176       }
177   }
178
179   public static void destroyWindow()
180   {
181     synchronized (nWindowsLock)
182       {
183         numberOfWindows--;
184         if (numberOfWindows == 0)
185           endMainThread();
186       }
187   }
188 }