Added support for options force_startup_notify and backup_as_hidden.
[lxde/pcmanfm.git] / src / pcmanfm.c
CommitLineData
b6e3c554
HJYP
1/*
2 * pcmanfm.c
d3451adb 3 *
7b7d923f 4 * Copyright 2009 - 2010 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
984ccbd9 5 * Copyright 2012 Andriy Grytsenko (LStranger) <andrej@rep.kiev.ua>
d3451adb 6 *
b6e3c554
HJYP
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.
d3451adb 11 *
b6e3c554
HJYP
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.
d3451adb 16 *
b6e3c554
HJYP
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
08e70fea 23#ifdef HAVE_CONFIG_H
b6e3c554 24#include <config.h>
08e70fea
HJYP
25#endif
26
b6e3c554 27#include <gtk/gtk.h>
1098cfe7 28#include <gdk/gdkx.h>
b6e3c554 29#include <stdio.h>
f8f2bfad
HJYP
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>
f8f2bfad
HJYP
36#include <signal.h>
37#include <unistd.h> /* for getcwd */
b6e3c554 38
20c0bc9a 39#include <libfm/fm-gtk.h>
4d55886c 40#include "app-config.h"
b6e3c554 41#include "main-win.h"
8505a8ef 42#include "desktop.h"
71f82759 43#include "volume-manager.h"
c5fccf1d 44#include "pref.h"
df6826e0 45#include "pcmanfm.h"
cc448d7f 46#include "single-inst.h"
f8f2bfad 47
94435bc3 48static int signal_pipe[2] = {-1, -1};
f8f2bfad 49gboolean daemon_mode = FALSE;
3d141640 50static guint save_config_idle = 0;
f8f2bfad 51
f8f2bfad 52static char** files_to_open = NULL;
cc448d7f 53static int n_files_to_open = 0;
f970e846 54static char* profile = NULL;
f8f2bfad
HJYP
55static gboolean no_desktop = FALSE;
56static gboolean show_desktop = FALSE;
57static gboolean desktop_off = FALSE;
58static gboolean desktop_running = FALSE;
107cdb22 59/* static gboolean new_tab = FALSE; */
f8f2bfad
HJYP
60static int show_pref = 0;
61static gboolean desktop_pref = FALSE;
62static char* set_wallpaper = NULL;
107cdb22 63static char* wallpaper_mode = NULL;
9197e75e 64/* static gboolean new_win = FALSE; */
f8f2bfad 65static gboolean find_files = FALSE;
5b890032 66static char* ipc_cwd = NULL;
fbce80c9 67/* static char* window_role = NULL; */
f8f2bfad
HJYP
68
69static int n_pcmanfm_ref = 0;
70
71static GOptionEntry opt_entries[] =
8505a8ef 72{
cda6259f 73 /* options only acceptable by first pcmanfm instance. These options are not passed through IPC */
a48f9fc8 74 { "profile", 'p', 0, G_OPTION_ARG_STRING, &profile, N_("Name of configuration profile"), "<profile name>" },
cda6259f
HJYP
75 { "daemon-mode", 'd', 0, G_OPTION_ARG_NONE, &daemon_mode, N_("Run PCManFM as a daemon"), NULL },
76 { "no-desktop", '\0', 0, G_OPTION_ARG_NONE, &no_desktop, N_("No function. Just to be compatible with nautilus"), NULL },
77
78 /* options that are acceptable for every instance of pcmanfm and will be passed through IPC. */
f8f2bfad
HJYP
79 { "desktop", '\0', 0, G_OPTION_ARG_NONE, &show_desktop, N_("Launch desktop manager"), NULL },
80 { "desktop-off", '\0', 0, G_OPTION_ARG_NONE, &desktop_off, N_("Turn off desktop manager if it's running"), NULL },
f8f2bfad 81 { "desktop-pref", '\0', 0, G_OPTION_ARG_NONE, &desktop_pref, N_("Open desktop preference dialog"), NULL },
f970e846 82 { "set-wallpaper", 'w', 0, G_OPTION_ARG_FILENAME, &set_wallpaper, N_("Set desktop wallpaper"), N_("<image file>") },
8ee5c1ac 83 /* don't translate list of modes in description, please */
107cdb22 84 { "wallpaper-mode", '\0', 0, G_OPTION_ARG_STRING, &wallpaper_mode, N_("Set mode of desktop wallpaper. <mode>=(color|stretch|fit|center|tile)"), N_("<mode>") },
a48f9fc8 85 { "show-pref", '\0', 0, G_OPTION_ARG_INT, &show_pref, N_("Open preference dialog. 'n' is number of the page you want to show (1, 2, 3...)."), "n" },
9197e75e 86 /* { "new-win", '\0', 'n', G_OPTION_ARG_NONE, &new_win, N_("Open new window"), NULL }, */
1d071341 87 /* { "find-files", 'f', 0, G_OPTION_ARG_NONE, &find_files, N_("Open Find Files utility"), NULL }, */
fbce80c9 88 /* { "role", '\0', 0, G_OPTION_ARG_STRING, &window_role, N_("Window role for usage by window manager", N_("ROLE") }, */
f8f2bfad
HJYP
89 {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &files_to_open, NULL, N_("[FILE1, FILE2,...]")},
90 { NULL }
91};
92
107cdb22
HJYP
93static const char* valid_wallpaper_modes[] = {"color", "stretch", "fit", "center", "tile"};
94
f8f2bfad 95static gboolean pcmanfm_run();
b6e3c554 96
94435bc3
HJYP
97/* it's not safe to call gtk+ functions in unix signal handler
98 * since the process is interrupted here and the state of gtk+ is unpredictable. */
99static void unix_signal_handler(int sig_num)
100{
101 /* postpond the signal handling by using a pipe */
3aebc679
AG
102 if (write(signal_pipe[1], &sig_num, sizeof(sig_num)) != sizeof(sig_num)) {
103 g_critical("cannot bounce the signal, stop");
104 exit(2);
105 }
94435bc3
HJYP
106}
107
108static gboolean on_unix_signal(GIOChannel* ch, GIOCondition cond, gpointer user_data)
109{
110 int sig_num;
2ddc3882
AG
111 GIOStatus status;
112 gsize got;
113
114 while(1)
94435bc3 115 {
2ddc3882
AG
116 status = g_io_channel_read_chars(ch, (gchar*)&sig_num, sizeof(sig_num),
117 &got, NULL);
118 if(status == G_IO_STATUS_AGAIN) /* we read all the pipe */
119 {
120 g_debug("got G_IO_STATUS_AGAIN");
121 return TRUE;
122 }
123 if(status != G_IO_STATUS_NORMAL || got != sizeof(sig_num)) /* broken pipe */
124 {
125 g_debug("signal pipe is broken");
126 gtk_main_quit();
127 return FALSE;
128 }
129 g_debug("got signal %d from pipe", sig_num);
130 switch(sig_num)
131 {
132 case SIGTERM:
133 default:
134 gtk_main_quit();
135 return FALSE;
136 }
94435bc3
HJYP
137 }
138 return TRUE;
139}
140
1098cfe7 141static void single_inst_cb(const char* cwd, int screen_num)
cc448d7f 142{
cda6259f
HJYP
143 g_free(ipc_cwd);
144 ipc_cwd = g_strdup(cwd);
145
146 if(files_to_open)
cc448d7f 147 {
cda6259f 148 int i;
6033d802 149 n_files_to_open = g_strv_length(files_to_open);
cda6259f
HJYP
150 /* canonicalize filename if needed. */
151 for(i = 0; i < n_files_to_open; ++i)
cc448d7f 152 {
cda6259f
HJYP
153 char* file = files_to_open[i];
154 char* scheme = g_uri_parse_scheme(file);
6033d802 155 g_debug("file: %s", file);
cda6259f 156 if(scheme) /* a valid URI */
cc448d7f 157 {
cda6259f
HJYP
158 /* FIXME: should we canonicalize URIs? and how about file:///? */
159 g_free(scheme);
160 }
161 else /* a file path */
162 {
163 files_to_open[i] = fm_canonicalize_filename(file, cwd);
164 g_free(file);
cc448d7f 165 }
cc448d7f 166 }
cc448d7f 167 }
cda6259f 168 pcmanfm_run();
cc448d7f
HJYP
169}
170
b6e3c554
HJYP
171int main(int argc, char** argv)
172{
4d55886c 173 FmConfig* config;
f8f2bfad 174 GError* err = NULL;
21df32aa 175 SingleInstData inst;
cda6259f 176
f8f2bfad
HJYP
177#ifdef ENABLE_NLS
178 bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
179 bind_textdomain_codeset ( GETTEXT_PACKAGE, "UTF-8" );
180 textdomain ( GETTEXT_PACKAGE );
181#endif
182
183 /* initialize GTK+ and parse the command line arguments */
184 if(G_UNLIKELY(!gtk_init_with_args(&argc, &argv, "", opt_entries, GETTEXT_PACKAGE, &err)))
185 {
186 g_printf("%s\n", err->message);
c5fccf1d 187 g_error_free(err);
f8f2bfad
HJYP
188 return 1;
189 }
190
cc448d7f 191 /* ensure that there is only one instance of pcmanfm. */
21df32aa
AG
192 inst.prog_name = "pcmanfm";
193 inst.cb = single_inst_cb;
194 inst.opt_entries = opt_entries + 3;
195 inst.screen_num = gdk_x11_get_default_screen();
196 switch(single_inst_init(&inst))
cc448d7f
HJYP
197 {
198 case SINGLE_INST_CLIENT: /* we're not the first instance. */
21df32aa 199 single_inst_finalize(&inst);
cc448d7f
HJYP
200 gdk_notify_startup_complete();
201 return 0;
202 case SINGLE_INST_ERROR: /* error happened. */
21df32aa 203 single_inst_finalize(&inst);
cc448d7f 204 return 1;
3aebc679 205 case SINGLE_INST_SERVER: ; /* FIXME */
cc448d7f 206 }
f8f2bfad 207
94435bc3
HJYP
208 if(pipe(signal_pipe) == 0)
209 {
210 GIOChannel* ch = g_io_channel_unix_new(signal_pipe[0]);
211 g_io_add_watch(ch, G_IO_IN|G_IO_PRI, (GIOFunc)on_unix_signal, NULL);
212 g_io_channel_unref(ch);
213
214 /* intercept signals */
ae2947d9
HJYP
215 // signal( SIGPIPE, SIG_IGN );
216 signal( SIGHUP, unix_signal_handler );
94435bc3 217 signal( SIGTERM, unix_signal_handler );
2ddc3882 218 signal( SIGINT, unix_signal_handler );
94435bc3 219 }
b6e3c554 220
f970e846 221 config = fm_app_config_new(); /* this automatically load libfm config file. */
17d12cc9 222
f970e846 223 /* load pcmanfm-specific config file */
17d12cc9 224 fm_app_config_load_from_profile(FM_APP_CONFIG(config), profile);
f970e846 225
94435bc3 226 fm_gtk_init(config);
f8f2bfad
HJYP
227 /* the main part */
228 if(pcmanfm_run())
229 {
71f82759 230 fm_volume_manager_init();
94435bc3 231 gtk_main();
2ddc3882 232 /* g_debug("main loop ended"); */
f8f2bfad
HJYP
233 if(desktop_running)
234 fm_desktop_manager_finalize();
3d141640
HJYP
235
236 pcmanfm_save_config(TRUE);
237 if(save_config_idle)
238 {
239 g_source_remove(save_config_idle);
240 save_config_idle = 0;
241 }
71f82759 242 fm_volume_manager_finalize();
f8f2bfad 243 }
cc448d7f 244
21df32aa 245 single_inst_finalize(&inst);
f8f2bfad 246 fm_gtk_finalize();
ae2947d9 247
f8f2bfad 248 g_object_unref(config);
94435bc3 249 return 0;
f8f2bfad
HJYP
250}
251
ee12f37e
HJYP
252static FmJobErrorAction on_file_info_job_error(FmFileInfoJob* job, GError* err, FmJobErrorSeverity severity, gpointer user_data)
253{
16a17d6b 254 if(err->domain == G_IO_ERROR)
ee12f37e 255 {
16a17d6b
HJYP
256 if(err->code == G_IO_ERROR_NOT_MOUNTED)
257 {
258 if(fm_mount_path(NULL, fm_file_info_job_get_current(job), TRUE))
259 return FM_JOB_RETRY;
260 }
261 else if(err->code == G_IO_ERROR_FAILED_HANDLED)
262 return FM_JOB_CONTINUE;
ee12f37e 263 }
5089e13a 264 fm_show_error(NULL, NULL, err->message);
ee12f37e
HJYP
265 return FM_JOB_CONTINUE;
266}
f8f2bfad
HJYP
267
268gboolean pcmanfm_run()
269{
270 gboolean ret = TRUE;
f8f2bfad 271
f8f2bfad
HJYP
272 if(!files_to_open)
273 {
274 /* Launch desktop manager */
275 if(show_desktop)
276 {
277 if(!desktop_running)
278 {
279 fm_desktop_manager_init();
280 desktop_running = TRUE;
281 }
19abb8bf 282 show_desktop = FALSE;
f8f2bfad
HJYP
283 return TRUE;
284 }
285 else if(desktop_off)
286 {
287 if(desktop_running)
288 {
289 desktop_running = FALSE;
290 fm_desktop_manager_finalize();
291 }
19abb8bf 292 desktop_off = FALSE;
f8f2bfad
HJYP
293 return FALSE;
294 }
295 else if(show_pref > 0)
296 {
7d78ab22 297 /* FIXME: pass screen number from client */
c65ba572 298 fm_edit_preference(GTK_WINDOW(fm_desktop_get(0, 0)), show_pref - 1);
c5fccf1d 299 show_pref = 0;
f8f2bfad
HJYP
300 return TRUE;
301 }
302 else if(desktop_pref)
303 {
7d78ab22 304 /* FIXME: pass screen number from client */
c65ba572 305 fm_desktop_preference(NULL, GTK_WINDOW(fm_desktop_get(0, 0)));
19abb8bf 306 desktop_pref = FALSE;
f8f2bfad
HJYP
307 return TRUE;
308 }
107cdb22 309 else
f8f2bfad 310 {
107cdb22
HJYP
311 gboolean need_to_exit = (wallpaper_mode || set_wallpaper);
312 gboolean wallpaper_changed = FALSE;
313 if(set_wallpaper) /* a new wallpaper is assigned */
314 {
315 /* g_debug("\'%s\'", set_wallpaper); */
316 /* Make sure this is a support image file. */
317 if(gdk_pixbuf_get_file_info(set_wallpaper, NULL, NULL))
318 {
319 if(app_config->wallpaper)
320 g_free(app_config->wallpaper);
e0854cdb 321 app_config->wallpaper = g_strdup(set_wallpaper);
107cdb22
HJYP
322 if(! wallpaper_mode) /* if wallpaper mode is not specified */
323 {
324 /* do not use solid color mode; otherwise wallpaper won't be shown. */
325 if(app_config->wallpaper_mode == FM_WP_COLOR)
326 app_config->wallpaper_mode = FM_WP_FIT;
327 }
328 wallpaper_changed = TRUE;
329 }
330 }
331
332 if(wallpaper_mode)
333 {
6f0f1950 334 guint i = 0;
107cdb22
HJYP
335 for(i = 0; i < G_N_ELEMENTS(valid_wallpaper_modes); ++i)
336 {
337 if(strcmp(valid_wallpaper_modes[i], wallpaper_mode) == 0)
338 {
339 if(i != app_config->wallpaper_mode)
340 {
341 app_config->wallpaper_mode = i;
342 wallpaper_changed = TRUE;
343 }
344 break;
345 }
346 }
347 g_free(wallpaper_mode);
348 wallpaper_mode = NULL;
349 }
350
351 if(wallpaper_changed)
f8f2bfad 352 {
4b3e1fe9 353 fm_config_emit_changed(FM_CONFIG(app_config), "wallpaper");
17d12cc9 354 fm_app_config_save_profile(app_config, profile);
f8f2bfad 355 }
107cdb22
HJYP
356
357 if(need_to_exit)
358 return FALSE;
f8f2bfad
HJYP
359 }
360 }
361
362 if(G_UNLIKELY(find_files))
363 {
364 /* FIXME: find files */
365 }
366 else
367 {
df6826e0
HJYP
368 if(files_to_open)
369 {
370 char** filename;
6a9e415d 371 /* FIXME: use fm_launch_paths_simple() so don't use job */
3aebc679 372 FmFileInfoJob* job = fm_file_info_job_new(NULL, 0);
cacf261a 373 FmPath* cwd = NULL;
d951adb8 374 GList* infos;
df6826e0
HJYP
375 for(filename=files_to_open; *filename; ++filename)
376 {
cacf261a 377 FmPath* path;
9197e75e
HJYP
378 if( **filename == '/') /* absolute path */
379 path = fm_path_new_for_path(*filename);
380 else if(strstr(*filename, ":/") ) /* URI */
381 path = fm_path_new_for_uri(*filename);
0d8dce1a
HJYP
382 else if( strcmp(*filename, "~") == 0 ) /* special case for home dir */
383 {
384 path = fm_path_get_home();
385 fm_main_win_add_win(NULL, path);
386 continue;
387 }
cacf261a
HJYP
388 else /* basename */
389 {
390 if(G_UNLIKELY(!cwd))
391 {
392 /* FIXME: This won't work if those filenames are passed via IPC since the receiving process has different cwd. */
9197e75e 393 /* FIXME: should we use ipc_cwd here? */
cacf261a 394 char* cwd_str = g_get_current_dir();
653af525 395 cwd = fm_path_new_for_str(cwd_str);
cacf261a
HJYP
396 g_free(cwd_str);
397 }
398 path = fm_path_new_relative(cwd, *filename);
399 }
3aebc679 400 fm_file_info_job_add(job, path);
df6826e0
HJYP
401 fm_path_unref(path);
402 }
cacf261a
HJYP
403 if(cwd)
404 fm_path_unref(cwd);
6a9e415d 405 /* FIXME: use fm_launch_paths_simple() instead */
ee12f37e 406 g_signal_connect(job, "error", G_CALLBACK(on_file_info_job_error), NULL);
3aebc679 407 fm_job_run_sync_with_mainloop(FM_JOB(job));
5a89e062 408 infos = fm_file_info_list_peek_head_link(job->file_infos);
d951adb8 409 fm_launch_files_simple(NULL, NULL, infos, pcmanfm_open_folder, NULL);
df6826e0 410 g_object_unref(job);
cacf261a 411 ret = (n_pcmanfm_ref >= 1); /* if there is opened window, return true to run the main loop. */
2b46b521
HJYP
412
413 g_strfreev(files_to_open);
414 files_to_open = NULL;
df6826e0
HJYP
415 }
416 else
f8f2bfad 417 {
bc88a8dc
HJYP
418 static gboolean first_run = TRUE;
419 if(first_run && daemon_mode)
3d141640 420 {
bc88a8dc
HJYP
421 /* If the function is called the first time and we're in daemon mode,
422 * don't open any folder.
423 * Checking if pcmanfm_run() is called the first time is needed to fix
424 * #3397444 - pcmanfm dont show window in daemon mode if i call 'pcmanfm' */
425 }
426 else
427 {
428 /* If we're not in daemon mode, or pcmanfm_run() is called because another
429 * instance send signal to us, open cwd by default. */
3d141640
HJYP
430 FmPath* path;
431 char* cwd = ipc_cwd ? ipc_cwd : g_get_current_dir();
432 path = fm_path_new_for_path(cwd);
433 fm_main_win_add_win(NULL, path);
434 fm_path_unref(path);
435 g_free(cwd);
436 ipc_cwd = NULL;
fbce80c9 437 /* FIXME: bug #3453052: honor --role option */
3d141640 438 }
bc88a8dc 439 first_run = FALSE;
f8f2bfad
HJYP
440 }
441 }
442 return ret;
443}
444
445/* After opening any window/dialog/tool, this should be called. */
446void pcmanfm_ref()
447{
448 ++n_pcmanfm_ref;
449 /* g_debug("ref: %d", n_pcmanfm_ref); */
450}
451
452/* After closing any window/dialog/tool, this should be called.
453 * If the last window is closed and we are not a deamon, pcmanfm will quit.
454 */
455void pcmanfm_unref()
456{
457 --n_pcmanfm_ref;
458 /* g_debug("unref: %d, daemon_mode=%d, desktop_running=%d", n_pcmanfm_ref, daemon_mode, desktop_running); */
459 if( 0 == n_pcmanfm_ref && !daemon_mode && !desktop_running )
460 gtk_main_quit();
b6e3c554 461}
df6826e0 462
7d78ab22
AG
463static void move_window_to_desktop(FmMainWin* win, FmDesktop* desktop)
464{
465 GdkScreen* screen = gtk_widget_get_screen(GTK_WIDGET(desktop));
466 Atom atom;
467 char* atom_name = "_NET_WM_DESKTOP";
468 XClientMessageEvent xev;
469
470 gtk_window_set_screen(GTK_WINDOW(win), screen);
38459ae5 471 if(!XInternAtoms(gdk_x11_get_default_xdisplay(), &atom_name, 1, False, &atom))
7d78ab22
AG
472 {
473 /* g_debug("cannot get Atom for _NET_WM_DESKTOP"); */
474 return;
475 }
476 xev.type = ClientMessage;
38459ae5 477 xev.window = GDK_WINDOW_XID(gtk_widget_get_window(GTK_WIDGET(win)));
7d78ab22
AG
478 xev.message_type = atom;
479 xev.format = 32;
480 xev.data.l[0] = desktop->cur_desktop;
481 xev.data.l[1] = 0;
482 xev.data.l[2] = 0;
483 xev.data.l[3] = 0;
484 xev.data.l[4] = 0;
485 /* g_debug("moving window to current desktop"); */
38459ae5 486 XSendEvent(gdk_x11_get_default_xdisplay(), GDK_ROOT_WINDOW(), False,
7d78ab22
AG
487 (SubstructureNotifyMask | SubstructureRedirectMask),
488 (XEvent *) &xev);
489}
490
df6826e0
HJYP
491gboolean pcmanfm_open_folder(GAppLaunchContext* ctx, GList* folder_infos, gpointer user_data, GError** err)
492{
df6826e0 493 GList* l = folder_infos;
fbce80c9
AG
494 /* FIXME: honor --new-win option and in that case: */
495 /* FIXME: bug #3453052: honor --role from client */
df6826e0
HJYP
496 for(; l; l=l->next)
497 {
498 FmFileInfo* fi = (FmFileInfo*)l->data;
0b951729 499 fm_main_win_open_in_last_active(fm_file_info_get_path(fi));
df6826e0 500 }
7d78ab22
AG
501 if(user_data && FM_IS_DESKTOP(user_data))
502 move_window_to_desktop(fm_main_win_get_last_active(), user_data);
df6826e0
HJYP
503 return TRUE;
504}
dcecce78 505
3d141640 506static gboolean on_save_config_idle(gpointer user_data)
dcecce78 507{
3d141640
HJYP
508 pcmanfm_save_config(TRUE);
509 save_config_idle = 0;
510 return FALSE;
511}
512
513void pcmanfm_save_config(gboolean immediate)
514{
515 if(immediate)
516 {
517 fm_config_save(fm_config, NULL);
518 fm_app_config_save_profile(app_config, profile);
519 }
520 else
521 {
522 /* install an idle handler to save the config file. */
f04f9105
AG
523 if( 0 == save_config_idle)
524 save_config_idle = g_idle_add_full(G_PRIORITY_LOW, (GSourceFunc)on_save_config_idle, NULL, NULL);
3d141640 525 }
dcecce78 526}
c56a211a
HJYP
527
528void pcmanfm_open_folder_in_terminal(GtkWindow* parent, FmPath* dir)
529{
530 GAppInfo* app;
c56a211a
HJYP
531 char** argv;
532 int argc;
533 if(!fm_config->terminal)
534 {
5089e13a 535 fm_show_error(parent, NULL, _("Terminal emulator is not set."));
c56a211a
HJYP
536 fm_edit_preference(parent, PREF_ADVANCED);
537 return;
538 }
539 if(!g_shell_parse_argv(fm_config->terminal, &argc, &argv, NULL))
540 return;
541 app = g_app_info_create_from_commandline(argv[0], NULL, 0, NULL);
542 g_strfreev(argv);
543 if(app)
544 {
545 GError* err = NULL;
3aebc679 546 GdkAppLaunchContext* ctx = gdk_app_launch_context_new();
c56a211a 547 char* cwd_str;
1dfc8e4c 548 char* old_cwd = g_get_current_dir();
c56a211a
HJYP
549
550 if(fm_path_is_native(dir))
551 cwd_str = fm_path_to_str(dir);
552 else
553 {
554 GFile* gf = fm_path_to_gfile(dir);
555 cwd_str = g_file_get_path(gf);
556 g_object_unref(gf);
557 }
3aebc679
AG
558 gdk_app_launch_context_set_screen(ctx, parent ? gtk_widget_get_screen(GTK_WIDGET(parent)) : gdk_screen_get_default());
559 gdk_app_launch_context_set_timestamp(ctx, gtk_get_current_event_time());
c56a211a
HJYP
560 g_chdir(cwd_str); /* FIXME: currently we don't have better way for this. maybe a wrapper script? */
561 g_free(cwd_str);
1dfc8e4c 562
3aebc679 563 if(!g_app_info_launch(app, NULL, G_APP_LAUNCH_CONTEXT(ctx), &err))
c56a211a 564 {
5089e13a 565 fm_show_error(parent, NULL, err->message);
c56a211a
HJYP
566 g_error_free(err);
567 }
568 g_object_unref(ctx);
569 g_object_unref(app);
1dfc8e4c
HJYP
570
571 /* switch back to old cwd and fix #3114626 - PCManFM 0.9.9 Umount partitions problem */
572 g_chdir(old_cwd); /* This is really dirty, but we don't have better solution now. */
573 g_free(old_cwd);
c56a211a
HJYP
574 }
575}
7cb06c27 576
92f8ca49
HJYP
577char* pcmanfm_get_profile_dir(gboolean create)
578{
579 char* dir = g_build_filename(g_get_user_config_dir(), "pcmanfm", profile ? profile : "default", NULL);
580 if(create)
581 g_mkdir_with_parents(dir, 0700);
582 return dir;
583}