4 * ROX-Filer, filer for the ROX desktop project
5 * By Thomas Leonard, <tal197@ecs.soton.ac.uk>.
8 /* filer.c - code for handling filer windows */
19 #include <gdk/gdkprivate.h> /* XXX - find another way to do this */
20 #include <gdk/gdkkeysyms.h>
21 #include "collection.h"
25 #include "gui_support.h"
34 #define MAX_ICON_HEIGHT 42
35 #define PANEL_BORDER 2
37 FilerWindow
*window_with_focus
= NULL
;
39 /* Link paths to GLists of filer windows */
40 GHashTable
*path_to_window_list
= NULL
;
42 static FilerWindow
*window_with_selection
= NULL
;
43 static FilerWindow
*panel_with_timeout
= NULL
;
44 static gint panel_timeout
;
46 /* Static prototypes */
47 static void filer_window_destroyed(GtkWidget
*widget
,
48 FilerWindow
*filer_window
);
49 static gboolean
idle_scan_dir(gpointer data
);
50 static void draw_item(GtkWidget
*widget
,
53 void show_menu(Collection
*collection
, GdkEventButton
*event
,
54 int number_selected
, gpointer user_data
);
55 static int sort_by_name(const void *item1
, const void *item2
);
56 static void add_item(FilerWindow
*filer_window
, char *leafname
);
57 static gboolean
test_point(Collection
*collection
,
58 int point_x
, int point_y
,
60 int width
, int height
);
61 static void stop_scanning(FilerWindow
*filer_window
);
62 static gint
focus_in(GtkWidget
*widget
,
64 FilerWindow
*filer_window
);
65 static gint
focus_out(GtkWidget
*widget
,
67 FilerWindow
*filer_window
);
68 static void add_view(FilerWindow
*filer_window
);
69 static void remove_view(FilerWindow
*filer_window
);
71 static GdkAtom xa_string
;
80 xa_string
= gdk_atom_intern("STRING", FALSE
);
82 path_to_window_list
= g_hash_table_new(g_str_hash
, g_str_equal
);
86 /* When a filer window shows a directory, use this function to add
87 * it to the list of directories to be updated when the contents
90 static void add_view(FilerWindow
*filer_window
)
92 GList
*list
, *newlist
;
94 g_return_if_fail(filer_window
!= NULL
);
96 list
= g_hash_table_lookup(path_to_window_list
, filer_window
->path
);
97 newlist
= g_list_prepend(list
, filer_window
);
99 g_hash_table_insert(path_to_window_list
, filer_window
->path
,
103 /* When a filer window no longer shows a directory, call this to reverse
104 * the effect of add_view().
106 static void remove_view(FilerWindow
*filer_window
)
108 GList
*list
, *newlist
;
110 g_return_if_fail(filer_window
!= NULL
);
112 list
= g_hash_table_lookup(path_to_window_list
, filer_window
->path
);
113 newlist
= g_list_remove(list
, filer_window
);
115 g_hash_table_insert(path_to_window_list
, filer_window
->path
,
119 /* Go though all the FileItems in a collection, freeing all the temp
121 * TODO: Maybe we should cache icons?
123 static void free_temp_icons(FilerWindow
*filer_window
)
126 Collection
*collection
= filer_window
->collection
;
128 for (i
= 0; i
< collection
->number_of_items
; i
++)
130 FileItem
*item
= (FileItem
*) collection
->items
[i
].data
;
131 if (item
->flags
& ITEM_FLAG_TEMP_ICON
)
133 gdk_pixmap_unref(item
->image
->pixmap
);
134 gdk_pixmap_unref(item
->image
->mask
);
136 item
->image
= default_pixmap
+ TYPE_ERROR
;
141 static void filer_window_destroyed(GtkWidget
*widget
,
142 FilerWindow
*filer_window
)
144 if (window_with_selection
== filer_window
)
145 window_with_selection
= NULL
;
146 if (window_with_focus
== filer_window
)
147 window_with_focus
= NULL
;
148 if (panel_with_timeout
== filer_window
)
150 /* Can this happen? */
151 panel_with_timeout
= NULL
;
152 gtk_timeout_remove(panel_timeout
);
155 remove_view(filer_window
);
157 free_temp_icons(filer_window
);
158 if (filer_window
->dir
)
159 stop_scanning(filer_window
);
160 g_free(filer_window
->path
);
161 g_free(filer_window
);
163 if (--number_of_windows
< 1)
167 static void stop_scanning(FilerWindow
*filer_window
)
169 g_return_if_fail(filer_window
->dir
!= NULL
);
171 closedir(filer_window
->dir
);
172 gtk_idle_remove(filer_window
->idle_scan_id
);
173 filer_window
->dir
= NULL
;
176 /* This is called while we are scanning the directory */
177 static gboolean
idle_scan_dir(gpointer data
)
180 FilerWindow
*filer_window
= (FilerWindow
*) data
;
184 next
= readdir(filer_window
->dir
);
187 closedir(filer_window
->dir
);
188 filer_window
->dir
= NULL
;
190 collection_set_item_size(filer_window
->collection
,
191 filer_window
->scan_min_width
,
192 filer_window
->collection
->item_height
);
193 collection_qsort(filer_window
->collection
,
195 return FALSE
; /* Finished */
198 add_item(filer_window
, next
->d_name
);
199 } while (!gtk_events_pending());
204 /* Add a single object to a directory display */
205 static void add_item(FilerWindow
*filer_window
, char *leafname
)
213 if (leafname
[0] == '.')
215 if (filer_window
->show_hidden
== FALSE
|| leafname
[1] == '\0'
216 || (leafname
[1] == '.' && leafname
[2] == '\0'))
220 item
= g_malloc(sizeof(FileItem
));
221 item
->leafname
= g_strdup(leafname
);
224 path
= make_path(filer_window
->path
, leafname
);
225 if (lstat(path
->str
, &info
))
226 base_type
= TYPE_ERROR
;
229 if (S_ISREG(info
.st_mode
))
230 base_type
= TYPE_FILE
;
231 else if (S_ISDIR(info
.st_mode
))
233 base_type
= TYPE_DIRECTORY
;
235 if (g_hash_table_lookup(mtab_mounts
, path
->str
))
236 item
->flags
|= ITEM_FLAG_MOUNT_POINT
238 else if (g_hash_table_lookup(fstab_mounts
, path
->str
))
239 item
->flags
|= ITEM_FLAG_MOUNT_POINT
;
241 else if (S_ISBLK(info
.st_mode
))
242 base_type
= TYPE_BLOCK_DEVICE
;
243 else if (S_ISCHR(info
.st_mode
))
244 base_type
= TYPE_CHAR_DEVICE
;
245 else if (S_ISFIFO(info
.st_mode
))
246 base_type
= TYPE_PIPE
;
247 else if (S_ISSOCK(info
.st_mode
))
248 base_type
= TYPE_SOCKET
;
249 else if (S_ISLNK(info
.st_mode
))
251 if (stat(path
->str
, &info
))
253 base_type
= TYPE_ERROR
;
257 if (S_ISREG(info
.st_mode
))
258 base_type
= TYPE_FILE
;
259 else if (S_ISDIR(info
.st_mode
))
260 base_type
= TYPE_DIRECTORY
;
261 else if (S_ISBLK(info
.st_mode
))
262 base_type
= TYPE_BLOCK_DEVICE
;
263 else if (S_ISCHR(info
.st_mode
))
264 base_type
= TYPE_CHAR_DEVICE
;
265 else if (S_ISFIFO(info
.st_mode
))
266 base_type
= TYPE_PIPE
;
267 else if (S_ISSOCK(info
.st_mode
))
268 base_type
= TYPE_SOCKET
;
270 base_type
= TYPE_UNKNOWN
;
273 item
->flags
|= ITEM_FLAG_SYMLINK
;
276 base_type
= TYPE_UNKNOWN
;
279 item
->base_type
= base_type
;
280 item
->mime_type
= NULL
;
282 if (base_type
== TYPE_DIRECTORY
)
284 /* Might be an application directory - better check... */
285 g_string_append(path
, "/AppRun");
286 if (!stat(path
->str
, &info
))
288 item
->flags
|= ITEM_FLAG_APPDIR
;
292 if (item
->flags
& ITEM_FLAG_APPDIR
) /* path still ends /AppRun */
294 MaskedPixmap
*app_icon
;
296 g_string_truncate(path
, path
->len
- 3);
297 g_string_append(path
, "Icon.xpm");
298 app_icon
= load_pixmap_from(filer_window
->window
, path
->str
);
301 item
->image
= app_icon
;
302 item
->flags
|= ITEM_FLAG_TEMP_ICON
;
305 item
->image
= default_pixmap
+ TYPE_APPDIR
;
309 if (base_type
== TYPE_FILE
&&
310 (info
.st_mode
& (S_IXUSR
| S_IXGRP
| S_IXOTH
)))
312 item
->image
= default_pixmap
+ TYPE_EXEC_FILE
;
313 item
->flags
|= ITEM_FLAG_EXEC_FILE
;
315 else if (base_type
== TYPE_FILE
)
317 item
->mime_type
= type_from_path(path
->str
);
318 item
->image
= type_to_icon(filer_window
->window
,
322 item
->image
= default_pixmap
+ base_type
;
325 item
->text_width
= gdk_string_width(filer_window
->window
->style
->font
,
328 /* XXX: Must be a better way... */
329 item
->pix_width
= ((GdkPixmapPrivate
*) item
->image
->pixmap
)->width
;
330 item
->pix_height
= ((GdkPixmapPrivate
*) item
->image
->pixmap
)->height
;
332 item_width
= MAX(item
->pix_width
, item
->text_width
) + 4;
334 if (item_width
> filer_window
->scan_min_width
)
335 filer_window
->scan_min_width
= item_width
;
337 if (item_width
> filer_window
->collection
->item_width
)
338 collection_set_item_size(filer_window
->collection
,
340 filer_window
->collection
->item_height
);
342 collection_insert(filer_window
->collection
, item
);
345 static gboolean
test_point(Collection
*collection
,
346 int point_x
, int point_y
,
347 CollectionItem
*colitem
,
348 int width
, int height
)
350 FileItem
*item
= (FileItem
*) colitem
->data
;
351 GdkFont
*font
= GTK_WIDGET(collection
)->style
->font
;
352 int text_height
= font
->ascent
+ font
->descent
;
353 int x_off
= ABS(point_x
- (width
>> 1));
354 int image_y
= MAX(0, MAX_ICON_HEIGHT
- item
->pix_height
);
356 if (x_off
<= (item
->pix_width
>> 1) + 2 &&
357 point_y
>= image_y
&& point_y
<= image_y
+ item
->pix_height
)
360 if (x_off
<= (item
->text_width
>> 1) + 2 &&
361 point_y
> height
- text_height
- 2)
367 static void draw_item(GtkWidget
*widget
,
368 CollectionItem
*colitem
,
371 FileItem
*item
= (FileItem
*) colitem
->data
;
372 GdkGC
*gc
= colitem
->selected
? widget
->style
->white_gc
373 : widget
->style
->black_gc
;
374 int image_x
= area
->x
+ ((area
->width
- item
->pix_width
) >> 1);
375 GdkFont
*font
= widget
->style
->font
;
376 int text_x
= area
->x
+ ((area
->width
- item
->text_width
) >> 1);
377 int text_y
= area
->y
+ area
->height
- font
->descent
- 2;
378 int text_height
= font
->ascent
+ font
->descent
;
384 gdk_gc_set_clip_mask(gc
, item
->image
->mask
);
386 image_y
= MAX(0, MAX_ICON_HEIGHT
- item
->pix_height
);
387 gdk_gc_set_clip_origin(gc
, image_x
, area
->y
+ image_y
);
388 gdk_draw_pixmap(widget
->window
, gc
,
390 0, 0, /* Source x,y */
391 image_x
, area
->y
+ image_y
, /* Dest x,y */
392 -1, MIN(item
->pix_height
, MAX_ICON_HEIGHT
));
394 if (item
->flags
& ITEM_FLAG_SYMLINK
)
396 gdk_gc_set_clip_origin(gc
, image_x
, area
->y
+ 8);
397 gdk_gc_set_clip_mask(gc
,
398 default_pixmap
[TYPE_SYMLINK
].mask
);
399 gdk_draw_pixmap(widget
->window
, gc
,
400 default_pixmap
[TYPE_SYMLINK
].pixmap
,
401 0, 0, /* Source x,y */
402 image_x
, area
->y
+ 8, /* Dest x,y */
405 else if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
407 int type
= item
->flags
& ITEM_FLAG_MOUNTED
410 gdk_gc_set_clip_origin(gc
, image_x
, area
->y
+ 8);
411 gdk_gc_set_clip_mask(gc
,
412 default_pixmap
[type
].mask
);
413 gdk_draw_pixmap(widget
->window
, gc
,
414 default_pixmap
[type
].pixmap
,
415 0, 0, /* Source x,y */
416 image_x
, area
->y
+ 8, /* Dest x,y */
420 gdk_gc_set_clip_mask(gc
, NULL
);
421 gdk_gc_set_clip_origin(gc
, 0, 0);
424 if (colitem
->selected
)
425 gtk_paint_flat_box(widget
->style
, widget
->window
,
426 GTK_STATE_SELECTED
, GTK_SHADOW_NONE
,
427 NULL
, widget
, "text",
428 text_x
, text_y
- font
->ascent
,
432 gdk_draw_text(widget
->window
,
434 colitem
->selected
? widget
->style
->white_gc
435 : widget
->style
->black_gc
,
437 item
->leafname
, strlen(item
->leafname
));
440 void show_menu(Collection
*collection
, GdkEventButton
*event
,
441 int item
, gpointer user_data
)
443 show_filer_menu((FilerWindow
*) user_data
, event
, item
);
446 static void may_rescan(FilerWindow
*filer_window
)
450 g_return_if_fail(filer_window
!= NULL
);
452 if (stat(filer_window
->path
, &info
))
454 delayed_error("ROX-Filer", "Directory deleted");
455 gtk_widget_destroy(filer_window
->window
);
457 else if (info
.st_mtime
> filer_window
->m_time
)
459 if (filer_window
->dir
)
460 filer_window
->flags
|= FILER_NEEDS_RESCAN
;
462 scan_dir(filer_window
);
466 void scan_dir(FilerWindow
*filer_window
)
470 if (filer_window
->dir
)
471 stop_scanning(filer_window
);
472 if (panel_with_timeout
== filer_window
)
474 panel_with_timeout
= NULL
;
475 gtk_timeout_remove(panel_timeout
);
480 free_temp_icons(filer_window
);
481 collection_clear(filer_window
->collection
);
482 gtk_window_set_title(GTK_WINDOW(filer_window
->window
),
485 if (stat(filer_window
->path
, &info
))
487 report_error("Error statting directory", g_strerror(errno
));
490 filer_window
->m_time
= info
.st_mtime
;
492 filer_window
->dir
= opendir(filer_window
->path
);
493 if (!filer_window
->dir
)
495 report_error("Error scanning directory", g_strerror(errno
));
499 filer_window
->scan_min_width
= 64;
501 filer_window
->idle_scan_id
= gtk_idle_add(idle_scan_dir
, filer_window
);
504 /* Another app has grabbed the selection */
505 static gint
collection_lose_selection(GtkWidget
*widget
,
506 GdkEventSelection
*event
)
508 if (window_with_selection
&&
509 window_with_selection
->collection
== COLLECTION(widget
))
511 FilerWindow
*filer_window
= window_with_selection
;
512 window_with_selection
= NULL
;
513 collection_clear_selection(filer_window
->collection
);
519 /* Someone wants us to send them the selection */
520 static void selection_get(GtkWidget
*widget
,
521 GtkSelectionData
*selection_data
,
526 GString
*reply
, *header
;
527 FilerWindow
*filer_window
;
529 Collection
*collection
;
531 filer_window
= gtk_object_get_data(GTK_OBJECT(widget
), "filer_window");
533 reply
= g_string_new(NULL
);
534 header
= g_string_new(NULL
);
539 g_string_sprintf(header
, " %s",
540 make_path(filer_window
->path
, "")->str
);
542 case TARGET_URI_LIST
:
543 g_string_sprintf(header
, " file://%s%s",
545 make_path(filer_window
->path
, "")->str
);
549 collection
= filer_window
->collection
;
550 for (i
= 0; i
< collection
->number_of_items
; i
++)
552 if (collection
->items
[i
].selected
)
555 (FileItem
*) collection
->items
[i
].data
;
557 g_string_append(reply
, header
->str
);
558 g_string_append(reply
, item
->leafname
);
561 g_string_append_c(reply
, ' ');
563 gtk_selection_data_set(selection_data
, xa_string
,
564 8, reply
->str
+ 1, reply
->len
- 1);
565 g_string_free(reply
, TRUE
);
566 g_string_free(header
, TRUE
);
569 /* No items are now selected. This might be because another app claimed
570 * the selection or because the user unselected all the items.
572 static void lose_selection(Collection
*collection
,
576 FilerWindow
*filer_window
= (FilerWindow
*) user_data
;
578 if (window_with_selection
== filer_window
)
580 window_with_selection
= NULL
;
581 gtk_selection_owner_set(NULL
,
582 GDK_SELECTION_PRIMARY
,
587 static void gain_selection(Collection
*collection
,
591 FilerWindow
*filer_window
= (FilerWindow
*) user_data
;
593 if (gtk_selection_owner_set(GTK_WIDGET(collection
),
594 GDK_SELECTION_PRIMARY
,
597 window_with_selection
= filer_window
;
600 collection_clear_selection(filer_window
->collection
);
603 static int sort_by_name(const void *item1
, const void *item2
)
605 return strcmp((*((FileItem
**)item1
))->leafname
,
606 (*((FileItem
**)item2
))->leafname
);
609 static gint
clear_panel_hilight(gpointer data
)
611 collection_set_cursor_item(panel_with_timeout
->collection
, -1);
612 panel_with_timeout
= NULL
;
617 /* It is possible to highlight an item briefly on a panel by calling this
620 void panel_set_timeout(FilerWindow
*filer_window
, gulong msec
)
622 if (panel_with_timeout
)
624 /* Can't have two timeouts at once */
625 gtk_timeout_remove(panel_timeout
);
626 clear_panel_hilight(NULL
);
631 panel_with_timeout
= filer_window
;
632 panel_timeout
= gtk_timeout_add(msec
,
633 clear_panel_hilight
, NULL
);
637 void open_item(Collection
*collection
,
638 gpointer item_data
, int item_number
,
641 FilerWindow
*filer_window
= (FilerWindow
*) user_data
;
642 FileItem
*item
= (FileItem
*) item_data
;
643 GdkEventButton
*event
;
646 gboolean shift
, adjust
;
648 event
= (GdkEventButton
*) gtk_get_current_event();
649 full_path
= make_path(filer_window
->path
, item
->leafname
)->str
;
651 if (filer_window
->panel
)
653 panel_set_timeout(NULL
, 0);
654 collection_set_cursor_item(collection
, item_number
);
656 panel_set_timeout(filer_window
, 200);
659 if (event
->type
== GDK_2BUTTON_PRESS
|| event
->type
== GDK_BUTTON_PRESS
)
661 shift
= event
->state
& GDK_SHIFT_MASK
;
662 adjust
= event
->button
!= 1 || event
->state
& GDK_CONTROL_MASK
;
670 widget
= filer_window
->window
;
672 switch (item
->base_type
)
675 if (item
->flags
& ITEM_FLAG_APPDIR
&& !shift
)
677 run_app(make_path(filer_window
->path
,
678 item
->leafname
)->str
);
679 if (adjust
&& !filer_window
->panel
)
680 gtk_widget_destroy(widget
);
683 if (adjust
|| filer_window
->panel
)
684 filer_opendir(full_path
, FALSE
, BOTTOM
);
687 remove_view(filer_window
);
688 filer_window
->path
= pathdup(full_path
);
689 add_view(filer_window
);
690 scan_dir(filer_window
);
694 if (item
->flags
& ITEM_FLAG_EXEC_FILE
)
696 char *argv
[] = {full_path
, NULL
};
698 if (spawn_full(argv
, getenv("HOME"), 0))
700 if (adjust
&& !filer_window
->panel
)
701 gtk_widget_destroy(widget
);
704 report_error("ROX-Filer",
705 "Failed to fork() child");
710 MIME_type
*type
= item
->mime_type
;
712 g_return_if_fail(type
!= NULL
);
714 if (type_open(full_path
, type
))
716 if (adjust
&& !filer_window
->panel
)
717 gtk_widget_destroy(widget
);
721 message
= g_string_new(NULL
);
722 g_string_sprintf(message
, "No open "
723 "action specified for files of "
727 report_error("ROX-Filer", message
->str
);
728 g_string_free(message
, TRUE
);
733 report_error("open_item",
734 "I don't know how to open that");
739 static gint
pointer_in(GtkWidget
*widget
,
740 GdkEventCrossing
*event
,
741 FilerWindow
*filer_window
)
743 may_rescan(filer_window
);
747 static gint
focus_in(GtkWidget
*widget
,
748 GdkEventFocus
*event
,
749 FilerWindow
*filer_window
)
751 window_with_focus
= filer_window
;
756 static gint
focus_out(GtkWidget
*widget
,
757 GdkEventFocus
*event
,
758 FilerWindow
*filer_window
)
760 /* TODO: Shade the cursor */
765 /* Handle keys that can't be bound with the menu */
766 static gint
key_press_event(GtkWidget
*widget
,
768 FilerWindow
*filer_window
)
770 switch (event
->keyval
)
788 remove_view(filer_window
);
789 filer_window
->path
= pathdup(make_path(
792 add_view(filer_window
);
793 scan_dir(filer_window
);
800 FileItem
*selected_item(Collection
*collection
)
804 g_return_val_if_fail(collection
!= NULL
, NULL
);
805 g_return_val_if_fail(IS_COLLECTION(collection
), NULL
);
806 g_return_val_if_fail(collection
->number_selected
== 1, NULL
);
808 for (i
= 0; i
< collection
->number_of_items
; i
++)
809 if (collection
->items
[i
].selected
)
810 return (FileItem
*) collection
->items
[i
].data
;
812 g_warning("selected_item: number_selected is wrong\n");
817 /* Refresh all windows onto this directory */
818 void refresh_dirs(char *path
)
823 real
= pathdup(path
);
824 list
= g_hash_table_lookup(path_to_window_list
, real
);
830 may_rescan((FilerWindow
*) list
->data
);
835 void filer_opendir(char *path
, gboolean panel
, Side panel_side
)
837 GtkWidget
*hbox
, *scrollbar
, *collection
;
838 FilerWindow
*filer_window
;
839 GtkTargetEntry target_table
[] =
841 {"text/uri-list", 0, TARGET_URI_LIST
},
842 {"STRING", 0, TARGET_STRING
},
845 filer_window
= g_malloc(sizeof(FilerWindow
));
846 filer_window
->path
= pathdup(path
);
847 filer_window
->dir
= NULL
; /* Not scanning */
848 filer_window
->show_hidden
= FALSE
;
849 filer_window
->panel
= panel
;
850 filer_window
->panel_side
= panel_side
;
851 filer_window
->temp_item_selected
= FALSE
;
853 filer_window
->window
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
855 collection
= collection_new(NULL
);
856 gtk_object_set_data(GTK_OBJECT(collection
),
857 "filer_window", filer_window
);
858 filer_window
->collection
= COLLECTION(collection
);
859 collection_set_item_size(filer_window
->collection
, 64, 64);
860 collection_set_functions(filer_window
->collection
,
861 draw_item
, test_point
);
863 gtk_widget_add_events(filer_window
->window
, GDK_ENTER_NOTIFY
);
864 gtk_signal_connect(GTK_OBJECT(filer_window
->window
),
865 "enter-notify-event",
866 GTK_SIGNAL_FUNC(pointer_in
), filer_window
);
867 gtk_signal_connect(GTK_OBJECT(filer_window
->window
), "focus_in_event",
868 GTK_SIGNAL_FUNC(focus_in
), filer_window
);
869 gtk_signal_connect(GTK_OBJECT(filer_window
->window
), "focus_out_event",
870 GTK_SIGNAL_FUNC(focus_out
), filer_window
);
871 gtk_signal_connect(GTK_OBJECT(filer_window
->window
), "destroy",
872 filer_window_destroyed
, filer_window
);
874 gtk_signal_connect(GTK_OBJECT(filer_window
->collection
), "open_item",
875 open_item
, filer_window
);
876 gtk_signal_connect(GTK_OBJECT(collection
), "show_menu",
877 show_menu
, filer_window
);
878 gtk_signal_connect(GTK_OBJECT(collection
), "gain_selection",
879 gain_selection
, filer_window
);
880 gtk_signal_connect(GTK_OBJECT(collection
), "lose_selection",
881 lose_selection
, filer_window
);
882 gtk_signal_connect(GTK_OBJECT(collection
), "drag_selection",
883 drag_selection
, filer_window
);
884 gtk_signal_connect(GTK_OBJECT(collection
), "drag_data_get",
885 drag_data_get
, filer_window
);
886 gtk_signal_connect(GTK_OBJECT(collection
), "selection_clear_event",
887 GTK_SIGNAL_FUNC(collection_lose_selection
), NULL
);
888 gtk_signal_connect (GTK_OBJECT(collection
), "selection_get",
889 GTK_SIGNAL_FUNC(selection_get
), NULL
);
890 gtk_selection_add_targets(collection
, GDK_SELECTION_PRIMARY
,
892 sizeof(target_table
) / sizeof(*target_table
));
894 drag_set_dest(collection
);
898 int swidth
, sheight
, iwidth
, iheight
;
899 GtkWidget
*frame
, *win
= filer_window
->window
;
901 collection_set_panel(filer_window
->collection
, TRUE
);
903 gdk_window_get_size(GDK_ROOT_PARENT(), &swidth
, &sheight
);
904 iwidth
= filer_window
->collection
->item_width
;
905 iheight
= filer_window
->collection
->item_height
;
907 if (panel_side
== TOP
|| panel_side
== BOTTOM
)
909 int height
= iheight
+ PANEL_BORDER
;
910 int y
= panel_side
== TOP
912 : sheight
- height
- PANEL_BORDER
;
914 gtk_widget_set_usize(collection
, swidth
, height
);
915 gtk_widget_set_uposition(win
, 0, y
);
919 int width
= iwidth
+ PANEL_BORDER
;
920 int x
= panel_side
== LEFT
922 : swidth
- width
- PANEL_BORDER
;
924 gtk_widget_set_usize(collection
, width
, sheight
);
925 gtk_widget_set_uposition(win
, x
, 0);
928 frame
= gtk_frame_new(NULL
);
929 gtk_frame_set_shadow_type(GTK_FRAME(frame
), GTK_SHADOW_OUT
);
930 gtk_container_add(GTK_CONTAINER(frame
), collection
);
931 gtk_container_add(GTK_CONTAINER(win
), frame
);
933 gtk_widget_realize(win
);
934 make_panel_window(win
->window
);
938 gtk_signal_connect(GTK_OBJECT(filer_window
->window
),
940 GTK_SIGNAL_FUNC(key_press_event
), filer_window
);
941 gtk_window_set_default_size(GTK_WINDOW(filer_window
->window
),
944 hbox
= gtk_hbox_new(FALSE
, 0);
945 gtk_container_add(GTK_CONTAINER(filer_window
->window
), hbox
);
947 gtk_box_pack_start(GTK_BOX(hbox
), collection
, TRUE
, TRUE
, 0);
949 scrollbar
= gtk_vscrollbar_new(COLLECTION(collection
)->vadj
);
950 gtk_box_pack_start(GTK_BOX(hbox
), scrollbar
, FALSE
, TRUE
, 0);
951 gtk_accel_group_attach(filer_keys
,
952 GTK_OBJECT(filer_window
->window
));
955 gtk_widget_show_all(filer_window
->window
);
958 load_default_pixmaps(collection
->window
);
960 add_view(filer_window
);
961 scan_dir(filer_window
);