… | |
… | |
10 | #include <unistd.h> |
10 | #include <unistd.h> |
11 | #include <sys/types.h> |
11 | #include <sys/types.h> |
12 | #include <sys/stat.h> |
12 | #include <sys/stat.h> |
13 | #include <fcntl.h> |
13 | #include <fcntl.h> |
14 | |
14 | |
|
|
15 | static const char gtkbfc_version_string[] = "gtkbfc version 0.0"; |
|
|
16 | |
15 | static char *helper = "/etc/gtkbfc-helper"; |
17 | static char *helper = "/etc/gtkbfc-helper"; |
16 | |
18 | |
17 | static GObject *(*old_constructor) (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties); |
19 | static GObject *(*old_constructor) (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties); |
18 | |
20 | |
19 | static gchar *last_path; |
21 | static gchar *last_path; |
… | |
… | |
73 | static const gchar * |
75 | static const gchar * |
74 | from_uri (const gchar *uri) |
76 | from_uri (const gchar *uri) |
75 | { |
77 | { |
76 | const gchar *rv = uri; |
78 | const gchar *rv = uri; |
77 | |
79 | |
78 | if (uri && uri == strstr (uri, "file:///")) |
80 | if (!strncmp (uri, "file:///", sizeof ("file:///") - 1)) |
79 | rv = uri + 7; |
81 | rv += sizeof ("file:///") - 1; |
80 | |
82 | |
81 | return rv; |
83 | return rv; |
82 | } |
84 | } |
83 | |
85 | |
84 | static gchar * |
86 | static gchar * |
… | |
… | |
87 | gchar *rv = NULL; |
89 | gchar *rv = NULL; |
88 | |
90 | |
89 | if (file) |
91 | if (file) |
90 | { |
92 | { |
91 | GString *str = g_string_new ("file://"); |
93 | GString *str = g_string_new ("file://"); |
92 | |
|
|
93 | str = g_string_append (str, file); |
94 | str = g_string_append (str, file); |
94 | rv = g_strdup (str->str); |
95 | rv = g_strdup (str->str); |
95 | g_string_free (str, TRUE); |
96 | g_string_free (str, TRUE); |
96 | g_free (file); |
97 | g_free (file); |
97 | } |
98 | } |
… | |
… | |
118 | } |
119 | } |
119 | |
120 | |
120 | gchar *gtk_file_chooser_get_uri (GtkFileChooser *chooser) |
121 | gchar *gtk_file_chooser_get_uri (GtkFileChooser *chooser) |
121 | { |
122 | { |
122 | gchar *uri = to_uri(gtk_file_chooser_get_filename (chooser)); |
123 | gchar *uri = to_uri(gtk_file_chooser_get_filename (chooser)); |
123 | DEBUG ((printf ("gtk_file_chooser_get_uri<%s>\n", uri))); |
124 | DEBUG ((printf ("gtk_file_chooser_get_uri<%s>\n", uri))) |
124 | return uri; |
125 | return uri; |
125 | } |
126 | } |
126 | |
127 | |
127 | gboolean gtk_file_chooser_set_uri (GtkFileChooser *chooser, const char *uri) |
128 | gboolean gtk_file_chooser_set_uri (GtkFileChooser *chooser, const char *uri) |
128 | { |
129 | { |
… | |
… | |
146 | |
147 | |
147 | ///////////////////////////////////////////////////////////////////////////// |
148 | ///////////////////////////////////////////////////////////////////////////// |
148 | |
149 | |
149 | static gboolean disable_cb (gpointer data) |
150 | static gboolean disable_cb (gpointer data) |
150 | { |
151 | { |
151 | // set the path again to avoid a race condition |
|
|
152 | ((void (*)(void *, const char *)) dlsym (RTLD_NEXT, "gtk_file_chooser_set_filename"))(GTK_FILE_CHOOSER (data), "/tmp/gtkbfc/empty"); |
152 | ((void (*)(void *, const char *)) dlsym (RTLD_NEXT, "gtk_file_chooser_set_filename"))(GTK_FILE_CHOOSER (data), "/tmp/gtkbfc/empty"); |
153 | gtk_widget_set_sensitive (GTK_WIDGET (gtk_widget_get_toplevel (data)), 0); |
153 | |
154 | //gtk_widget_unmap (GTK_WIDGET (gtk_widget_get_toplevel (data))); |
154 | GtkWidget *toplevel = gtk_widget_get_toplevel (data); |
|
|
155 | if (toplevel) gtk_widget_set_sensitive (toplevel, 0); |
|
|
156 | |
|
|
157 | gtk_widget_unref (data); |
155 | return FALSE; |
158 | return FALSE; |
156 | } |
159 | } |
157 | |
160 | |
158 | static gboolean read_result (GIOChannel *source, GIOCondition condition, gpointer data) |
161 | static gboolean read_result (GIOChannel *source, GIOCondition condition, gpointer data) |
159 | { |
162 | { |
… | |
… | |
164 | } |
167 | } |
165 | |
168 | |
166 | g_io_channel_read_to_end (source, &last_path, 0, 0); |
169 | g_io_channel_read_to_end (source, &last_path, 0, 0); |
167 | g_io_channel_unref (source); |
170 | g_io_channel_unref (source); |
168 | |
171 | |
169 | gtk_widget_set_sensitive (GTK_WIDGET (gtk_widget_get_toplevel (data)), 1); |
172 | GtkWidget *toplevel = gtk_widget_get_toplevel (data); |
|
|
173 | if (toplevel) gtk_widget_set_sensitive (toplevel, 1); |
170 | |
174 | |
171 | if (!last_path || *last_path != '/') |
175 | if (!last_path || *last_path != '/') |
172 | { |
176 | { |
173 | DEBUG ((printf ("read_result cancel\n"))) |
177 | DEBUG ((printf ("read_result cancel\n"))) |
174 | g_free (last_path); |
178 | g_free (last_path); |
175 | last_path = 0; |
179 | last_path = 0; |
|
|
180 | |
|
|
181 | if (toplevel) |
|
|
182 | { |
|
|
183 | GdkEvent ev = { GDK_DELETE }; |
|
|
184 | g_signal_emit_by_name (toplevel, "delete-event", &ev); |
|
|
185 | } |
176 | } |
186 | } |
177 | else |
187 | else |
178 | { |
188 | { |
179 | DEBUG ((printf ("read_result<%s>\n", last_path))) |
189 | DEBUG ((printf ("read_result<%s>\n", last_path))) |
180 | gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (data), FALSE); |
190 | gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (data), FALSE); |
181 | g_signal_emit_by_name (GTK_FILE_CHOOSER (data), "file-activated"); |
191 | g_signal_emit_by_name (GTK_FILE_CHOOSER (data), "file-activated"); |
182 | } |
192 | } |
183 | |
193 | |
|
|
194 | gtk_widget_unref (data); |
184 | return FALSE; |
195 | return FALSE; |
185 | } |
196 | } |
186 | |
197 | |
187 | static gboolean show_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) |
198 | static gboolean map_cb (GtkWidget *widget, gpointer user_data) |
188 | { |
199 | { |
189 | gchar *argv[10]; |
200 | gchar *argv[10]; |
190 | gboolean save = 0; |
201 | gboolean save = 0; |
191 | char xid [40]; |
202 | char xid [40]; |
192 | |
203 | |
… | |
… | |
196 | { |
207 | { |
197 | case GTK_FILE_CHOOSER_ACTION_SAVE: argv [1] = "save "; save = 1;break; |
208 | case GTK_FILE_CHOOSER_ACTION_SAVE: argv [1] = "save "; save = 1;break; |
198 | case GTK_FILE_CHOOSER_ACTION_OPEN: argv [1] = "load "; break; |
209 | case GTK_FILE_CHOOSER_ACTION_OPEN: argv [1] = "load "; break; |
199 | case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER: argv [1] = "mkdir "; save = 1; break; |
210 | case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER: argv [1] = "mkdir "; save = 1; break; |
200 | case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: argv [1] = "cd "; break; |
211 | case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: argv [1] = "cd "; break; |
201 | default: argv [1] = "<filechooser> "; break; |
212 | default: argv [1] = "<unknown action> "; break; |
202 | } |
213 | } |
203 | |
214 | |
204 | GdkWindow *w = gtk_widget_get_parent_window (GTK_WIDGET (widget)); |
215 | GdkWindow *w = gtk_widget_get_parent_window (GTK_WIDGET (widget)); |
205 | |
216 | |
206 | snprintf (xid, 80, "%lu", (unsigned long)(w ? gdk_x11_drawable_get_xid (w) : 0)); |
217 | snprintf (xid, 80, "%lu", (unsigned long)(w ? gdk_x11_drawable_get_xid (w) : 0)); |
… | |
… | |
212 | |
223 | |
213 | ((void (*)(void *, const char *)) dlsym (RTLD_NEXT, "gtk_file_chooser_set_filename"))(GTK_FILE_CHOOSER (widget), "/tmp/gtkbfc/empty"); |
224 | ((void (*)(void *, const char *)) dlsym (RTLD_NEXT, "gtk_file_chooser_set_filename"))(GTK_FILE_CHOOSER (widget), "/tmp/gtkbfc/empty"); |
214 | |
225 | |
215 | gint stdout_fd = -1; |
226 | gint stdout_fd = -1; |
216 | |
227 | |
|
|
228 | gtk_widget_ref (widget); disable_cb (widget); |
|
|
229 | |
217 | if (g_spawn_async_with_pipes (0, argv, 0, 0, 0, 0, 0, 0, &stdout_fd, 0, 0)) |
230 | if (g_spawn_async_with_pipes (0, argv, 0, 0, 0, 0, 0, 0, &stdout_fd, 0, 0)) |
218 | { |
231 | { |
219 | GIOChannel *channel = g_io_channel_unix_new (stdout_fd); |
232 | GIOChannel *channel = g_io_channel_unix_new (stdout_fd); |
|
|
233 | |
220 | g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP, read_result, widget); |
234 | gtk_widget_ref (widget); g_io_add_watch (channel, G_IO_IN | G_IO_ERR | G_IO_HUP, read_result, widget); |
|
|
235 | |
|
|
236 | // disable again in an idle handler, to get around race conditions |
221 | g_idle_add (disable_cb, widget); |
237 | gtk_widget_ref (widget); g_idle_add (disable_cb, widget); |
222 | } |
238 | } |
223 | else |
|
|
224 | ;//gtk_widget_show (widget); |
|
|
225 | } |
239 | } |
226 | |
240 | |
227 | static GObject *new_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) |
241 | static GObject *new_constructor (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties) |
228 | { |
242 | { |
229 | GObject *ob = old_constructor (type, n_construct_properties, construct_properties); |
243 | GObject *ob = old_constructor (type, n_construct_properties, construct_properties); |
230 | g_signal_connect_after (ob, "map", G_CALLBACK (show_cb), 0); |
244 | g_signal_connect_after (ob, "map", G_CALLBACK (map_cb), 0); |
231 | return ob; |
245 | return ob; |
232 | } |
246 | } |
233 | |
247 | |
234 | __attribute__ ((constructor)) |
248 | __attribute__ ((constructor)) |
235 | static void init () |
249 | static void init () |