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 | |
---|
56 | struct NautilusShellDetails { |
---|
57 | NautilusApplication *application; |
---|
58 | }; |
---|
59 | |
---|
60 | static void finalize (GObject *shell); |
---|
61 | static void corba_open_windows (PortableServer_Servant servant, |
---|
62 | const Nautilus_URIList *list, |
---|
63 | const CORBA_char *geometry, |
---|
64 | CORBA_Environment *ev); |
---|
65 | static void corba_open_default_window (PortableServer_Servant servant, |
---|
66 | const CORBA_char *geometry, |
---|
67 | CORBA_Environment *ev); |
---|
68 | static void corba_start_desktop (PortableServer_Servant servant, |
---|
69 | CORBA_Environment *ev); |
---|
70 | static void corba_stop_desktop (PortableServer_Servant servant, |
---|
71 | CORBA_Environment *ev); |
---|
72 | static void corba_quit (PortableServer_Servant servant, |
---|
73 | CORBA_Environment *ev); |
---|
74 | static void corba_restart (PortableServer_Servant servant, |
---|
75 | CORBA_Environment *ev); |
---|
76 | static gboolean restore_window_states (NautilusShell *shell); |
---|
77 | |
---|
78 | BONOBO_CLASS_BOILERPLATE_FULL (NautilusShell, nautilus_shell, |
---|
79 | Nautilus_Shell, |
---|
80 | BonoboObject, BONOBO_OBJECT_TYPE) |
---|
81 | |
---|
82 | static void |
---|
83 | nautilus_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 | |
---|
95 | static void |
---|
96 | nautilus_shell_instance_init (NautilusShell *shell) |
---|
97 | { |
---|
98 | shell->details = g_new0 (NautilusShellDetails, 1); |
---|
99 | } |
---|
100 | |
---|
101 | static void |
---|
102 | finalize (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 | |
---|
112 | NautilusShell * |
---|
113 | nautilus_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 | |
---|
122 | static void |
---|
123 | open_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 | |
---|
145 | static void |
---|
146 | corba_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 | |
---|
163 | static void |
---|
164 | corba_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 | |
---|
178 | static void |
---|
179 | corba_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 | |
---|
191 | static void |
---|
192 | corba_stop_desktop (PortableServer_Servant servant, |
---|
193 | CORBA_Environment *ev) |
---|
194 | { |
---|
195 | nautilus_application_close_desktop (); |
---|
196 | } |
---|
197 | |
---|
198 | static void |
---|
199 | corba_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 | |
---|
225 | static void |
---|
226 | save_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 | |
---|
275 | static void |
---|
276 | restore_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 */ |
---|
333 | static gboolean |
---|
334 | restore_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 | |
---|
347 | static void |
---|
348 | corba_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 | } |
---|