diff --git a/brightray/brightray.gyp b/brightray/brightray.gyp index 532011bc9558..8dd2a64ce089 100644 --- a/brightray/brightray.gyp +++ b/brightray/brightray.gyp @@ -13,6 +13,7 @@ '.', '<(libchromiumcontent_include_dir)', '<(libchromiumcontent_include_dir)/third_party/skia/include/config', + '<(libchromiumcontent_include_dir)/third_party/skia/include/core', ], 'direct_dependent_settings': { 'include_dirs': [ diff --git a/brightray/browser/win/inspectable_web_contents_view_win.cc b/brightray/browser/win/inspectable_web_contents_view_win.cc index dca7ba4f3ebd..24a52b658f7d 100644 --- a/brightray/browser/win/inspectable_web_contents_view_win.cc +++ b/brightray/browser/win/inspectable_web_contents_view_win.cc @@ -6,6 +6,9 @@ #include "content/public/browser/web_contents_view.h" #include "ui/gfx/win/hwnd_util.h" +#include "ui/views/controls/single_split_view.h" +#include "ui/views/controls/webview/webview.h" +#include "ui/views/view.h" namespace brightray { @@ -15,6 +18,117 @@ const int kWindowInset = 100; } +class ContainerView : public views::View { + public: + explicit ContainerView(InspectableWebContentsViewWin* web_contents_view) + : container_view_created_(false), + dockside_("none"), // "none" is treated as "bottom". + web_view_(new views::WebView(NULL)), + web_contents_view_(web_contents_view) { + set_owned_by_client(); + web_view_->set_owned_by_client(); + web_view_->SetWebContents( + web_contents_view_->inspectable_web_contents()->GetWebContents()); + } + + views::View* GetWebView() const { + return web_view_.get(); + } + + void ShowDevTools() { + if (IsDevToolsViewShowing()) + return; + + RemoveChildView(web_view_.get()); + devtools_view_ = new views::WebView(NULL); + devtools_view_->SetWebContents(web_contents_view_-> + inspectable_web_contents()->devtools_web_contents()); + split_view_.reset(new views::SingleSplitView( + web_view_.get(), + devtools_view_, + GetSplitViewOrientation(), + NULL)); + split_view_->set_divider_offset(GetSplitVievDividerOffset()); + AddChildView(split_view_.get()); + Layout(); + + devtools_view_->RequestFocus(); + } + + void CloseDevTools() { + if (!IsDevToolsViewShowing()) + return; + + RemoveChildView(split_view_.get()); + split_view_.reset(); + AddChildView(web_view_.get()); + Layout(); + } + + bool IsDevToolsViewShowing() { + return split_view_; + } + + void SetDockSide(const std::string& side) { + if (dockside_ == side) + return; // no change from current location + + dockside_ = side; + if (!IsDevToolsViewShowing()) + return; + + split_view_->set_orientation(GetSplitViewOrientation()); + split_view_->set_divider_offset(GetSplitVievDividerOffset()); + split_view_->Layout(); + return; + } + + private: + // views::View: + virtual void Layout() OVERRIDE { + if (split_view_) + split_view_->SetBounds(0, 0, width(), height()); + else + web_view_->SetBounds(0, 0, width(), height()); + } + + virtual void ViewHierarchyChanged( + const ViewHierarchyChangedDetails& details) OVERRIDE { + View::ViewHierarchyChanged(details); + // We're not using child == this because a Widget may not be + // available when this is added to the hierarchy. + if (details.is_add && GetWidget() && !container_view_created_) { + container_view_created_ = true; + AddChildView(web_view_.get()); + } + } + + views::SingleSplitView::Orientation GetSplitViewOrientation() const { + if (dockside_ == "right") + return views::SingleSplitView::HORIZONTAL_SPLIT; + else + return views::SingleSplitView::VERTICAL_SPLIT; + } + + int GetSplitVievDividerOffset() const { + if (dockside_ == "right") + return width() * 2 / 3; + else + return height() * 2 / 3; + } + + // True if the container view has already been created, or false otherwise. + bool container_view_created_; + + std::string dockside_; + + scoped_ptr web_view_; + scoped_ptr split_view_; + views::WebView* devtools_view_; // Owned by split_view_. + + InspectableWebContentsViewWin* web_contents_view_; +}; + InspectableWebContentsView* CreateInspectableContentsView( InspectableWebContentsImpl* inspectable_web_contents) { return new InspectableWebContentsViewWin(inspectable_web_contents); @@ -22,7 +136,9 @@ InspectableWebContentsView* CreateInspectableContentsView( InspectableWebContentsViewWin::InspectableWebContentsViewWin( InspectableWebContentsImpl* inspectable_web_contents) - : inspectable_web_contents_(inspectable_web_contents) { + : inspectable_web_contents_(inspectable_web_contents), + undocked_(false), + container_(new ContainerView(this)) { } InspectableWebContentsViewWin::~InspectableWebContentsViewWin() { @@ -30,39 +146,65 @@ InspectableWebContentsViewWin::~InspectableWebContentsViewWin() { DestroyWindow(devtools_window_->hwnd()); } +views::View* InspectableWebContentsViewWin::GetView() const { + return container_.get(); +} + +views::View* InspectableWebContentsViewWin::GetWebView() const { + return container_->GetWebView(); +} + gfx::NativeView InspectableWebContentsViewWin::GetNativeView() const { auto web_contents = inspectable_web_contents_->GetWebContents(); return web_contents->GetView()->GetNativeView(); } void InspectableWebContentsViewWin::ShowDevTools() { - if (!devtools_window_) { - devtools_window_ = DevToolsWindow::Create(this)->AsWeakPtr(); - devtools_window_->Init(HWND_DESKTOP, gfx::Rect()); + if (undocked_) { + if (!devtools_window_) { + devtools_window_ = DevToolsWindow::Create(this)->AsWeakPtr(); + devtools_window_->Init(HWND_DESKTOP, gfx::Rect()); + } + + auto contents_view = inspectable_web_contents_->GetWebContents()->GetView(); + auto size = contents_view->GetContainerSize(); + size.Enlarge(-kWindowInset, -kWindowInset); + gfx::CenterAndSizeWindow(contents_view->GetNativeView(), + devtools_window_->hwnd(), + size); + + ShowWindow(devtools_window_->hwnd(), SW_SHOWNORMAL); + } else { + container_->ShowDevTools(); } - - auto contents_view = inspectable_web_contents_->GetWebContents()->GetView(); - auto size = contents_view->GetContainerSize(); - size.Enlarge(-kWindowInset, -kWindowInset); - gfx::CenterAndSizeWindow(contents_view->GetNativeView(), - devtools_window_->hwnd(), - size); - - ShowWindow(devtools_window_->hwnd(), SW_SHOWNORMAL); } void InspectableWebContentsViewWin::CloseDevTools() { - if (!devtools_window_) - return; - SendMessage(devtools_window_->hwnd(), WM_CLOSE, 0, 0); + if (undocked_) + SendMessage(devtools_window_->hwnd(), WM_CLOSE, 0, 0); + else + container_->CloseDevTools(); } bool InspectableWebContentsViewWin::IsDevToolsViewShowing() { - return devtools_window_; + return container_->IsDevToolsViewShowing() || devtools_window_; } bool InspectableWebContentsViewWin::SetDockSide(const std::string& side) { - return false; + if (side == "undocked") { + undocked_ = true; + container_->CloseDevTools(); + } else if (side == "right" || side == "bottom") { + undocked_ = false; + if (devtools_window_) + SendMessage(devtools_window_->hwnd(), WM_CLOSE, 0, 0); + container_->SetDockSide(side); + } else { + return false; + } + + ShowDevTools(); + return true; } } // namespace brightray diff --git a/brightray/browser/win/inspectable_web_contents_view_win.h b/brightray/browser/win/inspectable_web_contents_view_win.h index 55b09b2d3e4c..5f1321ae4181 100644 --- a/brightray/browser/win/inspectable_web_contents_view_win.h +++ b/brightray/browser/win/inspectable_web_contents_view_win.h @@ -4,10 +4,16 @@ #include "browser/inspectable_web_contents_view.h" #include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +namespace views { +class View; +} + namespace brightray { +class ContainerView; class DevToolsWindow; class InspectableWebContentsImpl; @@ -17,6 +23,18 @@ class InspectableWebContentsViewWin : public InspectableWebContentsView { InspectableWebContentsImpl* inspectable_web_contents_impl); ~InspectableWebContentsViewWin(); + // Returns the container control, which has devtools view attached. Unlike + // GetNativeView(), this returns a views::View instead of HWND, and can only + // be used by applications that use the views library, if you don't use the + // views library, you probably want to set dock side to "undocked" before + // showing the devtools, because devtools is showed attached by default and + // attached devtools is currently only supported when using views library. + views::View* GetView() const; + + // Returns the web view control, which can be used by the + // GetInitiallyFocusedView() to set initial focus to web view. + views::View* GetWebView() const; + virtual gfx::NativeView GetNativeView() const OVERRIDE; virtual void ShowDevTools() OVERRIDE; virtual void CloseDevTools() OVERRIDE; @@ -31,6 +49,8 @@ class InspectableWebContentsViewWin : public InspectableWebContentsView { // Owns us. InspectableWebContentsImpl* inspectable_web_contents_; + bool undocked_; + scoped_ptr container_; base::WeakPtr devtools_window_; DISALLOW_COPY_AND_ASSIGN(InspectableWebContentsViewWin);