| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk2.h" | 5 #include "chrome/browser/ui/libgtkui/select_file_dialog_impl_gtk.h" |
| 6 | 6 |
| 7 #include <gdk/gdkx.h> | 7 #include <gdk/gdkx.h> |
| 8 #include <gtk/gtk.h> | 8 #include <gtk/gtk.h> |
| 9 #include <stddef.h> | 9 #include <stddef.h> |
| 10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| 11 #include <sys/types.h> | 11 #include <sys/types.h> |
| 12 #include <unistd.h> | 12 #include <unistd.h> |
| 13 | 13 |
| 14 #include <map> | 14 #include <map> |
| 15 #include <memory> | 15 #include <memory> |
| 16 #include <set> | 16 #include <set> |
| 17 #include <vector> | 17 #include <vector> |
| 18 | 18 |
| 19 // Xlib defines RootWindow | 19 // Xlib defines RootWindow |
| 20 #undef RootWindow | 20 #undef RootWindow |
| 21 | 21 |
| 22 #include "base/logging.h" | 22 #include "base/logging.h" |
| 23 #include "base/message_loop/message_loop.h" | 23 #include "base/message_loop/message_loop.h" |
| 24 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
| 25 #include "base/strings/sys_string_conversions.h" | 25 #include "base/strings/sys_string_conversions.h" |
| 26 #include "base/strings/utf_string_conversions.h" | 26 #include "base/strings/utf_string_conversions.h" |
| 27 #include "base/threading/thread.h" | 27 #include "base/threading/thread.h" |
| 28 #include "base/threading/thread_restrictions.h" | 28 #include "base/threading/thread_restrictions.h" |
| 29 #include "chrome/browser/ui/libgtkui/gtk2_signal.h" | 29 #include "chrome/browser/ui/libgtkui/gtk_signal.h" |
| 30 #include "chrome/browser/ui/libgtkui/gtk2_util.h" | 30 #include "chrome/browser/ui/libgtkui/gtk_util.h" |
| 31 #include "chrome/browser/ui/libgtkui/select_file_dialog_impl.h" | 31 #include "chrome/browser/ui/libgtkui/select_file_dialog_impl.h" |
| 32 #include "ui/aura/window_observer.h" | 32 #include "ui/aura/window_observer.h" |
| 33 #include "ui/base/l10n/l10n_util.h" | 33 #include "ui/base/l10n/l10n_util.h" |
| 34 #include "ui/events/platform/x11/x11_event_source.h" | 34 #include "ui/events/platform/x11/x11_event_source.h" |
| 35 #include "ui/shell_dialogs/select_file_dialog.h" | 35 #include "ui/shell_dialogs/select_file_dialog.h" |
| 36 #include "ui/strings/grit/ui_strings.h" | 36 #include "ui/strings/grit/ui_strings.h" |
| 37 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" | 37 #include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h" |
| 38 | 38 |
| 39 namespace { | 39 namespace { |
| 40 | 40 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 62 | 62 |
| 63 // The size of the preview we display for selected image files. We set height | 63 // The size of the preview we display for selected image files. We set height |
| 64 // larger than width because generally there is more free space vertically | 64 // larger than width because generally there is more free space vertically |
| 65 // than horiztonally (setting the preview image will alway expand the width of | 65 // than horiztonally (setting the preview image will alway expand the width of |
| 66 // the dialog, but usually not the height). The image's aspect ratio will always | 66 // the dialog, but usually not the height). The image's aspect ratio will always |
| 67 // be preserved. | 67 // be preserved. |
| 68 static const int kPreviewWidth = 256; | 68 static const int kPreviewWidth = 256; |
| 69 static const int kPreviewHeight = 512; | 69 static const int kPreviewHeight = 512; |
| 70 | 70 |
| 71 SelectFileDialogImpl* SelectFileDialogImpl::NewSelectFileDialogImplGTK( | 71 SelectFileDialogImpl* SelectFileDialogImpl::NewSelectFileDialogImplGTK( |
| 72 Listener* listener, ui::SelectFilePolicy* policy) { | 72 Listener* listener, |
| 73 ui::SelectFilePolicy* policy) { |
| 73 return new SelectFileDialogImplGTK(listener, policy); | 74 return new SelectFileDialogImplGTK(listener, policy); |
| 74 } | 75 } |
| 75 | 76 |
| 76 SelectFileDialogImplGTK::SelectFileDialogImplGTK(Listener* listener, | 77 SelectFileDialogImplGTK::SelectFileDialogImplGTK(Listener* listener, |
| 77 ui::SelectFilePolicy* policy) | 78 ui::SelectFilePolicy* policy) |
| 78 : SelectFileDialogImpl(listener, policy), | 79 : SelectFileDialogImpl(listener, policy), preview_(NULL) {} |
| 79 preview_(NULL) { | |
| 80 } | |
| 81 | 80 |
| 82 SelectFileDialogImplGTK::~SelectFileDialogImplGTK() { | 81 SelectFileDialogImplGTK::~SelectFileDialogImplGTK() { |
| 83 for (std::set<aura::Window*>::iterator iter = parents_.begin(); | 82 for (std::set<aura::Window*>::iterator iter = parents_.begin(); |
| 84 iter != parents_.end(); ++iter) { | 83 iter != parents_.end(); ++iter) { |
| 85 (*iter)->RemoveObserver(this); | 84 (*iter)->RemoveObserver(this); |
| 86 } | 85 } |
| 87 while (dialogs_.begin() != dialogs_.end()) { | 86 while (dialogs_.begin() != dialogs_.end()) { |
| 88 gtk_widget_destroy(*(dialogs_.begin())); | 87 gtk_widget_destroy(*(dialogs_.begin())); |
| 89 } | 88 } |
| 90 } | 89 } |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 switch (type) { | 138 switch (type) { |
| 140 case SELECT_FOLDER: | 139 case SELECT_FOLDER: |
| 141 case SELECT_UPLOAD_FOLDER: | 140 case SELECT_UPLOAD_FOLDER: |
| 142 dialog = CreateSelectFolderDialog(type, title_string, default_path, | 141 dialog = CreateSelectFolderDialog(type, title_string, default_path, |
| 143 owning_window); | 142 owning_window); |
| 144 break; | 143 break; |
| 145 case SELECT_OPEN_FILE: | 144 case SELECT_OPEN_FILE: |
| 146 dialog = CreateFileOpenDialog(title_string, default_path, owning_window); | 145 dialog = CreateFileOpenDialog(title_string, default_path, owning_window); |
| 147 break; | 146 break; |
| 148 case SELECT_OPEN_MULTI_FILE: | 147 case SELECT_OPEN_MULTI_FILE: |
| 149 dialog = CreateMultiFileOpenDialog(title_string, default_path, | 148 dialog = |
| 150 owning_window); | 149 CreateMultiFileOpenDialog(title_string, default_path, owning_window); |
| 151 break; | 150 break; |
| 152 case SELECT_SAVEAS_FILE: | 151 case SELECT_SAVEAS_FILE: |
| 153 dialog = CreateSaveAsDialog(title_string, default_path, owning_window); | 152 dialog = CreateSaveAsDialog(title_string, default_path, owning_window); |
| 154 break; | 153 break; |
| 155 default: | 154 default: |
| 156 NOTREACHED(); | 155 NOTREACHED(); |
| 157 return; | 156 return; |
| 158 } | 157 } |
| 159 g_signal_connect(dialog, "delete-event", | 158 g_signal_connect(dialog, "delete-event", |
| 160 G_CALLBACK(gtk_widget_hide_on_delete), NULL); | 159 G_CALLBACK(gtk_widget_hide_on_delete), NULL); |
| 161 dialogs_.insert(dialog); | 160 dialogs_.insert(dialog); |
| 162 | 161 |
| 163 preview_ = gtk_image_new(); | 162 preview_ = gtk_image_new(); |
| 164 g_signal_connect(dialog, "destroy", | 163 g_signal_connect(dialog, "destroy", G_CALLBACK(OnFileChooserDestroyThunk), |
| 165 G_CALLBACK(OnFileChooserDestroyThunk), this); | 164 this); |
| 166 g_signal_connect(dialog, "update-preview", | 165 g_signal_connect(dialog, "update-preview", G_CALLBACK(OnUpdatePreviewThunk), |
| 167 G_CALLBACK(OnUpdatePreviewThunk), this); | 166 this); |
| 168 gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); | 167 gtk_file_chooser_set_preview_widget(GTK_FILE_CHOOSER(dialog), preview_); |
| 169 | 168 |
| 170 params_map_[dialog] = params; | 169 params_map_[dialog] = params; |
| 171 | 170 |
| 172 // Disable input events handling in the host window to make this dialog modal. | 171 // Disable input events handling in the host window to make this dialog modal. |
| 173 if (owning_window) { | 172 if (owning_window) { |
| 174 aura::WindowTreeHost* host = owning_window->GetHost(); | 173 aura::WindowTreeHost* host = owning_window->GetHost(); |
| 175 if (host) { | 174 if (host) { |
| 176 std::unique_ptr<base::Closure> callback = | 175 std::unique_ptr<base::Closure> callback = |
| 177 views::DesktopWindowTreeHostX11::GetHostForXID( | 176 views::DesktopWindowTreeHostX11::GetHostForXID( |
| 178 host->GetAcceleratedWidget())->DisableEventListening( | 177 host->GetAcceleratedWidget()) |
| 179 GDK_WINDOW_XID(gtk_widget_get_window(dialog))); | 178 ->DisableEventListening( |
| 179 GDK_WINDOW_XID(gtk_widget_get_window(dialog))); |
| 180 // OnFilePickerDestroy() is called when |dialog| destroyed, which allows | 180 // OnFilePickerDestroy() is called when |dialog| destroyed, which allows |
| 181 // to invoke the callback function to re-enable event handling on the | 181 // to invoke the callback function to re-enable event handling on the |
| 182 // owning window. | 182 // owning window. |
| 183 g_object_set_data_full(G_OBJECT(dialog), "callback", callback.release(), | 183 g_object_set_data_full( |
| 184 G_OBJECT(dialog), "callback", callback.release(), |
| 184 reinterpret_cast<GDestroyNotify>(OnFilePickerDestroy)); | 185 reinterpret_cast<GDestroyNotify>(OnFilePickerDestroy)); |
| 185 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); | 186 gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); |
| 186 } | 187 } |
| 187 } | 188 } |
| 188 | 189 |
| 189 gtk_widget_show_all(dialog); | 190 gtk_widget_show_all(dialog); |
| 190 | 191 |
| 191 // We need to call gtk_window_present after making the widgets visible to make | 192 // We need to call gtk_window_present after making the widgets visible to make |
| 192 // sure window gets correctly raised and gets focus. | 193 // sure window gets correctly raised and gets focus. |
| 193 gtk_window_present_with_time( | 194 gtk_window_present_with_time( |
| 194 GTK_WINDOW(dialog), ui::X11EventSource::GetInstance()->GetTimestamp()); | 195 GTK_WINDOW(dialog), ui::X11EventSource::GetInstance()->GetTimestamp()); |
| 195 } | 196 } |
| 196 | 197 |
| 197 void SelectFileDialogImplGTK::AddFilters(GtkFileChooser* chooser) { | 198 void SelectFileDialogImplGTK::AddFilters(GtkFileChooser* chooser) { |
| 198 for (size_t i = 0; i < file_types_.extensions.size(); ++i) { | 199 for (size_t i = 0; i < file_types_.extensions.size(); ++i) { |
| 199 GtkFileFilter* filter = NULL; | 200 GtkFileFilter* filter = NULL; |
| 200 std::set<std::string> fallback_labels; | 201 std::set<std::string> fallback_labels; |
| 201 | 202 |
| 202 for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) { | 203 for (size_t j = 0; j < file_types_.extensions[i].size(); ++j) { |
| 203 const std::string& current_extension = file_types_.extensions[i][j]; | 204 const std::string& current_extension = file_types_.extensions[i][j]; |
| 204 if (!current_extension.empty()) { | 205 if (!current_extension.empty()) { |
| 205 if (!filter) | 206 if (!filter) |
| 206 filter = gtk_file_filter_new(); | 207 filter = gtk_file_filter_new(); |
| 207 std::unique_ptr<std::string> file_extension( | 208 std::unique_ptr<std::string> file_extension( |
| 208 new std::string("." + current_extension)); | 209 new std::string("." + current_extension)); |
| 209 fallback_labels.insert(std::string("*").append(*file_extension)); | 210 fallback_labels.insert(std::string("*").append(*file_extension)); |
| 210 gtk_file_filter_add_custom( | 211 gtk_file_filter_add_custom( |
| 211 filter, | 212 filter, GTK_FILE_FILTER_FILENAME, |
| 212 GTK_FILE_FILTER_FILENAME, | |
| 213 reinterpret_cast<GtkFileFilterFunc>(FileFilterCaseInsensitive), | 213 reinterpret_cast<GtkFileFilterFunc>(FileFilterCaseInsensitive), |
| 214 file_extension.release(), | 214 file_extension.release(), |
| 215 reinterpret_cast<GDestroyNotify>(OnFileFilterDataDestroyed)); | 215 reinterpret_cast<GDestroyNotify>(OnFileFilterDataDestroyed)); |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 // We didn't find any non-empty extensions to filter on. | 218 // We didn't find any non-empty extensions to filter on. |
| 219 if (!filter) | 219 if (!filter) |
| 220 continue; | 220 continue; |
| 221 | 221 |
| 222 // The description vector may be blank, in which case we are supposed to | 222 // The description vector may be blank, in which case we are supposed to |
| 223 // use some sort of default description based on the filter. | 223 // use some sort of default description based on the filter. |
| 224 if (i < file_types_.extension_description_overrides.size()) { | 224 if (i < file_types_.extension_description_overrides.size()) { |
| 225 gtk_file_filter_set_name(filter, base::UTF16ToUTF8( | 225 gtk_file_filter_set_name( |
| 226 file_types_.extension_description_overrides[i]).c_str()); | 226 filter, |
| 227 base::UTF16ToUTF8(file_types_.extension_description_overrides[i]) |
| 228 .c_str()); |
| 227 } else { | 229 } else { |
| 228 // There is no system default filter description so we use | 230 // There is no system default filter description so we use |
| 229 // the extensions themselves if the description is blank. | 231 // the extensions themselves if the description is blank. |
| 230 std::vector<std::string> fallback_labels_vector(fallback_labels.begin(), | 232 std::vector<std::string> fallback_labels_vector(fallback_labels.begin(), |
| 231 fallback_labels.end()); | 233 fallback_labels.end()); |
| 232 std::string fallback_label = | 234 std::string fallback_label = |
| 233 base::JoinString(fallback_labels_vector, ","); | 235 base::JoinString(fallback_labels_vector, ","); |
| 234 gtk_file_filter_set_name(filter, fallback_label.c_str()); | 236 gtk_file_filter_set_name(filter, fallback_label.c_str()); |
| 235 } | 237 } |
| 236 | 238 |
| 237 gtk_file_chooser_add_filter(chooser, filter); | 239 gtk_file_chooser_add_filter(chooser, filter); |
| 238 if (i == file_type_index_ - 1) | 240 if (i == file_type_index_ - 1) |
| 239 gtk_file_chooser_set_filter(chooser, filter); | 241 gtk_file_chooser_set_filter(chooser, filter); |
| 240 } | 242 } |
| 241 | 243 |
| 242 // Add the *.* filter, but only if we have added other filters (otherwise it | 244 // Add the *.* filter, but only if we have added other filters (otherwise it |
| 243 // is implied). | 245 // is implied). |
| 244 if (file_types_.include_all_files && !file_types_.extensions.empty()) { | 246 if (file_types_.include_all_files && !file_types_.extensions.empty()) { |
| 245 GtkFileFilter* filter = gtk_file_filter_new(); | 247 GtkFileFilter* filter = gtk_file_filter_new(); |
| 246 gtk_file_filter_add_pattern(filter, "*"); | 248 gtk_file_filter_add_pattern(filter, "*"); |
| 247 gtk_file_filter_set_name(filter, | 249 gtk_file_filter_set_name( |
| 248 l10n_util::GetStringUTF8(IDS_SAVEAS_ALL_FILES).c_str()); | 250 filter, l10n_util::GetStringUTF8(IDS_SAVEAS_ALL_FILES).c_str()); |
| 249 gtk_file_chooser_add_filter(chooser, filter); | 251 gtk_file_chooser_add_filter(chooser, filter); |
| 250 } | 252 } |
| 251 } | 253 } |
| 252 | 254 |
| 253 void SelectFileDialogImplGTK::FileSelected(GtkWidget* dialog, | 255 void SelectFileDialogImplGTK::FileSelected(GtkWidget* dialog, |
| 254 const base::FilePath& path) { | 256 const base::FilePath& path) { |
| 255 if (type_ == SELECT_SAVEAS_FILE) { | 257 if (type_ == SELECT_SAVEAS_FILE) { |
| 256 *last_saved_path_ = path.DirName(); | 258 *last_saved_path_ = path.DirName(); |
| 257 } else if (type_ == SELECT_OPEN_FILE || type_ == SELECT_FOLDER || | 259 } else if (type_ == SELECT_OPEN_FILE || type_ == SELECT_FOLDER || |
| 258 type_ == SELECT_UPLOAD_FOLDER) { | 260 type_ == SELECT_UPLOAD_FOLDER) { |
| 259 *last_opened_path_ = path.DirName(); | 261 *last_opened_path_ = path.DirName(); |
| 260 } else { | 262 } else { |
| 261 NOTREACHED(); | 263 NOTREACHED(); |
| 262 } | 264 } |
| 263 | 265 |
| 264 if (listener_) { | 266 if (listener_) { |
| 265 GtkFileFilter* selected_filter = | 267 GtkFileFilter* selected_filter = |
| 266 gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog)); | 268 gtk_file_chooser_get_filter(GTK_FILE_CHOOSER(dialog)); |
| 267 GSList* filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog)); | 269 GSList* filters = gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog)); |
| 268 int idx = g_slist_index(filters, selected_filter); | 270 int idx = g_slist_index(filters, selected_filter); |
| 269 g_slist_free(filters); | 271 g_slist_free(filters); |
| 270 listener_->FileSelected(path, idx + 1, PopParamsForDialog(dialog)); | 272 listener_->FileSelected(path, idx + 1, PopParamsForDialog(dialog)); |
| 271 } | 273 } |
| 272 gtk_widget_destroy(dialog); | 274 gtk_widget_destroy(dialog); |
| 273 } | 275 } |
| 274 | 276 |
| 275 void SelectFileDialogImplGTK::MultiFilesSelected(GtkWidget* dialog, | 277 void SelectFileDialogImplGTK::MultiFilesSelected( |
| 278 GtkWidget* dialog, |
| 276 const std::vector<base::FilePath>& files) { | 279 const std::vector<base::FilePath>& files) { |
| 277 *last_opened_path_ = files[0].DirName(); | 280 *last_opened_path_ = files[0].DirName(); |
| 278 | 281 |
| 279 if (listener_) | 282 if (listener_) |
| 280 listener_->MultiFilesSelected(files, PopParamsForDialog(dialog)); | 283 listener_->MultiFilesSelected(files, PopParamsForDialog(dialog)); |
| 281 gtk_widget_destroy(dialog); | 284 gtk_widget_destroy(dialog); |
| 282 } | 285 } |
| 283 | 286 |
| 284 void SelectFileDialogImplGTK::FileNotSelected(GtkWidget* dialog) { | 287 void SelectFileDialogImplGTK::FileNotSelected(GtkWidget* dialog) { |
| 285 void* params = PopParamsForDialog(dialog); | 288 void* params = PopParamsForDialog(dialog); |
| 286 if (listener_) | 289 if (listener_) |
| 287 listener_->FileSelectionCanceled(params); | 290 listener_->FileSelectionCanceled(params); |
| 288 gtk_widget_destroy(dialog); | 291 gtk_widget_destroy(dialog); |
| 289 } | 292 } |
| 290 | 293 |
| 291 GtkWidget* SelectFileDialogImplGTK::CreateFileOpenHelper( | 294 GtkWidget* SelectFileDialogImplGTK::CreateFileOpenHelper( |
| 292 const std::string& title, | 295 const std::string& title, |
| 293 const base::FilePath& default_path, | 296 const base::FilePath& default_path, |
| 294 gfx::NativeWindow parent) { | 297 gfx::NativeWindow parent) { |
| 295 GtkWidget* dialog = | 298 GtkWidget* dialog = gtk_file_chooser_dialog_new( |
| 296 gtk_file_chooser_dialog_new(title.c_str(), NULL, | 299 title.c_str(), NULL, GTK_FILE_CHOOSER_ACTION_OPEN, "_Cancel", |
| 297 GTK_FILE_CHOOSER_ACTION_OPEN, | 300 GTK_RESPONSE_CANCEL, "_Open", GTK_RESPONSE_ACCEPT, nullptr); |
| 298 "_Cancel", GTK_RESPONSE_CANCEL, | |
| 299 "_Open", GTK_RESPONSE_ACCEPT, | |
| 300 nullptr); | |
| 301 SetGtkTransientForAura(dialog, parent); | 301 SetGtkTransientForAura(dialog, parent); |
| 302 AddFilters(GTK_FILE_CHOOSER(dialog)); | 302 AddFilters(GTK_FILE_CHOOSER(dialog)); |
| 303 | 303 |
| 304 if (!default_path.empty()) { | 304 if (!default_path.empty()) { |
| 305 if (CallDirectoryExistsOnUIThread(default_path)) { | 305 if (CallDirectoryExistsOnUIThread(default_path)) { |
| 306 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 306 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
| 307 default_path.value().c_str()); | 307 default_path.value().c_str()); |
| 308 } else { | 308 } else { |
| 309 // If the file doesn't exist, this will just switch to the correct | 309 // If the file doesn't exist, this will just switch to the correct |
| 310 // directory. That's good enough. | 310 // directory. That's good enough. |
| 311 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), | 311 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), |
| 312 default_path.value().c_str()); | 312 default_path.value().c_str()); |
| 313 } | 313 } |
| 314 } else if (!last_opened_path_->empty()) { | 314 } else if (!last_opened_path_->empty()) { |
| 315 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 315 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
| 316 last_opened_path_->value().c_str()); | 316 last_opened_path_->value().c_str()); |
| 317 } | 317 } |
| 318 return dialog; | 318 return dialog; |
| 319 } | 319 } |
| 320 | 320 |
| 321 GtkWidget* SelectFileDialogImplGTK::CreateSelectFolderDialog( | 321 GtkWidget* SelectFileDialogImplGTK::CreateSelectFolderDialog( |
| 322 Type type, | 322 Type type, |
| 323 const std::string& title, | 323 const std::string& title, |
| 324 const base::FilePath& default_path, | 324 const base::FilePath& default_path, |
| 325 gfx::NativeWindow parent) { | 325 gfx::NativeWindow parent) { |
| 326 std::string title_string = title; | 326 std::string title_string = title; |
| 327 if (title_string.empty()) { | 327 if (title_string.empty()) { |
| 328 title_string = (type == SELECT_UPLOAD_FOLDER) ? | 328 title_string = |
| 329 l10n_util::GetStringUTF8(IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE) : | 329 (type == SELECT_UPLOAD_FOLDER) |
| 330 l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE); | 330 ? l10n_util::GetStringUTF8(IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE) |
| 331 : l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE); |
| 331 } | 332 } |
| 332 std::string accept_button_label = (type == SELECT_UPLOAD_FOLDER) ? | 333 std::string accept_button_label = |
| 333 l10n_util::GetStringUTF8(IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON) : | 334 (type == SELECT_UPLOAD_FOLDER) |
| 334 "_Open"; | 335 ? l10n_util::GetStringUTF8( |
| 336 IDS_SELECT_UPLOAD_FOLDER_DIALOG_UPLOAD_BUTTON) |
| 337 : "_Open"; |
| 335 | 338 |
| 336 GtkWidget* dialog = | 339 GtkWidget* dialog = gtk_file_chooser_dialog_new( |
| 337 gtk_file_chooser_dialog_new(title_string.c_str(), NULL, | 340 title_string.c_str(), NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, |
| 338 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER, | 341 "_Cancel", GTK_RESPONSE_CANCEL, accept_button_label.c_str(), |
| 339 "_Cancel", GTK_RESPONSE_CANCEL, | 342 GTK_RESPONSE_ACCEPT, nullptr); |
| 340 accept_button_label.c_str(), | |
| 341 GTK_RESPONSE_ACCEPT, | |
| 342 nullptr); | |
| 343 SetGtkTransientForAura(dialog, parent); | 343 SetGtkTransientForAura(dialog, parent); |
| 344 | 344 |
| 345 if (!default_path.empty()) { | 345 if (!default_path.empty()) { |
| 346 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), | 346 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), |
| 347 default_path.value().c_str()); | 347 default_path.value().c_str()); |
| 348 } else if (!last_opened_path_->empty()) { | 348 } else if (!last_opened_path_->empty()) { |
| 349 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 349 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
| 350 last_opened_path_->value().c_str()); | 350 last_opened_path_->value().c_str()); |
| 351 } | 351 } |
| 352 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); | 352 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); |
| 353 g_signal_connect(dialog, "response", | 353 g_signal_connect(dialog, "response", |
| 354 G_CALLBACK(OnSelectSingleFolderDialogResponseThunk), this); | 354 G_CALLBACK(OnSelectSingleFolderDialogResponseThunk), this); |
| 355 return dialog; | 355 return dialog; |
| 356 } | 356 } |
| 357 | 357 |
| 358 GtkWidget* SelectFileDialogImplGTK::CreateFileOpenDialog( | 358 GtkWidget* SelectFileDialogImplGTK::CreateFileOpenDialog( |
| 359 const std::string& title, | 359 const std::string& title, |
| 360 const base::FilePath& default_path, | 360 const base::FilePath& default_path, |
| 361 gfx::NativeWindow parent) { | 361 gfx::NativeWindow parent) { |
| 362 std::string title_string = !title.empty() ? title : | 362 std::string title_string = |
| 363 l10n_util::GetStringUTF8(IDS_OPEN_FILE_DIALOG_TITLE); | 363 !title.empty() ? title |
| 364 : l10n_util::GetStringUTF8(IDS_OPEN_FILE_DIALOG_TITLE); |
| 364 | 365 |
| 365 GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent); | 366 GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent); |
| 366 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); | 367 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); |
| 367 g_signal_connect(dialog, "response", | 368 g_signal_connect(dialog, "response", |
| 368 G_CALLBACK(OnSelectSingleFileDialogResponseThunk), this); | 369 G_CALLBACK(OnSelectSingleFileDialogResponseThunk), this); |
| 369 return dialog; | 370 return dialog; |
| 370 } | 371 } |
| 371 | 372 |
| 372 GtkWidget* SelectFileDialogImplGTK::CreateMultiFileOpenDialog( | 373 GtkWidget* SelectFileDialogImplGTK::CreateMultiFileOpenDialog( |
| 373 const std::string& title, | 374 const std::string& title, |
| 374 const base::FilePath& default_path, | 375 const base::FilePath& default_path, |
| 375 gfx::NativeWindow parent) { | 376 gfx::NativeWindow parent) { |
| 376 std::string title_string = !title.empty() ? title : | 377 std::string title_string = |
| 377 l10n_util::GetStringUTF8(IDS_OPEN_FILES_DIALOG_TITLE); | 378 !title.empty() ? title |
| 379 : l10n_util::GetStringUTF8(IDS_OPEN_FILES_DIALOG_TITLE); |
| 378 | 380 |
| 379 GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent); | 381 GtkWidget* dialog = CreateFileOpenHelper(title_string, default_path, parent); |
| 380 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); | 382 gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), TRUE); |
| 381 g_signal_connect(dialog, "response", | 383 g_signal_connect(dialog, "response", |
| 382 G_CALLBACK(OnSelectMultiFileDialogResponseThunk), this); | 384 G_CALLBACK(OnSelectMultiFileDialogResponseThunk), this); |
| 383 return dialog; | 385 return dialog; |
| 384 } | 386 } |
| 385 | 387 |
| 386 GtkWidget* SelectFileDialogImplGTK::CreateSaveAsDialog(const std::string& title, | 388 GtkWidget* SelectFileDialogImplGTK::CreateSaveAsDialog( |
| 387 const base::FilePath& default_path, gfx::NativeWindow parent) { | 389 const std::string& title, |
| 388 std::string title_string = !title.empty() ? title : | 390 const base::FilePath& default_path, |
| 389 l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE); | 391 gfx::NativeWindow parent) { |
| 392 std::string title_string = |
| 393 !title.empty() ? title |
| 394 : l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE); |
| 390 | 395 |
| 391 GtkWidget* dialog = | 396 GtkWidget* dialog = gtk_file_chooser_dialog_new( |
| 392 gtk_file_chooser_dialog_new(title_string.c_str(), NULL, | 397 title_string.c_str(), NULL, GTK_FILE_CHOOSER_ACTION_SAVE, "_Cancel", |
| 393 GTK_FILE_CHOOSER_ACTION_SAVE, | 398 GTK_RESPONSE_CANCEL, "_Save", GTK_RESPONSE_ACCEPT, nullptr); |
| 394 "_Cancel", GTK_RESPONSE_CANCEL, | |
| 395 "_Save", GTK_RESPONSE_ACCEPT, | |
| 396 nullptr); | |
| 397 SetGtkTransientForAura(dialog, parent); | 399 SetGtkTransientForAura(dialog, parent); |
| 398 | 400 |
| 399 AddFilters(GTK_FILE_CHOOSER(dialog)); | 401 AddFilters(GTK_FILE_CHOOSER(dialog)); |
| 400 if (!default_path.empty()) { | 402 if (!default_path.empty()) { |
| 401 if (CallDirectoryExistsOnUIThread(default_path)) { | 403 if (CallDirectoryExistsOnUIThread(default_path)) { |
| 402 // If this is an existing directory, navigate to that directory, with no | 404 // If this is an existing directory, navigate to that directory, with no |
| 403 // filename. | 405 // filename. |
| 404 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), | 406 gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), |
| 405 default_path.value().c_str()); | 407 default_path.value().c_str()); |
| 406 } else { | 408 } else { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 436 bool is_cancel = response_id == GTK_RESPONSE_CANCEL || | 438 bool is_cancel = response_id == GTK_RESPONSE_CANCEL || |
| 437 response_id == GTK_RESPONSE_DELETE_EVENT; | 439 response_id == GTK_RESPONSE_DELETE_EVENT; |
| 438 if (is_cancel) | 440 if (is_cancel) |
| 439 return true; | 441 return true; |
| 440 | 442 |
| 441 DCHECK(response_id == GTK_RESPONSE_ACCEPT); | 443 DCHECK(response_id == GTK_RESPONSE_ACCEPT); |
| 442 return false; | 444 return false; |
| 443 } | 445 } |
| 444 | 446 |
| 445 void SelectFileDialogImplGTK::SelectSingleFileHelper(GtkWidget* dialog, | 447 void SelectFileDialogImplGTK::SelectSingleFileHelper(GtkWidget* dialog, |
| 446 gint response_id, | 448 gint response_id, |
| 447 bool allow_folder) { | 449 bool allow_folder) { |
| 448 if (IsCancelResponse(response_id)) { | 450 if (IsCancelResponse(response_id)) { |
| 449 FileNotSelected(dialog); | 451 FileNotSelected(dialog); |
| 450 return; | 452 return; |
| 451 } | 453 } |
| 452 | 454 |
| 453 gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); | 455 gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); |
| 454 if (!filename) { | 456 if (!filename) { |
| 455 FileNotSelected(dialog); | 457 FileNotSelected(dialog); |
| 456 return; | 458 return; |
| 457 } | 459 } |
| 458 | 460 |
| 459 base::FilePath path(filename); | 461 base::FilePath path(filename); |
| 460 g_free(filename); | 462 g_free(filename); |
| 461 | 463 |
| 462 if (allow_folder) { | 464 if (allow_folder) { |
| 463 FileSelected(dialog, path); | 465 FileSelected(dialog, path); |
| 464 return; | 466 return; |
| 465 } | 467 } |
| 466 | 468 |
| 467 if (CallDirectoryExistsOnUIThread(path)) | 469 if (CallDirectoryExistsOnUIThread(path)) |
| 468 FileNotSelected(dialog); | 470 FileNotSelected(dialog); |
| 469 else | 471 else |
| 470 FileSelected(dialog, path); | 472 FileSelected(dialog, path); |
| 471 } | 473 } |
| 472 | 474 |
| 473 void SelectFileDialogImplGTK::OnSelectSingleFileDialogResponse( | 475 void SelectFileDialogImplGTK::OnSelectSingleFileDialogResponse( |
| 474 GtkWidget* dialog, int response_id) { | 476 GtkWidget* dialog, |
| 477 int response_id) { |
| 475 SelectSingleFileHelper(dialog, response_id, false); | 478 SelectSingleFileHelper(dialog, response_id, false); |
| 476 } | 479 } |
| 477 | 480 |
| 478 void SelectFileDialogImplGTK::OnSelectSingleFolderDialogResponse( | 481 void SelectFileDialogImplGTK::OnSelectSingleFolderDialogResponse( |
| 479 GtkWidget* dialog, int response_id) { | 482 GtkWidget* dialog, |
| 483 int response_id) { |
| 480 SelectSingleFileHelper(dialog, response_id, true); | 484 SelectSingleFileHelper(dialog, response_id, true); |
| 481 } | 485 } |
| 482 | 486 |
| 483 void SelectFileDialogImplGTK::OnSelectMultiFileDialogResponse(GtkWidget* dialog, | 487 void SelectFileDialogImplGTK::OnSelectMultiFileDialogResponse(GtkWidget* dialog, |
| 484 int response_id) { | 488 int response_id) { |
| 485 if (IsCancelResponse(response_id)) { | 489 if (IsCancelResponse(response_id)) { |
| 486 FileNotSelected(dialog); | 490 FileNotSelected(dialog); |
| 487 return; | 491 return; |
| 488 } | 492 } |
| 489 | 493 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 521 std::set<aura::Window*>::iterator iter = parents_.find(parent); | 525 std::set<aura::Window*>::iterator iter = parents_.find(parent); |
| 522 if (iter != parents_.end()) { | 526 if (iter != parents_.end()) { |
| 523 (*iter)->RemoveObserver(this); | 527 (*iter)->RemoveObserver(this); |
| 524 parents_.erase(iter); | 528 parents_.erase(iter); |
| 525 } else { | 529 } else { |
| 526 NOTREACHED(); | 530 NOTREACHED(); |
| 527 } | 531 } |
| 528 } | 532 } |
| 529 | 533 |
| 530 void SelectFileDialogImplGTK::OnUpdatePreview(GtkWidget* chooser) { | 534 void SelectFileDialogImplGTK::OnUpdatePreview(GtkWidget* chooser) { |
| 531 gchar* filename = gtk_file_chooser_get_preview_filename( | 535 gchar* filename = |
| 532 GTK_FILE_CHOOSER(chooser)); | 536 gtk_file_chooser_get_preview_filename(GTK_FILE_CHOOSER(chooser)); |
| 533 if (!filename) { | 537 if (!filename) { |
| 534 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), | 538 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), |
| 535 FALSE); | 539 FALSE); |
| 536 return; | 540 return; |
| 537 } | 541 } |
| 538 | 542 |
| 539 // Don't attempt to open anything which isn't a regular file. If a named pipe, | 543 // Don't attempt to open anything which isn't a regular file. If a named pipe, |
| 540 // this may hang. See https://crbug.com/534754. | 544 // this may hang. See https://crbug.com/534754. |
| 541 struct stat stat_buf; | 545 struct stat stat_buf; |
| 542 if (stat(filename, &stat_buf) != 0 || !S_ISREG(stat_buf.st_mode)) { | 546 if (stat(filename, &stat_buf) != 0 || !S_ISREG(stat_buf.st_mode)) { |
| 543 g_free(filename); | 547 g_free(filename); |
| 544 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), | 548 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), |
| 545 FALSE); | 549 FALSE); |
| 546 return; | 550 return; |
| 547 } | 551 } |
| 548 | 552 |
| 549 // This will preserve the image's aspect ratio. | 553 // This will preserve the image's aspect ratio. |
| 550 GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, | 554 GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_size(filename, kPreviewWidth, |
| 551 kPreviewHeight, NULL); | 555 kPreviewHeight, NULL); |
| 552 g_free(filename); | 556 g_free(filename); |
| 553 if (pixbuf) { | 557 if (pixbuf) { |
| 554 gtk_image_set_from_pixbuf(GTK_IMAGE(preview_), pixbuf); | 558 gtk_image_set_from_pixbuf(GTK_IMAGE(preview_), pixbuf); |
| 555 g_object_unref(pixbuf); | 559 g_object_unref(pixbuf); |
| 556 } | 560 } |
| 557 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), | 561 gtk_file_chooser_set_preview_widget_active(GTK_FILE_CHOOSER(chooser), |
| 558 pixbuf ? TRUE : FALSE); | 562 pixbuf ? TRUE : FALSE); |
| 559 } | 563 } |
| 560 | 564 |
| 561 } // namespace libgtkui | 565 } // namespace libgtkui |
| OLD | NEW |