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

Revision 15821, 11.4 KB checked in by ghudson, 24 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r15820, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * GNOME panel swallow module.
3 * (C) 1997,1998,1999,2000 The Free Software Foundation
4 * (C) 2000 Eazel, Inc.
5 *
6 * Author: George Lebl
7 */
8
9#include <config.h>
10#include <stdio.h>
11#include <sys/types.h>
12#include <sys/stat.h>
13#include <unistd.h>
14#include <string.h>
15#include <gnome.h>
16#include <gdk/gdkx.h>
17#include <X11/Xlib.h>
18
19#include "panel-include.h"
20#include "panel-widget.h"
21
22#include "xstuff.h"
23
24/* from gtkhandlebox.c */
25#define DRAG_HANDLE_SIZE 10
26
27GList *check_swallows = NULL;
28
29extern GlobalConfig global_config;
30extern GSList *applets_last;
31
32static void socket_destroyed (GtkWidget *w, gpointer data);
33static void socket_realized (GtkWidget *w, gpointer data);
34
35static void
36socket_realized (GtkWidget *w, gpointer data)
37{
38        Swallow *swallow = gtk_object_get_user_data (GTK_OBJECT (w));
39
40        g_return_if_fail (swallow->title != NULL);
41       
42        gdk_error_trap_push ();
43
44        check_swallows = g_list_prepend (check_swallows, swallow);
45
46        xstuff_go_through_client_list ();
47
48        gdk_flush();
49        gdk_error_trap_pop ();
50}
51
52static void
53swallow_launch (Swallow *swallow)
54{
55        if ( ! string_empty (swallow->path)) {
56                char *p = strrchr (swallow->path, '.');
57                GnomeDesktopEntry *item;
58
59                /*only if such a file exists and ends in a .desktop, should
60                  we try to launch it as such*/
61                if(p != NULL &&
62                   (strcmp (p, ".desktop") == 0 ||
63                    strcmp (p, ".kdelnk") == 0) &&
64                   panel_file_exists (swallow->path) &&
65                   (item = gnome_desktop_entry_load (swallow->path)) != NULL) {
66                        char *curdir = g_get_current_dir ();
67                        chdir (g_get_home_dir ());
68
69                        gnome_desktop_entry_launch (item);
70                        gnome_desktop_entry_free (item);
71
72                        chdir (curdir);
73                        g_free (curdir);
74                } else {
75                        gnome_execute_shell (g_get_home_dir (), swallow->path);
76                }
77        }
78}
79
80static gboolean
81before_remove (Swallow *swallow)
82{
83        GtkWidget *dlg;
84
85        if (swallow->clean_remove)
86                return TRUE;
87
88        dlg = gnome_message_box_new (_("A swallowed application appears to "
89                                       "have died unexpectedly.\n"
90                                       "Attempt to reload it?"),
91                                     GNOME_MESSAGE_BOX_QUESTION,
92                                     _("Reload"),
93                                     GNOME_STOCK_BUTTON_CANCEL,
94                                     NULL);
95        gnome_dialog_set_close (GNOME_DIALOG (dlg),
96                                TRUE /* click_closes */);
97        gtk_window_set_wmclass (GTK_WINDOW (dlg),
98                                "swallow_crashed", "Panel");
99
100        if (gnome_dialog_run (GNOME_DIALOG (dlg)) == 0) {
101
102                /* make the socket again */
103                swallow->socket = gtk_socket_new ();
104                gtk_object_set_user_data (GTK_OBJECT (swallow->socket),
105                                          swallow);
106
107                if (swallow->width != 0 || swallow->height != 0)
108                        gtk_widget_set_usize(swallow->socket,
109                                             swallow->width, swallow->height);
110
111                gtk_signal_connect_after (GTK_OBJECT (swallow->socket),
112                                          "realize",
113                                          GTK_SIGNAL_FUNC (socket_realized),
114                                          NULL);
115                gtk_signal_connect (GTK_OBJECT (swallow->socket), "destroy",
116                                    GTK_SIGNAL_FUNC (socket_destroyed),
117                                    swallow);
118
119                gtk_container_add (GTK_CONTAINER (swallow->frame),
120                                   swallow->socket);
121                gtk_widget_show (swallow->socket);
122
123                /* launch the command if some exists */
124                swallow_launch (swallow);
125
126                check_swallows = g_list_prepend (check_swallows, swallow);
127                xstuff_go_through_client_list ();
128               
129                return FALSE;
130        }
131
132        return TRUE;
133}
134
135static void
136unref_swallow (Swallow *swallow)
137{
138        swallow->ref_count --;
139
140        if (swallow->ref_count == 0) {
141                g_free (swallow->title);
142                swallow->title = NULL;
143                g_free (swallow->path);
144                swallow->path = NULL;
145
146                g_free (swallow);
147        }
148}
149
150static Swallow *
151ref_swallow (Swallow *swallow)
152{
153        swallow->ref_count ++;
154
155        return swallow;
156}
157
158static void
159socket_destroyed (GtkWidget *w, gpointer data)
160{
161        Swallow *swallow = data;
162
163        swallow->wid = -1;
164       
165        if ( ! before_remove (swallow))
166                return;
167
168        gtk_widget_destroy (swallow->ebox);
169        swallow->ebox = NULL;
170
171        check_swallows = g_list_remove (check_swallows, swallow);
172
173        /* here is where the swallow really dies */
174        unref_swallow (swallow);
175}
176
177static void
178really_add_swallow(GtkWidget *d,int button, gpointer data)
179{
180        GtkWidget *title_e = gtk_object_get_data(GTK_OBJECT(d), "title_e");
181        GtkWidget *exec_e = gtk_object_get_data(GTK_OBJECT(d), "exec_e");
182        GtkWidget *width_s = gtk_object_get_data(GTK_OBJECT(d), "width_s");
183        GtkWidget *height_s = gtk_object_get_data(GTK_OBJECT(d), "height_s");
184        PanelWidget *panel = gtk_object_get_data(GTK_OBJECT(d), "panel");
185        int pos = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(d), "pos"));
186        gboolean exactpos =
187                GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(d), "exactpos"));
188
189        switch (button) {
190        case 1: /* cancel */
191                gtk_widget_destroy(d);
192                return;
193        case 2: /* help */
194                panel_show_help ("specialobjects.html#SWALLOWEDAPPS");
195                return;
196        default:
197                break;
198        }
199       
200        load_swallow_applet(gtk_entry_get_text(GTK_ENTRY(exec_e)),
201                            gtk_entry_get_text(GTK_ENTRY(title_e)),
202                            gtk_spin_button_get_value_as_int(
203                                                GTK_SPIN_BUTTON(width_s)),
204                            gtk_spin_button_get_value_as_int(
205                                                GTK_SPIN_BUTTON(height_s)),
206                            panel, pos, exactpos);
207        gtk_widget_destroy(d);
208}
209
210static void
211act_really_add_swallow(GtkWidget *w, gpointer data)
212{
213        GtkWidget *d = data;
214       
215        /*just call the above handler for the dialog*/
216        really_add_swallow (d, 0, NULL);
217}
218
219/*I couldn't resist the naming of this function*/
220void
221ask_about_swallowing(PanelWidget *panel, int pos, gboolean exactpos)
222{
223        GtkWidget *d;
224       
225        GtkWidget *title_e;
226        GtkWidget *exec_e;
227        GtkWidget *width_s;
228        GtkWidget *height_s;
229        GtkWidget *w;
230        GtkWidget *box, *i_box;
231        GtkAdjustment *adj;
232       
233        d = gnome_dialog_new(_("Create swallow applet"),
234                             GNOME_STOCK_BUTTON_OK,
235                             GNOME_STOCK_BUTTON_CANCEL,
236                             GNOME_STOCK_BUTTON_HELP,
237                             NULL);
238        gtk_window_set_wmclass(GTK_WINDOW(d),
239                               "create_swallow","Panel");
240        /*gtk_window_set_position(GTK_WINDOW(d), GTK_WIN_POS_CENTER);*/
241        gtk_window_set_policy(GTK_WINDOW(d), FALSE, FALSE, TRUE);
242
243        gtk_object_set_data(GTK_OBJECT(d),"panel",panel);
244        gtk_object_set_data(GTK_OBJECT(d),"pos",GINT_TO_POINTER(pos));
245        gtk_object_set_data(GTK_OBJECT(d),"exactpos",GINT_TO_POINTER(exactpos));
246
247        box = gtk_hbox_new(FALSE,GNOME_PAD_SMALL);
248        gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(d)->vbox),box, TRUE,TRUE,0);
249        w = gtk_label_new(_("Title of application to swallow"));
250        gtk_box_pack_start(GTK_BOX(box),w,FALSE,FALSE,0);
251        w = gnome_entry_new("swallow_title");
252        gtk_box_pack_start(GTK_BOX(box),w,TRUE,TRUE,0);
253        title_e = gnome_entry_gtk_entry(GNOME_ENTRY(w));
254        gtk_signal_connect(GTK_OBJECT(title_e),"activate",
255                           GTK_SIGNAL_FUNC(act_really_add_swallow),d);
256
257        box = gtk_hbox_new(FALSE,GNOME_PAD_SMALL);
258        gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(d)->vbox),box, TRUE,TRUE,0);
259        w = gtk_label_new(_("Command (optional)"));
260        gtk_box_pack_start(GTK_BOX(box),w,FALSE,FALSE,0);
261        w = gnome_file_entry_new("execute",_("Browse"));
262        gtk_box_pack_start(GTK_BOX(box),w,TRUE,TRUE,0);
263        exec_e = gnome_file_entry_gtk_entry (GNOME_FILE_ENTRY (w));
264        gtk_signal_connect(GTK_OBJECT(exec_e),"activate",
265                           GTK_SIGNAL_FUNC(act_really_add_swallow),d);
266
267        box = gtk_hbox_new(FALSE,GNOME_PAD_SMALL);
268        gtk_box_pack_start(GTK_BOX(GNOME_DIALOG(d)->vbox),box, TRUE,TRUE,0);
269
270        w = gtk_label_new(_("Width"));
271        gtk_box_pack_start(GTK_BOX(box),w,FALSE,FALSE,0);
272        adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0,
273                                                    (float)gdk_screen_width(),
274                                                    1.0, 5.0, 0.0);
275        gtk_adjustment_set_value(adj, 48);
276        width_s = gtk_spin_button_new(adj,0,0);
277        gtk_box_pack_start(GTK_BOX(box),width_s,FALSE,FALSE,0);
278
279
280        i_box =gtk_hbox_new(FALSE,0);
281        gtk_box_pack_start(GTK_BOX(box), i_box, FALSE, FALSE, GNOME_PAD_SMALL);
282       
283        w = gtk_label_new(_("Height"));
284        gtk_box_pack_start(GTK_BOX(box),w,FALSE,FALSE,0);
285        adj = (GtkAdjustment *) gtk_adjustment_new (0.0, 0.0,
286                                                    (float)gdk_screen_height(),
287                                                    1.0, 5.0, 0.0);
288        gtk_adjustment_set_value(adj, 48);
289        height_s = gtk_spin_button_new(adj,0,0);
290        gtk_box_pack_start(GTK_BOX(box),height_s,FALSE,FALSE,0);
291       
292        gtk_signal_connect(GTK_OBJECT(d),"clicked",
293                           GTK_SIGNAL_FUNC(really_add_swallow),NULL);
294        gtk_object_set_data(GTK_OBJECT(d),"title_e",title_e);
295        gtk_object_set_data(GTK_OBJECT(d),"exec_e",exec_e);
296        gtk_object_set_data(GTK_OBJECT(d),"width_s",width_s);
297        gtk_object_set_data(GTK_OBJECT(d),"height_s",height_s);
298
299
300        gnome_dialog_close_hides(GNOME_DIALOG(d),FALSE);
301
302        gnome_dialog_set_default(GNOME_DIALOG(d),0);
303
304        gtk_widget_grab_focus(title_e);
305
306        gtk_widget_show_all (d);
307        panel_set_dialog_layer (d);
308}
309
310static int
311ignore_1st_click(GtkWidget *widget, GdkEvent *event)
312{
313        GdkEventButton *buttonevent = (GdkEventButton *)event;
314
315        if((event->type == GDK_BUTTON_PRESS &&
316            buttonevent->button == 1) ||
317           (event->type == GDK_BUTTON_RELEASE &&
318            buttonevent->button == 1)) {
319                buttonevent->button = 2;
320        }
321         
322        return FALSE;
323}
324
325static Swallow *
326create_swallow_applet(char *title, char *path, int width, int height, SwallowOrient orient)
327{
328        Swallow *swallow;
329       
330        swallow = g_new (Swallow, 1);
331        swallow->ref_count = 1;
332
333        swallow->clean_remove = TRUE;
334
335        swallow->ebox = gtk_event_box_new ();
336        gtk_widget_show (swallow->ebox);
337
338        swallow->socket = gtk_socket_new ();
339        if (width != 0 || height != 0)
340                gtk_widget_set_usize(swallow->socket, width, height);
341        gtk_signal_connect_after (GTK_OBJECT (swallow->socket), "realize",
342                                  GTK_SIGNAL_FUNC (socket_realized), NULL);
343        gtk_signal_connect (GTK_OBJECT (swallow->socket), "destroy",
344                            GTK_SIGNAL_FUNC (socket_destroyed), swallow);
345       
346       
347        swallow->handle_box = gtk_handle_box_new ();
348        gtk_signal_connect (GTK_OBJECT (swallow->handle_box), "event",
349                            GTK_SIGNAL_FUNC (ignore_1st_click), NULL);
350       
351        gtk_container_add (GTK_CONTAINER(swallow->ebox),
352                           swallow->handle_box);
353       
354        swallow->frame = gtk_frame_new (NULL);
355       
356        gtk_frame_set_shadow_type (GTK_FRAME(swallow->frame), GTK_SHADOW_IN);
357        gtk_container_add (GTK_CONTAINER(swallow->handle_box), swallow->frame);
358       
359        gtk_widget_show (swallow->handle_box);
360        gtk_container_add (GTK_CONTAINER (swallow->frame),
361                           swallow->socket);
362
363        gtk_widget_show (swallow->socket);
364        gtk_object_set_user_data (GTK_OBJECT (swallow->socket), swallow);
365
366        swallow->title = g_strdup (title);
367        swallow->path = path ? g_strdup (path) : NULL;
368        swallow->width = width;
369        swallow->height = height;
370        swallow->wid = -1;
371
372        set_swallow_applet_orient (swallow, orient);
373
374        return swallow;
375}
376
377void
378set_swallow_applet_orient(Swallow *swallow, SwallowOrient orient)
379{
380        if (GTK_HANDLE_BOX(swallow->handle_box)->child_detached) {
381                if (orient == SWALLOW_VERTICAL) {
382                        GTK_HANDLE_BOX(swallow->handle_box)->handle_position = GTK_POS_TOP;
383                        gtk_widget_set_usize (swallow->handle_box, swallow->width,
384                                              DRAG_HANDLE_SIZE);
385                } else {
386                        GTK_HANDLE_BOX(swallow->handle_box)->handle_position = GTK_POS_LEFT;
387                        gtk_widget_set_usize (swallow->handle_box, DRAG_HANDLE_SIZE,
388                                              swallow->height);
389                }
390        } else {
391                if (orient == SWALLOW_VERTICAL) {
392                        GTK_HANDLE_BOX(swallow->handle_box)->handle_position = GTK_POS_TOP;
393                        gtk_widget_set_usize (swallow->handle_box, swallow->width,
394                                              swallow->height + DRAG_HANDLE_SIZE);
395                } else {
396                        GTK_HANDLE_BOX(swallow->handle_box)->handle_position = GTK_POS_LEFT;
397                        gtk_widget_set_usize (swallow->handle_box,
398                                              swallow->width + DRAG_HANDLE_SIZE,
399                                              swallow->height);
400                }
401        }
402}
403
404void
405load_swallow_applet (char *path, char *params, int width, int height,
406                     PanelWidget *panel, int pos, gboolean exactpos)
407{
408        Swallow *swallow;
409
410        swallow = create_swallow_applet (params, path, width, height,
411                                         SWALLOW_HORIZONTAL);
412        if (swallow == NULL)
413                return;
414
415        if ( ! register_toy (swallow->ebox,
416                             ref_swallow (swallow),
417                             (GDestroyNotify) unref_swallow,
418                             panel, pos,
419                             exactpos, APPLET_SWALLOW))
420                return;
421
422        swallow->clean_remove = FALSE;
423
424        applet_add_callback (applets_last->data, "help",
425                             GNOME_STOCK_PIXMAP_HELP,
426                             _("Help"));
427
428        swallow_launch (swallow);
429}
Note: See TracBrowser for help on using the repository browser.