Release 1.2.0.
[lxde/pcmanfm.git] / src / pcmanfm.c
1 /*
2 * pcmanfm.c
3 *
4 * Copyright 2009 - 2010 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
5 * Copyright 2012-2014 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <gtk/gtk.h>
28 #include <gdk/gdkx.h>
29 #include <stdio.h>
30 #include <glib/gi18n.h>
31
32 #include <stdlib.h>
33 #include <string.h>
34 /* socket is used to keep single instance */
35 #include <sys/types.h>
36 #include <signal.h>
37 #include <unistd.h> /* for getcwd */
38
39 #include <libfm/fm-gtk.h>
40 #include "app-config.h"
41 #include "main-win.h"
42 #include "desktop.h"
43 #include "volume-manager.h"
44 #include "pref.h"
45 #include "pcmanfm.h"
46 #include "single-inst.h"
47
48 static int signal_pipe[2] = {-1, -1};
49 static gboolean daemon_mode = FALSE;
50 static gboolean first_run = TRUE;
51 static guint save_config_idle = 0;
52
53 static char** files_to_open = NULL;
54 static int n_files_to_open = 0;
55 static char* profile = NULL;
56 static gboolean no_desktop = FALSE;
57 static gboolean show_desktop = FALSE;
58 static gboolean desktop_off = FALSE;
59 static gboolean desktop_running = FALSE;
60 static gboolean one_screen = FALSE;
61 /* static gboolean new_tab = FALSE; */
62 static gint show_pref = -1;
63 static gboolean desktop_pref = FALSE;
64 static char* set_wallpaper = NULL;
65 static char* wallpaper_mode = NULL;
66 static gboolean new_win = FALSE;
67 #if FM_CHECK_VERSION(1, 0, 2)
68 static gboolean find_files = FALSE;
69 #endif
70 static char* ipc_cwd = NULL;
71 static char* window_role = NULL;
72
73 static int n_pcmanfm_ref = 0;
74
75 static GOptionEntry opt_entries[] =
76 {
77 /* options only acceptable by first pcmanfm instance. These options are not passed through IPC */
78 { "profile", 'p', 0, G_OPTION_ARG_STRING, &profile, N_("Name of configuration profile"), N_("PROFILE") },
79 { "daemon-mode", 'd', 0, G_OPTION_ARG_NONE, &daemon_mode, N_("Run PCManFM as a daemon"), NULL },
80 { "no-desktop", '\0', 0, G_OPTION_ARG_NONE, &no_desktop, N_("No function. Just to be compatible with nautilus"), NULL },
81
82 /* options that are acceptable for every instance of pcmanfm and will be passed through IPC. */
83 { "desktop", '\0', 0, G_OPTION_ARG_NONE, &show_desktop, N_("Launch desktop manager"), NULL },
84 { "desktop-off", '\0', 0, G_OPTION_ARG_NONE, &desktop_off, N_("Turn off desktop manager if it's running"), NULL },
85 { "desktop-pref", '\0', 0, G_OPTION_ARG_NONE, &desktop_pref, N_("Open desktop preference dialog"), NULL },
86 { "one-screen", '\0', 0, G_OPTION_ARG_NONE, &one_screen, N_("Use --desktop option only for one screen"), NULL },
87 { "set-wallpaper", 'w', 0, G_OPTION_ARG_FILENAME, &set_wallpaper, N_("Set desktop wallpaper from image FILE"), N_("FILE") },
88 /* don't translate list of modes in description, please */
89 { "wallpaper-mode", '\0', 0, G_OPTION_ARG_STRING, &wallpaper_mode, N_("Set mode of desktop wallpaper. MODE=(color|stretch|fit|crop|center|tile|screen)"), N_("MODE") },
90 { "show-pref", '\0', 0, G_OPTION_ARG_INT, &show_pref, N_("Open Preferences dialog on the page N"), N_("N") },
91 { "new-win", 'n', 0, G_OPTION_ARG_NONE, &new_win, N_("Open new window"), NULL },
92 #if FM_CHECK_VERSION(1, 0, 2)
93 { "find-files", 'f', 0, G_OPTION_ARG_NONE, &find_files, N_("Open a Find Files window"), NULL },
94 #endif
95 { "role", '\0', 0, G_OPTION_ARG_STRING, &window_role, N_("Window role for usage by window manager"), N_("ROLE") },
96 {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &files_to_open, NULL, N_("[FILE1, FILE2,...]")},
97 { NULL }
98 };
99
100 static gboolean pcmanfm_run(gint screen_num);
101
102 /* it's not safe to call gtk+ functions in unix signal handler
103 * since the process is interrupted here and the state of gtk+ is unpredictable. */
104 static void unix_signal_handler(int sig_num)
105 {
106 /* postpond the signal handling by using a pipe */
107 if (write(signal_pipe[1], &sig_num, sizeof(sig_num)) != sizeof(sig_num)) {
108 g_critical("cannot bounce the signal, stop");
109 exit(2);
110 }
111 }
112
113 static gboolean on_unix_signal(GIOChannel* ch, GIOCondition cond, gpointer user_data)
114 {
115 int sig_num;
116 GIOStatus status;
117 gsize got;
118
119 while(1)
120 {
121 status = g_io_channel_read_chars(ch, (gchar*)&sig_num, sizeof(sig_num),
122 &got, NULL);
123 if(status == G_IO_STATUS_AGAIN) /* we read all the pipe */
124 {
125 g_debug("got G_IO_STATUS_AGAIN");
126 return TRUE;
127 }
128 if(status != G_IO_STATUS_NORMAL || got != sizeof(sig_num)) /* broken pipe */
129 {
130 g_debug("signal pipe is broken");
131 gtk_main_quit();
132 return FALSE;
133 }
134 g_debug("got signal %d from pipe", sig_num);
135 switch(sig_num)
136 {
137 case SIGTERM:
138 default:
139 gtk_main_quit();
140 return FALSE;
141 }
142 }
143 return TRUE;
144 }
145
146 static void single_inst_cb(const char* cwd, int screen_num)
147 {
148 g_free(ipc_cwd);
149 ipc_cwd = g_strdup(cwd);
150
151 if(files_to_open)
152 {
153 int i;
154 n_files_to_open = g_strv_length(files_to_open);
155 /* canonicalize filename if needed. */
156 for(i = 0; i < n_files_to_open; ++i)
157 {
158 char* file = files_to_open[i];
159 char* scheme = g_uri_parse_scheme(file);
160 g_debug("file: %s", file);
161 if(scheme) /* a valid URI */
162 {
163 g_free(scheme);
164 }
165 else /* a file path */
166 {
167 files_to_open[i] = fm_canonicalize_filename(file, cwd);
168 g_free(file);
169 }
170 }
171 }
172 pcmanfm_run(screen_num);
173 window_role = NULL; /* reset it for clients callbacks */
174 }
175
176 #if FM_CHECK_VERSION(1, 2, 0)
177 /* ---- statusbar plugins support ---- */
178 FM_MODULE_DEFINE_TYPE(tab_page_status, FmTabPageStatusInit, 1)
179
180 GList *_tab_page_modules = NULL;
181
182 static gboolean fm_module_callback_tab_page_status(const char *name, gpointer init, int ver)
183 {
184 /* add module callbacks into own data list */
185 if (((FmTabPageStatusInit*)init)->sel_message == NULL)
186 return FALSE;
187 if (((FmTabPageStatusInit*)init)->init && !((FmTabPageStatusInit*)init)->init())
188 return FALSE;
189 _tab_page_modules = g_list_append(_tab_page_modules, init);
190 return TRUE;
191 }
192 #endif
193
194 static void on_config_changed(FmAppConfig *cfg, gpointer _unused)
195 {
196 pcmanfm_save_config(FALSE);
197 }
198
199 int main(int argc, char** argv)
200 {
201 FmConfig* config;
202 GError* err = NULL;
203 SingleInstData inst;
204 #if FM_CHECK_VERSION(1, 2, 0)
205 GList *l;
206 #endif
207
208 #ifdef ENABLE_NLS
209 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
210 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
211 textdomain ( GETTEXT_PACKAGE );
212 #endif
213
214 /* initialize GTK+ and parse the command line arguments */
215 if(G_UNLIKELY(!gtk_init_with_args(&argc, &argv, " ", opt_entries, GETTEXT_PACKAGE, &err)))
216 {
217 g_printf("%s\n", err->message);
218 g_error_free(err);
219 return 1;
220 }
221
222 /* ensure that there is only one instance of pcmanfm. */
223 inst.prog_name = "pcmanfm";
224 inst.cb = single_inst_cb;
225 inst.opt_entries = opt_entries + 3;
226 inst.screen_num = gdk_x11_get_default_screen();
227 switch(single_inst_init(&inst))
228 {
229 case SINGLE_INST_CLIENT: /* we're not the first instance. */
230 single_inst_finalize(&inst);
231 gdk_notify_startup_complete();
232 return 0;
233 case SINGLE_INST_ERROR: /* error happened. */
234 single_inst_finalize(&inst);
235 return 1;
236 case SINGLE_INST_SERVER: ; /* FIXME */
237 }
238
239 if(pipe(signal_pipe) == 0)
240 {
241 GIOChannel* ch = g_io_channel_unix_new(signal_pipe[0]);
242 g_io_add_watch(ch, G_IO_IN|G_IO_PRI, (GIOFunc)on_unix_signal, NULL);
243 g_io_channel_unref(ch);
244
245 /* intercept signals */
246 // signal( SIGPIPE, SIG_IGN );
247 signal( SIGHUP, unix_signal_handler );
248 signal( SIGTERM, unix_signal_handler );
249 signal( SIGINT, unix_signal_handler );
250 }
251
252 config = fm_app_config_new(); /* this automatically load libfm config file. */
253
254 fm_gtk_init(config);
255
256 #if FM_CHECK_VERSION(1, 2, 0)
257 /* register our modules */
258 fm_modules_add_directory(PACKAGE_MODULES_DIR);
259 fm_module_register_tab_page_status();
260 #endif
261
262 #if FM_CHECK_VERSION(1, 0, 2)
263 # if !FM_CHECK_VERSION(1, 2, 0)
264 /* the sort_by value isn't loaded with LibFM 1.1.x so we need a workaround */
265 /* a little trick to initialize FmFolderModel class */
266 gpointer null_model = fm_folder_model_new(NULL, FALSE);
267 g_object_unref(null_model);
268 # endif
269 #endif
270
271 /* load pcmanfm-specific config file */
272 fm_app_config_load_from_profile(FM_APP_CONFIG(config), profile);
273 g_signal_connect(config, "changed::saved_search", G_CALLBACK(on_config_changed), NULL);
274
275 /* the main part */
276 if(pcmanfm_run(gdk_screen_get_number(gdk_screen_get_default())))
277 {
278 first_run = FALSE;
279 window_role = NULL; /* reset it for clients callbacks */
280 fm_volume_manager_init();
281 #if !GTK_CHECK_VERSION(3, 6, 0)
282 GDK_THREADS_ENTER();
283 #endif
284 gtk_main();
285 /* g_debug("main loop ended"); */
286 #if !GTK_CHECK_VERSION(3, 6, 0)
287 GDK_THREADS_LEAVE();
288 #endif
289
290 if(save_config_idle)
291 {
292 pcmanfm_save_config(TRUE);
293 g_source_remove(save_config_idle);
294 save_config_idle = 0;
295 }
296 fm_volume_manager_finalize();
297 }
298
299 #if FM_CHECK_VERSION(1, 2, 0)
300 for (l = _tab_page_modules; l; l = l->next)
301 if (((FmTabPageStatusInit*)l->data)->finalize)
302 ((FmTabPageStatusInit*)l->data)->finalize();
303 fm_module_unregister_type("tab_page_status");
304 g_list_free(_tab_page_modules);
305 _tab_page_modules = NULL;
306 #endif
307
308 single_inst_finalize(&inst);
309 fm_gtk_finalize();
310
311 g_object_unref(config);
312 return 0;
313 }
314
315 gboolean pcmanfm_run(gint screen_num)
316 {
317 FmMainWin *win = NULL;
318 gboolean ret = TRUE;
319
320 if(!files_to_open)
321 {
322 /* FIXME: use screen number from client and pointer position */
323 FmDesktop *desktop = fm_desktop_get(0, 0);
324
325 /* Launch desktop manager */
326 if(show_desktop)
327 {
328 if(!desktop_running)
329 {
330 fm_desktop_manager_init(one_screen ? screen_num : -1);
331 desktop_running = TRUE;
332 one_screen = FALSE;
333 }
334 show_desktop = FALSE;
335 return TRUE;
336 }
337 else if(desktop_off)
338 {
339 if(desktop_running)
340 {
341 desktop_running = FALSE;
342 fm_desktop_manager_finalize();
343 }
344 desktop_off = FALSE;
345 return FALSE;
346 }
347 else if(show_pref > 0)
348 {
349 fm_edit_preference(GTK_WINDOW(desktop), show_pref - 1);
350 show_pref = -1;
351 return TRUE;
352 }
353 else if(desktop == NULL)
354 {
355 /* ignore desktop-oriented commands if no desktop support */
356 if (desktop_pref || wallpaper_mode || set_wallpaper)
357 {
358 fm_show_error(NULL, NULL, _("Desktop manager is not active."));
359 return FALSE;
360 }
361 }
362 else if(desktop_pref)
363 {
364 fm_desktop_preference(NULL, desktop);
365 desktop_pref = FALSE;
366 return TRUE;
367 }
368 else if(wallpaper_mode || set_wallpaper)
369 {
370 gboolean wallpaper_changed = FALSE;
371 if(set_wallpaper) /* a new wallpaper is assigned */
372 {
373 /* g_debug("\'%s\'", set_wallpaper); */
374 /* Make sure this is a support image file. */
375 if(gdk_pixbuf_get_file_info(set_wallpaper, NULL, NULL))
376 {
377 if(desktop->conf.wallpaper)
378 g_free(desktop->conf.wallpaper);
379 desktop->conf.wallpaper = set_wallpaper;
380 if(! wallpaper_mode) /* if wallpaper mode is not specified */
381 {
382 /* do not use solid color mode; otherwise wallpaper won't be shown. */
383 if(desktop->conf.wallpaper_mode == FM_WP_COLOR)
384 desktop->conf.wallpaper_mode = FM_WP_FIT;
385 }
386 wallpaper_changed = TRUE;
387 }
388 else
389 g_free(set_wallpaper);
390 set_wallpaper = NULL;
391 }
392
393 if(wallpaper_mode)
394 {
395 FmWallpaperMode mode = fm_app_wallpaper_get_mode_by_name(wallpaper_mode);
396
397 if (mode != (FmWallpaperMode)-1
398 && mode != desktop->conf.wallpaper_mode)
399 {
400 desktop->conf.wallpaper_mode = mode;
401 wallpaper_changed = TRUE;
402 }
403 g_free(wallpaper_mode);
404 wallpaper_mode = NULL;
405 }
406
407 if(wallpaper_changed)
408 fm_desktop_wallpaper_changed(desktop);
409
410 return FALSE;
411 }
412 }
413
414 if(files_to_open)
415 {
416 char** filename;
417 FmPath* cwd = NULL;
418 GList* paths = NULL;
419 for(filename=files_to_open; *filename; ++filename)
420 {
421 FmPath* path;
422 if( **filename == '/') /* absolute path */
423 path = fm_path_new_for_path(*filename);
424 else if(strstr(*filename, ":/") ) /* URI */
425 path = fm_path_new_for_uri(*filename);
426 else if( strcmp(*filename, "~") == 0 ) /* special case for home dir */
427 {
428 path = fm_path_get_home();
429 win = fm_main_win_add_win(NULL, path);
430 if(new_win && window_role)
431 gtk_window_set_role(GTK_WINDOW(win), window_role);
432 continue;
433 }
434 else /* basename */
435 {
436 if(G_UNLIKELY(!cwd))
437 {
438 char* cwd_str = ipc_cwd ? ipc_cwd : g_get_current_dir();
439 cwd = fm_path_new_for_str(cwd_str);
440 g_free(cwd_str);
441 }
442 path = fm_path_new_relative(cwd, *filename);
443 }
444 paths = g_list_append(paths, path);
445 }
446 if(cwd)
447 fm_path_unref(cwd);
448 fm_launch_paths_simple(NULL, NULL, paths, pcmanfm_open_folder, NULL);
449 g_list_foreach(paths, (GFunc)fm_path_unref, NULL);
450 g_list_free(paths);
451 ret = (n_pcmanfm_ref >= 1); /* if there is opened window, return true to run the main loop. */
452
453 g_strfreev(files_to_open);
454 files_to_open = NULL;
455 }
456 else
457 {
458 if(first_run && daemon_mode)
459 {
460 /* If the function is called the first time and we're in daemon mode,
461 * don't open any folder.
462 * Checking if pcmanfm_run() is called the first time is needed to fix
463 * #3397444 - pcmanfm dont show window in daemon mode if i call 'pcmanfm' */
464 pcmanfm_ref();
465 }
466 #if FM_CHECK_VERSION(1, 0, 2)
467 else if (G_LIKELY(!find_files || n_pcmanfm_ref < 1))
468 #else
469 else
470 #endif
471 {
472 /* If we're not in daemon mode, or pcmanfm_run() is called because another
473 * instance send signal to us, open cwd by default. */
474 FmPath* path;
475 char* cwd = ipc_cwd ? ipc_cwd : g_get_current_dir();
476 path = fm_path_new_for_path(cwd);
477 win = fm_main_win_add_win(NULL, path);
478 if(new_win && window_role)
479 gtk_window_set_role(GTK_WINDOW(win), window_role);
480 fm_path_unref(path);
481 g_free(cwd);
482 ipc_cwd = NULL;
483 }
484 }
485
486 #if FM_CHECK_VERSION(1, 0, 2)
487 /* we got a reference at this point so we can open a search dialog */
488 if (ret && find_files)
489 fm_launch_search_simple(GTK_WINDOW(win), NULL, NULL,
490 pcmanfm_open_folder, NULL);
491 find_files = FALSE;
492 #endif
493 return ret;
494 }
495
496 /* After opening any window/dialog/tool, this should be called. */
497 void pcmanfm_ref()
498 {
499 ++n_pcmanfm_ref;
500 /* g_debug("ref: %d", n_pcmanfm_ref); */
501 }
502
503 /* After closing any window/dialog/tool, this should be called.
504 * If the last window is closed and we are not a deamon, pcmanfm will quit.
505 */
506 void pcmanfm_unref()
507 {
508 --n_pcmanfm_ref;
509 /* g_debug("unref: %d, daemon_mode=%d, desktop_running=%d", n_pcmanfm_ref, daemon_mode, desktop_running); */
510 if( 0 == n_pcmanfm_ref )
511 gtk_main_quit();
512 }
513
514 static void move_window_to_desktop(FmMainWin* win, FmDesktop* desktop)
515 {
516 GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(desktop));
517 Atom atom;
518 char* atom_name = "_NET_WM_DESKTOP";
519 XClientMessageEvent xev;
520
521 gtk_window_set_screen(GTK_WINDOW(win), screen);
522 if(!XInternAtoms(gdk_x11_get_default_xdisplay(), &atom_name, 1, False, &atom))
523 {
524 /* g_debug("cannot get Atom for _NET_WM_DESKTOP"); */
525 return;
526 }
527 xev.type = ClientMessage;
528 xev.window = GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(win)));
529 xev.message_type = atom;
530 xev.format = 32;
531 xev.data.l[0] = desktop->cur_desktop;
532 xev.data.l[1] = 0;
533 xev.data.l[2] = 0;
534 xev.data.l[3] = 0;
535 xev.data.l[4] = 0;
536 /* g_debug("moving window to current desktop"); */
537 XSendEvent(gdk_x11_get_default_xdisplay(), GDK_ROOT_WINDOW(), False,
538 (SubstructureNotifyMask | SubstructureRedirectMask),
539 (XEvent *) &xev);
540 }
541
542 gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err)
543 {
544 GList* l = folder_infos;
545 gboolean use_new_win = new_win;
546
547 /* for desktop folder open it in new win if set in config */
548 if (!use_new_win && user_data && FM_IS_DESKTOP(user_data))
549 use_new_win = app_config->desktop_folder_new_win;
550 if(use_new_win)
551 {
552 FmMainWin *win = fm_main_win_add_win(NULL,
553 fm_file_info_get_path((FmFileInfo*)l->data));
554 if(window_role)
555 gtk_window_set_role(GTK_WINDOW(win), window_role);
556 new_win = FALSE;
557 l = l->next;
558 }
559 for(; l; l=l->next)
560 {
561 FmFileInfo* fi = (FmFileInfo*)l->data;
562 fm_main_win_open_in_last_active(fm_file_info_get_path(fi));
563 }
564 if(user_data && FM_IS_DESKTOP(user_data))
565 move_window_to_desktop(fm_main_win_get_last_active(), user_data);
566 return TRUE;
567 }
568
569 static gboolean on_save_config_idle(gpointer user_data)
570 {
571 pcmanfm_save_config(TRUE);
572 save_config_idle = 0;
573 return FALSE;
574 }
575
576 void pcmanfm_save_config(gboolean immediate)
577 {
578 if(immediate)
579 {
580 fm_config_save(fm_config, NULL);
581 fm_app_config_save_profile(app_config, profile);
582 }
583 else
584 {
585 /* install an idle handler to save the config file. */
586 if( 0 == save_config_idle)
587 save_config_idle = gdk_threads_add_idle_full(G_PRIORITY_LOW, (GSourceFunc)on_save_config_idle, NULL, NULL);
588 }
589 }
590
591 void pcmanfm_open_folder_in_terminal(GtkWindow* parent, FmPath* dir)
592 {
593 GAppInfo* app;
594 char** argv;
595 int argc;
596 if(!fm_config->terminal)
597 {
598 fm_show_error(parent, NULL, _("Terminal emulator is not set."));
599 fm_edit_preference(parent, PREF_ADVANCED);
600 return;
601 }
602 if(!g_shell_parse_argv(fm_config->terminal, &argc, &argv, NULL))
603 return;
604 app = g_app_info_create_from_commandline(argv[0], NULL, 0, NULL);
605 g_strfreev(argv);
606 if(app)
607 {
608 GError* err = NULL;
609 GdkAppLaunchContext* ctx = gdk_app_launch_context_new();
610 char* cwd_str;
611 char* old_cwd = g_get_current_dir();
612
613 if(fm_path_is_native(dir))
614 cwd_str = fm_path_to_str(dir);
615 else
616 {
617 GFile* gf = fm_path_to_gfile(dir);
618 cwd_str = g_file_get_path(gf);
619 g_object_unref(gf);
620 }
621 gdk_app_launch_context_set_screen(ctx, parent ? gtk_widget_get_screen(GTK_WIDGET(parent)) : gdk_screen_get_default());
622 gdk_app_launch_context_set_timestamp(ctx, gtk_get_current_event_time());
623 g_chdir(cwd_str); /* FIXME: currently we don't have better way for this. maybe a wrapper script? */
624 g_free(cwd_str);
625
626 if(!g_app_info_launch(app, NULL, G_APP_LAUNCH_CONTEXT(ctx), &err))
627 {
628 fm_show_error(parent, NULL, err->message);
629 g_error_free(err);
630 }
631 g_object_unref(ctx);
632 g_object_unref(app);
633
634 /* switch back to old cwd and fix #3114626 - PCManFM 0.9.9 Umount partitions problem */
635 g_chdir(old_cwd); /* This is really dirty, but we don't have better solution now. */
636 g_free(old_cwd);
637 }
638 }
639
640 char* pcmanfm_get_profile_dir(gboolean create)
641 {
642 char* dir = g_build_filename(g_get_user_config_dir(), "pcmanfm", profile ? profile : "default", NULL);
643 if(create)
644 g_mkdir_with_parents(dir, 0700);
645 return dir;
646 }