Skip to content

Commit

Permalink
feat: add multi BrowserView support to BrowserWindow (#16148)
Browse files Browse the repository at this point in the history
* feat: add multi BrowserView support to BrowserWindow

Add functions addBrowserView, removeBroserView, getBrowserViews to
BrowserWindow class. Existing API as setBrowserView and
getBrowserView code replaced to use new api inside.

* fix: for lint and osx compile errors

* fix: lint error in test code

* feat: add multi BrowserView support to BrowserWindow

Add functions addBrowserView, removeBroserView, getBrowserViews to
BrowserWindow class. Existing API as setBrowserView and
getBrowserView code replaced to use new api inside.

* fix: for lint and osx compile errors

* fix: lint error in test code

* fix: method to be accessible on mac api impl

* fix: missed function declarations for mac impl

* fix: use base class reset function
  • Loading branch information
summeroff authored and Cheng Zhao committed Dec 22, 2018
1 parent 18ca4b6 commit 5ae3d1a
Show file tree
Hide file tree
Showing 12 changed files with 243 additions and 73 deletions.
24 changes: 23 additions & 1 deletion atom/browser/api/atom_api_browser_window.cc
Expand Up @@ -304,7 +304,29 @@ void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
}

void BrowserWindow::SetBrowserView(v8::Local<v8::Value> value) {
TopLevelWindow::SetBrowserView(value);
TopLevelWindow::ResetBrowserViews();
TopLevelWindow::AddBrowserView(value);
#if defined(OS_MACOSX)
UpdateDraggableRegions(nullptr, draggable_regions_);
#endif
}

void BrowserWindow::AddBrowserView(v8::Local<v8::Value> value) {
TopLevelWindow::AddBrowserView(value);
#if defined(OS_MACOSX)
UpdateDraggableRegions(nullptr, draggable_regions_);
#endif
}

void BrowserWindow::RemoveBrowserView(v8::Local<v8::Value> value) {
TopLevelWindow::RemoveBrowserView(value);
#if defined(OS_MACOSX)
UpdateDraggableRegions(nullptr, draggable_regions_);
#endif
}

void BrowserWindow::ResetBrowserViews() {
TopLevelWindow::ResetBrowserViews();
#if defined(OS_MACOSX)
UpdateDraggableRegions(nullptr, draggable_regions_);
#endif
Expand Down
3 changes: 3 additions & 0 deletions atom/browser/api/atom_api_browser_window.h
Expand Up @@ -72,6 +72,9 @@ class BrowserWindow : public TopLevelWindow,
void Blur() override;
void SetBackgroundColor(const std::string& color_name) override;
void SetBrowserView(v8::Local<v8::Value> value) override;
void AddBrowserView(v8::Local<v8::Value> value) override;
void RemoveBrowserView(v8::Local<v8::Value> value) override;
void ResetBrowserViews() override;
void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) override;

// BrowserWindow APIs.
Expand Down
6 changes: 4 additions & 2 deletions atom/browser/api/atom_api_browser_window_mac.mm
Expand Up @@ -108,8 +108,10 @@ - (NSView*)hitTest:(NSPoint)aPoint {
DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight);
}

if (window_->browser_view())
window_->browser_view()->UpdateDraggableRegions(drag_exclude_rects);
auto browser_views = window_->browser_views();
for (NativeBrowserView* view : browser_views) {
(view)->UpdateDraggableRegions(drag_exclude_rects);
}

// Create and add a ControlRegionView for each region that needs to be
// excluded from the dragging.
Expand Down
82 changes: 63 additions & 19 deletions atom/browser/api/atom_api_top_level_window.cc
Expand Up @@ -159,7 +159,7 @@ void TopLevelWindow::OnWindowClosed() {
Emit("closed");

RemoveFromParentChildWindows();
ResetBrowserView();
TopLevelWindow::ResetBrowserViews();

// Destroy the native class when window is closed.
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, GetDestroyClosure());
Expand Down Expand Up @@ -294,6 +294,7 @@ void TopLevelWindow::OnWindowMessage(UINT message,
#endif

void TopLevelWindow::SetContentView(mate::Handle<View> view) {
ResetBrowserViews();
content_view_.Reset(isolate(), view.ToV8());
window_->SetContentView(view->view());
}
Expand Down Expand Up @@ -681,18 +682,37 @@ void TopLevelWindow::SetParentWindow(v8::Local<v8::Value> value,
}

void TopLevelWindow::SetBrowserView(v8::Local<v8::Value> value) {
ResetBrowserView();
ResetBrowserViews();
AddBrowserView(value);
}

void TopLevelWindow::AddBrowserView(v8::Local<v8::Value> value) {
mate::Handle<BrowserView> browser_view;
if (value->IsNull() || value->IsUndefined()) {
window_->SetBrowserView(nullptr);
} else if (mate::ConvertFromV8(isolate(), value, &browser_view)) {
window_->SetBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(window_.get());
browser_view_.Reset(isolate(), value);
if (value->IsObject() &&
mate::ConvertFromV8(isolate(), value, &browser_view)) {
auto get_that_view = browser_views_.find(browser_view->weak_map_id());
if (get_that_view == browser_views_.end()) {
window_->AddBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(window_.get());
browser_views_[browser_view->weak_map_id()].Reset(isolate(), value);
}
}
}

void TopLevelWindow::RemoveBrowserView(v8::Local<v8::Value> value) {
mate::Handle<BrowserView> browser_view;
if (value->IsObject() &&
mate::ConvertFromV8(isolate(), value, &browser_view)) {
auto get_that_view = browser_views_.find(browser_view->weak_map_id());
if (get_that_view != browser_views_.end()) {
window_->RemoveBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(nullptr);

(*get_that_view).second.Reset(isolate(), value);
browser_views_.erase(get_that_view);
}
}
}
v8::Local<v8::Value> TopLevelWindow::GetNativeWindowHandle() {
// TODO(MarshallOfSound): Replace once
// https://chromium-review.googlesource.com/c/chromium/src/+/1253094/ has
Expand Down Expand Up @@ -847,12 +867,29 @@ std::vector<v8::Local<v8::Object>> TopLevelWindow::GetChildWindows() const {
return child_windows_.Values(isolate());
}

v8::Local<v8::Value> TopLevelWindow::GetBrowserView() const {
if (browser_view_.IsEmpty()) {
v8::Local<v8::Value> TopLevelWindow::GetBrowserView(
mate::Arguments* args) const {
if (browser_views_.size() == 0) {
return v8::Null(isolate());
} else if (browser_views_.size() == 1) {
auto first_view = browser_views_.begin();
return v8::Local<v8::Value>::New(isolate(), (*first_view).second);
} else {
args->ThrowError(
"BrowserWindow have multiple BrowserViews, "
"Use getBrowserViews() instead");
return v8::Null(isolate());
}
}

return v8::Local<v8::Value>::New(isolate(), browser_view_);
std::vector<v8::Local<v8::Value>> TopLevelWindow::GetBrowserViews() const {
std::vector<v8::Local<v8::Value>> ret;

for (auto const& views_iter : browser_views_) {
ret.push_back(v8::Local<v8::Value>::New(isolate(), views_iter.second));
}

return ret;
}

bool TopLevelWindow::IsModal() const {
Expand Down Expand Up @@ -944,17 +981,21 @@ int32_t TopLevelWindow::GetID() const {
return weak_map_id();
}

void TopLevelWindow::ResetBrowserView() {
if (browser_view_.IsEmpty())
return;
void TopLevelWindow::ResetBrowserViews() {
for (auto& item : browser_views_) {
mate::Handle<BrowserView> browser_view;
if (mate::ConvertFromV8(isolate(),
v8::Local<v8::Value>::New(isolate(), item.second),
&browser_view) &&
!browser_view.IsEmpty()) {
window_->RemoveBrowserView(browser_view->view());
browser_view->web_contents()->SetOwnerWindow(nullptr);
}

mate::Handle<BrowserView> browser_view;
if (mate::ConvertFromV8(isolate(), GetBrowserView(), &browser_view) &&
!browser_view.IsEmpty()) {
browser_view->web_contents()->SetOwnerWindow(nullptr);
item.second.Reset();
}

browser_view_.Reset();
browser_views_.clear();
}

void TopLevelWindow::RemoveFromParentChildWindows() {
Expand Down Expand Up @@ -1064,6 +1105,8 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
.SetMethod("setMenu", &TopLevelWindow::SetMenu)
.SetMethod("setParentWindow", &TopLevelWindow::SetParentWindow)
.SetMethod("setBrowserView", &TopLevelWindow::SetBrowserView)
.SetMethod("addBrowserView", &TopLevelWindow::AddBrowserView)
.SetMethod("removeBrowserView", &TopLevelWindow::RemoveBrowserView)
.SetMethod("getNativeWindowHandle",
&TopLevelWindow::GetNativeWindowHandle)
.SetMethod("setProgressBar", &TopLevelWindow::SetProgressBar)
Expand Down Expand Up @@ -1101,6 +1144,7 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getParentWindow", &TopLevelWindow::GetParentWindow)
.SetMethod("getChildWindows", &TopLevelWindow::GetChildWindows)
.SetMethod("getBrowserView", &TopLevelWindow::GetBrowserView)
.SetMethod("getBrowserViews", &TopLevelWindow::GetBrowserViews)
.SetMethod("isModal", &TopLevelWindow::IsModal)
.SetMethod("setThumbarButtons", &TopLevelWindow::SetThumbarButtons)
#if defined(TOOLKIT_VIEWS)
Expand Down
8 changes: 6 additions & 2 deletions atom/browser/api/atom_api_top_level_window.h
Expand Up @@ -165,6 +165,10 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
void SetParentWindow(v8::Local<v8::Value> value, mate::Arguments* args);
virtual void SetBrowserView(v8::Local<v8::Value> value);
virtual void AddBrowserView(v8::Local<v8::Value> value);
virtual void RemoveBrowserView(v8::Local<v8::Value> value);
virtual std::vector<v8::Local<v8::Value>> GetBrowserViews() const;
virtual void ResetBrowserViews();
v8::Local<v8::Value> GetNativeWindowHandle();
void SetProgressBar(double progress, mate::Arguments* args);
void SetOverlayIcon(const gfx::Image& overlay,
Expand Down Expand Up @@ -195,7 +199,7 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
v8::Local<v8::Value> GetContentView() const;
v8::Local<v8::Value> GetParentWindow() const;
std::vector<v8::Local<v8::Object>> GetChildWindows() const;
v8::Local<v8::Value> GetBrowserView() const;
v8::Local<v8::Value> GetBrowserView(mate::Arguments* args) const;
bool IsModal() const;

// Extra APIs added in JS.
Expand Down Expand Up @@ -238,7 +242,7 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
#endif

v8::Global<v8::Value> content_view_;
v8::Global<v8::Value> browser_view_;
std::map<int32_t, v8::Global<v8::Value>> browser_views_;
v8::Global<v8::Value> menu_;
v8::Global<v8::Value> parent_window_;
KeyWeakMap<int> child_windows_;
Expand Down
18 changes: 13 additions & 5 deletions atom/browser/native_window.h
Expand Up @@ -5,6 +5,7 @@
#ifndef ATOM_BROWSER_NATIVE_WINDOW_H_
#define ATOM_BROWSER_NATIVE_WINDOW_H_

#include <list>
#include <map>
#include <memory>
#include <string>
Expand Down Expand Up @@ -155,7 +156,8 @@ class NativeWindow : public base::SupportsUserData,
virtual void SetFocusable(bool focusable);
virtual void SetMenu(AtomMenuModel* menu);
virtual void SetParentWindow(NativeWindow* parent);
virtual void SetBrowserView(NativeBrowserView* browser_view) = 0;
virtual void AddBrowserView(NativeBrowserView* browser_view) = 0;
virtual void RemoveBrowserView(NativeBrowserView* browser_view) = 0;
virtual gfx::NativeView GetNativeView() const = 0;
virtual gfx::NativeWindow GetNativeWindow() const = 0;
virtual gfx::AcceleratedWidget GetAcceleratedWidget() const = 0;
Expand Down Expand Up @@ -286,10 +288,11 @@ class NativeWindow : public base::SupportsUserData,
bool transparent() const { return transparent_; }
bool enable_larger_than_screen() const { return enable_larger_than_screen_; }

NativeBrowserView* browser_view() const { return browser_view_; }
NativeWindow* parent() const { return parent_; }
bool is_modal() const { return is_modal_; }

std::list<NativeBrowserView*> browser_views() const { return browser_views_; }

protected:
NativeWindow(const mate::Dictionary& options, NativeWindow* parent);

Expand All @@ -298,8 +301,13 @@ class NativeWindow : public base::SupportsUserData,
const views::Widget* GetWidget() const override;

void set_content_view(views::View* view) { content_view_ = view; }
void set_browser_view(NativeBrowserView* browser_view) {
browser_view_ = browser_view;

void add_browser_view(NativeBrowserView* browser_view) {
browser_views_.push_back(browser_view);
}
void remove_browser_view(NativeBrowserView* browser_view) {
browser_views_.remove_if(
[&browser_view](NativeBrowserView* n) { return (n == browser_view); });
}

private:
Expand Down Expand Up @@ -340,7 +348,7 @@ class NativeWindow : public base::SupportsUserData,
bool is_modal_ = false;

// The browser view layer.
NativeBrowserView* browser_view_ = nullptr;
std::list<NativeBrowserView*> browser_views_;

// Observers of this window.
base::ObserverList<NativeWindowObserver> observers_;
Expand Down
3 changes: 2 additions & 1 deletion atom/browser/native_window_mac.h
Expand Up @@ -102,7 +102,8 @@ class NativeWindowMac : public NativeWindow {
bool IsDocumentEdited() override;
void SetIgnoreMouseEvents(bool ignore, bool forward) override;
void SetContentProtection(bool enable) override;
void SetBrowserView(NativeBrowserView* browser_view) override;
void AddBrowserView(NativeBrowserView* browser_view) override;
void RemoveBrowserView(NativeBrowserView* browser_view) override;
void SetParentWindow(NativeWindow* parent) override;
gfx::NativeView GetNativeView() const override;
gfx::NativeWindow GetNativeWindow() const override;
Expand Down
25 changes: 17 additions & 8 deletions atom/browser/native_window_mac.mm
Expand Up @@ -1069,22 +1069,16 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) {
setSharingType:enable ? NSWindowSharingNone : NSWindowSharingReadOnly];
}

void NativeWindowMac::SetBrowserView(NativeBrowserView* view) {
void NativeWindowMac::AddBrowserView(NativeBrowserView* view) {
[CATransaction begin];
[CATransaction setDisableActions:YES];

if (browser_view()) {
[browser_view()->GetInspectableWebContentsView()->GetNativeView()
removeFromSuperview];
set_browser_view(nullptr);
}

if (!view) {
[CATransaction commit];
return;
}

set_browser_view(view);
add_browser_view(view);
auto* native_view = view->GetInspectableWebContentsView()->GetNativeView();
[[window_ contentView] addSubview:native_view
positioned:NSWindowAbove
Expand All @@ -1094,6 +1088,21 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) {
[CATransaction commit];
}

void NativeWindowMac::RemoveBrowserView(NativeBrowserView* view) {
[CATransaction begin];
[CATransaction setDisableActions:YES];

if (!view) {
[CATransaction commit];
return;
}

[view->GetInspectableWebContentsView()->GetNativeView() removeFromSuperview];
remove_browser_view(view);

[CATransaction commit];
}

void NativeWindowMac::SetParentWindow(NativeWindow* parent) {
InternalSetParentWindow(parent, IsVisible());
}
Expand Down

0 comments on commit 5ae3d1a

Please sign in to comment.