Merge pull request #55 from brightray/windows-attached-devtools
Implement attached devtools on Windows
This commit is contained in:
commit
8180075944
3 changed files with 181 additions and 18 deletions
|
@ -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': [
|
||||
|
|
|
@ -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<views::WebView> web_view_;
|
||||
scoped_ptr<views::SingleSplitView> 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
|
||||
|
|
|
@ -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<ContainerView> container_;
|
||||
base::WeakPtr<DevToolsWindow> devtools_window_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(InspectableWebContentsViewWin);
|
||||
|
|
Loading…
Reference in a new issue