source: trunk/third/gnome-core/panel/main.c @ 17167

Revision 17167, 14.8 KB checked in by ghudson, 23 years ago (diff)
Merge with gnome-core 1.4.0.6.
Line 
1/* Gnome panel: Initialization routines
2 * (C) 1997,1998,1999,2000 the Free Software Foundation
3 * (C) 2000 Eazel, Inc.
4 *
5 * Authors: Federico Mena
6 *          Miguel de Icaza
7 *          George Lebl
8 */
9
10#include <config.h>
11#include <string.h>
12#include <signal.h>
13#include <sys/wait.h>
14#include <gnome.h>
15#include <libgnorba/gnorba.h>
16#include <libgnomeui/gnome-window-icon.h>
17
18#include "panel-include.h"
19
20#include "gwmh.h"
21
22#include "xstuff.h"
23#include "multiscreen-stuff.h"
24#include "conditional.h"
25
26extern int config_sync_timeout;
27extern int applets_to_sync;
28extern int panels_to_sync;
29extern int need_complete_save;
30
31extern GSList *panels;
32
33extern GSList *applets;
34extern GSList *applets_last;
35extern int applet_count;
36
37extern gboolean commie_mode;
38extern GlobalConfig global_config;
39extern char *panel_cfg_path;
40extern char *old_panel_cfg_path;
41
42extern GdkPixmap *desktop_pixmap;
43
44/*list of all panel widgets created*/
45extern GSList *panel_list;
46
47GtkTooltips *panel_tooltips = NULL;
48
49GnomeClient *client = NULL;
50
51char *kde_menudir = NULL;
52char *kde_icondir = NULL;
53char *kde_mini_icondir = NULL;
54
55char *merge_merge_dir = NULL;
56int merge_main_dir_len = 0;
57char *merge_main_dir = NULL;
58
59gboolean panel_in_startup = TRUE;
60
61static gboolean
62menu_age_timeout(gpointer data)
63{
64        GSList *li;
65        for(li=applets;li!=NULL;li=g_slist_next(li)) {
66                AppletInfo *info = li->data;
67                if(info->menu && info->menu_age++>=6 &&
68                   !GTK_WIDGET_VISIBLE(info->menu)) {
69                        gtk_widget_unref(info->menu);
70                        info->menu = NULL;
71                        info->menu_age = 0;
72                }
73                /*if we are allowed to, don't destroy applet menus*/
74                if(!global_config.hungry_menus &&
75                   info->type == APPLET_MENU) {
76                        Menu *menu = info->data;
77                        if(menu->menu && menu->age++>=6 &&
78                           !GTK_WIDGET_VISIBLE(menu->menu)) {
79                                gtk_widget_unref(menu->menu);
80                                menu->menu = NULL;
81                                menu->age = 0;
82                        }
83                }
84        }
85       
86        /*skip panel menus if we are memory hungry*/
87        if(global_config.hungry_menus)
88                return TRUE;
89       
90        for(li = panel_list; li != NULL; li = g_slist_next(li)) {
91                PanelData *pd = li->data;
92                if(pd->menu && pd->menu_age++>=6 &&
93                   !GTK_WIDGET_VISIBLE(pd->menu)) {
94                        gtk_widget_unref(pd->menu);
95                        pd->menu = NULL;
96                        pd->menu_age = 0;
97                }
98        }
99
100        return TRUE;
101}
102
103/* Some important code copied from PonG */
104typedef struct _AppletContainer AppletContainer;
105struct _AppletContainer {
106        GdkWindow *win;
107        gboolean hide_mode;
108        int state;
109        int x, y, xs, ys;
110        int handler;
111        GdkPixmap *phsh[4];
112        GdkBitmap *phsh_mask[4];
113};
114AppletContainer phsh = {0};
115
116static void
117phsh_kill (void)
118{
119        int i;
120        for (i = 0; i < 4; i++) {
121                gdk_pixmap_unref (phsh.phsh[i]);
122                gdk_bitmap_unref (phsh.phsh_mask[i]);
123        }
124        gdk_window_destroy (phsh.win);
125        gtk_timeout_remove (phsh.handler);
126        memset (&phsh, 0, sizeof (AppletContainer));
127}
128
129static gboolean
130phsh_move (gpointer data)
131{
132        int orient, state;
133        gboolean change = TRUE;
134
135        phsh.x += phsh.xs;
136        phsh.y += phsh.ys;
137        if (phsh.x <= -60 ||
138            phsh.x >= gdk_screen_width ()) {
139                phsh_kill ();
140                return FALSE;
141        }
142        if (phsh.y <= 0 ||
143            phsh.y >= gdk_screen_height () - 40 ||
144            rand() % (phsh.hide_mode?10:50) == 0)
145                phsh.ys = -phsh.ys;
146
147        phsh.state ++;
148        if (phsh.state % (phsh.hide_mode?2:4) == 0)
149                change = TRUE;
150        if (phsh.state >= (phsh.hide_mode?4:8))
151                phsh.state = 0;
152
153        state = phsh.state >= (phsh.hide_mode?2:4) ? 1 : 0;
154        orient = phsh.xs >= 0 ? 0 : 2;
155
156        if (change) {
157                gdk_window_set_back_pixmap (phsh.win, phsh.phsh[orient + state], FALSE);
158                gdk_window_shape_combine_mask (phsh.win, phsh.phsh_mask[orient + state], 0, 0);
159                gdk_window_clear (phsh.win);
160        }
161
162        gdk_window_move (phsh.win, phsh.x, phsh.y);
163        gdk_window_raise (phsh.win);
164
165        return TRUE;
166}
167
168static void
169phsh_reverse (GdkPixbuf *gp)
170{
171        guchar *pixels = gdk_pixbuf_get_pixels (gp);
172        int x, y;
173        int rs = gdk_pixbuf_get_rowstride (gp);
174#define DOSWAP(x,y) tmp = x; x = y; y = tmp;
175        for (y = 0; y < 40; y++, pixels += rs) {
176                guchar *p = pixels;
177                guchar *p2 = pixels + 60*4 - 4;
178                for (x = 0; x < 30; x++, p+=4, p2-=4) {
179                        guchar tmp;
180                        DOSWAP (p[0], p2[0]);
181                        DOSWAP (p[1], p2[1]);
182                        DOSWAP (p[2], p2[2]);
183                        DOSWAP (p[3], p2[3]);
184                }
185        }
186#undef DOSWAP
187}
188
189/* This dered's the phsh */
190static void
191phsh_dered(GdkPixbuf *gp)
192{
193        guchar *pixels = gdk_pixbuf_get_pixels (gp);
194        int x, y;
195        int rs = gdk_pixbuf_get_rowstride (gp);
196        for (y = 0; y < 40; y++, pixels += rs) {
197                guchar *p = pixels;
198                for (x = 0; x < 60; x++, p+=4) {
199                        if (p[0] < 55 && p[1] > 100)
200                               p[3] = 0;       
201                }
202        }
203}
204
205static GdkFilterReturn
206phsh_filter (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
207{
208        XEvent *xevent = (XEvent *)gdk_xevent;
209
210        if (xevent->type == ButtonPress &&
211            ! phsh.hide_mode) {
212                gtk_timeout_remove (phsh.handler);
213                phsh.handler = gtk_timeout_add (90, phsh_move, NULL);
214                phsh.xs *= 2.0;
215                phsh.ys *= 2.5;
216                phsh.hide_mode = TRUE;
217                if (phsh.x < (gdk_screen_width () / 2))
218                        phsh.xs *= -1;
219        }
220        return GDK_FILTER_CONTINUE;
221}
222
223/* this checks the screen */
224static void
225check_screen (void)
226{
227        GdkWindowAttr attributes;
228        char *phsh_file;
229        char *name;
230        GdkPixbuf *gp, *tmp;
231
232        if (phsh.win != NULL)
233                return;
234
235        name = g_strdup_printf ("%cish/%cishanim.png",
236                                'f', 'f');
237        phsh_file = gnome_pixmap_file (name);
238        g_free (name);
239        if (phsh_file == NULL)
240                return;
241
242        tmp = gdk_pixbuf_new_from_file (phsh_file);
243        if (tmp == NULL)
244                return;
245
246        g_free (phsh_file);
247
248        if (gdk_pixbuf_get_width (tmp) != 180 ||
249            gdk_pixbuf_get_height (tmp) != 40) {
250                gdk_pixbuf_unref (tmp);
251                return;
252        }
253
254        phsh.state = 0;
255        phsh.hide_mode = FALSE;
256
257        gp = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, 60, 40);
258        gdk_pixbuf_copy_area (tmp, 60, 0, 60, 40, gp, 0, 0);
259
260        phsh_dered (gp);
261        gdk_pixbuf_render_pixmap_and_mask (gp, &phsh.phsh[2], &phsh.phsh_mask[2], 128);
262        phsh_reverse (gp);
263        gdk_pixbuf_render_pixmap_and_mask (gp, &phsh.phsh[0], &phsh.phsh_mask[0], 128);
264
265        gdk_pixbuf_copy_area (tmp, 120, 0, 60, 40, gp, 0, 0);
266
267        phsh_dered (gp);
268        gdk_pixbuf_render_pixmap_and_mask (gp, &phsh.phsh[3], &phsh.phsh_mask[3], 128);
269        phsh_reverse (gp);
270        gdk_pixbuf_render_pixmap_and_mask (gp, &phsh.phsh[1], &phsh.phsh_mask[1], 128);
271        gdk_pixbuf_unref (gp);
272
273        gdk_pixbuf_unref (tmp);
274       
275        phsh.x = -60;
276        phsh.y = (rand() % (gdk_screen_height () - 40 - 2)) + 1;
277        phsh.xs = 8;
278        phsh.ys = (rand() % 2) + 1;
279
280        attributes.window_type = GDK_WINDOW_TEMP;
281        attributes.x = phsh.x;
282        attributes.y = phsh.y;
283        attributes.width = 60;
284        attributes.height = 40;
285        attributes.wclass = GDK_INPUT_OUTPUT;
286        attributes.visual = gdk_rgb_get_visual();
287        attributes.colormap = gdk_rgb_get_cmap();
288        attributes.event_mask = GDK_BUTTON_PRESS_MASK;
289
290        phsh.win = gdk_window_new (NULL, &attributes,
291                                   GDK_WA_X | GDK_WA_Y |
292                                   GDK_WA_VISUAL | GDK_WA_COLORMAP);
293        gdk_window_set_back_pixmap (phsh.win, phsh.phsh[0], FALSE);
294        gdk_window_shape_combine_mask (phsh.win, phsh.phsh_mask[0], 0, 0);
295
296        /* setup the keys filter */
297        gdk_window_add_filter (phsh.win,
298                               phsh_filter,
299                               NULL);
300
301        gdk_window_show (phsh.win);
302        phsh.handler = gtk_timeout_add (150, phsh_move, NULL);
303}
304
305static guint screen_check_id = 0;
306
307static gboolean
308check_screen_timeout (gpointer data)
309{
310        screen_check_id = 0;
311
312        check_screen ();
313
314        screen_check_id = gtk_timeout_add (rand()%120*1000,
315                                           check_screen_timeout, NULL);
316        return FALSE;
317}
318
319void
320start_screen_check (void)
321{
322        if (screen_check_id > 0)
323                gtk_timeout_remove (screen_check_id);
324
325        screen_check_id = 0;
326        check_screen ();
327
328        screen_check_id = gtk_timeout_add (rand()%120*1000, check_screen_timeout, NULL);
329}
330
331static int
332try_config_sync(gpointer data)
333{
334        panel_config_sync();
335        return TRUE;
336}
337
338static void
339find_kde_directory(void)
340{
341        int i;
342        char *kdedir = g_getenv ("KDEDIR");
343        char *try_prefixes[] = {
344                "/usr",
345                "/opt/kde",
346                "/usr/local",
347                "/kde",
348                NULL
349        };
350        if(kdedir) {
351                kde_menudir = g_concat_dir_and_file(kdedir,"share/applnk");
352                kde_icondir = g_concat_dir_and_file(kdedir,"share/icons");
353                kde_mini_icondir = g_concat_dir_and_file(kdedir,"share/icons/mini");
354                return;
355        }
356
357        /* if what configure gave us works use that */
358        if(g_file_test(KDE_MENUDIR,G_FILE_TEST_ISDIR)) {
359                kde_menudir = g_strdup(KDE_MENUDIR);
360                kde_icondir = g_strdup(KDE_ICONDIR);
361                kde_mini_icondir = g_strdup(KDE_MINI_ICONDIR);
362                return;
363        }
364
365        for(i=0;try_prefixes[i];i++) {
366                char *try;
367                try = g_concat_dir_and_file(try_prefixes[i],"share/applnk");
368                if(g_file_test(try,G_FILE_TEST_ISDIR)) {
369                        kde_menudir = try;
370                        kde_icondir = g_concat_dir_and_file(try_prefixes[i],"share/icons");
371                        kde_mini_icondir = g_concat_dir_and_file(try_prefixes[i],"share/icons/mini");
372                        return;
373                }
374                g_free(try);
375        }
376
377        /* absolute fallback, these don't exist, but we're out of options
378           here */
379        kde_menudir = g_strdup(KDE_MENUDIR);
380        kde_icondir = g_strdup(KDE_ICONDIR);
381        kde_mini_icondir = g_strdup(KDE_MINI_ICONDIR);
382}
383
384static void
385setup_merge_directory(void)
386{
387        int len;
388
389        merge_main_dir = gnome_datadir_file("gnome/apps/");
390        merge_main_dir_len = merge_main_dir != NULL ? strlen (merge_main_dir) : 0;
391        merge_merge_dir = conditional_get_string ("/panel/Merge/Directory",
392                                                  "/etc/X11/applnk/",
393                                                  NULL);
394
395        if (string_empty (merge_merge_dir) ||
396            ! g_file_test(merge_merge_dir, G_FILE_TEST_ISDIR)) {
397                g_free(merge_merge_dir);
398                merge_merge_dir = NULL;
399                return;
400        }
401
402        len = strlen(merge_merge_dir);
403        if (merge_merge_dir[len-1] != '/') {
404                char *tmp = g_strconcat(merge_merge_dir, "/", NULL);
405                g_free(merge_merge_dir);
406                merge_merge_dir = tmp;
407        }
408}
409
410static void
411setup_visuals (void)
412{
413        gdk_rgb_init ();
414        gtk_widget_push_visual (gdk_rgb_get_visual ());
415        gtk_widget_push_colormap (gdk_rgb_get_cmap ());
416}
417
418static void
419kill_free_drawers (void)
420{
421        GSList *li;
422        for (li = panel_list; li != NULL; li = li->next) {
423                PanelData *pd = li->data;
424                if (IS_DRAWER_WIDGET (pd->panel) &&
425                    PANEL_WIDGET (BASEP_WIDGET (pd->panel)->panel)->master_widget == NULL) {
426                        status_unparent (pd->panel);
427                        gtk_widget_destroy (pd->panel);
428                }
429        }
430}
431
432/* gets a GdkPixmap for a given X atom name whose value is an X Pixmap */
433static GdkPixmap *
434get_pixmap_prop (char *prop_id)
435{
436        Atom prop, type;
437        int format;
438        unsigned long length, after;
439        unsigned char *data;
440        Pixmap p;
441
442        prop = XInternAtom(GDK_DISPLAY(), prop_id, True);
443
444        if (prop == None) {
445                return NULL;
446        }
447
448        XGetWindowProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), prop, 0L, 1L,
449                        False, AnyPropertyType, &type, &format, &length,
450                        &after, &data);
451
452        if (type != XA_PIXMAP) {
453                return NULL;
454        }
455
456        p = *((Pixmap *)data);
457
458        /* remember not to unref this pixmap */
459        return gdk_pixmap_foreign_new(p);
460}
461
462
463/* gets a GdkPixmap that refers to the GNOME desktop pixmap and stores it
464 * in desktop_pixmap.
465 */
466static void
467get_desktop_pixmap()
468{
469        desktop_pixmap = get_pixmap_prop ("_XROOTPMAP_ID");
470}
471
472/* an event handler for when the GNOME desktop pixmap changes */
473static GdkFilterReturn
474desktop_event_filter (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data)
475{
476        XEvent *xevent;
477        GSList *item;
478        PanelWidget *panel;
479
480        xevent = (XEvent *) gdk_xevent;
481
482        if (xevent->type == PropertyNotify && xevent->xproperty.atom ==
483                        gdk_atom_intern("ESETROOT_PMAP_ID", TRUE)) {
484
485                get_desktop_pixmap ();
486
487                for (item = panels; item; item = g_slist_next (item)) {
488                        panel = PANEL_WIDGET (item->data);
489
490                        if (panel->back_type == PANEL_BACK_TRANSLUCENT) {
491                                panel_widget_setup_translucent_background (panel);
492                                panel_widget_force_repaint (panel);
493                        }
494                }
495
496
497        }
498        return GDK_FILTER_CONTINUE;
499}
500
501/* set up the event handler */
502static void
503set_up_desktop_event_handler ()
504{
505        /* we need to watch for desktop image changes */
506        gdk_window_add_filter (GDK_ROOT_PARENT(), desktop_event_filter, NULL);
507}       
508
509
510int
511main(int argc, char **argv)
512{
513        CORBA_ORB orb;
514        CORBA_Environment ev;
515        gboolean duplicate;
516        gchar *real_global_path;
517       
518        bindtextdomain (PACKAGE, GNOMELOCALEDIR);
519        textdomain (PACKAGE);
520
521        CORBA_exception_init(&ev);
522        orb = gnome_CORBA_init("panel", VERSION,
523                               &argc, argv,
524                               GNORBA_INIT_SERVER_FUNC, &ev);
525        CORBA_exception_free(&ev);
526        gnome_window_icon_set_default_from_file (GNOME_ICONDIR"/gnome-panel.png");
527        setup_visuals ();
528
529        switch (panel_corba_gtk_init (orb)) {
530        case 0:
531                duplicate = FALSE;
532                break; /* success */
533        case -4: {
534                GtkWidget* box = gnome_question_dialog
535                        (_("I've detected a panel already running.\n"
536                           "Start another panel as well?\n"
537                           "(The new panel will not be restarted.)"), NULL, NULL);
538                panel_set_dialog_layer (box);
539                if (gnome_dialog_run_and_close (GNOME_DIALOG (box)))
540                        return 0;
541                duplicate = TRUE;
542                break;
543        }
544        default: {
545                GtkWidget *box = panel_error_dialog
546                        (_("There was a problem registering the panel "
547                           "with the GOAD server.\n"
548                           "The panel will now exit."));
549                gnome_dialog_run_and_close (GNOME_DIALOG (box));
550                return 0;
551                break;
552        }
553        }
554
555        setup_merge_directory();
556
557        find_kde_directory();
558
559        client = gnome_master_client ();
560
561        gnome_client_set_restart_style (client, duplicate
562                                        ? GNOME_RESTART_NEVER
563                                        : GNOME_RESTART_IMMEDIATELY);
564
565        gnome_client_set_priority (client, 40);
566
567
568        if (gnome_client_get_flags (client) & GNOME_CLIENT_RESTORED)
569                old_panel_cfg_path = g_strdup (gnome_client_get_config_prefix (client));
570        else
571                old_panel_cfg_path = g_strdup ("/panel.d/default/");
572
573#ifndef PER_SESSION_CONFIGURATION
574        real_global_path = gnome_config_get_real_path (old_panel_cfg_path);
575        if ( ! panel_file_exists (real_global_path)) {
576                g_free (old_panel_cfg_path);
577                old_panel_cfg_path = g_strdup ("/panel.d/default/");
578        }
579        g_free (real_global_path);
580#endif /* !PER_SESSION_CONFIGURATION */
581
582        gnome_client_set_global_config_prefix (client, PANEL_CONFIG_PATH);
583       
584        gtk_signal_connect (GTK_OBJECT (client), "save_yourself",
585                            GTK_SIGNAL_FUNC (panel_session_save), NULL);
586        gtk_signal_connect (GTK_OBJECT (client), "die",
587                            GTK_SIGNAL_FUNC (panel_session_die), NULL);
588
589        panel_tooltips = gtk_tooltips_new ();
590
591        xstuff_init ();
592        multiscreen_init ();
593
594        gnome_win_hints_init ();
595
596        load_system_wide ();
597
598        /* read, convert and remove old config */
599        if ( ! commie_mode)
600                convert_old_config ();
601
602        /* set the globals, it is important this is before
603         * init_user_applets */
604        load_up_globals ();
605        /* this is so the capplet gets the right defaults */
606        if ( ! commie_mode)
607                write_global_config ();
608
609        gwmh_init ();
610
611        init_fr_chunks ();
612       
613        init_menus ();
614
615        /* get the GNOME desktop image stuff */
616        get_desktop_pixmap ();
617        set_up_desktop_event_handler ();
618       
619        init_user_panels ();
620        init_user_applets ();
621
622        kill_free_drawers ();
623
624        load_tornoff ();
625
626        gnome_triggers_do ("Session startup", NULL, "gnome", "login", NULL);
627
628        /*add forbidden lists to ALL panels*/
629        g_slist_foreach (panels,
630                         (GFunc)panel_widget_add_forbidden,
631                         NULL);
632
633        /*this will make the drawers be hidden for closed panels etc ...*/
634        send_state_change ();
635
636        /*attempt to sync the config every 10 seconds, only if a change was
637          indicated though*/
638        config_sync_timeout = gtk_timeout_add (10*1000, try_config_sync, NULL);
639
640        /* add some timeouts */
641        gtk_timeout_add (10*1000, menu_age_timeout, NULL);
642
643        panel_in_startup = FALSE;
644       
645        /*load these as the last thing to prevent some races any races from
646          starting multiple goad_id's at once are libgnorba's problem*/
647        load_queued_externs ();
648
649        status_applet_create_offscreen ();
650
651        gtk_main ();
652
653        return 0;
654}
Note: See TracBrowser for help on using the repository browser.