diff --git a/atom.gyp b/atom.gyp index cc83cc199d95..2142819702ed 100644 --- a/atom.gyp +++ b/atom.gyp @@ -184,6 +184,8 @@ 'atom/browser/web_view/web_view_manager.h', 'atom/browser/web_view/web_view_renderer_state.cc', 'atom/browser/web_view/web_view_renderer_state.h', + 'atom/browser/web_dialog_helper.cc', + 'atom/browser/web_dialog_helper.h', 'atom/browser/window_list.cc', 'atom/browser/window_list.h', 'atom/browser/window_list_observer.h', @@ -300,6 +302,10 @@ 'chromium_src/chrome/browser/speech/tts_platform.cc', 'chromium_src/chrome/browser/speech/tts_platform.h', 'chromium_src/chrome/browser/speech/tts_win.cc', + 'chromium_src/chrome/browser/ui/browser_dialogs.h', + 'chromium_src/chrome/browser/ui/cocoa/color_chooser_mac.mm', + 'chromium_src/chrome/browser/ui/views/color_chooser_aura.cc', + 'chromium_src/chrome/browser/ui/views/color_chooser_aura.h', 'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.cc', 'chromium_src/chrome/browser/ui/libgtk2ui/app_indicator_icon_menu.h', 'chromium_src/chrome/browser/ui/libgtk2ui/gtk2_status_icon.cc', @@ -326,6 +332,11 @@ 'chromium_src/library_loaders/libspeechd.h', '<@(native_mate_files)', ], + 'lib_sources_win': [ + 'chromium_src/chrome/browser/ui/views/color_chooser_dialog.cc', + 'chromium_src/chrome/browser/ui/views/color_chooser_dialog.h', + 'chromium_src/chrome/browser/ui/views/color_chooser_win.cc', + ], 'framework_sources': [ 'atom/app/atom_library_main.cc', 'atom/app/atom_library_main.h', @@ -545,6 +556,9 @@ ], 'conditions': [ ['OS=="win"', { + 'sources': [ + '<@(lib_sources_win)', + ], 'link_settings': { 'libraries': [ '-limm32.lib', diff --git a/atom/browser/atom_browser_client.h b/atom/browser/atom_browser_client.h index 9dc5e7de34b2..7b13f6ba5006 100644 --- a/atom/browser/atom_browser_client.h +++ b/atom/browser/atom_browser_client.h @@ -18,25 +18,24 @@ class AtomBrowserClient : public brightray::BrowserClient { protected: // content::ContentBrowserClient: - virtual void RenderProcessWillLaunch( - content::RenderProcessHost* host) OVERRIDE; - virtual content::SpeechRecognitionManagerDelegate* + void RenderProcessWillLaunch(content::RenderProcessHost* host) override; + content::SpeechRecognitionManagerDelegate* GetSpeechRecognitionManagerDelegate() override; - virtual content::AccessTokenStore* CreateAccessTokenStore() OVERRIDE; - virtual void OverrideWebkitPrefs(content::RenderViewHost* render_view_host, - const GURL& url, - content::WebPreferences* prefs) OVERRIDE; - virtual bool ShouldSwapBrowsingInstancesForNavigation( + content::AccessTokenStore* CreateAccessTokenStore() override; + void OverrideWebkitPrefs(content::RenderViewHost* render_view_host, + const GURL& url, + content::WebPreferences* prefs) override; + bool ShouldSwapBrowsingInstancesForNavigation( content::SiteInstance* site_instance, const GURL& current_url, - const GURL& new_url) OVERRIDE; - virtual std::string GetApplicationLocale() OVERRIDE; - virtual void AppendExtraCommandLineSwitches(base::CommandLine* command_line, - int child_process_id) OVERRIDE; + const GURL& new_url) override; + std::string GetApplicationLocale() override; + void AppendExtraCommandLineSwitches(base::CommandLine* command_line, + int child_process_id) override; private: - virtual brightray::BrowserMainParts* OverrideCreateBrowserMainParts( - const content::MainFunctionParams&) OVERRIDE; + brightray::BrowserMainParts* OverrideCreateBrowserMainParts( + const content::MainFunctionParams&) override; // The render process which would be swapped out soon. content::RenderProcessHost* dying_render_process_; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 01d2bc157e50..3a4a7437986c 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -12,6 +12,7 @@ #include "atom/browser/atom_javascript_dialog_manager.h" #include "atom/browser/browser.h" #include "atom/browser/ui/file_dialog.h" +#include "atom/browser/web_dialog_helper.h" #include "atom/browser/window_list.h" #include "atom/common/api/api_messages.h" #include "atom/common/atom_version.h" @@ -30,6 +31,7 @@ #include "brightray/browser/inspectable_web_contents.h" #include "brightray/browser/inspectable_web_contents_view.h" #include "chrome/browser/printing/print_view_manager_basic.h" +#include "chrome/browser/ui/browser_dialogs.h" #include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/invalidate_type.h" #include "content/public/browser/navigation_entry.h" @@ -483,6 +485,28 @@ void NativeWindow::BeforeUnloadFired(content::WebContents* tab, } } +content::ColorChooser* NativeWindow::OpenColorChooser( + content::WebContents* web_contents, + SkColor color, + const std::vector& suggestions) { + return chrome::ShowColorChooser(web_contents, color); +} + +void NativeWindow::RunFileChooser(content::WebContents* web_contents, + const content::FileChooserParams& params) { + if (!web_dialog_helper_) + web_dialog_helper_.reset(new WebDialogHelper(this)); + web_dialog_helper_->RunFileChooser(web_contents, params); +} + +void NativeWindow::EnumerateDirectory(content::WebContents* web_contents, + int request_id, + const base::FilePath& path) { + if (!web_dialog_helper_) + web_dialog_helper_.reset(new WebDialogHelper(this)); + web_dialog_helper_->EnumerateDirectory(web_contents, request_id, path); +} + void NativeWindow::RequestToLockMouse(content::WebContents* web_contents, bool user_gesture, bool last_unlocked_by_target) { diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index b19304924b00..7a21083ab301 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -51,6 +51,7 @@ namespace atom { class AtomJavaScriptDialogManager; struct DraggableRegion; +class WebDialogHelper; class NativeWindow : public brightray::DefaultWebContentsDelegate, public brightray::InspectableWebContentsDelegate, @@ -229,6 +230,15 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, void BeforeUnloadFired(content::WebContents* tab, bool proceed, bool* proceed_to_fire_unload) override; + content::ColorChooser* OpenColorChooser( + content::WebContents* web_contents, + SkColor color, + const std::vector& suggestions) override; + void RunFileChooser(content::WebContents* web_contents, + const content::FileChooserParams& params) override; + void EnumerateDirectory(content::WebContents* web_contents, + int request_id, + const base::FilePath& path) override; void RequestToLockMouse(content::WebContents* web_contents, bool user_gesture, bool last_unlocked_by_target) override; @@ -313,6 +323,7 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate, base::WeakPtrFactory weak_factory_; + scoped_ptr web_dialog_helper_; scoped_ptr dialog_manager_; // Notice that inspectable_web_contents_ must be placed after dialog_manager_, diff --git a/atom/browser/web_dialog_helper.cc b/atom/browser/web_dialog_helper.cc new file mode 100644 index 000000000000..df600c37f149 --- /dev/null +++ b/atom/browser/web_dialog_helper.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/web_dialog_helper.h" + +#include + +#include "atom/browser/ui/file_dialog.h" +#include "base/bind.h" +#include "base/files/file_enumerator.h" +#include "base/strings/utf_string_conversions.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/web_contents.h" +#include "ui/shell_dialogs/selected_file_info.h" + +namespace atom { + +WebDialogHelper::WebDialogHelper(NativeWindow* window) + : window_(window), + weak_factory_(this) { +} + +WebDialogHelper::~WebDialogHelper() { +} + +void WebDialogHelper::RunFileChooser(content::WebContents* web_contents, + const content::FileChooserParams& params) { + std::vector result; + if (params.mode == content::FileChooserParams::Save) { + base::FilePath path; + if (file_dialog::ShowSaveDialog(window_, + base::UTF16ToUTF8(params.title), + params.default_file_name, + file_dialog::Filters(), + &path)) + result.push_back(ui::SelectedFileInfo(path, path)); + } else { + int flags = file_dialog::FILE_DIALOG_CREATE_DIRECTORY; + switch (params.mode) { + case content::FileChooserParams::OpenMultiple: + flags |= file_dialog::FILE_DIALOG_MULTI_SELECTIONS; + case content::FileChooserParams::Open: + flags |= file_dialog::FILE_DIALOG_OPEN_FILE; + break; + case content::FileChooserParams::UploadFolder: + flags |= file_dialog::FILE_DIALOG_OPEN_DIRECTORY; + break; + default: + NOTREACHED(); + } + + std::vector paths; + if (file_dialog::ShowOpenDialog(window_, + base::UTF16ToUTF8(params.title), + params.default_file_name, + file_dialog::Filters(), + flags, + &paths)) + for (auto& path : paths) + result.push_back(ui::SelectedFileInfo(path, path)); + } + + web_contents->GetRenderViewHost()->FilesSelectedInChooser( + result, params.mode); +} + +void WebDialogHelper::EnumerateDirectory(content::WebContents* web_contents, + int request_id, + const base::FilePath& dir) { + int types = base::FileEnumerator::FILES | + base::FileEnumerator::DIRECTORIES | + base::FileEnumerator::INCLUDE_DOT_DOT; + base::FileEnumerator file_enum(dir, false, types); + + base::FilePath path; + std::vector paths; + while (!(path = file_enum.Next()).empty()) + paths.push_back(path); + + web_contents->GetRenderViewHost()->DirectoryEnumerationFinished( + request_id, paths); +} + +} // namespace atom diff --git a/atom/browser/web_dialog_helper.h b/atom/browser/web_dialog_helper.h new file mode 100644 index 000000000000..a3472da4acbb --- /dev/null +++ b/atom/browser/web_dialog_helper.h @@ -0,0 +1,44 @@ +// Copyright (c) 2014 GitHub, Inc. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_WEB_DIALOG_HELPER_H_ +#define ATOM_BROWSER_WEB_DIALOG_HELPER_H_ + +#include "base/memory/weak_ptr.h" + +namespace base { +class FilePath; +} + +namespace content { +struct FileChooserParams; +class WebContents; +} + +namespace atom { + +class NativeWindow; + +class WebDialogHelper { + public: + explicit WebDialogHelper(NativeWindow* window); + ~WebDialogHelper(); + + void RunFileChooser(content::WebContents* web_contents, + const content::FileChooserParams& params); + void EnumerateDirectory(content::WebContents* web_contents, + int request_id, + const base::FilePath& path); + + private: + NativeWindow* window_; + + base::WeakPtrFactory weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(WebDialogHelper); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_WEB_DIALOG_HELPER_H_ diff --git a/chromium_src/chrome/browser/ui/browser_dialogs.h b/chromium_src/chrome/browser/ui/browser_dialogs.h new file mode 100644 index 000000000000..76d6e00a4fa4 --- /dev/null +++ b/chromium_src/chrome/browser/ui/browser_dialogs.h @@ -0,0 +1,26 @@ +// Copyright (c) 2012 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. + +#ifndef CHROME_BROWSER_UI_BROWSER_DIALOGS_H_ +#define CHROME_BROWSER_UI_BROWSER_DIALOGS_H_ + +#include "third_party/skia/include/core/SkColor.h" +#include "ui/gfx/native_widget_types.h" + +class SkBitmap; + +namespace content { +class ColorChooser; +class WebContents; +} + +namespace chrome { + +// Shows a color chooser that reports to the given WebContents. +content::ColorChooser* ShowColorChooser(content::WebContents* web_contents, + SkColor initial_color); + +} // namespace chrome + +#endif // CHROME_BROWSER_UI_BROWSER_DIALOGS_H_ diff --git a/chromium_src/chrome/browser/ui/cocoa/color_chooser_mac.mm b/chromium_src/chrome/browser/ui/cocoa/color_chooser_mac.mm new file mode 100644 index 000000000000..f2ce552bfcc3 --- /dev/null +++ b/chromium_src/chrome/browser/ui/cocoa/color_chooser_mac.mm @@ -0,0 +1,161 @@ +// Copyright (c) 2012 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. + +#import + +#include "base/logging.h" +#import "base/mac/scoped_nsobject.h" +#include "chrome/browser/ui/browser_dialogs.h" +#include "content/public/browser/color_chooser.h" +#include "content/public/browser/web_contents.h" +#include "skia/ext/skia_utils_mac.h" + +class ColorChooserMac; + +// A Listener class to act as a event target for NSColorPanel and send +// the results to the C++ class, ColorChooserMac. +@interface ColorPanelCocoa : NSObject { + @private + // We don't call DidChooseColor if the change wasn't caused by the user + // interacting with the panel. + BOOL nonUserChange_; + ColorChooserMac* chooser_; // weak, owns this +} + +- (id)initWithChooser:(ColorChooserMac*)chooser; + +// Called from NSColorPanel. +- (void)didChooseColor:(NSColorPanel*)panel; + +// Sets color to the NSColorPanel as a non user change. +- (void)setColor:(NSColor*)color; + +@end + +class ColorChooserMac : public content::ColorChooser { + public: + static ColorChooserMac* Open(content::WebContents* web_contents, + SkColor initial_color); + + ColorChooserMac(content::WebContents* tab, SkColor initial_color); + virtual ~ColorChooserMac(); + + // Called from ColorPanelCocoa. + void DidChooseColorInColorPanel(SkColor color); + void DidCloseColorPabel(); + + virtual void End() OVERRIDE; + virtual void SetSelectedColor(SkColor color) OVERRIDE; + + private: + static ColorChooserMac* current_color_chooser_; + + // The web contents invoking the color chooser. No ownership because it will + // outlive this class. + content::WebContents* web_contents_; + base::scoped_nsobject panel_; +}; + +ColorChooserMac* ColorChooserMac::current_color_chooser_ = NULL; + +// static +ColorChooserMac* ColorChooserMac::Open(content::WebContents* web_contents, + SkColor initial_color) { + if (current_color_chooser_) + current_color_chooser_->End(); + DCHECK(!current_color_chooser_); + current_color_chooser_ = + new ColorChooserMac(web_contents, initial_color); + return current_color_chooser_; +} + +ColorChooserMac::ColorChooserMac(content::WebContents* web_contents, + SkColor initial_color) + : web_contents_(web_contents) { + panel_.reset([[ColorPanelCocoa alloc] initWithChooser:this]); + [panel_ setColor:gfx::SkColorToDeviceNSColor(initial_color)]; + [[NSColorPanel sharedColorPanel] makeKeyAndOrderFront:nil]; +} + +ColorChooserMac::~ColorChooserMac() { + // Always call End() before destroying. + DCHECK(!panel_); +} + +void ColorChooserMac::DidChooseColorInColorPanel(SkColor color) { + if (web_contents_) + web_contents_->DidChooseColorInColorChooser(color); +} + +void ColorChooserMac::DidCloseColorPabel() { + End(); +} + +void ColorChooserMac::End() { + panel_.reset(); + DCHECK(current_color_chooser_ == this); + current_color_chooser_ = NULL; + if (web_contents_) + web_contents_->DidEndColorChooser(); +} + +void ColorChooserMac::SetSelectedColor(SkColor color) { + [panel_ setColor:gfx::SkColorToDeviceNSColor(color)]; +} + +@implementation ColorPanelCocoa + +- (id)initWithChooser:(ColorChooserMac*)chooser { + if ((self = [super init])) { + chooser_ = chooser; + NSColorPanel* panel = [NSColorPanel sharedColorPanel]; + [panel setShowsAlpha:NO]; + [panel setDelegate:self]; + [panel setTarget:self]; + [panel setAction:@selector(didChooseColor:)]; + } + return self; +} + +- (void)dealloc { + NSColorPanel* panel = [NSColorPanel sharedColorPanel]; + if ([panel delegate] == self) { + [panel setDelegate:nil]; + [panel setTarget:nil]; + [panel setAction:nil]; + } + + [super dealloc]; +} + +- (void)windowWillClose:(NSNotification*)notification { + nonUserChange_ = NO; + chooser_->DidCloseColorPabel(); +} + +- (void)didChooseColor:(NSColorPanel*)panel { + if (nonUserChange_) { + nonUserChange_ = NO; + return; + } + chooser_->DidChooseColorInColorPanel(gfx::NSDeviceColorToSkColor( + [[panel color] colorUsingColorSpaceName:NSDeviceRGBColorSpace])); + nonUserChange_ = NO; +} + +- (void)setColor:(NSColor*)color { + nonUserChange_ = YES; + [[NSColorPanel sharedColorPanel] setColor:color]; +} + +namespace chrome { + +content::ColorChooser* ShowColorChooser(content::WebContents* web_contents, + SkColor initial_color) { + return ColorChooserMac::Open(web_contents, initial_color); +} + +} // namepace chrome + +@end diff --git a/chromium_src/chrome/browser/ui/views/color_chooser_aura.cc b/chromium_src/chrome/browser/ui/views/color_chooser_aura.cc new file mode 100644 index 000000000000..95bdb7c46d94 --- /dev/null +++ b/chromium_src/chrome/browser/ui/views/color_chooser_aura.cc @@ -0,0 +1,69 @@ +// Copyright (c) 2012 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 "chrome/browser/ui/views/color_chooser_aura.h" + +#include "chrome/browser/ui/browser_dialogs.h" +#include "content/public/browser/web_contents.h" +#include "ui/views/color_chooser/color_chooser_view.h" +#include "ui/views/widget/widget.h" + +ColorChooserAura::ColorChooserAura(content::WebContents* web_contents, + SkColor initial_color) + : web_contents_(web_contents) { + view_ = new views::ColorChooserView(this, initial_color); + widget_ = views::Widget::CreateWindowWithParent( + view_, web_contents->GetTopLevelNativeWindow()); + widget_->Show(); +} + +void ColorChooserAura::OnColorChosen(SkColor color) { + if (web_contents_) + web_contents_->DidChooseColorInColorChooser(color); +} + +void ColorChooserAura::OnColorChooserDialogClosed() { + view_ = NULL; + widget_ = NULL; + DidEndColorChooser(); +} + +void ColorChooserAura::End() { + if (widget_) { + view_->set_listener(NULL); + widget_->Close(); + view_ = NULL; + widget_ = NULL; + // DidEndColorChooser will invoke Browser::DidEndColorChooser, which deletes + // this. Take care of the call order. + DidEndColorChooser(); + } +} + +void ColorChooserAura::DidEndColorChooser() { + if (web_contents_) + web_contents_->DidEndColorChooser(); +} + +void ColorChooserAura::SetSelectedColor(SkColor color) { + if (view_) + view_->OnColorChanged(color); +} + +// static +ColorChooserAura* ColorChooserAura::Open( + content::WebContents* web_contents, SkColor initial_color) { + return new ColorChooserAura(web_contents, initial_color); +} + +#if !defined(OS_WIN) +namespace chrome { + +content::ColorChooser* ShowColorChooser(content::WebContents* web_contents, + SkColor initial_color) { + return ColorChooserAura::Open(web_contents, initial_color); +} + +} // namespace chrome +#endif // OS_WIN diff --git a/chromium_src/chrome/browser/ui/views/color_chooser_aura.h b/chromium_src/chrome/browser/ui/views/color_chooser_aura.h new file mode 100644 index 000000000000..cb33d6a3983e --- /dev/null +++ b/chromium_src/chrome/browser/ui/views/color_chooser_aura.h @@ -0,0 +1,58 @@ +// Copyright 2013 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. + +#ifndef CHROME_BROWSER_UI_VIEWS_COLOR_CHOOSER_AURA_H_ +#define CHROME_BROWSER_UI_VIEWS_COLOR_CHOOSER_AURA_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "content/public/browser/color_chooser.h" +#include "ui/views/color_chooser/color_chooser_listener.h" + +namespace content { +class WebContents; +} + +namespace views { +class ColorChooserView; +class Widget; +} + +// TODO(mukai): rename this as -Ash and move to c/b/ui/ash after Linux-aura +// switches to its native color chooser. +class ColorChooserAura : public content::ColorChooser, + public views::ColorChooserListener { + public: + static ColorChooserAura* Open(content::WebContents* web_contents, + SkColor initial_color); + + private: + ColorChooserAura(content::WebContents* web_contents, SkColor initial_color); + + // content::ColorChooser overrides: + virtual void End() OVERRIDE; + virtual void SetSelectedColor(SkColor color) OVERRIDE; + + // views::ColorChooserListener overrides: + virtual void OnColorChosen(SkColor color) OVERRIDE; + virtual void OnColorChooserDialogClosed() OVERRIDE; + + void DidEndColorChooser(); + + // The actual view of the color chooser. No ownership because its parent + // view will take care of its lifetime. + views::ColorChooserView* view_; + + // The widget for the color chooser. No ownership because it's released + // automatically when closed. + views::Widget* widget_; + + // The web contents invoking the color chooser. No ownership because it will + // outlive this class. + content::WebContents* web_contents_; + + DISALLOW_COPY_AND_ASSIGN(ColorChooserAura); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_COLOR_CHOOSER_AURA_H_ diff --git a/chromium_src/chrome/browser/ui/views/color_chooser_dialog.cc b/chromium_src/chrome/browser/ui/views/color_chooser_dialog.cc new file mode 100644 index 000000000000..347f1043aac1 --- /dev/null +++ b/chromium_src/chrome/browser/ui/views/color_chooser_dialog.cc @@ -0,0 +1,85 @@ +// Copyright (c) 2012 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 "chrome/browser/ui/views/color_chooser_dialog.h" + +#include + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/threading/thread.h" +#include "content/public/browser/browser_thread.h" +#include "skia/ext/skia_utils_win.h" +#include "ui/views/color_chooser/color_chooser_listener.h" +#include "ui/views/win/hwnd_util.h" + +using content::BrowserThread; + +// static +COLORREF ColorChooserDialog::g_custom_colors[16]; + +ColorChooserDialog::ExecuteOpenParams::ExecuteOpenParams(SkColor color, + RunState run_state, + HWND owner) + : color(color), + run_state(run_state), + owner(owner) { +} + +ColorChooserDialog::ColorChooserDialog(views::ColorChooserListener* listener, + SkColor initial_color, + gfx::NativeWindow owning_window) + : listener_(listener) { + DCHECK(listener_); + CopyCustomColors(g_custom_colors, custom_colors_); + HWND owning_hwnd = views::HWNDForNativeWindow(owning_window); + ExecuteOpenParams execute_params(initial_color, BeginRun(owning_hwnd), + owning_hwnd); + execute_params.run_state.dialog_thread->message_loop()->PostTask(FROM_HERE, + base::Bind(&ColorChooserDialog::ExecuteOpen, this, execute_params)); +} + +ColorChooserDialog::~ColorChooserDialog() { +} + +bool ColorChooserDialog::IsRunning(gfx::NativeWindow owning_window) const { + return listener_ && IsRunningDialogForOwner( + views::HWNDForNativeWindow(owning_window)); +} + +void ColorChooserDialog::ListenerDestroyed() { + // Our associated listener has gone away, so we shouldn't call back to it if + // our worker thread returns after the listener is dead. + listener_ = NULL; +} + +void ColorChooserDialog::ExecuteOpen(const ExecuteOpenParams& params) { + CHOOSECOLOR cc; + cc.lStructSize = sizeof(CHOOSECOLOR); + cc.hwndOwner = params.owner; + cc.rgbResult = skia::SkColorToCOLORREF(params.color); + cc.lpCustColors = custom_colors_; + cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT; + bool success = !!ChooseColor(&cc); + DisableOwner(cc.hwndOwner); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&ColorChooserDialog::DidCloseDialog, this, success, + skia::COLORREFToSkColor(cc.rgbResult), params.run_state)); +} + +void ColorChooserDialog::DidCloseDialog(bool chose_color, + SkColor color, + RunState run_state) { + EndRun(run_state); + CopyCustomColors(custom_colors_, g_custom_colors); + if (listener_) { + if (chose_color) + listener_->OnColorChosen(color); + listener_->OnColorChooserDialogClosed(); + } +} + +void ColorChooserDialog::CopyCustomColors(COLORREF* src, COLORREF* dst) { + memcpy(dst, src, sizeof(COLORREF) * arraysize(g_custom_colors)); +} diff --git a/chromium_src/chrome/browser/ui/views/color_chooser_dialog.h b/chromium_src/chrome/browser/ui/views/color_chooser_dialog.h new file mode 100644 index 000000000000..8f2e6ffc8faa --- /dev/null +++ b/chromium_src/chrome/browser/ui/views/color_chooser_dialog.h @@ -0,0 +1,73 @@ +// Copyright (c) 2012 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. + +#ifndef CHROME_BROWSER_UI_VIEWS_COLOR_CHOOSER_DIALOG_H_ +#define CHROME_BROWSER_UI_VIEWS_COLOR_CHOOSER_DIALOG_H_ + +#include "base/memory/ref_counted.h" +#include "chrome/browser/ui/views/color_chooser_dialog.h" +#include "third_party/skia/include/core/SkColor.h" +#include "ui/shell_dialogs/base_shell_dialog.h" +#include "ui/shell_dialogs/base_shell_dialog_win.h" + +namespace views { +class ColorChooserListener; +} + +class ColorChooserDialog + : public base::RefCountedThreadSafe, + public ui::BaseShellDialog, + public ui::BaseShellDialogImpl { + public: + ColorChooserDialog(views::ColorChooserListener* listener, + SkColor initial_color, + gfx::NativeWindow owning_window); + virtual ~ColorChooserDialog(); + + // BaseShellDialog: + virtual bool IsRunning(gfx::NativeWindow owning_window) const OVERRIDE; + virtual void ListenerDestroyed() OVERRIDE; + + private: + struct ExecuteOpenParams { + ExecuteOpenParams(SkColor color, RunState run_state, HWND owner); + SkColor color; + RunState run_state; + HWND owner; + }; + + // Called on the dialog thread to show the actual color chooser. This is + // shown modal to |params.owner|. Once it's closed, calls back to + // DidCloseDialog() on the UI thread. + void ExecuteOpen(const ExecuteOpenParams& params); + + // Called on the UI thread when a color chooser is closed. |chose_color| is + // true if the user actually chose a color, in which case |color| is the + // chosen color. Calls back to the |listener_| (if applicable) to notify it + // of the results, and copies the modified array of |custom_colors_| back to + // |g_custom_colors| so future dialogs will see the changes. + void DidCloseDialog(bool chose_color, SkColor color, RunState run_state); + + // Copies the array of colors in |src| to |dst|. + void CopyCustomColors(COLORREF*, COLORREF*); + + // The user's custom colors. Kept process-wide so that they can be persisted + // from one dialog invocation to the next. + static COLORREF g_custom_colors[16]; + + // A copy of the custom colors for the current dialog to display and modify. + // This allows us to safely access the colors even if multiple windows are + // simultaneously showing color choosers (which would cause thread safety + // problems if we gave them direct handles to |g_custom_colors|). + COLORREF custom_colors_[16]; + + // The listener to notify when the user closes the dialog. This may be set to + // NULL before the color chooser is closed, signalling that the listener no + // longer cares about the outcome. + views::ColorChooserListener* listener_; + + DISALLOW_COPY_AND_ASSIGN(ColorChooserDialog); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_COLOR_CHOOSER_DIALOG_H_ diff --git a/chromium_src/chrome/browser/ui/views/color_chooser_win.cc b/chromium_src/chrome/browser/ui/views/color_chooser_win.cc new file mode 100644 index 000000000000..1a2aed45c385 --- /dev/null +++ b/chromium_src/chrome/browser/ui/views/color_chooser_win.cc @@ -0,0 +1,104 @@ +// Copyright (c) 2012 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 + +#include "chrome/browser/ui/browser_dialogs.h" +#include "chrome/browser/ui/views/color_chooser_aura.h" +#include "chrome/browser/ui/views/color_chooser_dialog.h" +#include "content/public/browser/color_chooser.h" +#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_widget_host_view.h" +#include "content/public/browser/web_contents.h" +#include "ui/views/color_chooser/color_chooser_listener.h" + +class ColorChooserWin : public content::ColorChooser, + public views::ColorChooserListener { + public: + static ColorChooserWin* Open(content::WebContents* web_contents, + SkColor initial_color); + + ColorChooserWin(content::WebContents* web_contents, + SkColor initial_color); + ~ColorChooserWin(); + + // content::ColorChooser overrides: + virtual void End() OVERRIDE; + virtual void SetSelectedColor(SkColor color) OVERRIDE {} + + // views::ColorChooserListener overrides: + virtual void OnColorChosen(SkColor color); + virtual void OnColorChooserDialogClosed(); + + private: + static ColorChooserWin* current_color_chooser_; + + // The web contents invoking the color chooser. No ownership. because it will + // outlive this class. + content::WebContents* web_contents_; + + // The color chooser dialog which maintains the native color chooser UI. + scoped_refptr color_chooser_dialog_; +}; + +ColorChooserWin* ColorChooserWin::current_color_chooser_ = NULL; + +ColorChooserWin* ColorChooserWin::Open(content::WebContents* web_contents, + SkColor initial_color) { + if (current_color_chooser_) + return NULL; + current_color_chooser_ = new ColorChooserWin(web_contents, initial_color); + return current_color_chooser_; +} + +ColorChooserWin::ColorChooserWin(content::WebContents* web_contents, + SkColor initial_color) + : web_contents_(web_contents) { + gfx::NativeWindow owning_window = (gfx::NativeWindow)::GetAncestor( + (HWND)web_contents->GetRenderViewHost()->GetView()->GetNativeView(), + GA_ROOT); + color_chooser_dialog_ = new ColorChooserDialog(this, + initial_color, + owning_window); +} + +ColorChooserWin::~ColorChooserWin() { + // Always call End() before destroying. + DCHECK(!color_chooser_dialog_); +} + +void ColorChooserWin::End() { + // The ColorChooserDialog's listener is going away. Ideally we'd + // programmatically close the dialog at this point. Since that's impossible, + // we instead tell the dialog its listener is going away, so that the dialog + // doesn't try to communicate with a destroyed listener later. (We also tell + // the renderer the dialog is closed, since from the renderer's perspective + // it effectively is.) + OnColorChooserDialogClosed(); +} + +void ColorChooserWin::OnColorChosen(SkColor color) { + if (web_contents_) + web_contents_->DidChooseColorInColorChooser(color); +} + +void ColorChooserWin::OnColorChooserDialogClosed() { + if (color_chooser_dialog_.get()) { + color_chooser_dialog_->ListenerDestroyed(); + color_chooser_dialog_ = NULL; + } + DCHECK(current_color_chooser_ == this); + current_color_chooser_ = NULL; + if (web_contents_) + web_contents_->DidEndColorChooser(); +} + +namespace chrome { + +content::ColorChooser* ShowColorChooser(content::WebContents* web_contents, + SkColor initial_color) { + return ColorChooserWin::Open(web_contents, initial_color); +} + +} // namespace chrome diff --git a/vendor/brightray b/vendor/brightray index ba89e08f8dce..b90f13be24a0 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit ba89e08f8dcec06a65068c6c959431e7914fc00d +Subproject commit b90f13be24a006c55b7e1c935be492101ac2736c