feat: add multi BrowserView support to BrowserWindow (#16148)
* 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
This commit is contained in:
parent
18ca4b6a3a
commit
5ae3d1a1b2
12 changed files with 244 additions and 74 deletions
|
@ -304,7 +304,29 @@ void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserWindow::SetBrowserView(v8::Local<v8::Value> value) {
|
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)
|
#if defined(OS_MACOSX)
|
||||||
UpdateDraggableRegions(nullptr, draggable_regions_);
|
UpdateDraggableRegions(nullptr, draggable_regions_);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -72,6 +72,9 @@ class BrowserWindow : public TopLevelWindow,
|
||||||
void Blur() override;
|
void Blur() override;
|
||||||
void SetBackgroundColor(const std::string& color_name) override;
|
void SetBackgroundColor(const std::string& color_name) override;
|
||||||
void SetBrowserView(v8::Local<v8::Value> value) 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;
|
void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) override;
|
||||||
|
|
||||||
// BrowserWindow APIs.
|
// BrowserWindow APIs.
|
||||||
|
|
|
@ -108,8 +108,10 @@ void BrowserWindow::UpdateDraggableRegions(
|
||||||
DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight);
|
DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window_->browser_view())
|
auto browser_views = window_->browser_views();
|
||||||
window_->browser_view()->UpdateDraggableRegions(drag_exclude_rects);
|
for (NativeBrowserView* view : browser_views) {
|
||||||
|
(view)->UpdateDraggableRegions(drag_exclude_rects);
|
||||||
|
}
|
||||||
|
|
||||||
// Create and add a ControlRegionView for each region that needs to be
|
// Create and add a ControlRegionView for each region that needs to be
|
||||||
// excluded from the dragging.
|
// excluded from the dragging.
|
||||||
|
|
|
@ -159,7 +159,7 @@ void TopLevelWindow::OnWindowClosed() {
|
||||||
Emit("closed");
|
Emit("closed");
|
||||||
|
|
||||||
RemoveFromParentChildWindows();
|
RemoveFromParentChildWindows();
|
||||||
ResetBrowserView();
|
TopLevelWindow::ResetBrowserViews();
|
||||||
|
|
||||||
// Destroy the native class when window is closed.
|
// Destroy the native class when window is closed.
|
||||||
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, GetDestroyClosure());
|
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, GetDestroyClosure());
|
||||||
|
@ -294,6 +294,7 @@ void TopLevelWindow::OnWindowMessage(UINT message,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void TopLevelWindow::SetContentView(mate::Handle<View> view) {
|
void TopLevelWindow::SetContentView(mate::Handle<View> view) {
|
||||||
|
ResetBrowserViews();
|
||||||
content_view_.Reset(isolate(), view.ToV8());
|
content_view_.Reset(isolate(), view.ToV8());
|
||||||
window_->SetContentView(view->view());
|
window_->SetContentView(view->view());
|
||||||
}
|
}
|
||||||
|
@ -681,18 +682,37 @@ void TopLevelWindow::SetParentWindow(v8::Local<v8::Value> value,
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopLevelWindow::SetBrowserView(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;
|
mate::Handle<BrowserView> browser_view;
|
||||||
if (value->IsNull() || value->IsUndefined()) {
|
if (value->IsObject() &&
|
||||||
window_->SetBrowserView(nullptr);
|
mate::ConvertFromV8(isolate(), value, &browser_view)) {
|
||||||
} else if (mate::ConvertFromV8(isolate(), value, &browser_view)) {
|
auto get_that_view = browser_views_.find(browser_view->weak_map_id());
|
||||||
window_->SetBrowserView(browser_view->view());
|
if (get_that_view == browser_views_.end()) {
|
||||||
browser_view->web_contents()->SetOwnerWindow(window_.get());
|
window_->AddBrowserView(browser_view->view());
|
||||||
browser_view_.Reset(isolate(), value);
|
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() {
|
v8::Local<v8::Value> TopLevelWindow::GetNativeWindowHandle() {
|
||||||
// TODO(MarshallOfSound): Replace once
|
// TODO(MarshallOfSound): Replace once
|
||||||
// https://chromium-review.googlesource.com/c/chromium/src/+/1253094/ has
|
// https://chromium-review.googlesource.com/c/chromium/src/+/1253094/ has
|
||||||
|
@ -847,12 +867,29 @@ std::vector<v8::Local<v8::Object>> TopLevelWindow::GetChildWindows() const {
|
||||||
return child_windows_.Values(isolate());
|
return child_windows_.Values(isolate());
|
||||||
}
|
}
|
||||||
|
|
||||||
v8::Local<v8::Value> TopLevelWindow::GetBrowserView() const {
|
v8::Local<v8::Value> TopLevelWindow::GetBrowserView(
|
||||||
if (browser_view_.IsEmpty()) {
|
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::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 {
|
bool TopLevelWindow::IsModal() const {
|
||||||
|
@ -944,17 +981,21 @@ int32_t TopLevelWindow::GetID() const {
|
||||||
return weak_map_id();
|
return weak_map_id();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopLevelWindow::ResetBrowserView() {
|
void TopLevelWindow::ResetBrowserViews() {
|
||||||
if (browser_view_.IsEmpty())
|
for (auto& item : browser_views_) {
|
||||||
return;
|
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;
|
item.second.Reset();
|
||||||
if (mate::ConvertFromV8(isolate(), GetBrowserView(), &browser_view) &&
|
|
||||||
!browser_view.IsEmpty()) {
|
|
||||||
browser_view->web_contents()->SetOwnerWindow(nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
browser_view_.Reset();
|
browser_views_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopLevelWindow::RemoveFromParentChildWindows() {
|
void TopLevelWindow::RemoveFromParentChildWindows() {
|
||||||
|
@ -1064,6 +1105,8 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
|
||||||
.SetMethod("setMenu", &TopLevelWindow::SetMenu)
|
.SetMethod("setMenu", &TopLevelWindow::SetMenu)
|
||||||
.SetMethod("setParentWindow", &TopLevelWindow::SetParentWindow)
|
.SetMethod("setParentWindow", &TopLevelWindow::SetParentWindow)
|
||||||
.SetMethod("setBrowserView", &TopLevelWindow::SetBrowserView)
|
.SetMethod("setBrowserView", &TopLevelWindow::SetBrowserView)
|
||||||
|
.SetMethod("addBrowserView", &TopLevelWindow::AddBrowserView)
|
||||||
|
.SetMethod("removeBrowserView", &TopLevelWindow::RemoveBrowserView)
|
||||||
.SetMethod("getNativeWindowHandle",
|
.SetMethod("getNativeWindowHandle",
|
||||||
&TopLevelWindow::GetNativeWindowHandle)
|
&TopLevelWindow::GetNativeWindowHandle)
|
||||||
.SetMethod("setProgressBar", &TopLevelWindow::SetProgressBar)
|
.SetMethod("setProgressBar", &TopLevelWindow::SetProgressBar)
|
||||||
|
@ -1101,6 +1144,7 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
|
||||||
.SetMethod("getParentWindow", &TopLevelWindow::GetParentWindow)
|
.SetMethod("getParentWindow", &TopLevelWindow::GetParentWindow)
|
||||||
.SetMethod("getChildWindows", &TopLevelWindow::GetChildWindows)
|
.SetMethod("getChildWindows", &TopLevelWindow::GetChildWindows)
|
||||||
.SetMethod("getBrowserView", &TopLevelWindow::GetBrowserView)
|
.SetMethod("getBrowserView", &TopLevelWindow::GetBrowserView)
|
||||||
|
.SetMethod("getBrowserViews", &TopLevelWindow::GetBrowserViews)
|
||||||
.SetMethod("isModal", &TopLevelWindow::IsModal)
|
.SetMethod("isModal", &TopLevelWindow::IsModal)
|
||||||
.SetMethod("setThumbarButtons", &TopLevelWindow::SetThumbarButtons)
|
.SetMethod("setThumbarButtons", &TopLevelWindow::SetThumbarButtons)
|
||||||
#if defined(TOOLKIT_VIEWS)
|
#if defined(TOOLKIT_VIEWS)
|
||||||
|
|
|
@ -165,6 +165,10 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
|
||||||
void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
|
void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
|
||||||
void SetParentWindow(v8::Local<v8::Value> value, mate::Arguments* args);
|
void SetParentWindow(v8::Local<v8::Value> value, mate::Arguments* args);
|
||||||
virtual void SetBrowserView(v8::Local<v8::Value> value);
|
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();
|
v8::Local<v8::Value> GetNativeWindowHandle();
|
||||||
void SetProgressBar(double progress, mate::Arguments* args);
|
void SetProgressBar(double progress, mate::Arguments* args);
|
||||||
void SetOverlayIcon(const gfx::Image& overlay,
|
void SetOverlayIcon(const gfx::Image& overlay,
|
||||||
|
@ -195,7 +199,7 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
|
||||||
v8::Local<v8::Value> GetContentView() const;
|
v8::Local<v8::Value> GetContentView() const;
|
||||||
v8::Local<v8::Value> GetParentWindow() const;
|
v8::Local<v8::Value> GetParentWindow() const;
|
||||||
std::vector<v8::Local<v8::Object>> GetChildWindows() 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;
|
bool IsModal() const;
|
||||||
|
|
||||||
// Extra APIs added in JS.
|
// Extra APIs added in JS.
|
||||||
|
@ -238,7 +242,7 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
v8::Global<v8::Value> content_view_;
|
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> menu_;
|
||||||
v8::Global<v8::Value> parent_window_;
|
v8::Global<v8::Value> parent_window_;
|
||||||
KeyWeakMap<int> child_windows_;
|
KeyWeakMap<int> child_windows_;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#ifndef ATOM_BROWSER_NATIVE_WINDOW_H_
|
#ifndef ATOM_BROWSER_NATIVE_WINDOW_H_
|
||||||
#define ATOM_BROWSER_NATIVE_WINDOW_H_
|
#define ATOM_BROWSER_NATIVE_WINDOW_H_
|
||||||
|
|
||||||
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -155,7 +156,8 @@ class NativeWindow : public base::SupportsUserData,
|
||||||
virtual void SetFocusable(bool focusable);
|
virtual void SetFocusable(bool focusable);
|
||||||
virtual void SetMenu(AtomMenuModel* menu);
|
virtual void SetMenu(AtomMenuModel* menu);
|
||||||
virtual void SetParentWindow(NativeWindow* parent);
|
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::NativeView GetNativeView() const = 0;
|
||||||
virtual gfx::NativeWindow GetNativeWindow() const = 0;
|
virtual gfx::NativeWindow GetNativeWindow() const = 0;
|
||||||
virtual gfx::AcceleratedWidget GetAcceleratedWidget() const = 0;
|
virtual gfx::AcceleratedWidget GetAcceleratedWidget() const = 0;
|
||||||
|
@ -286,10 +288,11 @@ class NativeWindow : public base::SupportsUserData,
|
||||||
bool transparent() const { return transparent_; }
|
bool transparent() const { return transparent_; }
|
||||||
bool enable_larger_than_screen() const { return enable_larger_than_screen_; }
|
bool enable_larger_than_screen() const { return enable_larger_than_screen_; }
|
||||||
|
|
||||||
NativeBrowserView* browser_view() const { return browser_view_; }
|
|
||||||
NativeWindow* parent() const { return parent_; }
|
NativeWindow* parent() const { return parent_; }
|
||||||
bool is_modal() const { return is_modal_; }
|
bool is_modal() const { return is_modal_; }
|
||||||
|
|
||||||
|
std::list<NativeBrowserView*> browser_views() const { return browser_views_; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NativeWindow(const mate::Dictionary& options, NativeWindow* parent);
|
NativeWindow(const mate::Dictionary& options, NativeWindow* parent);
|
||||||
|
|
||||||
|
@ -298,8 +301,13 @@ class NativeWindow : public base::SupportsUserData,
|
||||||
const views::Widget* GetWidget() const override;
|
const views::Widget* GetWidget() const override;
|
||||||
|
|
||||||
void set_content_view(views::View* view) { content_view_ = view; }
|
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:
|
private:
|
||||||
|
@ -340,7 +348,7 @@ class NativeWindow : public base::SupportsUserData,
|
||||||
bool is_modal_ = false;
|
bool is_modal_ = false;
|
||||||
|
|
||||||
// The browser view layer.
|
// The browser view layer.
|
||||||
NativeBrowserView* browser_view_ = nullptr;
|
std::list<NativeBrowserView*> browser_views_;
|
||||||
|
|
||||||
// Observers of this window.
|
// Observers of this window.
|
||||||
base::ObserverList<NativeWindowObserver> observers_;
|
base::ObserverList<NativeWindowObserver> observers_;
|
||||||
|
|
|
@ -102,7 +102,8 @@ class NativeWindowMac : public NativeWindow {
|
||||||
bool IsDocumentEdited() override;
|
bool IsDocumentEdited() override;
|
||||||
void SetIgnoreMouseEvents(bool ignore, bool forward) override;
|
void SetIgnoreMouseEvents(bool ignore, bool forward) override;
|
||||||
void SetContentProtection(bool enable) 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;
|
void SetParentWindow(NativeWindow* parent) override;
|
||||||
gfx::NativeView GetNativeView() const override;
|
gfx::NativeView GetNativeView() const override;
|
||||||
gfx::NativeWindow GetNativeWindow() const override;
|
gfx::NativeWindow GetNativeWindow() const override;
|
||||||
|
|
|
@ -1069,22 +1069,16 @@ void NativeWindowMac::SetContentProtection(bool enable) {
|
||||||
setSharingType:enable ? NSWindowSharingNone : NSWindowSharingReadOnly];
|
setSharingType:enable ? NSWindowSharingNone : NSWindowSharingReadOnly];
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowMac::SetBrowserView(NativeBrowserView* view) {
|
void NativeWindowMac::AddBrowserView(NativeBrowserView* view) {
|
||||||
[CATransaction begin];
|
[CATransaction begin];
|
||||||
[CATransaction setDisableActions:YES];
|
[CATransaction setDisableActions:YES];
|
||||||
|
|
||||||
if (browser_view()) {
|
|
||||||
[browser_view()->GetInspectableWebContentsView()->GetNativeView()
|
|
||||||
removeFromSuperview];
|
|
||||||
set_browser_view(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!view) {
|
if (!view) {
|
||||||
[CATransaction commit];
|
[CATransaction commit];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_browser_view(view);
|
add_browser_view(view);
|
||||||
auto* native_view = view->GetInspectableWebContentsView()->GetNativeView();
|
auto* native_view = view->GetInspectableWebContentsView()->GetNativeView();
|
||||||
[[window_ contentView] addSubview:native_view
|
[[window_ contentView] addSubview:native_view
|
||||||
positioned:NSWindowAbove
|
positioned:NSWindowAbove
|
||||||
|
@ -1094,6 +1088,21 @@ void NativeWindowMac::SetBrowserView(NativeBrowserView* view) {
|
||||||
[CATransaction commit];
|
[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) {
|
void NativeWindowMac::SetParentWindow(NativeWindow* parent) {
|
||||||
InternalSetParentWindow(parent, IsVisible());
|
InternalSetParentWindow(parent, IsVisible());
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,11 +315,6 @@ NativeWindowViews::~NativeWindowViews() {
|
||||||
void NativeWindowViews::SetContentView(views::View* view) {
|
void NativeWindowViews::SetContentView(views::View* view) {
|
||||||
if (content_view()) {
|
if (content_view()) {
|
||||||
root_view_->RemoveChildView(content_view());
|
root_view_->RemoveChildView(content_view());
|
||||||
if (browser_view()) {
|
|
||||||
content_view()->RemoveChildView(
|
|
||||||
browser_view()->GetInspectableWebContentsView()->GetView());
|
|
||||||
set_browser_view(nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
set_content_view(view);
|
set_content_view(view);
|
||||||
focused_view_ = view;
|
focused_view_ = view;
|
||||||
|
@ -960,27 +955,33 @@ void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowViews::SetBrowserView(NativeBrowserView* view) {
|
void NativeWindowViews::AddBrowserView(NativeBrowserView* view) {
|
||||||
if (!content_view())
|
if (!content_view())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (browser_view()) {
|
|
||||||
content_view()->RemoveChildView(
|
|
||||||
browser_view()->GetInspectableWebContentsView()->GetView());
|
|
||||||
set_browser_view(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!view) {
|
if (!view) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add as child of the main web view to avoid (0, 0) origin from overlapping
|
add_browser_view(view);
|
||||||
// with menu bar.
|
|
||||||
set_browser_view(view);
|
|
||||||
content_view()->AddChildView(
|
content_view()->AddChildView(
|
||||||
view->GetInspectableWebContentsView()->GetView());
|
view->GetInspectableWebContentsView()->GetView());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeWindowViews::RemoveBrowserView(NativeBrowserView* view) {
|
||||||
|
if (!content_view())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!view) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
content_view()->RemoveChildView(
|
||||||
|
view->GetInspectableWebContentsView()->GetView());
|
||||||
|
remove_browser_view(view);
|
||||||
|
}
|
||||||
|
|
||||||
void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
|
void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
|
||||||
NativeWindow::SetParentWindow(parent);
|
NativeWindow::SetParentWindow(parent);
|
||||||
|
|
||||||
|
@ -1175,6 +1176,26 @@ void NativeWindowViews::OnWidgetActivationChanged(views::Widget* changed_widget,
|
||||||
root_view_->ResetAltState();
|
root_view_->ResetAltState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NativeWindowViews::AutoresizeBrowserView(int width_delta,
|
||||||
|
int height_delta,
|
||||||
|
NativeBrowserView* browser_view) {
|
||||||
|
const auto flags =
|
||||||
|
static_cast<NativeBrowserViewViews*>(browser_view)->GetAutoResizeFlags();
|
||||||
|
if (!(flags & kAutoResizeWidth)) {
|
||||||
|
width_delta = 0;
|
||||||
|
}
|
||||||
|
if (!(flags & kAutoResizeHeight)) {
|
||||||
|
height_delta = 0;
|
||||||
|
}
|
||||||
|
if (height_delta || width_delta) {
|
||||||
|
auto* view = browser_view->GetInspectableWebContentsView()->GetView();
|
||||||
|
auto new_view_size = view->size();
|
||||||
|
new_view_size.set_width(new_view_size.width() + width_delta);
|
||||||
|
new_view_size.set_height(new_view_size.height() + height_delta);
|
||||||
|
view->SetSize(new_view_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
|
void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
|
||||||
const gfx::Rect& bounds) {
|
const gfx::Rect& bounds) {
|
||||||
if (changed_widget != widget())
|
if (changed_widget != widget())
|
||||||
|
@ -1184,23 +1205,10 @@ void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
|
||||||
// handle minimized windows on Windows.
|
// handle minimized windows on Windows.
|
||||||
const auto new_bounds = GetBounds();
|
const auto new_bounds = GetBounds();
|
||||||
if (widget_size_ != new_bounds.size()) {
|
if (widget_size_ != new_bounds.size()) {
|
||||||
if (browser_view()) {
|
int width_delta = new_bounds.width() - widget_size_.width();
|
||||||
const auto flags = static_cast<NativeBrowserViewViews*>(browser_view())
|
int height_delta = new_bounds.height() - widget_size_.height();
|
||||||
->GetAutoResizeFlags();
|
for (NativeBrowserView* item : browser_views()) {
|
||||||
int width_delta = 0;
|
AutoresizeBrowserView(width_delta, height_delta, item);
|
||||||
int height_delta = 0;
|
|
||||||
if (flags & kAutoResizeWidth) {
|
|
||||||
width_delta = new_bounds.width() - widget_size_.width();
|
|
||||||
}
|
|
||||||
if (flags & kAutoResizeHeight) {
|
|
||||||
height_delta = new_bounds.height() - widget_size_.height();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* view = browser_view()->GetInspectableWebContentsView()->GetView();
|
|
||||||
auto new_view_size = view->size();
|
|
||||||
new_view_size.set_width(new_view_size.width() + width_delta);
|
|
||||||
new_view_size.set_height(new_view_size.height() + height_delta);
|
|
||||||
view->SetSize(new_view_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NotifyWindowResize();
|
NotifyWindowResize();
|
||||||
|
|
|
@ -112,7 +112,8 @@ class NativeWindowViews : public NativeWindow,
|
||||||
void SetContentProtection(bool enable) override;
|
void SetContentProtection(bool enable) override;
|
||||||
void SetFocusable(bool focusable) override;
|
void SetFocusable(bool focusable) override;
|
||||||
void SetMenu(AtomMenuModel* menu_model) override;
|
void SetMenu(AtomMenuModel* menu_model) override;
|
||||||
void SetBrowserView(NativeBrowserView* browser_view) override;
|
void AddBrowserView(NativeBrowserView* browser_view) override;
|
||||||
|
void RemoveBrowserView(NativeBrowserView* browser_view) override;
|
||||||
void SetParentWindow(NativeWindow* parent) override;
|
void SetParentWindow(NativeWindow* parent) override;
|
||||||
gfx::NativeView GetNativeView() const override;
|
gfx::NativeView GetNativeView() const override;
|
||||||
gfx::NativeWindow GetNativeWindow() const override;
|
gfx::NativeWindow GetNativeWindow() const override;
|
||||||
|
@ -157,7 +158,9 @@ class NativeWindowViews : public NativeWindow,
|
||||||
void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
|
void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
|
||||||
void OnWidgetBoundsChanged(views::Widget* widget,
|
void OnWidgetBoundsChanged(views::Widget* widget,
|
||||||
const gfx::Rect& bounds) override;
|
const gfx::Rect& bounds) override;
|
||||||
|
void AutoresizeBrowserView(int width_delta,
|
||||||
|
int height_delta,
|
||||||
|
NativeBrowserView* browser_view);
|
||||||
// views::WidgetDelegate:
|
// views::WidgetDelegate:
|
||||||
void DeleteDelegate() override;
|
void DeleteDelegate() override;
|
||||||
views::View* GetInitiallyFocusedView() override;
|
views::View* GetInitiallyFocusedView() override;
|
||||||
|
|
|
@ -1601,11 +1601,29 @@ removed in future Electron releases.
|
||||||
|
|
||||||
#### `win.setBrowserView(browserView)` _Experimental_
|
#### `win.setBrowserView(browserView)` _Experimental_
|
||||||
|
|
||||||
* `browserView` [BrowserView](browser-view.md)
|
* `browserView` [BrowserView](browser-view.md). Attach browserView to win.
|
||||||
|
If there is some other browserViews was attached they will be removed from
|
||||||
|
this window.
|
||||||
|
|
||||||
#### `win.getBrowserView()` _Experimental_
|
#### `win.getBrowserView()` _Experimental_
|
||||||
|
|
||||||
Returns `BrowserView | null` - an attached BrowserView. Returns `null` if none is attached.
|
Returns `BrowserView | null` - an BrowserView what is attached. Returns `null`
|
||||||
|
if none is attached. Throw error if multiple BrowserViews is attached.
|
||||||
|
|
||||||
|
#### `win.addBrowserView(browserView)` _Experimental_
|
||||||
|
|
||||||
|
* `browserView` [BrowserView](browser-view.md)
|
||||||
|
|
||||||
|
Replacement API for setBrowserView supporting work with multi browser views.
|
||||||
|
|
||||||
|
#### `win.removeBrowserView(browserView)` _Experimental_
|
||||||
|
|
||||||
|
* `browserView` [BrowserView](browser-view.md)
|
||||||
|
|
||||||
|
#### `win.getBrowserViews()` _Experimental_
|
||||||
|
|
||||||
|
Returns array of `BrowserView` what was an attached with addBrowserView
|
||||||
|
or setBrowserView.
|
||||||
|
|
||||||
**Note:** The BrowserView API is currently experimental and may change or be
|
**Note:** The BrowserView API is currently experimental and may change or be
|
||||||
removed in future Electron releases.
|
removed in future Electron releases.
|
||||||
|
|
|
@ -132,6 +132,54 @@ describe('BrowserView module', () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('BrowserWindow.addBrowserView()', () => {
|
||||||
|
it('does not throw for valid args', () => {
|
||||||
|
let view1 = new BrowserView()
|
||||||
|
w.addBrowserView(view1)
|
||||||
|
let view2 = new BrowserView()
|
||||||
|
w.addBrowserView(view2)
|
||||||
|
view1.destroy()
|
||||||
|
view1 = null
|
||||||
|
view2.destroy()
|
||||||
|
view2 = null
|
||||||
|
})
|
||||||
|
it('does not throw if called multiple times with same view', () => {
|
||||||
|
view = new BrowserView()
|
||||||
|
w.addBrowserView(view)
|
||||||
|
w.addBrowserView(view)
|
||||||
|
w.addBrowserView(view)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('BrowserWindow.removeBrowserView()', () => {
|
||||||
|
it('does not throw if called multiple times with same view', () => {
|
||||||
|
view = new BrowserView()
|
||||||
|
w.addBrowserView(view)
|
||||||
|
w.removeBrowserView(view)
|
||||||
|
w.removeBrowserView(view)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('BrowserWindow.getBrowserViews()', () => {
|
||||||
|
it('returns same views as was added', () => {
|
||||||
|
let view1 = new BrowserView()
|
||||||
|
w.addBrowserView(view1)
|
||||||
|
let view2 = new BrowserView()
|
||||||
|
w.addBrowserView(view2)
|
||||||
|
|
||||||
|
expect(view1.id).to.be.not.null()
|
||||||
|
const views = w.getBrowserViews()
|
||||||
|
expect(views.length).to.equal(2)
|
||||||
|
expect(views[0].webContents.id).to.equal(view1.webContents.id)
|
||||||
|
expect(views[1].webContents.id).to.equal(view2.webContents.id)
|
||||||
|
|
||||||
|
view1.destroy()
|
||||||
|
view1 = null
|
||||||
|
view2.destroy()
|
||||||
|
view2 = null
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe('BrowserView.webContents.getOwnerBrowserWindow()', () => {
|
describe('BrowserView.webContents.getOwnerBrowserWindow()', () => {
|
||||||
it('points to owning window', () => {
|
it('points to owning window', () => {
|
||||||
view = new BrowserView()
|
view = new BrowserView()
|
||||||
|
|
Loading…
Reference in a new issue