source: trunk/third/gnome-core/panel/status-docklet.c @ 15821

Revision 15821, 8.9 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15820, which included commits to RCS files with non-trunk default branches.
Line 
1#include <config.h>
2#include <string.h>
3#include <X11/X.h>
4#include <X11/Xlib.h>
5#include <gtk/gtk.h>
6#include <gdk/gdkx.h>
7#include <gnome.h>
8
9#include <status-docklet.h>
10#include <libgnorba/gnorba.h>
11#include <libgnorba/gnome-factory.h>
12
13#include "gnome-panel.h"
14
15#define pg_return_if_fail(x) if(!(x)) { g_print("type = %d exid = %s\n", ev._major, ev._repo_id); return; }
16#define pg_return_val_if_fail(x,y) if(!(x)) { g_print("type = %d exid = %s\n", ev._major, ev._repo_id); return y;}
17
18static void status_docklet_class_init   (StatusDockletClass *klass);
19static void status_docklet_init         (StatusDocklet      *status_docklet);
20static void status_docklet_destroy      (GtkObject          *o);
21static void status_docklet_build_plug   (StatusDocklet      *docklet,
22                                         GtkWidget          *plug);
23
24
25typedef void (*BuildSignal) (GtkObject * object,
26                             GtkWidget * wid,
27                             gpointer data);
28
29static GtkObjectClass *parent_class;
30
31guint
32status_docklet_get_type (void)
33{
34        static guint status_docklet_type = 0;
35
36        if (status_docklet_type == 0) {
37                static const GtkTypeInfo status_docklet_info = {
38                        "StatusDocklet",
39                        sizeof (StatusDocklet),
40                        sizeof (StatusDockletClass),
41                        (GtkClassInitFunc) status_docklet_class_init,
42                        (GtkObjectInitFunc) status_docklet_init,
43                        NULL,
44                        NULL,
45                        NULL
46                };
47
48                status_docklet_type = gtk_type_unique (gtk_object_get_type (),
49                                                       &status_docklet_info);
50        }
51
52        return status_docklet_type;
53}
54
55enum {
56        BUILD_PLUG_SIGNAL,
57        LAST_SIGNAL
58};
59
60static guint status_docklet_signals[LAST_SIGNAL] = {0};
61
62static void
63marshal_signal_build (GtkObject * object,
64                      GtkSignalFunc func,
65                      gpointer func_data,
66                      GtkArg * args)
67{
68        BuildSignal rfunc;
69
70        rfunc = (BuildSignal) func;
71
72        (*rfunc) (object,
73                  GTK_VALUE_POINTER (args[0]),
74                  func_data);
75}
76
77static void
78status_docklet_class_init (StatusDockletClass *class)
79{
80        GtkObjectClass *object_class;
81
82        object_class = (GtkObjectClass*) class;
83
84        parent_class = gtk_type_class (gtk_object_get_type ());
85
86        status_docklet_signals[BUILD_PLUG_SIGNAL] =
87                gtk_signal_new("build_plug",
88                               GTK_RUN_FIRST,
89                               object_class->type,
90                               GTK_SIGNAL_OFFSET(StatusDockletClass,
91                                                 build_plug),
92                               marshal_signal_build,
93                               GTK_TYPE_NONE,
94                               1,
95                               GTK_TYPE_POINTER);
96
97        gtk_object_class_add_signals(object_class,status_docklet_signals,
98                                     LAST_SIGNAL);
99
100        class->build_plug = status_docklet_build_plug;
101        object_class->destroy = status_docklet_destroy;
102}
103
104static void
105status_docklet_init (StatusDocklet *docklet)
106{
107        g_return_if_fail(docklet != NULL);
108        g_return_if_fail(IS_STATUS_DOCKLET(docklet));
109       
110        docklet->timeout_handle = -1;
111        docklet->sspot = CORBA_OBJECT_NIL;
112}
113
114static void
115status_docklet_destroy(GtkObject *o)
116{
117        StatusDocklet *docklet;
118
119        g_return_if_fail(o != NULL);
120        g_return_if_fail(IS_STATUS_DOCKLET(o));
121       
122        docklet = STATUS_DOCKLET(o);
123       
124        if(docklet->timeout_handle != -1)
125                gtk_timeout_remove(docklet->timeout_handle);
126       
127        /*if we do have a plug, set the "status_docklet" data to NULL,
128          so that any timeout on it fails*/
129        if(docklet->plug)
130                gtk_object_set_data(GTK_OBJECT(docklet->plug),"status_docklet",NULL);
131       
132        /*this will actually kill the status spot, including destroying the
133          plug for us, so we don't really want to destroy it if we can just
134          do this*/
135        if(docklet->sspot != CORBA_OBJECT_NIL) {
136                CORBA_Environment ev;
137
138                CORBA_exception_init(&ev);
139                GNOME_StatusSpot_remove(docklet->sspot, &ev);
140                CORBA_Object_release(docklet->sspot, &ev);
141                CORBA_exception_free(&ev);
142        }
143       
144        if (GTK_OBJECT_CLASS (parent_class)->destroy)
145                (* GTK_OBJECT_CLASS (parent_class)->destroy) (o);
146}
147
148static void
149status_docklet_build_plug(StatusDocklet *docklet, GtkWidget *plug)
150{
151        g_return_if_fail(docklet != NULL);
152        g_return_if_fail(IS_STATUS_DOCKLET(docklet));
153
154        docklet->plug = plug;
155}
156
157/**
158 * status_docklet_new:
159 *
160 * Description:  Creates a new status docklet object with the default
161 * parameters.  By default the docklet object will try to contact a panel
162 * %STATUS_DOCKLET_DEFAULT_RETRIES times (20).  It will try to find a
163 * panel every 15 seconds.  You need to bind the build_plug signal
164 * in which you build your own widget and add it to the provided container.
165 * By default the docklet object will handle a panel restart, in which case
166 * your widget will be destroyed and when the panel is contacted again the
167 * build_plug signal will be emitted again.  You also must call the
168 * #status_docklet_run function after you bind the build_plug signal.
169 *
170 * Returns: new status docklet object.
171 **/
172GtkObject*
173status_docklet_new(void)
174{
175        return status_docklet_new_full(STATUS_DOCKLET_DEFAULT_RETRIES,TRUE);
176}
177
178static void
179plug_destroyed(GtkWidget *plug, gpointer data)
180{
181        StatusDocklet *docklet = gtk_object_get_data(GTK_OBJECT(plug),"status_docklet");
182        if(!docklet) return;
183
184        docklet->plug = NULL;
185
186        if(docklet->sspot != CORBA_OBJECT_NIL) {
187                CORBA_Environment ev;
188                CORBA_exception_init(&ev);
189                CORBA_Object_release(docklet->sspot, &ev);
190                docklet->sspot = CORBA_OBJECT_NIL;
191                CORBA_exception_free(&ev);
192        }
193       
194        if(docklet->handle_restarts) {
195                docklet->tries = 0;
196                status_docklet_run(docklet);
197        }
198}
199
200static gboolean
201try_getting_plug(StatusDocklet *docklet)
202{
203        CORBA_Environment ev;
204        GNOME_Panel panel_client = CORBA_OBJECT_NIL;
205        GNOME_StatusSpot spot = CORBA_OBJECT_NIL;
206        CORBA_unsigned_long wid = 0;
207       
208        /*XXX: can these two next cases actually happen???*/
209
210        /*huh? what's going on here, just smash this and let's do it over*/
211        if(docklet->plug != NULL) {
212                gtk_object_set_data(GTK_OBJECT(docklet->plug), "status_docklet", NULL);
213                gtk_widget_destroy(docklet->plug);
214                docklet->plug = NULL;
215        }
216
217        /*huh? yet again, something is terribly wrong*/
218        if(docklet->sspot != CORBA_OBJECT_NIL) {
219                CORBA_exception_init(&ev);
220                CORBA_Object_release(docklet->sspot, &ev);
221                docklet->sspot = CORBA_OBJECT_NIL;
222                CORBA_exception_free(&ev);
223        }
224
225        panel_client =
226                goad_server_activate_with_repo_id(NULL,
227                                                  "IDL:GNOME/Panel:1.0",
228                                                  GOAD_ACTIVATE_EXISTING_ONLY,
229                                                  NULL);
230       
231        if(panel_client == NULL)
232                return FALSE;
233
234        CORBA_exception_init(&ev);
235        spot = GNOME_Panel_add_status(panel_client, &wid, &ev);
236        /*something must have gone wrong*/
237        if(ev._major != CORBA_NO_EXCEPTION) {
238                CORBA_exception_free(&ev);
239                return FALSE;
240        }
241
242        /*we are probably inhibited from adding because of panel quitting*/
243        if(wid == 0) {
244                if(spot != CORBA_OBJECT_NIL)
245                        CORBA_Object_release(spot, &ev);
246                CORBA_exception_free(&ev);
247                return FALSE;
248        }
249
250        docklet->sspot = spot;
251        docklet->plug = gtk_plug_new(wid);
252
253        /*something must have gone terribly wrong*/
254        if(docklet->plug == NULL) {
255                CORBA_Object_release(spot, &ev);
256                docklet->sspot = CORBA_OBJECT_NIL;
257                CORBA_exception_free(&ev);
258                return FALSE;
259        }
260
261        CORBA_exception_free(&ev);
262
263        gtk_object_set_data(GTK_OBJECT(docklet->plug), "status_docklet", docklet);
264        gtk_signal_connect(GTK_OBJECT(docklet->plug), "destroy",
265                           GTK_SIGNAL_FUNC(plug_destroyed),
266                           NULL);
267        gtk_widget_show(docklet->plug);
268
269        gtk_signal_emit(GTK_OBJECT(docklet),
270                        status_docklet_signals[BUILD_PLUG_SIGNAL],
271                        docklet->plug);
272       
273        return TRUE;
274}
275
276/**
277 * status_docklet_new_full:
278 * @maximum_retries:  Maximum number of times to try to contact panel
279 * @handle_restarts:  If you handle panel restarts
280 *
281 * Description:  Creates a neew status docklet object with the specified
282 * parameters.  See the description of #status_docklet_new for details.
283 *
284 * Returns:  a new docklet object
285 **/
286GtkObject*
287status_docklet_new_full(int maximum_retries, gboolean handle_restarts)
288{
289        StatusDocklet *docklet;
290
291        docklet = STATUS_DOCKLET(gtk_type_new(status_docklet_get_type()));
292       
293        docklet->maximum_retries = maximum_retries;
294        docklet->handle_restarts = handle_restarts;
295       
296        return GTK_OBJECT(docklet);
297}
298
299static gint
300try_timeout(gpointer data)
301{
302        StatusDocklet *docklet = data;
303
304        g_return_val_if_fail(docklet != NULL,FALSE);
305        g_return_val_if_fail(IS_STATUS_DOCKLET(docklet),FALSE);
306
307        docklet->timeout_handle = -1;
308       
309        /*lets try it again*/
310        status_docklet_run(docklet);
311       
312        return FALSE;
313}
314
315/**
316 * status_docklet_run:
317 * @docklet: #StatusDocklet to run
318 *
319 * Description:  Search for the panel and add the plug if it finds it.  This
320 * function is also called internally from the timeout.  If called externally
321 * more times, a panel lookup will be forced and one try will be wasted.  You
322 * need to call this function at least once after binding the build_plug
323 * signal to tell the status docklet to start looking for the panel.
324 * If the status docklet handles restarts you don't have to call this
325 * function ever again.
326 **/
327void
328status_docklet_run(StatusDocklet *docklet)
329{
330        g_return_if_fail(docklet != NULL);
331        g_return_if_fail(IS_STATUS_DOCKLET(docklet));
332
333        if(docklet->timeout_handle != -1)
334                gtk_timeout_remove(docklet->timeout_handle);
335
336        if(!try_getting_plug(docklet)) {
337                docklet->tries ++;
338                if(docklet->tries < docklet->maximum_retries)
339                        docklet->timeout_handle = gtk_timeout_add(STATUS_DOCKLET_RETRY_EVERY*1000,
340                                                                  try_timeout,docklet);
341                else
342                        docklet->tries = 0;
343        } else {
344                docklet->tries = 0;
345        }
346}
Note: See TracBrowser for help on using the repository browser.