26
36
#include "vfs-file-monitor.h"
27
37
#include "vfs-volume.h"
38
#include "vfs-thumbnail-loader.h"
29
40
#include "ptk-utils.h"
30
#include "app-chooser-dialog.h"
41
#include "ptk-app-chooser.h"
42
#include "ptk-file-properties.h"
43
#include "ptk-file-menu.h"
32
#include "glade-support.h"
33
45
#include "settings.h"
35
static char* init_path = NULL;
57
static gboolean initialized = FALSE;
38
60
GIOChannel* io_channel = NULL;
62
gboolean daemon_mode = FALSE;
64
static char* default_files[2] = {NULL, NULL};
65
static char** files = NULL;
66
static gboolean no_desktop = FALSE;
67
static gboolean old_show_desktop = FALSE;
69
static gboolean new_tab = FALSE;
70
static gboolean file_prop = FALSE;
71
static gboolean file_menu = FALSE;
74
static char* mount = NULL;
75
static char* umount = NULL;
76
static char* eject = NULL;
79
static GOptionEntry opt_entries[] =
81
{ "no-desktop", '\0', 0, G_OPTION_ARG_NONE, &no_desktop, N_("Don't show desktop icons."), NULL },
82
{ "daemon-mode", 'd', 0, G_OPTION_ARG_NONE, &daemon_mode, N_("Run PCManFM as a daemon"), NULL },
83
{ "new-tab", 't', 0, G_OPTION_ARG_NONE, &new_tab, N_("Open folders in new tabs of the last used window instead of creating new windows"), NULL },
84
/* { "file-prop", 'p', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &file_prop, NULL, NULL },
85
{ "file-menu", 'n', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_NONE, &file_menu, NULL, NULL }, */
87
/* hidden arguments used to mount volumes */
88
{ "mount", 'm', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &mount, NULL, NULL },
89
{ "umount", 'u', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &umount, NULL, NULL },
90
{ "eject", 'e', G_OPTION_FLAG_HIDDEN, G_OPTION_ARG_STRING, &eject, NULL, NULL },
92
{G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &files, NULL, N_("[FILE1, FILE2,...]")},
96
static gboolean single_instance_check();
97
static void single_instance_finalize();
98
static void get_socket_name( char* buf, int len );
99
static gboolean on_socket_event( GIOChannel* ioc, GIOCondition cond, gpointer data );
101
static void init_folder();
102
static void check_icon_theme();
104
static gboolean handle_parsed_commandline_args();
40
106
static FMMainWindow* create_main_window();
42
107
static void open_file( const char* path );
44
static gboolean on_socket_event( GIOChannel* ioc,
109
static GList* get_file_info_list( char** files );
111
gboolean on_socket_event( GIOChannel* ioc, GIOCondition cond, gpointer data )
49
114
socklen_t addr_len = 0;
50
struct sockaddr_un client_addr =
54
FMMainWindow* main_window;
55
static char path[ PATH_MAX ];
115
struct sockaddr_un client_addr ={ 0 };
116
static char buf[ 1024 ];
57
121
if ( cond & G_IO_IN )
59
123
client = accept( g_io_channel_unix_get_fd( ioc ), (struct sockaddr *)&client_addr, &addr_len );
60
124
if ( client != -1 )
62
r = read( client, path, PATH_MAX );
67
if ( g_file_test( path, G_FILE_TEST_IS_DIR ) )
69
main_window = create_main_window();
70
fm_main_window_add_new_tab( main_window, path,
71
appSettings.showSidePane,
72
appSettings.sidePaneMode );
73
gtk_window_present( GTK_WINDOW(main_window) );
126
args = g_string_new_len( NULL, 2048 );
127
while( (r = read( client, buf, sizeof(buf) )) > 0 )
128
g_string_append_len( args, buf, r);
81
129
shutdown( client, 2 );
136
switch( args->str[0] )
147
case CMD_DAEMON_MODE:
149
g_string_free( args, TRUE );
154
files = g_strsplit( args->str + 1, "\n", 0 );
157
g_string_free( args, TRUE );
163
for( file = files; *file; ++file )
165
if( ! **file ) /* remove empty string at tail */
169
handle_parsed_commandline_args();
88
static void get_socket_name( char* buf, int len )
178
void get_socket_name( char* buf, int len )
90
g_snprintf( buf, len, "/tmp/.pcmanfm-socket%s-%s", gdk_get_display(), g_get_user_name() );
180
char* dpy = gdk_get_display();
181
g_snprintf( buf, len, "/tmp/.pcmanfm-socket%s-%s", dpy, g_get_user_name() );
93
static void single_instance_init()
185
gboolean single_instance_check()
95
187
struct sockaddr_un addr;
106
198
addr.sun_family = AF_UNIX;
107
199
get_socket_name( addr.sun_path, sizeof( addr.sun_path ) );
110
201
addr_len = SUN_LEN( &addr );
113
204
addr_len = strlen( addr.sun_path ) + sizeof( addr.sun_family );
207
/* try to connect to existing instance */
116
208
if ( connect( sock, ( struct sockaddr* ) & addr, addr_len ) == 0 )
118
210
/* connected successfully */
119
write( sock, init_path, strlen( init_path ) );
215
cmd = CMD_DAEMON_MODE;
223
write( sock, &cmd, sizeof(char) );
227
for( file = files; *file; ++file )
229
write( sock, *file, strlen( *file ) );
230
write( sock, "\n", 1 );
120
234
shutdown( sock, 2 );
122
gdk_notify_startup_complete();
128
/* There is no existing server. So, we are in the first instance. */
240
/* There is no existing server, and we are in the first instance. */
129
241
unlink( addr.sun_path ); /* delete old socket file if it exists. */
131
243
ret = setsockopt( sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof( reuse ) );
219
main ( int argc, char *argv[] )
221
FMMainWindow * main_window;
222
GtkSettings *settings;
223
gboolean is_init_path_dir;
227
/* Use multithreading */
228
g_thread_init( NULL );
231
gtk_init ( &argc, &argv );
233
/* FIXME: Support opening mutiple dirs|files from command line */
235
/* FIXME: support command line options */
237
/* Add check for -- to skip unknown options */
238
if ( argc > 0 && *argv[ argc ] && strncmp( argv[ argc ], "--", 2 ) )
240
/* If this is a URI */
241
if ( 0 == g_ascii_strncasecmp( argv[ argc ], "file:", 5 ) )
242
init_path = g_filename_from_uri( argv[ argc ], NULL, NULL );
244
init_path = vfs_file_resolve_path( NULL, argv[ argc ] );
245
is_init_path_dir = g_file_test( init_path, G_FILE_TEST_IS_DIR );
249
init_path = g_strdup( g_get_home_dir() );
250
is_init_path_dir = TRUE;
253
/* if ( appSettings.singleInstance ) */
254
single_instance_init();
336
G_LOCK_DEFINE(gdk_lock);
337
void debug_gdk_threads_enter (const char* message)
339
g_debug( "Thread %p tries to get GDK lock: %s", g_thread_self (), message );
341
g_debug( "Thread %p got GDK lock: %s", g_thread_self (), message );
344
static void _debug_gdk_threads_enter ()
346
debug_gdk_threads_enter( "called from GTK+ internal" );
349
void debug_gdk_threads_leave( const char* message )
351
g_debug( "Thread %p tries to release GDK lock: %s", g_thread_self (), message );
353
g_debug( "Thread %p released GDK lock: %s", g_thread_self (), message );
356
static void _debug_gdk_threads_leave()
358
debug_gdk_threads_leave( "called from GTK+ internal" );
364
if( G_LIKELY(initialized) )
367
app_settings.bookmarks = ptk_bookmarks_get();
370
vfs_thumbnail_init();
372
vfs_mime_type_set_icon_size( app_settings.big_icon_size,
373
app_settings.small_icon_size );
374
vfs_file_info_set_thumbnail_size( app_settings.big_icon_size,
375
app_settings.small_icon_size );
383
/* FIXME: Currently, this cannot be supported without HAL */
385
static int handle_mount( char** argv )
390
success = vfs_volume_mount_by_udi( mount, NULL );
392
success = vfs_volume_umount_by_udi( umount, NULL );
393
else /* if( eject ) */
394
success = vfs_volume_eject_by_udi( eject, NULL );
395
vfs_volume_finalize();
396
return success ? 0 : 1;
400
GList* get_file_info_list( char** file_paths )
402
GList* file_list = NULL;
406
for( file = file_paths; *file; ++file )
408
fi = vfs_file_info_new();
409
if( vfs_file_info_get( fi, *file, NULL ) )
410
file_list = g_list_append( file_list, fi );
412
vfs_file_info_unref( fi );
418
gboolean delayed_popup( GtkWidget* popup )
422
gtk_menu_popup( GTK_MENU( popup ), NULL, NULL,
423
NULL, NULL, 0, gtk_get_current_event_time() );
430
gboolean handle_parsed_commandline_args()
432
FMMainWindow * main_window = NULL;
435
/* If no files are specified, open home dir by defualt. */
436
if( G_LIKELY( ! files ) )
438
files = default_files;
439
files[0] = (char *) g_get_home_dir();
442
/* get the last active window, if available */
445
main_window = fm_main_window_get_last_active();
447
else if( file_menu ) /* show popup menu for files */
449
/* FIXME: This doesn't work properly */
455
g_warning( "--file-menu is only availble when pcmanfm daemon is running." );
459
file_list = get_file_info_list( files );
463
char* dir_name = g_path_get_dirname( files[0] );
464
popup = ptk_file_menu_new(
465
files[0], (VFSFileInfo*)file_list->data,
468
/* FIXME: I have no idea why this crap is needed.
469
* Without this delay, the menu will fail to popup. */
470
g_timeout_add( 150, (GSourceFunc)delayed_popup, popup );
473
if( files != default_files )
478
else if( file_prop ) /* show file properties dialog */
482
file_list = get_file_info_list( files );
486
char* dir_name = g_path_get_dirname( files[0] );
487
dlg = file_properties_dlg_new( NULL, dir_name, file_list );
488
gtk_dialog_run( dlg );
489
gtk_widget_destroy( dlg );
492
if( files != default_files )
498
/* open files passed in command line arguments */
499
for( file = files; *file; ++file )
501
char* file_path, *real_path;
503
if( ! **file ) /* skip empty string */
506
if( g_str_has_prefix( *file, "file:" ) ) /* It's a URI */
508
file_path = g_filename_from_uri( *file, NULL, NULL );
515
real_path = vfs_file_resolve_path( NULL, file_path );
516
if( g_file_test( real_path, G_FILE_TEST_IS_DIR ) )
518
if( G_UNLIKELY( ! main_window ) ) /* create main window if needed */
520
/* initialize things required by folder view... */
521
if( G_UNLIKELY( ! daemon_mode ) )
523
main_window = create_main_window();
525
fm_main_window_add_new_tab( main_window, real_path,
526
app_settings.show_side_pane,
527
app_settings.side_pane_mode );
531
open_file( real_path );
536
if( files != default_files )
544
int main ( int argc, char *argv[] )
546
gboolean run = FALSE;
256
549
#ifdef ENABLE_NLS
257
550
bindtextdomain ( GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR );
259
552
textdomain ( GETTEXT_PACKAGE );
555
/* Initialize multithreading
556
No matter we use threads or not, it's safer to initialize this earlier. */
558
gdk_threads_set_lock_functions(_debug_gdk_threads_enter, _debug_gdk_threads_leave);
560
g_thread_init( NULL );
563
/* initialize GTK+ and parse the command line arguments */
564
if( G_UNLIKELY( ! gtk_init_with_args( &argc, &argv, "", opt_entries, GETTEXT_PACKAGE, &err ) ) )
568
/* If the user wants to mount/umount/eject a device */
569
if( G_UNLIKELY( mount || umount || eject ) )
570
return handle_mount( argv );
573
/* ensure that there is only one instance of pcmanfm.
574
if there is an existing instance, command line arguments
575
will be passed to the existing instance, and exit() will be called here. */
576
single_instance_check( argc - 1, argv + 1 );
578
load_settings(); /* load config file */
580
/* initialize the file alteration monitor */
581
if( G_UNLIKELY( ! vfs_file_monitor_init() ) )
583
ptk_show_error( NULL, _("Error"), _("Error: Unable to establish connection with FAM.\n\nDo you have \"FAM\" or \"Gamin\" installed and running?") );
584
vfs_file_monitor_clean();
589
/* check if the filename encoding is UTF-8 */
262
590
vfs_file_info_set_utf8_filename( g_get_filename_charsets( NULL ) );
592
/* Initialize our mime-type system */
263
593
vfs_mime_type_init();
265
if ( ! is_init_path_dir )
267
open_file( init_path );
274
vfs_mime_type_set_icon_size( appSettings.bigIconSize,
275
appSettings.smallIconSize );
276
vfs_file_info_set_thumbnail_size( appSettings.bigIconSize,
277
appSettings.smallIconSize );
281
if( appSettings.showDesktop )
595
/* temporarily turn off desktop if needed */
596
if( G_LIKELY( no_desktop ) )
598
/* No matter what the value of show_desktop is, we don't showdesktop icons
599
* if --no-desktop argument is passed by the users. */
600
old_show_desktop = app_settings.show_desktop;
601
/* This config value will be restored before saving config files, if needed. */
602
app_settings.show_desktop = FALSE;
605
/* handle the parsed result of command line args */
606
if( daemon_mode || app_settings.show_desktop )
609
run = TRUE; /* we always need to run the main loop for daemon mode */
611
/* FIXME: are these necessary?? */
612
signal( SIGPIPE, SIG_IGN );
613
signal( SIGHUP, gtk_main_quit );
614
signal( SIGINT, gtk_main_quit );
615
signal( SIGTERM, gtk_main_quit );
618
run = handle_parsed_commandline_args();
620
if( app_settings.show_desktop )
285
main_window = create_main_window();
286
fm_main_window_add_new_tab( main_window, init_path,
287
appSettings.showSidePane,
288
appSettings.sidePaneMode );
622
fm_turn_on_desktop_icons();
295
/* if ( appSettings.singleInstance ) */
625
if( run ) /* run the main loop */
296
628
single_instance_finalize();
630
if( app_settings.show_desktop )
631
fm_turn_off_desktop_icons();
633
if( no_desktop ) /* desktop icons is temporarily supressed */
635
if( old_show_desktop ) /* restore original settings */
637
old_show_desktop = app_settings.show_desktop;
638
app_settings.show_desktop = TRUE;
643
save_settings(); /* write config file */
647
vfs_volume_finalize();
302
648
vfs_mime_type_clean();
303
649
vfs_file_monitor_clean();
305
if( appSettings.showDesktop )
306
fm_desktop_cleanup();