|
|
1 | /* this file is publiched under the gnu gpl license, version 3 or any later */ |
|
|
2 | |
1 | #define _GNU_SOURCE |
3 | #define _GNU_SOURCE |
2 | |
4 | |
3 | #include <dlfcn.h> |
5 | #include <dlfcn.h> |
4 | #include <glib.h> |
6 | #include <glib.h> |
5 | #include <gtk/gtk.h> |
7 | #include <gtk/gtk.h> |
6 | #include <stdlib.h> |
8 | #include <stdlib.h> |
|
|
9 | #include <string.h> |
|
|
10 | #include <unistd.h> |
|
|
11 | #include <sys/types.h> |
|
|
12 | #include <sys/stat.h> |
|
|
13 | #include <fcntl.h> |
7 | |
14 | |
8 | static char *helper = "/etc/gtkbfc-helper"; |
15 | static char *helper = "/etc/gtkbfc-helper"; |
9 | |
16 | |
10 | static GObject *(*old_constructor) (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties); |
17 | static GObject *(*old_constructor) (GType type, guint n_construct_properties, GObjectConstructParam *construct_properties); |
11 | |
18 | |
|
|
19 | static gchar *last_path; |
|
|
20 | |
|
|
21 | #if 0 |
|
|
22 | # define DEBUG(stmt) stmt; |
|
|
23 | #else |
|
|
24 | # define DEBUG(stmt) |
|
|
25 | #endif |
|
|
26 | |
|
|
27 | ///////////////////////////////////////////////////////////////////////////// |
|
|
28 | |
|
|
29 | gchar *gtk_file_chooser_get_filename (GtkFileChooser *chooser) |
|
|
30 | { |
|
|
31 | DEBUG ((printf ("gtk_file_chooser_get_filename %s\n", last_path))) |
|
|
32 | return g_strdup (last_path ? last_path : "/nonex1st4nt"); |
|
|
33 | } |
|
|
34 | |
|
|
35 | gboolean gtk_file_chooser_select_filename (GtkFileChooser *chooser, const char *filename) |
|
|
36 | { |
|
|
37 | return 1; |
|
|
38 | } |
|
|
39 | |
|
|
40 | void gtk_file_chooser_unselect_all (GtkFileChooser *chooser) |
|
|
41 | { |
|
|
42 | } |
|
|
43 | |
|
|
44 | gboolean gtk_file_chooser_set_filename (GtkFileChooser *chooser, const char *filename) |
|
|
45 | { |
|
|
46 | return 1; |
|
|
47 | } |
|
|
48 | |
|
|
49 | void gtk_file_chooser_set_current_name (GtkFileChooser *chooser, const char *filename) |
|
|
50 | { |
|
|
51 | } |
|
|
52 | |
|
|
53 | GSList *gtk_file_chooser_get_filenames (GtkFileChooser *chooser) |
|
|
54 | { |
|
|
55 | GSList *rv = 0; |
|
|
56 | rv = g_slist_prepend (rv, gtk_file_chooser_get_filename (chooser)); |
|
|
57 | return rv; |
|
|
58 | } |
|
|
59 | |
|
|
60 | gboolean gtk_file_chooser_set_current_folder (GtkFileChooser *chooser, const gchar *folder) |
|
|
61 | { |
|
|
62 | return 1; |
|
|
63 | } |
|
|
64 | |
|
|
65 | gchar * gtk_file_chooser_get_current_folder (GtkFileChooser *chooser) |
|
|
66 | { |
|
|
67 | DEBUG ((printf ("gtk_file_chooser_get_current_folder\n"))) |
|
|
68 | return g_strdup ("/tmp/gtkbfc"); |
|
|
69 | } |
|
|
70 | |
|
|
71 | ///////////////////////////////////////////////////////////////////////////// |
|
|
72 | |
|
|
73 | static const gchar * |
|
|
74 | from_uri (const gchar *uri) |
|
|
75 | { |
|
|
76 | const gchar *rv = uri; |
|
|
77 | |
|
|
78 | if (uri && uri == strstr (uri, "file:///")) |
|
|
79 | rv = uri + 7; |
|
|
80 | |
|
|
81 | return rv; |
|
|
82 | } |
|
|
83 | |
|
|
84 | static gchar * |
|
|
85 | to_uri (gchar *file) |
|
|
86 | { |
|
|
87 | gchar *rv = NULL; |
|
|
88 | |
|
|
89 | if (file) |
|
|
90 | { |
|
|
91 | GString *str = g_string_new ("file://"); |
|
|
92 | |
|
|
93 | str = g_string_append (str, file); |
|
|
94 | rv = g_strdup (str->str); |
|
|
95 | g_string_free (str, TRUE); |
|
|
96 | g_free (file); |
|
|
97 | } |
|
|
98 | |
|
|
99 | return rv; |
|
|
100 | } |
|
|
101 | |
|
|
102 | static GSList * |
|
|
103 | to_uris (GSList *files) |
|
|
104 | { |
|
|
105 | GSList *item = files; |
|
|
106 | |
|
|
107 | for (; item; item = g_slist_next (item)) |
|
|
108 | { |
|
|
109 | GString *str = g_string_new ("file://"); |
|
|
110 | gchar *cur = item->data; |
|
|
111 | |
|
|
112 | str = g_string_append (str, cur); |
|
|
113 | item->data = g_string_free (str, FALSE); |
|
|
114 | g_free (cur); |
|
|
115 | } |
|
|
116 | |
|
|
117 | return files; |
|
|
118 | } |
|
|
119 | |
|
|
120 | gchar *gtk_file_chooser_get_uri (GtkFileChooser *chooser) |
|
|
121 | { |
|
|
122 | gchar *uri = to_uri(gtk_file_chooser_get_filename (chooser)); |
|
|
123 | DEBUG ((printf ("gtk_file_chooser_get_uri %s\n", uri))); |
|
|
124 | return uri; |
|
|
125 | } |
|
|
126 | |
|
|
127 | gboolean gtk_file_chooser_set_uri (GtkFileChooser *chooser, const char *uri) |
|
|
128 | { |
|
|
129 | return gtk_file_chooser_set_filename (chooser, from_uri (uri)); |
|
|
130 | } |
|
|
131 | |
|
|
132 | GSList *gtk_file_chooser_get_uris (GtkFileChooser *chooser) |
|
|
133 | { |
|
|
134 | return to_uris (gtk_file_chooser_get_filenames (chooser)); |
|
|
135 | } |
|
|
136 | |
|
|
137 | gboolean gtk_file_chooser_set_current_folder_uri(GtkFileChooser *chooser, const gchar *uri) |
|
|
138 | { |
|
|
139 | return gtk_file_chooser_set_current_folder (chooser, from_uri (uri)); |
|
|
140 | } |
|
|
141 | |
|
|
142 | gchar *gtk_file_chooser_get_current_folder_uri (GtkFileChooser *chooser) |
|
|
143 | { |
|
|
144 | return to_uri (gtk_file_chooser_get_current_folder (chooser)); |
|
|
145 | } |
|
|
146 | |
|
|
147 | ///////////////////////////////////////////////////////////////////////////// |
|
|
148 | |
12 | static gboolean activate_cb (gpointer data) |
149 | static gboolean activate_cb (gpointer data) |
13 | { |
150 | { |
|
|
151 | gtk_widget_set_sensitive (GTK_WIDGET (gtk_widget_get_toplevel (data)), 1); |
14 | gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (data), FALSE); |
152 | gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (data), FALSE); |
|
|
153 | //fprintf (stderr, "ad %d\n", gtk_window_activate_default (GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (data))))); |
15 | g_signal_emit_by_name (GTK_FILE_CHOOSER (data), "file-activated"); |
154 | g_signal_emit_by_name (GTK_FILE_CHOOSER (data), "file-activated"); |
16 | return FALSE; |
155 | return FALSE; |
17 | } |
156 | } |
18 | |
157 | |
|
|
158 | static gboolean unmap_cb (gpointer data) |
|
|
159 | { |
|
|
160 | // set the path again to avoid a race condition |
|
|
161 | ((void (*)(void *, const char *)) dlsym (RTLD_NEXT, "gtk_file_chooser_set_filename"))(GTK_FILE_CHOOSER (data), "/tmp/gtkbfc/empty"); |
|
|
162 | gtk_widget_set_sensitive (GTK_WIDGET (gtk_widget_get_toplevel (data)), 0); |
|
|
163 | //gtk_widget_unmap (GTK_WIDGET (gtk_widget_get_toplevel (data))); |
|
|
164 | return FALSE; |
|
|
165 | } |
|
|
166 | |
|
|
167 | static gboolean read_result (GIOChannel *source, GIOCondition condition, gpointer data) |
|
|
168 | { |
|
|
169 | if (last_path) |
|
|
170 | { |
|
|
171 | g_free (last_path); |
|
|
172 | last_path = 0; |
|
|
173 | } |
|
|
174 | |
|
|
175 | g_io_channel_read_to_end (source, &last_path, 0, 0); |
|
|
176 | g_io_channel_unref (source); |
|
|
177 | activate_cb (data); |
|
|
178 | |
|
|
179 | DEBUG ((printf ("read_result<%s>\n", last_path))); |
|
|
180 | |
|
|
181 | return FALSE; |
|
|
182 | } |
|
|
183 | |
19 | static gboolean show_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) |
184 | static gboolean show_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data) |
20 | { |
185 | { |
21 | gchar *argv[3]; |
186 | gchar *argv[10]; |
22 | gchar *output; |
187 | gboolean save = 0; |
|
|
188 | char xid [40]; |
23 | |
189 | |
24 | argv [0] = helper; |
190 | argv [0] = helper; |
25 | |
191 | |
26 | switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (widget))) |
192 | switch (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (widget))) |
27 | { |
193 | { |
28 | case GTK_FILE_CHOOSER_ACTION_SAVE: argv [1] = "save "; break; |
194 | case GTK_FILE_CHOOSER_ACTION_SAVE: argv [1] = "save "; save = 1;break; |
29 | case GTK_FILE_CHOOSER_ACTION_OPEN: argv [1] = "load "; break; |
195 | case GTK_FILE_CHOOSER_ACTION_OPEN: argv [1] = "load "; break; |
30 | case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER: argv [1] = "mkdir "; break; |
196 | case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER: argv [1] = "mkdir "; save = 1; break; |
31 | case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: argv [1] = "cd "; break; |
197 | case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER: argv [1] = "cd "; break; |
32 | default: argv [1] = "<filechooser> "; break; |
198 | default: argv [1] = "<filechooser> "; break; |
33 | } |
199 | } |
34 | |
200 | |
|
|
201 | GdkWindow *w = gtk_widget_get_parent_window (GTK_WIDGET (widget)); |
|
|
202 | |
|
|
203 | snprintf (xid, 80, "%lu", (unsigned long)(w ? gdk_x11_drawable_get_xid (w) : 0)); |
|
|
204 | argv [2] = xid; |
35 | argv [2] = 0; |
205 | argv [3] = 0; |
36 | |
206 | |
|
|
207 | mkdir ("/tmp/gtkbfc", 0777); |
|
|
208 | close (open ("/tmp/gtkbfc/empty", O_WRONLY|O_CREAT|O_TRUNC, 0666)); |
|
|
209 | |
|
|
210 | ((void (*)(void *, const char *)) dlsym (RTLD_NEXT, "gtk_file_chooser_set_filename"))(GTK_FILE_CHOOSER (widget), "/tmp/gtkbfc/empty"); |
|
|
211 | |
|
|
212 | gint stdout_fd = -1; |
|
|
213 | |
37 | if (g_spawn_sync (0, argv, 0, 0, 0, 0, &output, 0, 0, 0)) |
214 | if (g_spawn_async_with_pipes (0, argv, 0, 0, 0, 0, 0, 0, &stdout_fd, 0, 0)) |
38 | { |
215 | { |
39 | if (gtk_file_chooser_get_action (GTK_FILE_CHOOSER (widget)) == GTK_FILE_CHOOSER_ACTION_SAVE |
216 | GIOChannel *channel = g_io_channel_unix_new (stdout_fd); |
40 | || gtk_file_chooser_get_action (GTK_FILE_CHOOSER (widget)) == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER) |
217 | //gtk_widget_hide (GTK_WIDGET (gtk_widget_get_toplevel (widget))); |
41 | gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (widget), output); |
218 | g_io_add_watch (channel, G_IO_IN, read_result, widget); |
42 | else |
|
|
43 | gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget), output); |
|
|
44 | |
|
|
45 | g_free (output); |
|
|
46 | |
|
|
47 | //gtk_widget_hide (widget); |
|
|
48 | //g_idle_add (activate_cb, widget); |
219 | g_idle_add (unmap_cb, widget); |
49 | g_timeout_add (100, activate_cb, widget); |
220 | //g_timeout_add (1, unmap_cb, widget); |
50 | } |
221 | } |
51 | else |
222 | else |
52 | ;//gtk_widget_show (widget); |
223 | ;//gtk_widget_show (widget); |
53 | } |
224 | } |
54 | |
225 | |