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

Revision 15821, 8.0 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/* Gnome panel: status applet
2 * (C) 1999-2000 the Free Software Foundation
3 *
4 * Authors:  George Lebl
5 */
6
7#include <config.h>
8#include <string.h>
9#include <signal.h>
10#include <gnome.h>
11#include <gdk/gdkx.h>
12#include <X11/Xlib.h>
13#include <X11/Xatom.h>
14
15#include "panel-include.h"
16#include "gnome-panel.h"
17
18#include "xstuff.h"
19
20static StatusApplet *the_status = NULL; /*"there can only be one" status
21                                          applet*/
22static GtkWidget *offscreen = NULL; /*offscreen window for putting status
23                                      spots if there is no status applet*/
24static GtkWidget *fixed = NULL; /*the fixed container in which the docklets reside*/
25static GSList *spots = NULL;
26static int nspots = 0;
27
28gboolean status_inhibit = FALSE; /*inhibit adding and updating for the purpose
29                                   of quitting*/
30
31extern GSList *applets;
32extern GSList *applets_last;
33extern int applet_count;
34
35extern PortableServer_POA thepoa;
36
37#define DOCKLET_SPOT 22
38
39#define MINIMUM_WIDTH 10
40
41/*this will show debug output and put the offscreen window on 10 10 to
42  view it*/
43/*#define DEBUG_STATUS 1*/
44
45#ifdef DEBUG_STATUS
46#define DPUTS(x) puts(x)
47#define DPRINTD(d) printf("%s: %d\n",#d,d)
48#else
49#define DPUTS(x)
50#define DPRINTD(d)
51#endif
52
53StatusSpot *
54status_applet_get_ss(guint32 winid)
55{
56        GSList *li;
57        for(li = spots; li; li = li->next) {
58                StatusSpot *ss = li->data;
59                GtkSocket *s = GTK_SOCKET(ss->socket);
60                if(s->plug_window &&
61                   GDK_WINDOW_XWINDOW(s->plug_window) == winid)
62                        return ss;
63        }
64        return NULL;
65}
66
67static void
68ensure_fixed_and_offscreen(void)
69{
70        if(!offscreen) {
71                /* this is not supposed to happen so give a warning */
72                g_warning("offscreen not created yet, we must be on crack");
73                status_applet_create_offscreen();
74        }
75        if(!fixed) {
76                /* this is even weirder */
77                g_warning("fixed not created yet, we must really be on crack");
78                status_applet_create_offscreen();
79                fixed = gtk_fixed_new();
80                gtk_container_add(GTK_CONTAINER(offscreen), fixed);
81                gtk_widget_show_now(fixed);
82        }
83}
84
85void
86status_applet_update(StatusApplet *s)
87{
88        GSList *li;
89        int w,h;
90        int sz;
91        int rows;
92        int i,j;
93       
94        if(status_inhibit)
95                return;
96       
97        DPUTS("STATUS_APPLET_UPDATE");
98        DPRINTD(nspots);
99
100        if(s->orient == PANEL_HORIZONTAL)
101                GTK_HANDLE_BOX(s->handle)->handle_position = GTK_POS_LEFT;
102        else
103                GTK_HANDLE_BOX(s->handle)->handle_position = GTK_POS_TOP;
104       
105        sz = s->size;
106       
107        rows = s->size / DOCKLET_SPOT;
108
109        if (rows <= 0)
110                rows = 1;
111
112        if(nspots%rows == 0)
113                w = DOCKLET_SPOT*(nspots/rows);
114        else
115                w = DOCKLET_SPOT*((nspots/rows)+1);
116       
117        /*make minimum size*/
118        if(w < MINIMUM_WIDTH) w = MINIMUM_WIDTH;       
119
120        h = DOCKLET_SPOT*rows;
121
122        /*if we are vertical just switch stuff around*/
123        if(s->orient == PANEL_VERTICAL) {
124                int t = w;
125                w = h;
126                h = t;
127        }
128       
129        gtk_widget_set_usize(fixed,w,h);
130
131        DPRINTD(w);
132        DPRINTD(h);
133       
134        i = j = 0;
135        for(li = spots; li; li = li->next) {
136                StatusSpot *ss = li->data;
137                gtk_fixed_move(GTK_FIXED(fixed),ss->socket,i,j);
138                i+=DOCKLET_SPOT;
139                if(i>=w) {
140                        i = 0;
141                        j+=DOCKLET_SPOT;
142                }
143        }
144        if(s->handle && s->handle->parent)
145                gtk_widget_queue_resize(s->handle->parent);
146}
147
148static void
149status_socket_destroyed(GtkWidget *w, StatusSpot *ss)
150{
151        /*so that we don't get called recursively, we set the ->socket to
152          null inside status_spot_remove*/
153        if(ss->socket)
154                status_spot_remove(ss, FALSE);
155}
156
157StatusSpot *
158new_status_spot(void)
159{
160        StatusSpot *ss;
161       
162        if(status_inhibit)
163                return NULL;
164       
165        DPUTS("NEW_STATUS_SPOT");
166
167        ss = g_new0(StatusSpot,1);
168        ss->wid = 0;
169        ss->sspot = CORBA_OBJECT_NIL;
170
171        spots = g_slist_prepend(spots,ss);
172        nspots++;
173
174        ss->socket = gtk_socket_new();
175        gtk_widget_set_usize(ss->socket,DOCKLET_SPOT,DOCKLET_SPOT);
176
177        /* ensures that fixed and offscreen exist, even though they
178         * should have been created long ago, but I guess it's better
179         * then failing an assert and disappearing */
180        ensure_fixed_and_offscreen();
181
182        gtk_fixed_put(GTK_FIXED(fixed),ss->socket,0,0);
183        if(the_status)
184                status_applet_update(the_status);
185
186        gtk_widget_show_now(ss->socket);
187        gtk_signal_connect(GTK_OBJECT(ss->socket),"destroy",
188                           GTK_SIGNAL_FUNC(status_socket_destroyed),
189                           ss);
190       
191        ss->wid = GDK_WINDOW_XWINDOW(ss->socket->window);
192        return ss;
193}
194
195void
196status_spot_remove(StatusSpot *ss, gboolean destroy_socket)
197{
198        CORBA_Environment ev;
199        PortableServer_ObjectId *id;
200        GtkWidget *w;
201
202        spots = g_slist_remove(spots,ss);
203        nspots--;
204       
205        /*set socket to NULL, as to indicate that we have taken
206          care of destruction here*/
207        if(destroy_socket) {
208                w = ss->socket;
209                ss->socket = NULL;
210                gtk_widget_destroy(w);
211        }
212
213        DPUTS("STATUS_SPOT_REMOVE");
214        DPRINTD(nspots);
215        DPRINTD(g_slist_length(spots));
216
217        if(ss->sspot != CORBA_OBJECT_NIL) {
218                CORBA_exception_init(&ev);
219                CORBA_Object_release(ss->sspot, &ev);
220                id = PortableServer_POA_servant_to_id(thepoa, ss, &ev);
221                PortableServer_POA_deactivate_object(thepoa, id, &ev);
222                CORBA_free (id);
223                POA_GNOME_StatusSpot__fini((PortableServer_Servant) ss, &ev);
224                CORBA_exception_free(&ev);
225        }
226
227        g_free(ss);
228        if(the_status) status_applet_update(the_status);
229}
230
231/*kill all status spots*/
232void
233status_spot_remove_all(void)
234{
235        DPUTS("STATUS_SPOT_REMOVE_ALL");
236
237        while(spots)
238                status_spot_remove(spots->data, TRUE);
239       
240        DPUTS("DONE REMOVE_ALL");
241}
242
243void
244status_applet_put_offscreen(StatusApplet *s)
245{
246        DPUTS("PUT_OFFSCREEN");
247
248        /* ensures that fixed and offscreen exist, even though they
249         * should have been created long ago, but I guess it's better
250         * then failing an assert and disappearing */
251        ensure_fixed_and_offscreen();
252
253        if(fixed->parent != offscreen) {
254                DPUTS("REPARENT");
255                gtk_widget_reparent(fixed, offscreen);
256                DPUTS("REPARENT DONE");
257        }
258}
259
260void
261status_applet_create_offscreen(void)
262{
263        DPUTS("CREATE OFFSCREEN");
264        offscreen = gtk_window_new(GTK_WINDOW_POPUP);
265#ifdef DEBUG_STATUS
266        gtk_widget_set_uposition(offscreen,10,10);
267#else
268        gtk_widget_set_uposition(offscreen, gdk_screen_width()+10,
269                                 gdk_screen_height()+10);
270#endif
271        if(!fixed) {
272                fixed = gtk_fixed_new();
273                gtk_widget_show(fixed);
274
275                gtk_container_add(GTK_CONTAINER(offscreen), fixed);
276        }
277
278        gtk_widget_show_now(offscreen);
279
280        /* if this fails we are seriously in trouble */
281        g_assert(offscreen->window);
282
283        xstuff_setup_kde_dock_thingie(offscreen->window);
284}
285
286static int
287ignore_1st_click(GtkWidget *widget, GdkEvent *event)
288{
289        GdkEventButton *buttonevent = (GdkEventButton *)event;
290
291        if((event->type == GDK_BUTTON_PRESS &&
292            buttonevent->button == 1) ||
293           (event->type == GDK_BUTTON_RELEASE &&
294            buttonevent->button == 1)) {
295                buttonevent->button = 2;
296        }
297         
298        return FALSE;
299}
300
301static void
302free_status (gpointer data)
303{
304        StatusApplet *s = data;
305        g_free(s);
306
307        the_status = NULL;
308}
309
310static void
311reparent_fixed(GtkWidget *frame)
312{
313        if(fixed->parent != frame) {
314                DPUTS("REPARENT");
315                gtk_widget_reparent(fixed, frame);
316                DPUTS("REPARENT DONE");
317        }
318}
319
320gboolean
321load_status_applet(PanelWidget *panel, int pos, gboolean exactpos)
322{
323        GtkWidget *ebox;
324        if(the_status)
325                return FALSE;
326
327        DPUTS("LOAD_STATUS_APPLET");
328       
329        the_status = g_new0(StatusApplet,1);
330        the_status->orient = panel->orient;
331        the_status->size = panel->sz;
332        the_status->handle = gtk_handle_box_new();
333        gtk_handle_box_set_shadow_type(GTK_HANDLE_BOX(the_status->handle),
334                                       GTK_SHADOW_IN);
335        gtk_container_set_border_width(GTK_CONTAINER(the_status->handle),
336                                       1);
337        gtk_signal_connect(GTK_OBJECT(the_status->handle), "event",
338                           GTK_SIGNAL_FUNC(ignore_1st_click), NULL);
339
340        if(!fixed) {
341                DPUTS("NO FIXED");
342                fixed = gtk_fixed_new();
343                gtk_container_set_border_width(GTK_CONTAINER(fixed),
344                                               0);
345                gtk_widget_show(fixed);
346
347                gtk_container_add(GTK_CONTAINER(the_status->handle), fixed);
348        } else {
349                gtk_signal_connect_after(GTK_OBJECT(the_status->handle), "realize",
350                                         GTK_SIGNAL_FUNC(reparent_fixed),
351                                         NULL);
352        }
353       
354        status_applet_update(the_status);
355       
356        ebox = gtk_event_box_new();
357        gtk_container_set_border_width(GTK_CONTAINER(ebox),
358                                       0);
359        gtk_widget_show(ebox);
360        gtk_container_add(GTK_CONTAINER(ebox),the_status->handle);
361
362        if(!register_toy(ebox, the_status, free_status,
363                         panel, pos, exactpos, APPLET_STATUS))
364                return TRUE;
365        the_status->info = applets_last->data;
366        applet_add_callback(applets_last->data, "help",
367                            GNOME_STOCK_PIXMAP_HELP,
368                            _("Help"));
369        return TRUE;
370}
Note: See TracBrowser for help on using the repository browser.