diff options
-rw-r--r-- | chrome/browser/browser.h | 4 | ||||
-rw-r--r-- | chrome/browser/browser.scons | 1 | ||||
-rw-r--r-- | chrome/browser/download/download_manager.cc | 19 | ||||
-rw-r--r-- | chrome/browser/download/download_manager.h | 4 | ||||
-rw-r--r-- | chrome/browser/gtk/dialogs_gtk.cc | 182 | ||||
-rw-r--r-- | chrome/browser/shell_dialogs.h | 6 | ||||
-rw-r--r-- | chrome/browser/tab_contents/web_contents.h | 2 | ||||
-rw-r--r-- | chrome/common/temp_scaffolding_stubs.h | 2 |
8 files changed, 209 insertions, 11 deletions
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index 3c3bb7e..025a8e5 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -10,7 +10,7 @@ #include <set> #include <vector> -#if defined(OS_MACOSX) || defined(OS_LINUX) +#if defined(OS_MACOSX) // Remove when we've finished porting the supporting classes. #include "chrome/common/temp_scaffolding_stubs.h" #endif @@ -29,7 +29,7 @@ #include "base/task.h" #include "skia/include/SkBitmap.h" -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) #include "chrome/browser/shell_dialogs.h" #endif diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index a572a0b..70da7dc 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -747,6 +747,7 @@ if env.Bit('linux'): 'gtk/browser_window_factory_gtk.cc', 'gtk/browser_window_gtk.cc', 'gtk/custom_button.cc', + 'gtk/dialogs_gtk.cc', 'gtk/download_item_gtk.cc', 'gtk/download_shelf_gtk.cc', 'gtk/find_bar_gtk.cc', diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index 719efa0..98b0e32 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -45,6 +45,10 @@ #include "chrome/common/win_util.h" #endif +#if defined(OS_LINUX) +#include <gtk/gtk.h> +#endif + // Periodically update our observers. class DownloadItemUpdateTask : public Task { public: @@ -618,7 +622,7 @@ void DownloadManager::CheckIfSuggestedPathExists(DownloadCreateInfo* info) { } void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) DCHECK(MessageLoop::current() == ui_loop_); DCHECK(info); @@ -629,20 +633,27 @@ void DownloadManager::OnPathExistenceAvailable(DownloadCreateInfo* info) { WebContents* contents = tab_util::GetWebContentsByID( info->render_process_id, info->render_view_id); +#if defined(OS_WIN) std::wstring filter = win_util::GetFileFilterFromPath(info->suggested_path.value()); - HWND owning_hwnd = + gfx::NativeWindow owning_window = contents ? GetAncestor(contents->GetNativeView(), GA_ROOT) : NULL; +#elif defined(OS_LINUX) + std::wstring filter; + gfx::NativeWindow owning_window = contents ? + GTK_WINDOW(gtk_widget_get_toplevel(contents->GetNativeView())) : + NULL; +#endif select_file_dialog_->SelectFile(SelectFileDialog::SELECT_SAVEAS_FILE, std::wstring(), info->suggested_path.ToWStringHack(), filter, std::wstring(), - owning_hwnd, info); + owning_window, info); } else { // No prompting for download, just continue with the suggested name. ContinueStartDownload(info, info->suggested_path); } -#elif defined(OS_POSIX) +#elif defined(OS_MACOSX) // TODO(port): port this file -- need dialogs. NOTIMPLEMENTED(); #endif diff --git a/chrome/browser/download/download_manager.h b/chrome/browser/download/download_manager.h index de1f3ab..4a3125b 100644 --- a/chrome/browser/download/download_manager.h +++ b/chrome/browser/download/download_manager.h @@ -53,10 +53,10 @@ #include "chrome/browser/history/history.h" #include "chrome/common/pref_member.h" -#if defined(OS_WIN) +#if defined(OS_WIN) || defined(OS_LINUX) // TODO(port): port this header. #include "chrome/browser/shell_dialogs.h" -#elif defined(OS_POSIX) +#elif defined(OS_MACOSX) #include "chrome/common/temp_scaffolding_stubs.h" #endif diff --git a/chrome/browser/gtk/dialogs_gtk.cc b/chrome/browser/gtk/dialogs_gtk.cc new file mode 100644 index 0000000..c2d2f3f --- /dev/null +++ b/chrome/browser/gtk/dialogs_gtk.cc @@ -0,0 +1,182 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <gtk/gtk.h> +#include <map> +#include <set> + +#include "base/file_path.h" +#include "base/logging.h" +#include "base/string_util.h" +#include "chrome/browser/shell_dialogs.h" + +// Implementation of SelectFileDialog that shows a Gtk common dialog for +// choosing a file or folder. +// This acts as a modal dialog. Ideally we want to only act modally for the +// parent window and allow other toplevel chrome windows to still function while +// the dialog is showing, but we need the GtkWindowGroup or something similar to +// get that, and that API is only available in more recent versions of GTK. +// TODO(port): fix modality: crbug.com/8727 +class SelectFileDialogImpl : public SelectFileDialog { + public: + explicit SelectFileDialogImpl(Listener* listener); + virtual ~SelectFileDialogImpl(); + + // BaseShellDialog implementation. + virtual bool IsRunning(gfx::NativeWindow parent_window) const; + virtual void ListenerDestroyed(); + + // SelectFileDialog implementation. + // |params| is user data we pass back via the Listener interface. + virtual void SelectFile(Type type, const std::wstring& title, + const std::wstring& default_path, + const std::wstring& filter, + const std::wstring& default_extension, + gfx::NativeWindow parent_window, + void* params); + + private: + // Notifies the listener that a single file was chosen. + void FileSelected(GtkWidget* dialog, const FilePath& path); + + // Notifies the listener that no file was chosen (the action was canceled). + // Dialog is passed so we can find that |params| pointer that was passed to + // us when we were told to show the dialog. + void FileNotSelected(GtkWidget* dialog); + + // Removes and returns the |params| associated with |dialog| from + // |params_map_|. + void* PopParamsForDialog(GtkWidget* dialog); + + // Removes and returns the parent associated with |dialog| from |parents_|. + void RemoveParentForDialog(GtkWidget* dialog); + + // Callback for when the user cancels or closes the dialog. + static void OnSelectFileDialogResponse(GtkWidget* dialog, gint response_id, + SelectFileDialogImpl* dialog_impl); + + // The listener to be notified of selection completion. + Listener* listener_; + + // Our parent window. + gfx::NativeWindow parent_window_; + + // A map from dialog windows to the |params| user data associated with them. + std::map<GtkWidget*, void*> params_map_; + + // The set of all parent windows for which we are currently running dialogs. + std::set<GtkWindow*> parents_; + + DISALLOW_COPY_AND_ASSIGN(SelectFileDialogImpl); +}; + +// static +SelectFileDialog* SelectFileDialog::Create(Listener* listener) { + return new SelectFileDialogImpl(listener); +} + +SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener) + : listener_(listener) { +} + +SelectFileDialogImpl::~SelectFileDialogImpl() { +} + +bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const { + return parents_.find(parent_window) != parents_.end(); +} + +void SelectFileDialogImpl::ListenerDestroyed() { + listener_ = NULL; +} + +// We ignore |filter| and |default_extension|. +void SelectFileDialogImpl::SelectFile( + Type type, + const std::wstring& title, + const std::wstring& default_path, + const std::wstring& filter, + const std::wstring& default_extension, + gfx::NativeWindow parent_window, + void* params) { + // TODO(estade): on windows, parent_window may be null. But I'm not sure when + // that's used and how to deal with it here. For now, don't allow it. + DCHECK(parent_window); + parents_.insert(parent_window); + + if (type != SELECT_SAVEAS_FILE) { + NOTIMPLEMENTED(); + return; + } + + // TODO(port): get rid of these conversions when the parameter types are + // ported. + std::string title_string = WideToUTF8(title); + FilePath default_file_path = FilePath::FromWStringHack(default_path); + + GtkWidget* dialog = + gtk_file_chooser_dialog_new(title_string.c_str(), parent_window, + GTK_FILE_CHOOSER_ACTION_SAVE, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, + NULL); + params_map_[dialog] = params; + gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), + default_file_path.DirName().value().c_str()); + gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), + default_file_path.BaseName().value().c_str()); + gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE); + gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); + g_signal_connect(G_OBJECT(dialog), "response", + G_CALLBACK(OnSelectFileDialogResponse), this); + gtk_widget_show_all(dialog); +} + +void SelectFileDialogImpl::FileSelected(GtkWidget* dialog, + const FilePath& path) { + void* params = PopParamsForDialog(dialog); + if (listener_) + listener_->FileSelected(path.ToWStringHack(), params); + RemoveParentForDialog(dialog); + gtk_widget_destroy(dialog); +} + +void SelectFileDialogImpl::FileNotSelected(GtkWidget* dialog) { + void* params = PopParamsForDialog(dialog); + if (listener_) + listener_->FileSelectionCanceled(params); + RemoveParentForDialog(dialog); + gtk_widget_destroy(dialog); +} + +void* SelectFileDialogImpl::PopParamsForDialog(GtkWidget* dialog) { + std::map<GtkWidget*, void*>::iterator iter = params_map_.find(dialog); + DCHECK(iter != params_map_.end()); + void* params = iter->second; + params_map_.erase(iter); + return params; +} + +void SelectFileDialogImpl::RemoveParentForDialog(GtkWidget* dialog) { + GtkWindow* parent = gtk_window_get_transient_for(GTK_WINDOW(dialog)); + DCHECK(parent); + std::set<GtkWindow*>::iterator iter = parents_.find(parent); + DCHECK(iter != parents_.end()); + parents_.erase(iter); +} + +// static +void SelectFileDialogImpl::OnSelectFileDialogResponse( + GtkWidget* dialog, gint response_id, + SelectFileDialogImpl* dialog_impl) { + if (response_id == GTK_RESPONSE_CANCEL || + response_id == GTK_RESPONSE_DELETE_EVENT) { + dialog_impl->FileNotSelected(dialog); + return; + } + + DCHECK(response_id == GTK_RESPONSE_ACCEPT); + gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); + dialog_impl->FileSelected(dialog, FilePath(filename)); +} diff --git a/chrome/browser/shell_dialogs.h b/chrome/browser/shell_dialogs.h index bbc3bc7..d368a99 100644 --- a/chrome/browser/shell_dialogs.h +++ b/chrome/browser/shell_dialogs.h @@ -21,7 +21,7 @@ class BaseShellDialog { public: // Returns true if the a shell dialog box is currently being shown modally // to the specified owner. - virtual bool IsRunning(gfx::NativeView owning_window) const = 0; + virtual bool IsRunning(gfx::NativeWindow owning_window) const = 0; // Notifies the dialog box that the listener has been destroyed and it should // no longer be sent notifications. @@ -137,12 +137,12 @@ class SelectFontDialog // at a time (for obvious reasons). // TODO(beng): support specifying the default font selected in the list when // the dialog appears. - virtual void SelectFont(gfx::NativeView owning_window, + virtual void SelectFont(gfx::NativeWindow owning_window, void* params) = 0; // Same as above - also support specifying the default font selected in the // list when the dialog appears. - virtual void SelectFont(gfx::NativeView owning_window, + virtual void SelectFont(gfx::NativeWindow owning_window, void* params, const std::wstring& font_name, int font_size) = 0; diff --git a/chrome/browser/tab_contents/web_contents.h b/chrome/browser/tab_contents/web_contents.h index 37c4ef7..5a07b5f 100644 --- a/chrome/browser/tab_contents/web_contents.h +++ b/chrome/browser/tab_contents/web_contents.h @@ -29,6 +29,8 @@ #include "chrome/common/temp_scaffolding_stubs.h" #elif defined(OS_WIN) #include "chrome/browser/printing/print_view_manager.h" +#endif +#if defined(OS_LINUX) || defined(OS_WIN) #include "chrome/browser/shell_dialogs.h" #endif diff --git a/chrome/common/temp_scaffolding_stubs.h b/chrome/common/temp_scaffolding_stubs.h index 71c534d..bd8ee62 100644 --- a/chrome/common/temp_scaffolding_stubs.h +++ b/chrome/common/temp_scaffolding_stubs.h @@ -419,6 +419,7 @@ class FaviconStatus { GURL url_; }; +#if defined(OS_MACOSX) class SelectFileDialog : public base::RefCountedThreadSafe<SelectFileDialog> { public: enum Type { @@ -439,6 +440,7 @@ class SelectFileDialog : public base::RefCountedThreadSafe<SelectFileDialog> { return new SelectFileDialog; } }; +#endif class DockInfo { public: |