source: trunk/third/nautilus/src/nautilus-shell.c @ 18663

Revision 18663, 9.9 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18662, which included commits to RCS files with non-trunk default branches.
Line 
1/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3/*
4 * Nautilus
5 *
6 * Copyright (C) 2000 Eazel, Inc.
7 *
8 * Nautilus is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * Nautilus is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the
20 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 * Boston, MA 02111-1307, USA.
22 */
23
24/* nautilus-shell.h: Server side of the Nautilus:Shell CORBA object
25 * that represents the shell across processes.
26 */
27
28#include <config.h>
29#include "nautilus-shell.h"
30
31#include "nautilus-desktop-window.h"
32#include "nautilus-main.h"
33#include <eel/eel-glib-extensions.h>
34#include <eel/eel-gtk-extensions.h>
35#include <eel/eel-gtk-macros.h>
36#include <eel/eel-stock-dialogs.h>
37#include <eel/eel-string.h>
38#include <gtk/gtkframe.h>
39#include <gtk/gtkhbox.h>
40#include <gtk/gtklabel.h>
41#include <gtk/gtkmain.h>
42#include <gtk/gtksignal.h>
43#include <libgnome/gnome-i18n.h>
44#include <libgnomeui/gnome-stock-icons.h>
45#include <libgnomeui/gnome-uidefs.h>
46#include <libnautilus-private/nautilus-file-utilities.h>
47#include <libnautilus-private/nautilus-global-preferences.h>
48#include <stdlib.h>
49
50/* Keep window from shrinking down ridiculously small; numbers are somewhat arbitrary */
51#define APPLICATION_WINDOW_MIN_WIDTH    300
52#define APPLICATION_WINDOW_MIN_HEIGHT   100
53
54#define START_STATE_CONFIG "start-state"
55
56struct NautilusShellDetails {
57        NautilusApplication *application;
58};
59
60static void     finalize                         (GObject              *shell);
61static void     corba_open_windows              (PortableServer_Servant  servant,
62                                                 const Nautilus_URIList *list,
63                                                 const CORBA_char       *geometry,
64                                                 CORBA_Environment      *ev);
65static void     corba_open_default_window       (PortableServer_Servant  servant,
66                                                 const CORBA_char       *geometry,
67                                                 CORBA_Environment      *ev);
68static void     corba_start_desktop             (PortableServer_Servant  servant,
69                                                 CORBA_Environment      *ev);
70static void     corba_stop_desktop              (PortableServer_Servant  servant,
71                                                 CORBA_Environment      *ev);
72static void     corba_quit                      (PortableServer_Servant  servant,
73                                                 CORBA_Environment      *ev);
74static void     corba_restart                   (PortableServer_Servant  servant,
75                                                 CORBA_Environment      *ev);
76static gboolean restore_window_states           (NautilusShell          *shell);
77
78BONOBO_CLASS_BOILERPLATE_FULL (NautilusShell, nautilus_shell,
79                               Nautilus_Shell,
80                               BonoboObject, BONOBO_OBJECT_TYPE)
81
82static void
83nautilus_shell_class_init (NautilusShellClass *klass)
84{
85        G_OBJECT_CLASS (klass)->finalize = finalize;
86
87        klass->epv.open_windows = corba_open_windows;
88        klass->epv.open_default_window = corba_open_default_window;
89        klass->epv.start_desktop = corba_start_desktop;
90        klass->epv.stop_desktop = corba_stop_desktop;
91        klass->epv.quit = corba_quit;
92        klass->epv.restart = corba_restart;
93}
94
95static void
96nautilus_shell_instance_init (NautilusShell *shell)
97{
98        shell->details = g_new0 (NautilusShellDetails, 1);
99}
100
101static void
102finalize (GObject *object)
103{
104        NautilusShell *shell;
105
106        shell = NAUTILUS_SHELL (object);
107        g_free (shell->details);
108
109        EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object));
110}
111
112NautilusShell *
113nautilus_shell_new (NautilusApplication *application)
114{
115        NautilusShell *shell;
116
117        shell = NAUTILUS_SHELL (g_object_new (NAUTILUS_TYPE_SHELL, NULL));
118        shell->details->application = application;
119        return shell;
120}
121
122static void
123open_window (NautilusShell *shell, const char *uri, const char *geometry)
124{
125        NautilusWindow *window;
126
127        window = nautilus_application_create_window (shell->details->application,
128                                                     gdk_screen_get_default ());
129
130        if (geometry != NULL) {
131                eel_gtk_window_set_initial_geometry_from_string (GTK_WINDOW (window),
132                                                                      geometry,
133                                                                      APPLICATION_WINDOW_MIN_WIDTH,
134                                                                      APPLICATION_WINDOW_MIN_HEIGHT,
135                                                                      FALSE);
136        }
137
138        if (uri == NULL) {
139                nautilus_window_go_home (window);
140        } else {
141                nautilus_window_go_to (window, uri);
142        }
143}
144
145static void
146corba_open_windows (PortableServer_Servant servant,
147                    const Nautilus_URIList *list,
148                    const CORBA_char *geometry,
149                    CORBA_Environment *ev)
150{
151        NautilusShell *shell;
152        guint i;
153
154        shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant));
155
156        /* Open windows at each requested location. */
157        for (i = 0; i < list->_length; i++) {
158                g_assert (list->_buffer[i] != NULL);
159                open_window (shell, list->_buffer[i], geometry);
160        }
161}
162
163static void
164corba_open_default_window (PortableServer_Servant servant,
165                           const CORBA_char *geometry,
166                           CORBA_Environment *ev)
167{
168        NautilusShell *shell;
169
170        shell = NAUTILUS_SHELL (bonobo_object_from_servant (servant));
171
172        if (!restore_window_states (shell)) {
173                /* Open a window pointing at the default location. */
174                open_window (shell, NULL, geometry);
175        }
176}
177
178static void
179corba_start_desktop (PortableServer_Servant servant,
180                      CORBA_Environment *ev)
181{
182        NautilusShell         *shell;
183        NautilusApplication   *application;
184
185        shell       = NAUTILUS_SHELL (bonobo_object_from_servant (servant));
186        application = NAUTILUS_APPLICATION (shell->details->application);
187       
188        nautilus_application_open_desktop (application);
189}
190
191static void
192corba_stop_desktop (PortableServer_Servant servant,
193                    CORBA_Environment *ev)
194{       
195        nautilus_application_close_desktop ();
196}
197
198static void
199corba_quit (PortableServer_Servant servant,
200            CORBA_Environment *ev)
201{
202        nautilus_main_event_loop_quit ();
203}
204
205/*
206 * code for saving the state of nautilus windows across a restart
207 *
208 * for now, only the window geometry & uri is saved, into "start-state",
209 * in a list of strings like:
210 *
211 *     "<width>,<height>,<x>,<y>,<location>"
212 *
213 * For example:
214 *
215 *     "800,600,10,10,file:///tmp"
216 */
217
218#define WINDOW_STATE_ATTRIBUTE_WIDTH    0
219#define WINDOW_STATE_ATTRIBUTE_HEIGHT   1
220#define WINDOW_STATE_ATTRIBUTE_X        2
221#define WINDOW_STATE_ATTRIBUTE_Y        3
222#define WINDOW_STATE_ATTRIBUTE_LOCATION 4
223#define WINDOW_STATE_ATTRIBUTE_SCREEN   5
224
225static void
226save_window_states (void)
227{
228        GList *windows;
229        GList *node;
230        NautilusWindow *window;
231        GdkWindow *gdk_window;
232        char *window_attributes;
233        int x, y, width, height;
234        char *location;
235        EelStringList *states;
236        int screen_num = -1;
237
238        states = NULL;
239        windows = nautilus_application_get_window_list ();
240        for (node = windows; node; node = g_list_next (node)) {
241                g_assert (node->data != NULL);
242                window = node->data;
243
244                width = GTK_WIDGET (window)->allocation.width;
245                height = GTK_WIDGET (window)->allocation.height;
246
247                /* need root origin (origin of all the window dressing) */
248                gdk_window = GTK_WIDGET (window)->window;
249                gdk_window_get_root_origin (gdk_window, &x, &y);
250
251                location = nautilus_window_get_location (window);
252
253                screen_num = gdk_screen_get_number (
254                                        gtk_window_get_screen (GTK_WINDOW (window)));
255
256                window_attributes = g_strdup_printf ("%d,%d,%d,%d,%s,%d",
257                                                     width, height,
258                                                     x, y,
259                                                     location,
260                                                     screen_num);
261                g_free (location);
262               
263                if (states == NULL) {
264                        states = eel_string_list_new (TRUE);
265                }
266                eel_string_list_insert (states, window_attributes);
267                g_free (window_attributes);
268        }
269
270        eel_preferences_set_string_list (START_STATE_CONFIG, states);
271
272        eel_string_list_free (states);
273}
274
275static void
276restore_one_window_callback (const char *attributes,
277                             gpointer callback_data)
278{
279        NautilusShell *shell;
280        EelStringList *attribute_list;
281        int x;
282        int y;
283        int width;
284        int height;
285        char *location;
286        NautilusWindow *window;
287        GdkScreen *screen = NULL;
288        int screen_num;
289        int list_length;
290
291        g_return_if_fail (eel_strlen (attributes) > 0);
292        g_return_if_fail (NAUTILUS_IS_SHELL (callback_data));
293
294        shell = NAUTILUS_SHELL (callback_data);
295
296        attribute_list = eel_string_list_new_from_tokens (attributes, ",", TRUE);
297
298        list_length = eel_string_list_get_length (attribute_list);
299
300        eel_string_list_nth_as_integer (attribute_list, WINDOW_STATE_ATTRIBUTE_WIDTH, &width);
301        eel_string_list_nth_as_integer (attribute_list, WINDOW_STATE_ATTRIBUTE_HEIGHT, &height);
302        eel_string_list_nth_as_integer (attribute_list, WINDOW_STATE_ATTRIBUTE_X, &x);
303        eel_string_list_nth_as_integer (attribute_list, WINDOW_STATE_ATTRIBUTE_Y, &y);
304        location = eel_string_list_nth (attribute_list, WINDOW_STATE_ATTRIBUTE_LOCATION);
305
306        /* Support sessions with no screen number for backwards compat.
307         */
308        if (list_length >= WINDOW_STATE_ATTRIBUTE_SCREEN + 1) {
309                eel_string_list_nth_as_integer (
310                        attribute_list, WINDOW_STATE_ATTRIBUTE_SCREEN, &screen_num);
311
312                screen = gdk_display_get_screen (gdk_display_get_default (), screen_num);
313        } else {
314                screen = gdk_screen_get_default ();
315        }
316
317        window = nautilus_application_create_window (shell->details->application, screen);
318       
319        if (eel_strlen (location) > 0) {
320                nautilus_window_go_to (window, location);
321        } else {
322                nautilus_window_go_home (window);
323        }
324
325        gtk_window_move (GTK_WINDOW (window), x, y);
326        gtk_widget_set_size_request (GTK_WIDGET (window), width, height);
327
328        g_free (location);
329        eel_string_list_free (attribute_list);
330}
331
332/* returns TRUE if there was state info which has been used to create new windows */
333static gboolean
334restore_window_states (NautilusShell *shell)
335{
336        EelStringList *states;
337        gboolean result;
338
339        states = eel_preferences_get_string_list (START_STATE_CONFIG);
340        result = eel_string_list_get_length (states) > 0;
341        eel_string_list_for_each (states, restore_one_window_callback, shell);
342        eel_string_list_free (states);
343        eel_preferences_set_string_list (START_STATE_CONFIG, NULL);
344        return result;
345}
346
347static void
348corba_restart (PortableServer_Servant servant,
349               CORBA_Environment *ev)
350{
351        save_window_states ();
352
353        nautilus_main_event_loop_quit ();
354        eel_setenv ("_NAUTILUS_RESTART", "yes", 1);
355}
Note: See TracBrowser for help on using the repository browser.