source: trunk/third/bonobo/bonobo/bonobo-main.c @ 17169

Revision 17169, 7.0 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17168, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2/*
3 * bonobo-main.c: Bonobo Main
4 *
5 * Author:
6 *    Miguel de Icaza  (miguel@gnu.org)
7 *    Nat Friedman     (nat@nat.org)
8 *    Peter Wainwright (prw@wainpr.demo.co.uk)
9 *
10 * Copyright 1999 Helix Code, Inc.
11 */
12#include <config.h>
13
14#include <bonobo/bonobo-exception.h>
15#include <bonobo/bonobo-main.h>
16#include <bonobo/bonobo-object.h>
17#include <bonobo/bonobo-context.h>
18
19#include <signal.h>
20#include <gtk/gtkmain.h>
21#include <liboaf/liboaf.h>
22
23#include <X11/Xlib.h>
24#include <libintl.h>
25
26CORBA_ORB                 __bonobo_orb;
27PortableServer_POA        __bonobo_poa;
28PortableServer_POAManager __bonobo_poa_manager = NULL;
29
30/**
31 * bonobo_orb:
32 *
33 * fetches the bonobo orb
34 *
35 * Returns: The ORB used for this Bonobo application.  The ORB
36 * is created in bonobo_init().
37 */
38CORBA_ORB
39bonobo_orb (void)
40{
41        return __bonobo_orb;
42}
43
44/**
45 * bonobo_poa:
46 *
47 * fetches the bonobo poa
48 *
49 * Returns: The POA used for this Bonobo application.  The POA
50 * is created when bonobo_init() is called.
51 */
52PortableServer_POA
53bonobo_poa (void)
54{
55        return __bonobo_poa;
56}
57
58/**
59 * bonobo_poa_manager:
60 *
61 * fetches the bonobo poa manager.
62 *
63 * Returns: The POA Manager used for this Bonobo application.  The POA
64 * Manager is created when bonobo_init() is called, but it is not
65 * activated until bonobo_main() is called.
66 */
67PortableServer_POAManager
68bonobo_poa_manager (void)
69{
70        return __bonobo_poa_manager;
71}
72
73static int (*gdk_x_error) (Display *, XErrorEvent *);
74
75static int
76bonobo_x_error_handler (Display *display, XErrorEvent *error)
77{
78        if (!error->error_code)
79                return 0;
80
81        /*
82         * If we got a BadDrawable or a BadWindow, we ignore it for
83         * now.  FIXME: We need to somehow distinguish real errors
84         * from X-server-induced errors.  Keeping a list of windows
85         * for which we will ignore BadDrawables would be a good idea.
86         */
87        if (error->error_code == BadDrawable ||
88            error->error_code == BadWindow)
89                return 0;
90
91        /*
92         * Otherwise, let gdk deal.
93         */
94
95        return gdk_x_error (display, error);
96}
97
98/**
99 * bonobo_setup_x_error_handler:
100 *
101 * To do graphical embedding in the X window system, Bonobo
102 * uses the classic foreign-window-reparenting trick.  The
103 * GtkPlug/GtkSocket widgets are used for this purpose.  However,
104 * serious robustness problems arise if the GtkSocket end of the
105 * connection unexpectedly dies.  The X server sends out DestroyNotify
106 * events for the descendants of the GtkPlug (i.e., your embedded
107 * component's windows) in effectively random order.  Furthermore, if
108 * you happened to be drawing on any of those windows when the
109 * GtkSocket was destroyed (a common state of affairs), an X error
110 * will kill your application.
111 *
112 * To solve this latter problem, Bonobo sets up its own X error
113 * handler which ignores certain X errors that might have been
114 * caused by such a scenario.  Other X errors get passed to gdk_x_error
115 * normally.
116 */
117void
118bonobo_setup_x_error_handler (void)
119{
120        static gboolean error_handler_setup = FALSE;
121
122        if (error_handler_setup)
123                return;
124
125        error_handler_setup = TRUE;
126
127        gdk_x_error = XSetErrorHandler (bonobo_x_error_handler);
128}
129
130/**
131 * bonobo_init:
132 * @orb: the ORB in which we run
133 * @poa: optional, a POA.
134 * @manager: optional, a POA Manager
135 *
136 * Initializes the bonobo document model.  It requires at least
137 * the value for @orb.  If @poa is CORBA_OBJECT_NIL, then the
138 * RootPOA will be used, in this case @manager should be CORBA_OBJECT_NIL.
139 *
140 * Returns %TRUE on success, or %FALSE on failure.
141 */
142gboolean
143bonobo_init (CORBA_ORB orb, PortableServer_POA poa, PortableServer_POAManager manager)
144{
145        CORBA_Environment ev;
146
147        CORBA_exception_init (&ev);
148
149        /*
150         * In Bonobo, components and containers must not crash if the
151         * remote end crashes.  If a remote server crashes and then we
152         * try to make a CORBA call on it, we may get a SIGPIPE.  So,
153         * for lack of a better solution, we ignore SIGPIPE here.  This
154         * is open for reconsideration in the future.
155         *
156         * When SIGPIPE is ignored, write() calls which would
157         * ordinarily trigger a signal will instead return -1 and set
158         * errno to EPIPE.  So ORBit will be able to catch these
159         * errors instead of letting them kill the component.
160         *
161         * Possibilities are the MSG_PEEK trick, where you test if the
162         * connection is dead right before doing the writev().  That
163         * approach has two problems:
164         *
165         *   1. There is the possibility of a race condition, where
166         *      the remote end calls right after the test, and right
167         *      before the writev().
168         *
169         *   2. An extra system call per write might be regarded by
170         *      some as a performance hit.
171         *
172         * Another possibility is to surround the call to writev() in
173         * ORBit (giop-msg-buffer.c:197 or so) with something like
174         * this:
175         *
176         *              orbit_ignore_sigpipe = 1;
177         *
178         *              result = writev ( ... );
179         *
180         *              orbit_ignore_sigpipe = 0;
181         *
182         * The SIGPIPE signal handler will check the global
183         * orbit_ignore_sigpipe variable and ignore the signal if it
184         * is 1.  If it is 0, it can proxy to the user's original
185         * signal handler.  This is a real possibility.
186         */
187        signal (SIGPIPE, SIG_IGN);
188
189        /*
190         * Create the POA.
191         */
192        if (orb == CORBA_OBJECT_NIL) {
193                orb = oaf_orb_get ();
194                if (orb == CORBA_OBJECT_NIL) {
195                        g_warning ("Can not resolve initial reference to ORB");
196                        CORBA_exception_free (&ev);
197                        return FALSE;
198                }
199        }
200       
201        if (CORBA_Object_is_nil ((CORBA_Object) poa, &ev)) {
202                poa = (PortableServer_POA) CORBA_ORB_resolve_initial_references (orb, "RootPOA", &ev);
203                if (BONOBO_EX (&ev)) {
204                        g_warning ("Can not resolve initial reference to RootPOA");
205                        CORBA_exception_free (&ev);
206                        return FALSE;
207                }
208               
209        }
210
211        /*
212         * Create the POA Manager.
213         */
214        if (CORBA_Object_is_nil ((CORBA_Object)manager, &ev)){
215                manager = PortableServer_POA__get_the_POAManager (poa, &ev);
216                if (BONOBO_EX (&ev)){
217                        g_warning ("Can not get the POA manager");
218                        CORBA_exception_free (&ev);
219                        return FALSE;
220                }
221        }
222
223        /*
224         * Store global copies of these which can be retrieved with
225         * bonobo_orb()/bonobo_poa()/bonobo_poa_manager().
226         */
227        __bonobo_orb = orb;
228        __bonobo_poa = poa;
229        __bonobo_poa_manager = manager;
230
231        CORBA_exception_free (&ev);
232
233        bonobo_object_init ();
234
235        bonobo_context_init ();
236
237        bindtextdomain (PACKAGE, BONOBO_LOCALEDIR);
238
239        return TRUE;
240}
241
242/**
243 * bonobo_activate:
244 *
245 * Activates the Bonobo POA manager registered by bonobo_init.
246 * This should be called at the end of application initialization.
247 * You do not need to call this function if you use bonobo_main().
248 *
249 * Returns %TRUE on success, or %FALSE on failure.
250 */
251gboolean
252bonobo_activate (void)
253{
254        CORBA_Environment ev;
255
256        CORBA_exception_init (&ev);
257
258        if (!__bonobo_poa_manager) {
259                g_warning ("Tried to activate Bonobo before initializing");
260                CORBA_exception_free (&ev);
261                return FALSE;
262        }
263        PortableServer_POAManager_activate (__bonobo_poa_manager, &ev);
264        if (BONOBO_EX (&ev)){
265                g_warning ("Failed to activate the Bonobo POA manager");
266                CORBA_exception_free (&ev);
267                return FALSE;
268        }
269
270        CORBA_exception_free (&ev);
271       
272        return TRUE;
273}
274
275/**
276 * bonobo_main:
277 *
278 * Activates the Bonobo POA Manager and enters the main event loop.
279 */
280void
281bonobo_main (void)
282{
283        bonobo_activate ();
284        gtk_main ();
285}
Note: See TracBrowser for help on using the repository browser.