source: trunk/third/gnome-core/panel/extern.c @ 17152

Revision 17152, 48.9 KB checked in by ghudson, 23 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17151, which included commits to RCS files with non-trunk default branches.
Line 
1/* Gnome panel: extern applet functions
2 * (C) 1997,1998,1999,2000 the Free Software Foundation
3 * (C) 2000 Eazel, Inc.
4 *
5 * Authors:  George Lebl
6 *           Federico Mena
7 *           Miguel de Icaza
8 */
9
10#include "config.h"
11#include <gnome.h>
12
13#include <gdk/gdkx.h>
14#include <string.h>
15#include <signal.h>
16
17#include "panel-include.h"
18#include "gnome-panel.h"
19#include "gnome-run.h"
20
21#define APPLET_EVENT_MASK (GDK_BUTTON_PRESS_MASK |              \
22                           GDK_BUTTON_RELEASE_MASK |            \
23                           GDK_POINTER_MOTION_MASK |            \
24                           GDK_POINTER_MOTION_HINT_MASK)
25
26#define pg_return_if_fail(evp,x) {if(!(x)) { g_warning("file %s: line %d: Corba Exception: type = %d exid = %s\n", __FILE__, __LINE__, (evp)->_major, (evp)->_repo_id); return; }}
27#define pg_return_val_if_fail(evp,x,y) {if(!(x)) { g_warning("file %s: line %d: Corba Exception: type = %d exid = %s\n", __FILE__, __LINE__, (evp)->_major, (evp)->_repo_id); return y;}}
28
29extern GSList *panels;
30
31extern GSList *applets;
32extern GSList *applets_last;
33extern int applet_count;
34
35extern int config_sync_timeout;
36extern int applets_to_sync;
37extern int panels_to_sync;
38extern int need_complete_save;
39
40extern GtkTooltips *panel_tooltips;
41
42extern GlobalConfig global_config;
43extern gboolean commie_mode;
44
45extern char *panel_cfg_path;
46extern char *old_panel_cfg_path;
47
48extern int ss_cur_applet;
49extern gboolean ss_done_save;
50extern GtkWidget* ss_timeout_dlg;
51extern gushort ss_cookie;
52
53extern gboolean panel_in_startup;
54
55/* Launching applets into other things then the panel */
56
57typedef struct {
58        char *goad_id;
59        GNOME_PanelAppletBooter booter;
60} OutsideExtern;
61
62static GSList *outside_externs = NULL;
63
64static void
65push_outside_extern (const char *goad_id,
66                     const GNOME_PanelAppletBooter booter,
67                     CORBA_Environment *ev)
68{
69        OutsideExtern *oe;
70
71        g_return_if_fail (goad_id != NULL);
72        g_return_if_fail (booter != CORBA_OBJECT_NIL);
73
74        oe = g_new0 (OutsideExtern, 1);
75
76        oe->goad_id = g_strdup (goad_id);
77        oe->booter = CORBA_Object_duplicate (booter, ev);
78
79        outside_externs = g_slist_prepend (outside_externs, oe);
80}
81
82static GNOME_PanelAppletBooter
83pop_outside_extern (const char *goad_id)
84{
85        GSList *li;
86
87        g_return_val_if_fail (goad_id != NULL, CORBA_OBJECT_NIL);
88
89        for (li = outside_externs; li != NULL; li = li->next) {
90                OutsideExtern *oe = li->data;
91
92                if (strcmp (oe->goad_id, goad_id) == 0) {
93                        GNOME_PanelAppletBooter booter = oe->booter;
94                        g_free (oe->goad_id);
95                        oe->goad_id = NULL;
96                        g_free (oe);
97                        return booter;
98                }
99        }
100        return CORBA_OBJECT_NIL;
101}
102
103/********************* CORBA Stuff *******************/
104
105CORBA_ORB orb = NULL;
106CORBA_Environment ev;
107PortableServer_POA thepoa;
108
109/***Panel stuff***/
110static GNOME_PanelSpot
111s_panel_add_applet (PortableServer_Servant servant,
112                    const GNOME_Applet panel_applet,
113                    const CORBA_char *goad_id,
114                    CORBA_char ** cfgpath,
115                    CORBA_char ** globcfgpath,
116                    CORBA_unsigned_long* wid,
117                    CORBA_Environment *ev);
118
119static GNOME_PanelSpot
120s_panel_add_applet_full (PortableServer_Servant servant,
121                         const GNOME_Applet panel_applet,
122                         const CORBA_char *goad_id,
123                         const CORBA_short panel,
124                         const CORBA_short pos,
125                         CORBA_char ** cfgpath,
126                         CORBA_char ** globcfgpath,
127                         CORBA_unsigned_long* wid,
128                         CORBA_Environment *ev);
129
130static void
131s_panel_quit(PortableServer_Servant servant, CORBA_Environment *ev);
132
133static CORBA_boolean
134s_panel_get_in_drag(PortableServer_Servant servant, CORBA_Environment *ev);
135
136static GNOME_StatusSpot
137s_panel_add_status(PortableServer_Servant servant,
138                   CORBA_unsigned_long* wid,
139                   CORBA_Environment *ev);
140
141static void
142s_panel_notice_config_changes(PortableServer_Servant servant,
143                              CORBA_Environment *ev);
144
145
146/** Panel2 additions **/
147void s_panel_suggest_sync (PortableServer_Servant _servant,
148                           CORBA_Environment * ev);
149void s_panel_add_launcher (PortableServer_Servant _servant,
150                           const CORBA_char * launcher_desktop,
151                           const CORBA_short panel,
152                           const CORBA_short pos,
153                           CORBA_Environment * ev);
154void s_panel_ask_about_launcher (PortableServer_Servant _servant,
155                                 const CORBA_char * exec_string,
156                                 const CORBA_short panel,
157                                 const CORBA_short pos,
158                                 CORBA_Environment * ev);
159void s_panel_add_launcher_from_info (PortableServer_Servant _servant,
160                                     const CORBA_char * name,
161                                     const CORBA_char * comment,
162                                     const CORBA_char * exec,
163                                     const CORBA_char * icon,
164                                     const CORBA_short panel,
165                                     const CORBA_short pos,
166                                     CORBA_Environment * ev);
167void s_panel_add_launcher_from_info_url (PortableServer_Servant _servant,
168                                         const CORBA_char * name,
169                                         const CORBA_char * comment,
170                                         const CORBA_char * url,
171                                         const CORBA_char * icon,
172                                         const CORBA_short panel,
173                                         const CORBA_short pos,
174                                         CORBA_Environment * ev);
175void s_panel_run_box (PortableServer_Servant _servant,
176                      const CORBA_char * initial_string,
177                      CORBA_Environment * ev);
178void s_panel_main_menu (PortableServer_Servant _servant,
179                        CORBA_Environment * ev);
180void s_panel_launch_an_applet (PortableServer_Servant _servant,
181                               const CORBA_char * goad_id,
182                               const GNOME_PanelSpot spot,
183                               CORBA_Environment * ev);
184
185/*** PanelSpot stuff ***/
186
187static CORBA_char *
188s_panelspot_get_tooltip(PortableServer_Servant servant,
189                        CORBA_Environment *ev);
190
191static void
192s_panelspot_set_tooltip(PortableServer_Servant servant,
193                        const CORBA_char *val,
194                        CORBA_Environment *ev);
195
196static CORBA_short
197s_panelspot_get_parent_panel(PortableServer_Servant servant,
198                             CORBA_Environment *ev);
199
200static CORBA_short
201s_panelspot_get_spot_pos(PortableServer_Servant servant,
202                         CORBA_Environment *ev);
203
204static GNOME_Panel_OrientType
205s_panelspot_get_parent_orient(PortableServer_Servant servant,
206                              CORBA_Environment *ev);
207
208static CORBA_short
209s_panelspot_get_parent_size(PortableServer_Servant servant,
210                            CORBA_Environment *ev);
211
212static CORBA_short
213s_panelspot_get_free_space(PortableServer_Servant servant,
214                           CORBA_Environment *ev);
215
216static CORBA_boolean
217s_panelspot_get_send_position(PortableServer_Servant servant,
218                              CORBA_Environment *ev);
219static void
220s_panelspot_set_send_position(PortableServer_Servant servant,
221                              CORBA_boolean,
222                              CORBA_Environment *ev);
223
224static CORBA_boolean
225s_panelspot_get_send_draw(PortableServer_Servant servant,
226                          CORBA_Environment *ev);
227static void
228s_panelspot_set_send_draw(PortableServer_Servant servant,
229                          CORBA_boolean,
230                          CORBA_Environment *ev);
231
232static GNOME_Panel_RgbImage *
233s_panelspot_get_rgb_background(PortableServer_Servant servant,
234                               CORBA_Environment *ev);
235
236static void
237s_panelspot_register_us(PortableServer_Servant servant,
238                     CORBA_Environment *ev);
239
240static void
241s_panelspot_unregister_us(PortableServer_Servant servant,
242                       CORBA_Environment *ev);
243
244static void
245s_panelspot_abort_load(PortableServer_Servant servant,
246                       CORBA_Environment *ev);
247
248static void
249s_panelspot_show_menu(PortableServer_Servant servant,
250                      CORBA_Environment *ev);
251
252static void
253s_panelspot_drag_start(PortableServer_Servant servant,
254                       CORBA_Environment *ev);
255
256static void
257s_panelspot_drag_stop(PortableServer_Servant servant,
258                      CORBA_Environment *ev);
259
260static void
261s_panelspot_add_callback(PortableServer_Servant servant,
262                         const CORBA_char *callback_name,
263                         const CORBA_char *stock_item,
264                         const CORBA_char *menuitem_text,
265                         CORBA_Environment *ev);
266
267static void
268s_panelspot_remove_callback(PortableServer_Servant servant,
269                            const CORBA_char *callback_name,
270                            CORBA_Environment *ev);
271static void
272s_panelspot_callback_set_sensitive(PortableServer_Servant servant,
273                                   const CORBA_char *callback_name,
274                                   const CORBA_boolean sensitive,
275                                   CORBA_Environment *ev);
276
277static void
278s_panelspot_sync_config(PortableServer_Servant servant,
279                        CORBA_Environment *ev);
280
281static void
282s_panelspot_done_session_save(PortableServer_Servant servant,
283                              CORBA_boolean ret,
284                              CORBA_unsigned_long cookie,
285                              CORBA_Environment *ev);
286
287/*** StatusSpot stuff ***/
288
289static void
290s_statusspot_remove(POA_GNOME_StatusSpot *servant,
291                    CORBA_Environment *ev);
292
293
294static PortableServer_ServantBase__epv panel_base_epv = {
295        NULL, /* _private */
296        NULL, /* finalize */
297        NULL  /* use base default_POA function */
298};
299
300static POA_GNOME_Panel__epv panel_epv = {
301        NULL, /* private data */
302        s_panel_add_applet,
303        s_panel_add_applet_full,
304        s_panel_quit,
305        s_panel_get_in_drag,
306        s_panel_add_status,
307        s_panel_notice_config_changes
308};
309
310static POA_GNOME_Panel2__epv panel2_epv = {
311        NULL, /* private data */
312        s_panel_suggest_sync,
313        s_panel_add_launcher,
314        s_panel_ask_about_launcher,
315        s_panel_add_launcher_from_info,
316        s_panel_add_launcher_from_info_url,
317        s_panel_run_box,
318        s_panel_main_menu,
319        s_panel_launch_an_applet
320};
321
322static POA_GNOME_Panel2__vepv panel_vepv = { &panel_base_epv, &panel_epv, &panel2_epv };
323static POA_GNOME_Panel2 panel_servant = { NULL, &panel_vepv };
324
325
326static PortableServer_ServantBase__epv panelspot_base_epv = {
327  NULL, /* _private */
328  NULL, /* finalize */
329  NULL  /* use base default_POA function */
330};
331
332static POA_GNOME_PanelSpot__epv panelspot_epv = {
333  NULL, /* private data */
334  s_panelspot_get_tooltip,
335  s_panelspot_set_tooltip,
336  s_panelspot_get_parent_panel,
337  s_panelspot_get_spot_pos,
338  s_panelspot_get_parent_orient,
339  s_panelspot_get_parent_size,
340  s_panelspot_get_free_space,
341  s_panelspot_get_send_position,
342  s_panelspot_set_send_position,
343  s_panelspot_get_send_draw,
344  s_panelspot_set_send_draw,
345  s_panelspot_get_rgb_background,
346  s_panelspot_register_us,
347  s_panelspot_unregister_us,
348  s_panelspot_abort_load,
349  s_panelspot_show_menu,
350  s_panelspot_drag_start,
351  s_panelspot_drag_stop,
352  s_panelspot_add_callback,
353  s_panelspot_remove_callback,
354  s_panelspot_callback_set_sensitive,
355  s_panelspot_sync_config,
356  s_panelspot_done_session_save
357};
358static POA_GNOME_PanelSpot__vepv panelspot_vepv = { &panelspot_base_epv, &panelspot_epv };
359
360static PortableServer_ServantBase__epv statusspot_base_epv = {
361  NULL, /* _private */
362  NULL, /* finalize */
363  NULL  /* use base default_POA function */
364};
365
366static POA_GNOME_StatusSpot__epv statusspot_epv = {
367  NULL, /* private data */
368  (gpointer)&s_statusspot_remove
369};
370static POA_GNOME_StatusSpot__vepv statusspot_vepv = { &statusspot_base_epv, &statusspot_epv };
371
372/********************* NON-CORBA Stuff *******************/
373
374static void
375extern_start_new_goad_id(Extern *e)
376{
377        CORBA_Environment ev;
378        CORBA_exception_init(&ev);
379        CORBA_Object_release(goad_server_activate_with_id(NULL, e->goad_id, GOAD_ACTIVATE_NEW_ONLY|GOAD_ACTIVATE_ASYNC, NULL),&ev);
380        CORBA_exception_free(&ev);
381}
382
383Extern *
384extern_ref (Extern *ext)
385{
386        ext->refcount++;
387        return ext;
388}
389
390void
391extern_unref (Extern *ext)
392{
393        ext->refcount--;
394        if (ext->refcount == 0)
395                g_free (ext);
396}
397
398typedef struct {
399        char *goad_id;
400        char *cfgpath;
401        int pos;
402        int panel;
403} ReloadCallbackData;
404
405static void
406destroy_reload_callback_data (gpointer data)
407{
408        ReloadCallbackData *d = data;
409
410        g_free (d->goad_id);
411        d->goad_id = NULL;
412        g_free (d->cfgpath);
413        d->cfgpath = NULL;
414
415        g_free (d);
416}
417
418static void
419reload_applet_callback (GtkWidget *w, int button, gpointer data)
420{
421        PanelWidget *panel;
422        ReloadCallbackData *d = data;
423
424        /* unless the button was YES, just do nothing */
425        if (button != 0) {
426                return;
427        }
428
429        /*select the nth panel*/
430        g_assert (panels != NULL);
431        panel = g_slist_nth_data (panels, d->panel);
432        if (panel == NULL)
433                panel = panels->data;
434
435        load_extern_applet (d->goad_id, d->cfgpath, panel,
436                            d->pos, TRUE /*exactpos*/, FALSE /*queue*/);
437}
438
439void
440extern_before_remove (Extern *ext)
441{
442        char *s;
443        const char *id ="";
444        GtkWidget *dlg;
445        ReloadCallbackData *d;
446
447        if (ext->clean_remove ||
448            ext->didnt_want_save)
449                return;
450
451        id = ext->goad_id != NULL ? ext->goad_id : "";
452
453        /* a hack, but useful to users */
454        if (strcmp (id, "deskguide_applet") == 0) {
455                id = _("Deskguide (the desktop pager)");
456        } else if (strcmp (id, "tasklist_applet") == 0) {
457                id = _("Tasklist");
458        } else if (strcmp (id, "battery_applet") == 0) {
459                id = _("The Battery");
460        }
461
462        s = g_strdup_printf (_("%s applet appears to have "
463                               "died unexpectedly.\n\n"
464                               "Reload this applet?\n\n"
465                               "(If you choose not to reload it at "
466                               "this time you can always add it from\n"
467                               "the \"Applets\" submenu in the main "
468                               "menu.)"), id);
469
470        dlg = gnome_message_box_new (s, GNOME_MESSAGE_BOX_QUESTION,
471                                     _("Reload"),
472                                     GNOME_STOCK_BUTTON_CANCEL,
473                                     NULL);
474        gnome_dialog_set_close (GNOME_DIALOG (dlg),
475                                TRUE /* click_closes */);
476        gtk_window_set_wmclass (GTK_WINDOW (dlg),
477                                "applet_crashed", "Panel");
478
479        g_free (s);
480
481        d = g_new0 (ReloadCallbackData, 1);
482        d->goad_id = g_strdup (ext->goad_id);
483        d->cfgpath = g_strdup (ext->cfg);
484
485        if (ext->info->widget != NULL) {
486                AppletData *ad;
487                ad = gtk_object_get_data (GTK_OBJECT (ext->info->widget),
488                                          PANEL_APPLET_DATA);
489                d->pos = ad->pos;
490                d->panel = g_slist_index (panels,
491                                          ext->info->widget->parent);
492                if (d->panel < 0)
493                        d->panel = 0;
494        } else {
495                d->panel = 0;
496                d->pos = 0;
497        }
498
499        gtk_signal_connect_full
500                (GTK_OBJECT (dlg), "clicked",
501                 GTK_SIGNAL_FUNC (reload_applet_callback),
502                 NULL,
503                 d,
504                 destroy_reload_callback_data,
505                 FALSE /*object*/,
506                 FALSE /*after*/);
507
508        gtk_widget_show (dlg);
509
510        ext->clean_remove = TRUE;
511}
512
513void
514extern_clean (Extern *ext)
515{
516        CORBA_Environment ev;
517        PortableServer_ObjectId *id;
518        CORBA_exception_init (&ev);
519
520        /* to catch any weird cases, we won't be able to at the position here
521         * though so it will go to 0,0 */
522        extern_before_remove (ext);
523
524        g_free (ext->goad_id);
525        ext->goad_id = NULL;
526
527        g_free (ext->cfg);
528        ext->cfg = NULL;
529
530        CORBA_Object_release (ext->pspot, &ev);
531        ext->pspot = NULL;
532        CORBA_Object_release (ext->applet, &ev);
533        ext->applet = NULL;
534        id = PortableServer_POA_servant_to_id (thepoa, ext, &ev);
535        PortableServer_POA_deactivate_object (thepoa, id, &ev);
536        CORBA_free (id);
537        POA_GNOME_PanelSpot__fini ((PortableServer_Servant) ext, &ev);
538       
539        if (ext->send_draw_timeout != 0) {
540                gtk_timeout_remove (ext->send_draw_timeout);
541                ext->send_draw_timeout = 0;
542        }
543        if (ext->send_draw_idle != 0) {
544                gtk_idle_remove (ext->send_draw_idle);
545                ext->send_draw_idle = 0;
546        }
547
548        extern_unref (ext);
549
550        CORBA_exception_free (&ev);
551}
552
553static void
554extern_socket_destroy(GtkWidget *w, gpointer data)
555{
556        GtkSocket *socket = GTK_SOCKET(w);
557        Extern *ext = data;
558
559        if (socket->same_app &&
560            socket->plug_window != NULL) {
561                GtkWidget *plug_widget;
562                gdk_window_get_user_data (socket->plug_window,
563                                          (gpointer *)&plug_widget);
564                if(plug_widget != NULL) {
565                        /* XXX: hackaround to broken gtkplug/gtksocket!!!
566                           KILL all references to ourselves on the plug
567                           and all our references to the plug and then
568                           destroy it.*/
569                        GtkWidget *toplevel = gtk_widget_get_toplevel (w);
570                        if (toplevel && GTK_IS_WINDOW (toplevel))
571                                gtk_window_remove_embedded_xid (GTK_WINDOW (toplevel),
572                                                                GDK_WINDOW_XWINDOW (socket->plug_window));
573
574                        socket->plug_window = NULL;
575                        socket->same_app = FALSE;
576                        GTK_PLUG(plug_widget)->socket_window = NULL;
577                        GTK_PLUG(plug_widget)->same_app = FALSE;
578                        gtk_widget_destroy(plug_widget);
579                }
580        }
581
582        if (ext->ebox != NULL)
583                gtk_widget_destroy(ext->ebox);
584        ext->ebox = NULL;
585
586        extern_unref (ext);
587}
588
589/*static void
590sal(GtkWidget *applet, GtkAllocation *alloc)
591{
592        printf("SOCKET req:   %dx%d\nSOCKET alloc: %dx%d\n",
593               applet->requisition.width,
594               applet->requisition.height,
595               applet->allocation.width,
596               applet->allocation.height);
597}*/
598
599
600static void
601send_position_change(Extern *ext)
602{
603        /*ingore this until we get an ior*/
604        if(ext->applet) {
605                int x=0,y=0;
606                GtkWidget *wid=ext->ebox;
607               
608                CORBA_Environment ev;
609                CORBA_exception_init(&ev);
610                /*go the the toplevel panel widget*/
611                for(;;) {
612                        if(!GTK_WIDGET_NO_WINDOW(wid)) {
613                                x += wid->allocation.x;
614                                y += wid->allocation.y;
615                        }
616                        if(wid->parent)
617                                wid = wid->parent;
618                        else
619                                break;
620                }
621                GNOME_Applet_change_position(ext->applet, x, y, &ev);
622                if(ev._major)
623                        panel_clean_applet (ext->info);
624                CORBA_exception_free (&ev);
625        }
626}
627
628static void
629ebox_size_allocate (GtkWidget *applet, GtkAllocation *alloc, Extern *ext)
630{
631        if (ext->send_position)
632                send_position_change (ext);
633}
634
635static void
636socket_size_allocate (GtkWidget *applet, GtkAllocation *alloc)
637{
638       
639        GtkRequisition req;
640
641        gtk_widget_get_child_requisition (applet, &req);
642
643        /* This hack must be here.  The problem is that since it is a two
644         * widget deep hierarchy, an applet that shrink will not cause the
645         * panel to allocate less space.  Such as a tasklist in dynamic
646         * mode.  Since applets always get their requisition, then if they
647         * are ever allocated more, that means we can have the panel resize
648         * them to their preferred size.  Here applet->parent is the
649         * PanelWidget actually. */
650        if (req.width > 0 &&
651            req.height > 0 &&
652            (alloc->width > req.width ||
653             alloc->height > req.height))
654                gtk_widget_queue_resize (applet->parent);
655
656}
657
658static void
659socket_set_loading (GtkWidget *socket, PanelWidget *panel)
660{
661        static gboolean tried_loading = FALSE;
662        static GdkPixbuf *pb = NULL;
663        int size;
664
665        /* sanity */
666        if (socket == NULL ||
667            socket->window == NULL)
668                return;
669
670        size = panel->sz < 14 ? panel->sz : 14;
671
672        if ( ! tried_loading) {
673                char *file;
674                file = gnome_pixmap_file ("gnome-unknown.png");
675
676                if (file != NULL) {
677                        pb = gdk_pixbuf_new_from_file (file);
678
679                        g_free (file);
680                }
681        }
682        tried_loading = TRUE;
683
684        if (pb != NULL) {
685                GdkPixmap *pm;
686                GdkPixbuf *scaled;
687
688                if (gdk_pixbuf_get_width (pb) != size ||
689                    gdk_pixbuf_get_height (pb) != size) {
690                        scaled = gdk_pixbuf_scale_simple (pb, size, size,
691                                                          GDK_INTERP_BILINEAR);
692                } else {
693                        scaled = gdk_pixbuf_ref (pb);
694                }
695
696
697                pm = NULL;
698                gdk_pixbuf_render_pixmap_and_mask (scaled, &pm, NULL, 127);
699
700                gdk_pixbuf_unref (scaled);
701
702                if (pm != NULL) {
703                        gdk_window_set_back_pixmap (socket->window, pm, FALSE);
704
705                        gdk_pixmap_unref (pm);
706                }
707        }
708}
709
710static void
711socket_unset_loading (GtkWidget *socket)
712{
713        /* sanity */
714        if (socket == NULL)
715                return;
716
717        /* sanity */
718        if (socket->parent != NULL)
719                gtk_widget_queue_resize (socket->parent);
720
721        /* sanity */
722        if (socket->window != NULL)
723                gdk_window_set_back_pixmap (socket->window, NULL, FALSE);
724
725        /* sanity */
726        if (socket->parent != NULL) {
727                gtk_widget_set_usize (socket->parent, -1, -1);
728                gtk_signal_connect_after
729                        (GTK_OBJECT (socket),"size_allocate",
730                         GTK_SIGNAL_FUNC (socket_size_allocate), NULL);
731        }
732}
733
734/*note that type should be APPLET_EXTERN_RESERVED or APPLET_EXTERN_PENDING
735  only*/
736static CORBA_unsigned_long
737reserve_applet_spot (Extern *ext, PanelWidget *panel, int pos,
738                     AppletType type)
739{
740        int size;
741        GtkWidget *socket;
742
743        ext->ebox = gtk_event_box_new();
744        gtk_widget_set_events(ext->ebox, (gtk_widget_get_events(ext->ebox) |
745                                          APPLET_EVENT_MASK) &
746                              ~( GDK_POINTER_MOTION_MASK |
747                                 GDK_POINTER_MOTION_HINT_MASK));
748
749        size = panel->sz < 14 ? panel->sz : 14;
750
751        gtk_widget_set_usize (ext->ebox, size, size);
752
753        gtk_signal_connect_after (GTK_OBJECT (ext->ebox),"size_allocate",
754                                  GTK_SIGNAL_FUNC (ebox_size_allocate),
755                                  ext);
756
757        socket = gtk_socket_new();
758
759        if(!socket) {
760                g_warning("Can't create a socket");
761                return 0;
762        }
763
764        /* here for debugging purposes */
765        /*gtk_signal_connect_after(GTK_OBJECT(socket),"size_allocate",
766                                 GTK_SIGNAL_FUNC(sal),NULL);*/
767
768        gtk_container_add(GTK_CONTAINER(ext->ebox), socket);
769
770        gtk_widget_show_all (ext->ebox);
771       
772        /*we save the obj in the id field of the appletinfo and the
773          path in the path field */
774        ext->info = NULL;
775        if(!register_toy(ext->ebox,
776                         ext, (GDestroyNotify)extern_clean,
777                         panel, pos, ext->exactpos, type)) {
778                /* the ebox is destroyed in register_toy */
779                ext->ebox = NULL;
780                g_warning(_("Couldn't add applet"));
781                return 0;
782        }
783        ext->info = applets_last->data;
784
785        gtk_signal_connect(GTK_OBJECT (socket), "destroy",
786                           GTK_SIGNAL_FUNC (extern_socket_destroy),
787                           extern_ref (ext));
788       
789        if(!GTK_WIDGET_REALIZED(socket))
790                gtk_widget_realize(socket);
791
792        socket_set_loading (socket, panel);
793
794        return GDK_WINDOW_XWINDOW(socket->window);
795}
796
797/* Note exactpos may NOT be changed */
798static PanelWidget *
799get_us_position (const int panel, const int pos, const char *goad_id, int *newpos,
800                 gboolean *exactpos)
801{
802        PanelWidget *pw = NULL;
803
804        *newpos = pos;
805
806        /* Sanity? can this ever happen? */
807        if (goad_id == NULL) {
808                g_warning ("get_us_position: goad_id == NULL, bad bad");
809                goad_id = "foo";
810        }
811
812        if (panel < 0 || pos < 0) {
813                char *key = g_strdup_printf ("%sApplet_Position_Memory/%s/",
814                                             PANEL_CONFIG_PATH,
815                                             goad_id);
816                gnome_config_push_prefix (key);
817                g_free (key);
818
819                if (pos < 0)
820                        *newpos = gnome_config_get_int ("position=-1");
821                if (panel < 0) {
822                        guint32 unique_id = gnome_config_get_int ("panel_unique_id=0");
823                        if (unique_id != 0) {
824                                pw = panel_widget_get_by_id (unique_id);
825                        }
826                        if (pw == NULL) {
827                                *newpos = -1;
828                        }
829                }
830
831                gnome_config_pop_prefix ();
832        }
833
834        if (pw == NULL && panel < 0)
835                pw = panels->data;
836
837        if (*newpos < 0)
838                *newpos = 0;
839        else if (exactpos != NULL)
840                 *exactpos = TRUE;
841
842        if (pw == NULL) {
843                /*select the nth panel*/
844                GSList *node = g_slist_nth (panels, panel);
845                if (node == NULL)
846                        node = panels;
847                /* There's always at least one */
848                g_assert (node != NULL);
849                pw = node->data;
850        }
851
852        return pw;
853}
854
855
856void
857load_extern_applet (const char *goad_id, const char *cfgpath,
858                    PanelWidget *panel, int pos, gboolean exactpos,
859                    gboolean queue)
860{
861        char *cfg;
862        Extern *ext;
863        POA_GNOME_PanelSpot *panelspot_servant;
864
865        if (string_empty (cfgpath))
866                cfg = g_strconcat (PANEL_CONFIG_PATH,
867                                   "Applet_Dummy/", NULL);
868        else
869                /*we will free this lateer*/
870                cfg = g_strdup (cfgpath);
871
872        ext = g_new0 (Extern, 1);
873        ext->refcount = 1;
874        ext->started = FALSE;
875        ext->exactpos = exactpos;
876        ext->send_position = FALSE;
877        ext->send_draw = FALSE;
878        ext->orient = -1;
879
880        /* don't know until first save, but FALSE since
881         * we assume it will want to. */
882        ext->didnt_want_save = FALSE;
883
884        /* not until we are properly added */
885        ext->clean_remove = TRUE;
886
887        ext->send_draw_timeout = 0;
888        ext->send_draw_idle = 0;
889        ext->send_draw_queued = FALSE;
890
891
892        panelspot_servant = (POA_GNOME_PanelSpot *)ext;
893        panelspot_servant->_private = NULL;
894        panelspot_servant->vepv = &panelspot_vepv;
895
896        POA_GNOME_PanelSpot__init(panelspot_servant, &ev);
897       
898        CORBA_free(PortableServer_POA_activate_object(thepoa, panelspot_servant, &ev));
899        pg_return_if_fail(&ev, ev._major == CORBA_NO_EXCEPTION);
900
901        ext->pspot = CORBA_OBJECT_NIL; /*will be filled in during add_applet*/
902        ext->applet = CORBA_OBJECT_NIL;
903        ext->goad_id = g_strdup(goad_id);
904        ext->cfg = cfg;
905
906        if (panel == NULL || pos < 0) {
907                if (panel != NULL) {
908                        gboolean exactpos;
909                        /* We have a panel */
910                        PanelWidget *pw = get_us_position (-1, pos, goad_id,
911                                                           &pos, &exactpos);
912                        /* only use this position if
913                         * pw and panel are the same */
914                        if (pw != panel)
915                                pos = 0;
916                        else
917                                ext->exactpos = exactpos;
918                } else /* panel == NULL && pos < 0 */ {
919                        panel = get_us_position (-1, -1, goad_id, &pos,
920                                                 &ext->exactpos);
921                }
922        }
923
924        if(reserve_applet_spot (ext, panel, pos, APPLET_EXTERN_PENDING)==0) {
925                g_warning(_("Whoops! for some reason we can't add "
926                            "to the panel"));
927                extern_clean(ext);
928                return;
929        }
930
931        if(!queue) {
932                extern_start_new_goad_id(ext);
933                ext->started = TRUE;
934        }
935}
936
937void
938load_queued_externs(void)
939{
940        GSList *li;
941        for(li=applets;li!=NULL;li=g_slist_next(li)) {
942                AppletInfo *info = li->data;
943                if(info->type == APPLET_EXTERN_PENDING ||
944                   info->type == APPLET_EXTERN_RESERVED) {
945                        Extern *ext = info->data;
946                        if(!ext->started) {
947                                extern_start_new_goad_id(ext);
948                                ext->started = TRUE;
949                        }
950                }
951        }
952}
953
954/********************* CORBA Stuff *******************/
955
956
957static GNOME_PanelSpot
958s_panel_add_applet (PortableServer_Servant servant,
959                    const GNOME_Applet panel_applet,
960                    const CORBA_char *goad_id,
961                    CORBA_char ** cfgpath,
962                    CORBA_char ** globcfgpath,
963                    CORBA_unsigned_long* wid,
964                    CORBA_Environment *ev)
965{
966        return s_panel_add_applet_full (servant, panel_applet, goad_id, -1, -1,
967                                        cfgpath, globcfgpath, wid, ev);
968}
969
970static GNOME_PanelSpot
971s_panel_add_applet_full (PortableServer_Servant servant,
972                         const GNOME_Applet panel_applet,
973                         const CORBA_char *goad_id,
974                         const CORBA_short panel,
975                         const CORBA_short pos,
976                         CORBA_char ** cfgpath,
977                         CORBA_char ** globcfgpath,
978                         CORBA_unsigned_long* wid,
979                         CORBA_Environment *ev)
980{
981        PanelWidget *pw;
982        int newpos;
983        GSList *li;
984        Extern *ext;
985        POA_GNOME_PanelSpot *panelspot_servant;
986        GNOME_PanelSpot acc;
987        GNOME_PanelAppletBooter booter;
988
989        if (panel_in_startup)
990                return CORBA_OBJECT_NIL;
991
992        booter = pop_outside_extern (goad_id);
993        if (booter != CORBA_OBJECT_NIL) {
994                /* yeah, we do dump the panel and pos, since they
995                 * really don't make any sesnse, and aren't really
996                 * used anywhere in the first place */
997                acc = GNOME_PanelAppletBooter_add_applet (booter,
998                                                          panel_applet,
999                                                          goad_id,
1000                                                          cfgpath,
1001                                                          globcfgpath,
1002                                                          wid,
1003                                                          ev);
1004
1005                /* if we succeeded, then all fine and dandy, otherwise
1006                 * this thing was some stale thingie, so just ignore it
1007                 * and launch us into the panel.  This way we're always
1008                 * getting the applet, even if the booter crashed or we
1009                 * had a stale one around */
1010                if (ev->_major == CORBA_NO_EXCEPTION)
1011                        return acc;
1012
1013                /* recycle the exception */
1014                CORBA_exception_free (ev);
1015                CORBA_exception_init (ev);
1016        }
1017       
1018        for (li = applets; li != NULL; li = li->next) {
1019                AppletInfo *info = li->data;
1020                if (info && info->type == APPLET_EXTERN_PENDING) {
1021                        Extern *ext = info->data;
1022                        g_assert(ext);
1023                        g_assert(ext->info == info);
1024                        g_assert(ext->goad_id != NULL);
1025                        if (strcmp(ext->goad_id, goad_id)==0) {
1026                                /*we started this and already reserved a spot
1027                                  for it, including the socket widget*/
1028                                GtkWidget *socket =
1029                                        GTK_BIN(info->widget)->child;
1030                                if(!socket) {
1031                                        g_warning(_("No socket was created"));
1032                                        return CORBA_OBJECT_NIL;
1033                                }
1034
1035                                ext->applet = CORBA_Object_duplicate(panel_applet, ev);
1036                                *cfgpath = CORBA_string_dup(ext->cfg);
1037
1038                                *globcfgpath = CORBA_string_dup(PANEL_CONFIG_PATH);
1039                                info->type = APPLET_EXTERN_RESERVED;
1040                                *wid = GDK_WINDOW_XWINDOW(socket->window);
1041#ifdef PANEL_DEBUG
1042                                printf("\nSOCKET XID: %lX\n\n", (long)*wid);
1043#endif
1044
1045                                panelspot_servant = (POA_GNOME_PanelSpot *)ext;
1046                                acc = PortableServer_POA_servant_to_reference(thepoa, panelspot_servant, ev);
1047                                pg_return_val_if_fail(ev, ev->_major == CORBA_NO_EXCEPTION, CORBA_OBJECT_NIL);
1048                                ext->pspot = CORBA_Object_duplicate(acc, ev);
1049                                pg_return_val_if_fail(ev, ev->_major == CORBA_NO_EXCEPTION, CORBA_OBJECT_NIL);
1050
1051                                return CORBA_Object_duplicate(acc, ev);
1052                        }
1053                }
1054        }
1055       
1056        /*this is an applet that was started from outside, otherwise we would
1057          have already reserved a spot for it*/
1058        ext = g_new0(Extern, 1);
1059        ext->refcount = 1;
1060        ext->started = FALSE;
1061        ext->exactpos = FALSE;
1062        ext->send_position = FALSE;
1063        ext->send_draw = FALSE;
1064        ext->orient = -1;
1065        ext->applet = CORBA_Object_duplicate(panel_applet, ev);
1066        ext->goad_id = g_strdup(goad_id);
1067        ext->cfg = NULL;
1068
1069        panelspot_servant = (POA_GNOME_PanelSpot *)ext;
1070        panelspot_servant->_private = NULL;
1071        panelspot_servant->vepv = &panelspot_vepv;
1072
1073        POA_GNOME_PanelSpot__init (panelspot_servant, ev);
1074       
1075        CORBA_free(PortableServer_POA_activate_object (thepoa, panelspot_servant, ev));
1076        pg_return_val_if_fail(ev, ev->_major == CORBA_NO_EXCEPTION,
1077                              CORBA_OBJECT_NIL);
1078
1079        acc = PortableServer_POA_servant_to_reference (thepoa, panelspot_servant, ev);
1080        pg_return_val_if_fail(ev, ev->_major == CORBA_NO_EXCEPTION,
1081                              CORBA_OBJECT_NIL);
1082
1083        ext->pspot = CORBA_Object_duplicate(acc, ev);
1084
1085        pg_return_val_if_fail(ev, ev->_major == CORBA_NO_EXCEPTION,
1086                              CORBA_OBJECT_NIL);
1087
1088        pw = get_us_position (panel, pos, goad_id, &newpos, &ext->exactpos);
1089
1090        *wid = reserve_applet_spot (ext, pw, newpos,
1091                                    APPLET_EXTERN_RESERVED);
1092        if (*wid == 0) {
1093                extern_clean(ext);
1094                *globcfgpath = NULL;
1095                *cfgpath = NULL;
1096                return CORBA_OBJECT_NIL;
1097        }
1098        *cfgpath = CORBA_string_dup(PANEL_CONFIG_PATH "Applet_Dummy/");
1099        *globcfgpath = CORBA_string_dup (PANEL_CONFIG_PATH);
1100
1101        return CORBA_Object_duplicate(acc, ev);
1102}
1103
1104static void
1105s_panel_quit (PortableServer_Servant servant, CORBA_Environment *ev)
1106{
1107        panel_quit ();
1108}
1109
1110static CORBA_boolean
1111s_panel_get_in_drag (PortableServer_Servant servant, CORBA_Environment *ev)
1112{
1113        return panel_applet_in_drag;
1114}
1115
1116static GNOME_StatusSpot
1117s_panel_add_status (PortableServer_Servant servant,
1118                    CORBA_unsigned_long *wid,
1119                    CORBA_Environment *ev)
1120{
1121        POA_GNOME_StatusSpot *statusspot_servant;
1122        GNOME_StatusSpot acc;
1123        StatusSpot *ss;
1124       
1125        *wid = 0;
1126       
1127        ss = new_status_spot();
1128        if (ss == NULL)
1129                return CORBA_OBJECT_NIL;
1130       
1131        statusspot_servant = (POA_GNOME_StatusSpot *)ss;
1132        statusspot_servant->_private = NULL;
1133        statusspot_servant->vepv = &statusspot_vepv;
1134
1135        POA_GNOME_StatusSpot__init(statusspot_servant, ev);
1136       
1137        CORBA_free (PortableServer_POA_activate_object (thepoa, statusspot_servant, ev));
1138        pg_return_val_if_fail (ev, ev->_major == CORBA_NO_EXCEPTION,
1139                               CORBA_OBJECT_NIL);
1140
1141        acc = PortableServer_POA_servant_to_reference(thepoa, statusspot_servant, ev);
1142        pg_return_val_if_fail (ev, ev->_major == CORBA_NO_EXCEPTION,
1143                               CORBA_OBJECT_NIL);
1144
1145        ss->sspot = CORBA_Object_duplicate (acc, ev);
1146
1147        pg_return_val_if_fail(ev, ev->_major == CORBA_NO_EXCEPTION,
1148                              CORBA_OBJECT_NIL);
1149
1150        *wid = ss->wid;
1151        return CORBA_Object_duplicate(acc, ev);
1152}
1153
1154static void
1155s_panel_notice_config_changes(PortableServer_Servant servant,
1156                              CORBA_Environment *ev)
1157{
1158        load_up_globals();
1159}
1160
1161/** Panel2 additions **/
1162
1163void
1164s_panel_suggest_sync (PortableServer_Servant _servant,
1165                      CORBA_Environment * ev)
1166{
1167        need_complete_save = TRUE;
1168        panel_config_sync();
1169}
1170
1171void
1172s_panel_add_launcher (PortableServer_Servant _servant,
1173                      const CORBA_char * launcher_desktop,
1174                      const CORBA_short panel,
1175                      const CORBA_short pos,
1176                      CORBA_Environment * ev)
1177{
1178        Launcher *launcher;
1179        PanelWidget *panel_widget;
1180
1181        if (panel_in_startup)
1182                return;
1183
1184        g_assert (panels != NULL);
1185
1186        panel_widget = g_slist_nth_data (panels, panel);
1187        if (panel_widget == NULL)
1188                panel_widget = panels->data;
1189
1190        launcher = load_launcher_applet (launcher_desktop,
1191                                         panel_widget, pos, FALSE);
1192        if (launcher != NULL)
1193                launcher_hoard (launcher);
1194}
1195
1196void
1197s_panel_ask_about_launcher (PortableServer_Servant _servant,
1198                            const CORBA_char * exec_string,
1199                            const CORBA_short panel,
1200                            const CORBA_short pos,
1201                            CORBA_Environment * ev)
1202{
1203        PanelWidget *panel_widget;
1204
1205        if (panel_in_startup)
1206                return;
1207
1208        g_assert (panels != NULL);
1209
1210        panel_widget = g_slist_nth_data (panels, panel);
1211        if (panel_widget == NULL)
1212                panel_widget = panels->data;
1213
1214        ask_about_launcher (exec_string, panel_widget, pos, FALSE);
1215}
1216
1217void
1218s_panel_add_launcher_from_info (PortableServer_Servant _servant,
1219                                const CORBA_char * name,
1220                                const CORBA_char * comment,
1221                                const CORBA_char * exec,
1222                                const CORBA_char * icon,
1223                                const CORBA_short panel,
1224                                const CORBA_short pos,
1225                                CORBA_Environment * ev)
1226{
1227        PanelWidget *panel_widget;
1228        char *exec_argv[2] = { NULL, NULL };
1229
1230        if (panel_in_startup)
1231                return;
1232
1233        g_assert (panels != NULL);
1234
1235        panel_widget = g_slist_nth_data (panels, panel);
1236        if (panel_widget == NULL)
1237                panel_widget = panels->data;
1238
1239        /* ugly but works because of the way this actually works */
1240        exec_argv[0] = (char *)exec;
1241        load_launcher_applet_from_info (name, comment, exec_argv, 1,
1242                                        icon, panel_widget, pos, FALSE);
1243}
1244
1245void
1246s_panel_add_launcher_from_info_url (PortableServer_Servant _servant,
1247                                    const CORBA_char * name,
1248                                    const CORBA_char * comment,
1249                                    const CORBA_char * url,
1250                                    const CORBA_char * icon,
1251                                    const CORBA_short panel,
1252                                    const CORBA_short pos,
1253                                    CORBA_Environment * ev)
1254{
1255        PanelWidget *panel_widget;
1256
1257        if (panel_in_startup)
1258                return;
1259
1260        g_assert (panels != NULL);
1261
1262        panel_widget = g_slist_nth_data (panels, panel);
1263        if (panel_widget == NULL)
1264                panel_widget = panels->data;
1265
1266        load_launcher_applet_from_info_url (name, comment, url,
1267                                            icon, panel_widget, pos, FALSE);
1268}
1269
1270void
1271s_panel_run_box (PortableServer_Servant _servant,
1272                 const CORBA_char * initial_string,
1273                 CORBA_Environment * ev)
1274{
1275        if (string_empty (initial_string))
1276                show_run_dialog ();
1277        else
1278                show_run_dialog_with_text (initial_string);
1279}
1280
1281void
1282s_panel_main_menu (PortableServer_Servant _servant,
1283                   CORBA_Environment * ev)
1284{
1285        PanelWidget *panel;
1286        GtkWidget *menu, *basep;
1287
1288        /* check if anybody else has a grab */
1289        if (gdk_pointer_grab (GDK_ROOT_PARENT(), FALSE,
1290                              0, NULL, NULL, GDK_CURRENT_TIME)
1291            != GrabSuccess) {
1292                return;
1293        } else {
1294                gdk_pointer_ungrab (GDK_CURRENT_TIME);
1295        }
1296
1297        panel = panels->data;
1298        menu = make_popup_panel_menu (panel);
1299        basep = panel->panel_parent;
1300        if (IS_BASEP_WIDGET(basep)) {
1301                BASEP_WIDGET(basep)->autohide_inhibit = TRUE;
1302                basep_widget_autohide (BASEP_WIDGET (basep));
1303        }
1304        gtk_menu_popup (GTK_MENU (menu), NULL, NULL,
1305                        NULL, NULL, 0, GDK_CURRENT_TIME);
1306}
1307
1308void
1309s_panel_launch_an_applet (PortableServer_Servant _servant,
1310                          const CORBA_char *goad_id,
1311                          const GNOME_PanelSpot spot,
1312                          CORBA_Environment *ev)
1313{
1314        if (goad_id != NULL &&
1315            spot != CORBA_OBJECT_NIL) {
1316                CORBA_Object applet;
1317
1318                /* push us */
1319                push_outside_extern (goad_id, spot, ev);
1320
1321                /* launch the applet, EVIL! this way shlib applets
1322                 * get dumped into the panel.  Reason?  Simple:  the
1323                 * shlib applet logic is complex, broken, evil and
1324                 * whatever, we do not want to impose it upon an
1325                 * unsuspecting PanelSpot. */
1326                applet = goad_server_activate_with_id (NULL, goad_id,
1327                                                       GOAD_ACTIVATE_NEW_ONLY |
1328                                                       GOAD_ACTIVATE_ASYNC,
1329                                                       NULL);
1330
1331                CORBA_Object_release (applet, ev);
1332        }
1333}
1334
1335/*** PanelSpot stuff ***/
1336
1337static CORBA_char *
1338s_panelspot_get_tooltip(PortableServer_Servant servant,
1339                        CORBA_Environment *ev)
1340{
1341        Extern *ext = (Extern *)servant;
1342        GtkTooltipsData *d = gtk_tooltips_data_get(ext->ebox);
1343        if(!d || !d->tip_text)
1344                return CORBA_string_dup("");
1345        else
1346                return CORBA_string_dup(d->tip_text);
1347}
1348
1349static void
1350s_panelspot_set_tooltip(PortableServer_Servant servant,
1351                        const CORBA_char *val,
1352                        CORBA_Environment *ev)
1353{
1354        Extern *ext = (Extern *)servant;
1355        if(val && *val)
1356                gtk_tooltips_set_tip (panel_tooltips, ext->ebox, val, NULL);
1357        else
1358                gtk_tooltips_set_tip (panel_tooltips, ext->ebox, NULL, NULL);
1359}
1360
1361static CORBA_short
1362s_panelspot_get_parent_panel(PortableServer_Servant servant,
1363                             CORBA_Environment *ev)
1364{
1365        int panel;
1366        GSList *list;
1367        gpointer p;
1368        Extern *ext = (Extern *)servant;
1369
1370        g_assert(ext);
1371        g_assert(ext->info);
1372
1373        p = PANEL_WIDGET(ext->info->widget->parent);
1374
1375        for(panel=0,list=panels;list!=NULL;list=g_slist_next(list),panel++)
1376                if(list->data == p)
1377                        return panel;
1378        return -1;
1379}
1380
1381static CORBA_short
1382s_panelspot_get_spot_pos(PortableServer_Servant servant,
1383                         CORBA_Environment *ev)
1384{
1385        Extern *ext = (Extern *)servant;
1386        AppletData *ad;
1387
1388        g_assert(ext);
1389        g_assert(ext->info);
1390       
1391        ad = gtk_object_get_data(GTK_OBJECT(ext->info->widget),
1392                                 PANEL_APPLET_DATA);
1393        if(!ad)
1394                return -1;
1395        return ad->pos;
1396}
1397
1398static GNOME_Panel_OrientType
1399s_panelspot_get_parent_orient(PortableServer_Servant servant,
1400                              CORBA_Environment *ev)
1401{
1402        Extern *ext = (Extern *)servant;
1403        PanelWidget *panel;
1404
1405        g_assert(ext);
1406        g_assert(ext->info);
1407
1408        panel = PANEL_WIDGET(ext->info->widget->parent);
1409
1410        if(!panel) {
1411                g_warning("%s:%d ??? Applet with no panel ???",
1412                         __FILE__, __LINE__);
1413                return ORIENT_UP;
1414        }
1415
1416        return get_applet_orient(panel);
1417}
1418
1419static CORBA_short
1420s_panelspot_get_parent_size(PortableServer_Servant servant,
1421                            CORBA_Environment *ev)
1422{
1423        Extern *ext = (Extern *)servant;
1424        PanelWidget *panel;
1425
1426        g_assert(ext);
1427        g_assert(ext->info);
1428
1429        panel = PANEL_WIDGET(ext->info->widget->parent);
1430
1431        if(!panel) {
1432                g_warning("%s:%d ??? Applet with no panel ???",
1433                         __FILE__, __LINE__);
1434                return SIZE_STANDARD;
1435        }
1436
1437        return panel->sz;
1438}
1439
1440static CORBA_short
1441s_panelspot_get_free_space(PortableServer_Servant servant,
1442                           CORBA_Environment *ev)
1443{
1444        Extern *ext = (Extern *)servant;
1445        PanelWidget *panel;
1446
1447        g_assert(ext);
1448        g_assert(ext->info);
1449
1450        panel = PANEL_WIDGET(ext->info->widget->parent);
1451
1452        if(!panel) {
1453                g_warning("%s:%d ??? Applet with no panel ???",
1454                         __FILE__, __LINE__);
1455                return 0;
1456        }
1457       
1458        return panel_widget_get_free_space(panel,ext->info->widget);
1459}
1460
1461static CORBA_boolean
1462s_panelspot_get_send_position(PortableServer_Servant servant,
1463                              CORBA_Environment *ev)
1464{
1465        Extern *ext = (Extern *)servant;
1466
1467        g_assert(ext);
1468       
1469        return ext->send_position;
1470}
1471
1472static void
1473s_panelspot_set_send_position(PortableServer_Servant servant,
1474                              CORBA_boolean enable,
1475                              CORBA_Environment *ev)
1476{
1477        Extern *ext = (Extern *)servant;
1478
1479        g_assert(ext);
1480       
1481        ext->send_position = enable?TRUE:FALSE;
1482}
1483
1484static CORBA_boolean
1485s_panelspot_get_send_draw(PortableServer_Servant servant,
1486                          CORBA_Environment *ev)
1487{
1488        Extern *ext = (Extern *)servant;
1489
1490        g_assert(ext);
1491       
1492        return ext->send_draw;
1493}
1494
1495static void
1496s_panelspot_set_send_draw(PortableServer_Servant servant,
1497                          CORBA_boolean enable,
1498                          CORBA_Environment *ev)
1499{
1500        Extern *ext = (Extern *)servant;
1501
1502        g_assert(ext);
1503       
1504        ext->send_draw = enable?TRUE:FALSE;
1505}
1506
1507static GNOME_Panel_RgbImage *
1508s_panelspot_get_rgb_background(PortableServer_Servant servant,
1509                               CORBA_Environment *ev)
1510{
1511        Extern *ext = (Extern *)servant;
1512        PanelWidget *panel;
1513        GNOME_Panel_RgbImage *image;
1514        int w, h, rowstride;
1515        guchar *rgb;
1516        int r,g,b;
1517
1518        g_assert(ext);
1519        g_assert(ext->info);
1520
1521        panel = PANEL_WIDGET(ext->info->widget->parent);
1522
1523        panel_widget_get_applet_rgb_bg(panel, ext->ebox,
1524                                       &rgb,&w,&h,&rowstride,
1525                                       TRUE,&r,&g,&b);
1526
1527        image = GNOME_Panel_RgbImage__alloc();
1528        image->width = w;
1529        image->height = h;
1530               
1531        /* if we got an rgb */
1532        if(rgb) {
1533                image->data._buffer = CORBA_sequence_CORBA_octet_allocbuf(h*rowstride);
1534                image->data._length = image->data._maximum = h*rowstride;
1535                memcpy(image->data._buffer,rgb,sizeof(guchar)*h*rowstride);
1536                image->rowstride = rowstride;
1537                image->color_only = FALSE;
1538                g_free(rgb);
1539        } else { /* we must have gotten a color */
1540                image->data._buffer = CORBA_sequence_CORBA_octet_allocbuf(3);
1541                image->data._length = image->data._maximum = 3;
1542                *(image->data._buffer) = r;
1543                *(image->data._buffer+1) = g;
1544                *(image->data._buffer+2) = b;
1545                image->rowstride = 0;
1546                image->color_only = TRUE;
1547        }
1548        CORBA_sequence_set_release(&image->data, TRUE);
1549
1550        return image;
1551}
1552
1553static void
1554s_panelspot_register_us(PortableServer_Servant servant,
1555                        CORBA_Environment *ev)
1556{
1557        PanelWidget *panel;
1558        Extern *ext = (Extern *)servant;
1559
1560        g_assert (ext != NULL);
1561        g_assert (ext->info != NULL);
1562       
1563#ifdef PANEL_DEBUG
1564        printf("register ext: %lX\n",(long)ext);
1565        printf("register ext->info: %lX\n",(long)(ext->info));
1566#endif
1567
1568        panel = PANEL_WIDGET (ext->info->widget->parent);
1569        if (panel == NULL) {
1570                g_warning ("%s:%d ??? Applet with no panel ???",
1571                           __FILE__, __LINE__);
1572                return;
1573        }
1574
1575        /*no longer pending*/
1576        ext->info->type = APPLET_EXTERN;
1577        /* from now on warn on unclean removal */
1578        ext->clean_remove = FALSE;
1579
1580        if (ext->ebox != NULL)
1581                socket_unset_loading (GTK_BIN (ext->ebox)->child);
1582
1583        /* make sure things don't screw up */
1584        extern_ref (ext);
1585
1586        freeze_changes (ext->info);
1587        if (ext->info != NULL)
1588                orientation_change (ext->info, panel);
1589        if (ext->info != NULL)
1590                size_change (ext->info, panel);
1591        if (ext->info != NULL)
1592                back_change (ext->info, panel);
1593        if (ext->info != NULL &&
1594            ext->send_position)
1595                send_position_change(ext);
1596        if (ext->info != NULL)
1597                thaw_changes (ext->info);
1598
1599        /* just sanity */
1600        if (ext->applet != NULL)
1601                GNOME_Applet_set_tooltips_state
1602                        (ext->applet, global_config.tooltips_enabled, ev);
1603
1604        if (ev->_major) {
1605                /* well, we haven't really gotten anywhere, so it's not
1606                 * a good idea to bother the user with restarting us */
1607                ext->clean_remove = TRUE;
1608                panel_clean_applet (ext->info);
1609        }
1610
1611        extern_unref (ext);
1612}
1613
1614
1615static void
1616s_panelspot_unregister_us(PortableServer_Servant servant,
1617                          CORBA_Environment *ev)
1618{
1619        Extern *ext = (Extern *)servant;
1620
1621        extern_save_last_position (ext, TRUE /* sync */);
1622
1623        ext->clean_remove = TRUE;
1624        panel_clean_applet(ext->info);
1625}
1626
1627static void
1628s_panelspot_abort_load(PortableServer_Servant servant,
1629                       CORBA_Environment *ev)
1630{
1631        Extern *ext = (Extern *)servant;
1632
1633        g_assert (ext != NULL);
1634        g_assert (ext->info != NULL);
1635       
1636        /*only reserved spots can be canceled, if an applet
1637          wants to chance a pending applet it needs to first
1638          user reserve spot to obtain id and make it EXTERN_RESERVED*/
1639        if (ext->info->type != APPLET_EXTERN_RESERVED)
1640                return;
1641
1642        ext->clean_remove = TRUE;
1643        panel_clean_applet (ext->info);
1644}
1645
1646static void
1647s_panelspot_show_menu(PortableServer_Servant servant,
1648                      CORBA_Environment *ev)
1649{
1650        GtkWidget *panel;
1651        Extern *ext = (Extern *)servant;
1652       
1653#ifdef PANEL_DEBUG
1654        printf("show menu ext: %lX\n",(long)ext);
1655        printf("show menu ext->info: %lX\n",(long)(ext->info));
1656#endif
1657
1658        g_assert (ext != NULL);
1659        g_assert (ext->info != NULL);
1660
1661        panel = get_panel_parent (ext->info->widget);
1662
1663        if (!ext->info->menu)
1664                create_applet_menu(ext->info, IS_BASEP_WIDGET (panel));
1665
1666        if (IS_BASEP_WIDGET (panel)) {
1667                BASEP_WIDGET(panel)->autohide_inhibit = TRUE;
1668                basep_widget_queue_autohide(BASEP_WIDGET(panel));
1669        }
1670
1671        ext->info->menu_age = 0;
1672        gtk_menu_popup(GTK_MENU(ext->info->menu), NULL, NULL,
1673                       global_config.off_panel_popups?applet_menu_position:NULL,
1674                       ext->info, 3, GDK_CURRENT_TIME);
1675}
1676
1677
1678static void
1679s_panelspot_drag_start(PortableServer_Servant servant,
1680                       CORBA_Environment *ev)
1681{
1682        PanelWidget *panel;
1683        Extern *ext = (Extern *)servant;
1684
1685        g_assert (ext != NULL);
1686        g_assert (ext->info != NULL);
1687
1688        panel = PANEL_WIDGET (ext->info->widget->parent);
1689        if (panel == NULL) {
1690                g_warning("%s:%d ??? Applet with no panel ???",
1691                         __FILE__, __LINE__);
1692                return;
1693        }
1694
1695        panel_widget_applet_drag_start (panel, ext->info->widget,
1696                                        PW_DRAG_OFF_CENTER);
1697}
1698
1699static void
1700s_panelspot_drag_stop(PortableServer_Servant servant,
1701                      CORBA_Environment *ev)
1702{
1703        PanelWidget *panel;
1704        Extern *ext = (Extern *)servant;
1705
1706        g_assert(ext != NULL);
1707        g_assert(ext->info != NULL);
1708
1709        panel = PANEL_WIDGET(ext->info->widget->parent);
1710        if (panel == NULL) {
1711                g_warning("%s:%d ??? Applet with no panel ???",
1712                         __FILE__, __LINE__);
1713                return;
1714        }
1715
1716        panel_widget_applet_drag_end(panel);
1717}
1718
1719static void
1720s_panelspot_add_callback(PortableServer_Servant servant,
1721                         const CORBA_char *callback_name,
1722                         const CORBA_char *stock_item,
1723                         const CORBA_char *menuitem_text,
1724                         CORBA_Environment *ev)
1725{
1726        Extern *ext = (Extern *)servant;
1727
1728#ifdef PANEL_DEBUG
1729        printf("add callback ext: %lX\n",(long)ext);
1730#endif
1731
1732        g_assert(ext != NULL);
1733        g_assert(ext->info != NULL);
1734
1735        if (commie_mode &&
1736            callback_name != NULL &&
1737            (strcmp (callback_name, "preferences") == 0 ||
1738             strcmp (callback_name, "properties") == 0))
1739                return;
1740
1741        applet_add_callback(ext->info, callback_name, stock_item,
1742                            menuitem_text);
1743}
1744
1745static void
1746s_panelspot_remove_callback(PortableServer_Servant servant,
1747                            const CORBA_char *callback_name,
1748                            CORBA_Environment *ev)
1749{
1750        Extern *ext = (Extern *)servant;
1751
1752        g_assert(ext != NULL);
1753        g_assert(ext->info != NULL);
1754        applet_remove_callback(ext->info, callback_name);
1755}
1756
1757static void
1758s_panelspot_callback_set_sensitive(PortableServer_Servant servant,
1759                                   const CORBA_char *callback_name,
1760                                   const CORBA_boolean sensitive,
1761                                   CORBA_Environment *ev)
1762{
1763        Extern *ext = (Extern *)servant;
1764
1765        g_assert(ext != NULL);
1766        g_assert(ext->info != NULL);
1767        applet_callback_set_sensitive(ext->info, callback_name, sensitive);
1768}
1769
1770static void
1771s_panelspot_sync_config(PortableServer_Servant servant,
1772                        CORBA_Environment *ev)
1773{
1774        Extern *ext = (Extern *)servant;
1775
1776        g_assert(ext != NULL);
1777        g_assert(ext->info != NULL);
1778        applets_to_sync = TRUE;
1779        panel_config_sync();
1780}
1781
1782static int
1783save_next_idle(gpointer data)
1784{
1785        save_next_applet();
1786        return FALSE;
1787}
1788
1789void
1790save_applet (AppletInfo *info, gboolean ret)
1791{
1792        char *buf;
1793        PanelWidget *panel;
1794        AppletData *ad;
1795        Extern *ext;
1796        int panel_num;
1797       
1798        ext = info->data;
1799       
1800        buf = g_strdup_printf ("%sApplet_Config/Applet_%d/",
1801                               PANEL_CONFIG_PATH,
1802                               info->applet_id + 1);
1803        gnome_config_push_prefix (buf);
1804        g_free (buf);
1805
1806        panel = PANEL_WIDGET (info->widget->parent);
1807        ad = gtk_object_get_data (GTK_OBJECT (info->widget),
1808                                  PANEL_APPLET_DATA);
1809
1810        panel_num = g_slist_index (panels, panel);
1811        if (panel_num == -1) {
1812                /* Eeeeeeeeeeeeeek! */
1813                gnome_config_set_string ("id", EMPTY_ID);
1814                gnome_config_pop_prefix ();
1815                gnome_config_sync ();
1816                /*save next applet, but from an idle handler, so that
1817                  this call returns*/
1818                gtk_idle_add (save_next_idle, NULL);
1819                return;
1820        }
1821               
1822        /*have the applet do it's own session saving*/
1823        if (ret) {
1824                /* wanted to save */
1825                ext->didnt_want_save = FALSE;
1826
1827                gnome_config_set_string ("id", EXTERN_ID);
1828                gnome_config_set_string ("goad_id",
1829                                         ext->goad_id);
1830                gnome_config_set_int ("position", ad->pos);
1831                gnome_config_set_int ("panel", panel_num);
1832                gnome_config_set_int ("unique_panel_id", panel->unique_id);
1833                gnome_config_set_bool ("right_stick",
1834                                       panel_widget_is_applet_stuck (panel,
1835                                                                     info->widget));
1836        } else {
1837                /* ahh didn't want to save */
1838                ext->didnt_want_save = TRUE;
1839
1840                gnome_config_set_string ("id", EMPTY_ID);
1841        }
1842
1843        gnome_config_pop_prefix ();
1844
1845        gnome_config_sync ();
1846        /*save next applet, but from an idle handler, so that
1847          this call returns*/
1848        gtk_idle_add (save_next_idle, NULL);
1849}
1850
1851static void
1852s_panelspot_done_session_save(PortableServer_Servant servant,
1853                              CORBA_boolean ret,
1854                              CORBA_unsigned_long cookie,
1855                              CORBA_Environment *ev)
1856{
1857        GSList *cur;
1858        AppletInfo *info;
1859       
1860        /*ignore bad cookies*/
1861        if(cookie != ss_cookie)
1862                return;
1863
1864        /*increment cookie to kill the timeout warning*/
1865        ss_cookie++;
1866       
1867        if(ss_timeout_dlg) {
1868                gtk_widget_destroy(ss_timeout_dlg);
1869                ss_timeout_dlg = NULL;
1870        }
1871
1872        if(g_slist_length(applets)<=ss_cur_applet) {
1873                ss_done_save = TRUE;
1874                return;
1875        }
1876       
1877        cur = g_slist_nth(applets,ss_cur_applet);
1878       
1879        if(!cur) {
1880                ss_done_save = TRUE;
1881                return;
1882        }
1883       
1884        info = cur->data;
1885
1886        /*hmm, this came from a different applet?, we are
1887          getting seriously confused*/
1888        if(info->type!=APPLET_EXTERN ||
1889           (gpointer)servant!=(gpointer)info->data) {
1890                applets_to_sync = TRUE; /*we need to redo this yet again*/
1891                /*save next applet, but from an idle handler, so that
1892                  this call returns*/
1893                gtk_idle_add(save_next_idle,NULL);
1894                return;
1895        }
1896
1897        save_applet(info, ret);
1898}
1899
1900/*** StatusSpot stuff ***/
1901
1902static void
1903s_statusspot_remove(POA_GNOME_StatusSpot *servant,
1904                    CORBA_Environment *ev)
1905{
1906        StatusSpot *ss = (StatusSpot *)servant;
1907        status_spot_remove(ss, TRUE);
1908}
1909
1910
1911void
1912panel_corba_clean_up(void)
1913{
1914  goad_server_unregister(CORBA_OBJECT_NIL, "gnome_panel", "server", &ev);
1915  CORBA_ORB_shutdown(orb, CORBA_FALSE, &ev);
1916}
1917
1918gint
1919panel_corba_gtk_init(CORBA_ORB panel_orb)
1920{
1921  GNOME_Panel acc;
1922  CORBA_Object old_server;
1923  gint status;
1924
1925  CORBA_exception_init(&ev);
1926
1927  orb = panel_orb;
1928
1929  POA_GNOME_Panel2__init (&panel_servant, &ev);
1930  pg_return_val_if_fail (&ev, ev._major == CORBA_NO_EXCEPTION, -1);
1931
1932  thepoa = (PortableServer_POA)
1933    CORBA_ORB_resolve_initial_references (orb, "RootPOA", &ev);
1934  pg_return_val_if_fail(&ev, ev._major == CORBA_NO_EXCEPTION, -1);
1935
1936  PortableServer_POAManager_activate(PortableServer_POA__get_the_POAManager(thepoa, &ev), &ev);
1937  pg_return_val_if_fail(&ev, ev._major == CORBA_NO_EXCEPTION, -1);
1938
1939  CORBA_free(PortableServer_POA_activate_object(thepoa,
1940                                                &panel_servant, &ev));
1941  pg_return_val_if_fail(&ev, ev._major == CORBA_NO_EXCEPTION, -1);
1942
1943  acc = PortableServer_POA_servant_to_reference(thepoa, &panel_servant, &ev);
1944  pg_return_val_if_fail(&ev, ev._major == CORBA_NO_EXCEPTION, -1);
1945
1946  old_server = goad_server_activate_with_repo_id (NULL, "IDL:GNOME/Panel:1.0",
1947                                                  GOAD_ACTIVATE_EXISTING_ONLY,
1948                                                  NULL);
1949
1950  if(! CORBA_Object_is_nil(old_server, &ev)) {
1951    CORBA_Object_release(old_server, &ev);
1952    return -4;
1953  }
1954
1955  status = goad_server_register(CORBA_OBJECT_NIL, acc, "gnome_panel", "server", &ev);
1956
1957  /*
1958  CORBA_Object_release(acc, &ev);
1959  pg_return_val_if_fail(&ev, ev._major == CORBA_NO_EXCEPTION, -1);
1960  */
1961
1962  return status;
1963}
1964
1965static void
1966send_draw(Extern *ext)
1967{
1968        CORBA_Environment ev;
1969
1970        CORBA_exception_init (&ev);
1971        if (ext->applet != NULL) /* sanity */
1972                GNOME_Applet_draw (ext->applet, &ev);
1973        if (ev._major)
1974                panel_clean_applet (ext->info);
1975        CORBA_exception_free (&ev);
1976}
1977
1978static gboolean
1979send_draw_timeout(gpointer data)
1980{
1981        Extern *ext = data;
1982        if(ext->send_draw && ext->send_draw_queued) {
1983                ext->send_draw_queued = FALSE;
1984                send_draw(ext);
1985                return TRUE;
1986        }
1987        ext->send_draw_timeout = 0;
1988        return FALSE;
1989}
1990
1991static gboolean
1992send_draw_idle(gpointer data)
1993{
1994        Extern *ext = data;
1995        ext->send_draw_idle = 0;
1996        if(!ext->send_draw)
1997                return FALSE;
1998        if(!ext->send_draw_timeout) {
1999                ext->send_draw_queued = FALSE;
2000                send_draw(ext);
2001                ext->send_draw_timeout =
2002                        gtk_timeout_add(1000, send_draw_timeout, ext);
2003        } else
2004                ext->send_draw_queued = TRUE;
2005        return FALSE;
2006}
2007
2008void
2009extern_send_draw(Extern *ext)
2010{
2011        if(!ext || !ext->applet || !ext->send_draw)
2012                return;
2013        if(!ext->send_draw_idle)
2014                ext->send_draw_idle =
2015                        gtk_idle_add(send_draw_idle, ext);
2016}
2017
2018void
2019extern_save_last_position (Extern *ext, gboolean sync)
2020{
2021        char *key;
2022        int panel_num;
2023        AppletData *ad;
2024
2025        if (ext->goad_id == NULL)
2026                return;
2027
2028        /* Here comes a hack.  We probably want the next applet to load at
2029         * a similar location.  If none is given.  Think xchat, or any
2030         * app that just adds applets on it's own by just running them. */
2031        key = g_strdup_printf ("%sApplet_Position_Memory/%s/",
2032                               PANEL_CONFIG_PATH,
2033                               ext->goad_id);
2034        gnome_config_push_prefix (key);
2035        g_free (key);
2036
2037        ad = gtk_object_get_data (GTK_OBJECT (ext->info->widget),
2038                                  PANEL_APPLET_DATA);
2039
2040        panel_num = g_slist_index (panels, ext->info->widget->parent);
2041
2042        if (ad != NULL)
2043                gnome_config_set_int ("position", ad->pos);
2044        if (panel_num >= 0)
2045                gnome_config_set_int
2046                        ("panel_unique_id",
2047                         PANEL_WIDGET (ext->info->widget->parent)->unique_id);
2048       
2049        gnome_config_pop_prefix ();
2050        if (sync)
2051                gnome_config_sync ();
2052}
2053
Note: See TracBrowser for help on using the repository browser.