4 * ROX-Filer, filer for the ROX desktop project
5 * By Thomas Leonard, <tal197@ecs.soton.ac.uk>.
8 /* menu.c - code for handling the popup menu */
17 #include "gui_support.h"
21 #define C_ "<control>"
23 #define MENU_MARGIN 32
25 GtkAccelGroup
*filer_keys
;
26 GtkAccelGroup
*panel_keys
;
28 /* Static prototypes */
29 static void position_menu(GtkMenu
*menu
, gint
*x
, gint
*y
, gpointer data
);
30 static void menu_closed(GtkWidget
*widget
);
32 static void refresh(gpointer data
, guint action
, GtkWidget
*widget
);
33 static void mount(gpointer data
, guint action
, GtkWidget
*widget
);
34 static void delete(gpointer data
, guint action
, GtkWidget
*widget
);
35 static void show_options(gpointer data
, guint action
, GtkWidget
*widget
);
36 static void xterm_here(gpointer data
, guint action
, GtkWidget
*widget
);
37 static void open_parent(gpointer data
, guint action
, GtkWidget
*widget
);
39 static void open_as_dir(gpointer data
, guint action
, GtkWidget
*widget
);
40 static void close_panel(gpointer data
, guint action
, GtkWidget
*widget
);
42 static GtkWidget
*filer_menu
; /* The popup filer menu */
43 static GtkWidget
*panel_menu
; /* The popup panel menu */
45 static GtkItemFactoryEntry filer_menu_def
[] = {
46 {"/Display", NULL
, NULL
, 0, "<Branch>"},
47 {"/Display/Large Icons", NULL
, NULL
, 0, "<RadioItem>"},
48 {"/Display/Small Icons", NULL
, NULL
, 0, "/Display/Large Icons"},
49 {"/Display/Full Info", NULL
, NULL
, 0, "/Display/Large Icons"},
50 {"/Display/Separator", NULL
, NULL
, 0, "<Separator>"},
51 {"/Display/Sort by Name", NULL
, NULL
, 0, "<RadioItem>"},
52 {"/Display/Sort by Type", NULL
, NULL
, 0, "/Display/Sort by Name"},
53 {"/Display/Sort by Date", NULL
, NULL
, 0, "/Display/Sort by Name"},
54 {"/Display/Sort by Size", NULL
, NULL
, 0, "/Display/Sort by Name"},
55 {"/Display/Separator", NULL
, NULL
, 0, "<Separator>"},
56 {"/Display/Show Hidden", C_
"H", NULL
, 0, "<ToggleItem>"},
57 {"/Display/Refresh", C_
"L", refresh
, 0, NULL
},
58 {"/File", NULL
, NULL
, 0, "<Branch>"},
59 {"/File/Copy", NULL
, NULL
, 0, NULL
},
60 {"/File/Rename", NULL
, NULL
, 0, NULL
},
61 {"/File/Help", "F1", NULL
, 0, NULL
},
62 {"/File/Info", NULL
, NULL
, 0, NULL
},
63 {"/File/Mount", C_
"M", mount
, 0, NULL
},
64 {"/File/Separator", NULL
, NULL
, 0, "<Separator>"},
65 {"/File/Delete", C_
"X", delete, 0, NULL
},
66 {"/File/Disk Usage", C_
"U", NULL
, 0, NULL
},
67 {"/File/Permissions", NULL
, NULL
, 0, NULL
},
68 {"/File/Stamp", NULL
, NULL
, 0, NULL
},
69 {"/File/Find", NULL
, NULL
, 0, NULL
},
70 {"/Select All", C_
"A", NULL
, 0, NULL
},
71 {"/Clear Selection", C_
"Z", NULL
, 0, NULL
},
72 {"/Options...", NULL
, show_options
, 0, NULL
},
73 {"/New directory", NULL
, NULL
, 0, NULL
},
74 {"/Xterm here", NULL
, xterm_here
, 0, NULL
},
75 {"/Open parent", NULL
, open_parent
, 0, NULL
},
78 static GtkItemFactoryEntry panel_menu_def
[] = {
79 {"/Display", NULL
, NULL
, 0, "<Branch>"},
80 {"/Display/Large Icons", NULL
, NULL
, 0, "<RadioItem>"},
81 {"/Display/Small Icons", NULL
, NULL
, 0, "/Display/Large Icons"},
82 {"/Display/Full Info", NULL
, NULL
, 0, "/Display/Large Icons"},
83 {"/Display/Separator", NULL
, NULL
, 0, "<Separator>"},
84 {"/Display/Sort by Name", NULL
, NULL
, 0, "<RadioItem>"},
85 {"/Display/Sort by Type", NULL
, NULL
, 0, "/Display/Sort by Name"},
86 {"/Display/Sort by Date", NULL
, NULL
, 0, "/Display/Sort by Name"},
87 {"/Display/Sort by Size", NULL
, NULL
, 0, "/Display/Sort by Name"},
88 {"/Display/Separator", NULL
, NULL
, 0, "<Separator>"},
89 {"/Display/Show Hidden", C_
"H", NULL
, 0, "<ToggleItem>"},
90 {"/Display/Refresh", C_
"L", refresh
, 0, NULL
},
91 {"/File", NULL
, NULL
, 0, "<Branch>"},
92 {"/File/Delete", NULL
, NULL
, 0, NULL
},
93 {"/Open as directory", NULL
, open_as_dir
, 0, NULL
},
94 {"/Close panel", NULL
, close_panel
, 0, NULL
},
100 GtkItemFactory
*item_factory
;
103 filer_keys
= gtk_accel_group_new();
104 item_factory
= gtk_item_factory_new(GTK_TYPE_MENU
,
107 gtk_item_factory_create_items(item_factory
,
108 sizeof(filer_menu_def
) / sizeof(*filer_menu_def
),
111 filer_menu
= gtk_item_factory_get_widget(item_factory
, "<filer>");
113 panel_keys
= gtk_accel_group_new();
114 item_factory
= gtk_item_factory_new(GTK_TYPE_MENU
,
117 gtk_item_factory_create_items(item_factory
,
118 sizeof(panel_menu_def
) / sizeof(*panel_menu_def
),
121 panel_menu
= gtk_item_factory_get_widget(item_factory
, "<panel>");
123 menurc
= choices_find_path_load("menus");
125 gtk_item_factory_parse_rc(menurc
);
127 gtk_signal_connect(GTK_OBJECT(panel_menu
), "unmap_event",
128 GTK_SIGNAL_FUNC(menu_closed
), NULL
);
129 gtk_signal_connect(GTK_OBJECT(filer_menu
), "unmap_event",
130 GTK_SIGNAL_FUNC(menu_closed
), NULL
);
132 gtk_accel_group_lock(panel_keys
);
135 /* Save the keybindings... */
140 menurc
= choices_find_path_save("menus");
142 gtk_item_factory_dump_rc(menurc
, NULL
, TRUE
);
145 static void position_menu(GtkMenu
*menu
, gint
*x
, gint
*y
, gpointer data
)
147 int *pos
= (int *) data
;
149 GtkRequisition requisition
;
151 gdk_window_get_size(GDK_ROOT_PARENT(), &swidth
, &sheight
);
153 gtk_widget_size_request(GTK_WIDGET(menu
), &requisition
);
156 *x
= swidth
- MENU_MARGIN
- requisition
.width
;
157 else if (pos
[0] == -2)
160 *x
= pos
[0] - (requisition
.width
>> 2);
163 *y
= sheight
- MENU_MARGIN
- requisition
.height
;
164 else if (pos
[1] == -2)
167 *y
= pos
[1] - (requisition
.height
>> 2);
169 *x
= CLAMP(*x
, 0, swidth
- requisition
.width
);
170 *y
= CLAMP(*y
, 0, sheight
- requisition
.height
);
173 void show_filer_menu(FilerWindow
*filer_window
, GdkEventButton
*event
,
176 int pos
[] = {event
->x_root
, event
->y_root
};
178 window_with_focus
= filer_window
;
180 if (filer_window
->panel
)
182 switch (filer_window
->panel_side
)
184 case TOP
: pos
[1] = -2; break;
185 case BOTTOM
: pos
[1] = -1; break;
186 case LEFT
: pos
[0] = -2; break;
187 case RIGHT
: pos
[0] = -1; break;
191 if (filer_window
->panel
)
192 collection_clear_selection(filer_window
->collection
);
193 if (filer_window
->collection
->number_selected
== 0 && item
>= 0)
195 collection_select_item(filer_window
->collection
, item
);
196 filer_window
->temp_item_selected
= TRUE
;
199 filer_window
->temp_item_selected
= FALSE
;
201 gtk_menu_popup(filer_window
->panel
? GTK_MENU(panel_menu
)
202 : GTK_MENU(filer_menu
),
203 NULL
, NULL
, position_menu
,
204 (gpointer
) pos
, event
->button
, event
->time
);
207 static void menu_closed(GtkWidget
*widget
)
209 g_return_if_fail(window_with_focus
!= NULL
);
211 if (window_with_focus
->temp_item_selected
)
213 collection_clear_selection(window_with_focus
->collection
);
214 window_with_focus
->temp_item_selected
= FALSE
;
220 static void refresh(gpointer data
, guint action
, GtkWidget
*widget
)
222 g_return_if_fail(window_with_focus
!= NULL
);
224 scan_dir(window_with_focus
);
227 static void delete(gpointer data
, guint action
, GtkWidget
*widget
)
229 const char *start_args
[] = {"xterm", "-wf",
231 int argc
= sizeof(start_args
) / sizeof(char *);
233 Collection
*collection
;
238 g_return_if_fail(window_with_focus
!= NULL
);
240 collection
= window_with_focus
->collection
;
242 if (collection
->number_selected
< 1)
244 report_error("ROX-Filer", "Nothing to delete!");
248 argv
= g_malloc(sizeof(start_args
) +
249 sizeof(char *) * (collection
->number_selected
+ 1));
250 memcpy(argv
, start_args
, sizeof(start_args
));
252 for (i
= 0; i
< collection
->number_of_items
; i
++)
253 if (collection
->items
[i
].selected
)
255 item
= (FileItem
*) collection
->items
[i
].data
;
256 argv
[argc
++] = g_strdup(make_path(
257 window_with_focus
->path
,
258 item
->leafname
)->str
);
264 g_hash_table_insert(child_to_filer
,
265 (gpointer
) child
, window_with_focus
);
267 report_error("ROX-Filer", "Failed to fork() child "
270 for (i
= sizeof(start_args
) / sizeof(char *); i
< argc
; i
++)
275 static void mount(gpointer data
, guint action
, GtkWidget
*widget
)
279 Collection
*collection
;
282 g_return_if_fail(window_with_focus
!= NULL
);
284 collection
= window_with_focus
->collection
;
286 for (i
= 0; i
< collection
->number_of_items
; i
++)
287 if (collection
->items
[i
].selected
)
289 item
= (FileItem
*) collection
->items
[i
].data
;
290 if (item
->flags
& ITEM_FLAG_MOUNT_POINT
)
292 char *argv
[] = {"mount", NULL
, NULL
};
295 if (item
->flags
& ITEM_FLAG_MOUNTED
)
297 argv
[1] = make_path(window_with_focus
->path
,
298 item
->leafname
)->str
;
301 waitpid(child
, NULL
, 0);
303 error
= "Failed to run mount/umount";
306 scan_dir(window_with_focus
);
309 report_error("ROX-Filer", error
);
312 static void show_options(gpointer data
, guint action
, GtkWidget
*widget
)
314 g_return_if_fail(window_with_focus
!= NULL
);
316 options_edit(window_with_focus
);
319 static void xterm_here(gpointer data
, guint action
, GtkWidget
*widget
)
321 char *argv
[] = {"gnome-terminal", NULL
}; /* XXX: Bad default */
323 g_return_if_fail(window_with_focus
!= NULL
);
325 if (!spawn_in(argv
, window_with_focus
->path
))
326 report_error("ROX-Filer", "Failed to fork() child "
330 static void open_parent(gpointer data
, guint action
, GtkWidget
*widget
)
332 g_return_if_fail(window_with_focus
!= NULL
);
334 filer_opendir(make_path(window_with_focus
->path
, "/..")->str
,
338 static void open_as_dir(gpointer data
, guint action
, GtkWidget
*widget
)
340 g_return_if_fail(window_with_focus
!= NULL
);
342 filer_opendir(window_with_focus
->path
, FALSE
, BOTTOM
);
345 static void close_panel(gpointer data
, guint action
, GtkWidget
*widget
)
347 g_return_if_fail(window_with_focus
!= NULL
);
349 gtk_widget_destroy(window_with_focus
->window
);