1 /* GtkMainThread.java -- Wrapper for the GTK main thread, and some utilities.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
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)
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.
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
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
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. */
39 package gnu.java.awt.peer.gtk;
41 import gnu.java.awt.peer.NativeEventLoopRunningEvent;
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).
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
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.
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.
69 * GtkMainThread.mainThread is started when the window count goes from
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).
77 public class GtkMainThread extends Thread
79 /** Count of the number of open windows */
80 private static int numberOfWindows = 0;
82 /** Lock for the above */
83 private static Object nWindowsLock = new Object();
85 /** Indicates whether or not the GTK main loop is running. */
86 private static boolean running = false;
88 /** Lock for the above. */
89 private static Object runningLock = new Object();
91 /** The main thread instance (singleton) */
92 public static GtkMainThread mainThread;
94 /** Constructs a main thread */
95 private GtkMainThread()
97 super("GTK main thread");
102 GtkToolkit.gtkMain ();
105 private static void setRunning(boolean running)
107 synchronized (runningLock)
109 GtkMainThread.running = running;
110 runningLock.notifyAll();
114 private static void startMainThread()
116 synchronized (runningLock)
120 mainThread = new GtkMainThread();
129 catch (InterruptedException e)
131 System.err.println ("GtkMainThread.startMainThread:"
132 + " interrupted while waiting "
133 + " for GTK main loop to start");
137 .postEvent(new NativeEventLoopRunningEvent(Boolean.TRUE));
142 private static void endMainThread()
144 synchronized (runningLock)
148 GtkToolkit.gtkQuit();
156 catch (InterruptedException e)
158 System.err.println ("GtkMainThread.endMainThread:"
159 + " interrupted while waiting "
160 + " for GTK main loop to stop");
164 .postEvent(new NativeEventLoopRunningEvent(Boolean.FALSE));
169 public static void createWindow()
171 synchronized (nWindowsLock)
173 if (numberOfWindows == 0)
179 public static void destroyWindow()
181 synchronized (nWindowsLock)
184 if (numberOfWindows == 0)