feat: replace BrowserView with WebContentsView (#35658)
This commit is contained in:
parent
a94fb2cb5d
commit
15c6014324
76 changed files with 2987 additions and 1531 deletions
18
shell/browser/animation_util.h
Normal file
18
shell/browser/animation_util.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright (c) 2022 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_ANIMATION_UTIL_H_
|
||||
#define ELECTRON_SHELL_BROWSER_ANIMATION_UTIL_H_
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
class ScopedCAActionDisabler {
|
||||
public:
|
||||
ScopedCAActionDisabler();
|
||||
~ScopedCAActionDisabler();
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_ANIMATION_UTIL_H_
|
17
shell/browser/animation_util_mac.mm
Normal file
17
shell/browser/animation_util_mac.mm
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) 2022 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/animation_util.h"
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
// Disables actions within a scope.
|
||||
ScopedCAActionDisabler::ScopedCAActionDisabler() {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
}
|
||||
|
||||
ScopedCAActionDisabler::~ScopedCAActionDisabler() {
|
||||
[CATransaction commit];
|
||||
}
|
|
@ -13,7 +13,6 @@
|
|||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "gin/dictionary.h"
|
||||
#include "shell/browser/api/electron_api_browser_view.h"
|
||||
#include "shell/browser/api/electron_api_menu.h"
|
||||
#include "shell/browser/api/electron_api_view.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
|
@ -97,6 +96,8 @@ BaseWindow::BaseWindow(v8::Isolate* isolate,
|
|||
options, parent.IsEmpty() ? nullptr : parent->window_.get()));
|
||||
window_->AddObserver(this);
|
||||
|
||||
SetContentView(View::Create(isolate));
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
v8::Local<v8::Value> icon;
|
||||
if (options.Get(options::kIcon, &icon)) {
|
||||
|
@ -164,7 +165,6 @@ void BaseWindow::OnWindowClosed() {
|
|||
Emit("closed");
|
||||
|
||||
RemoveFromParentChildWindows();
|
||||
BaseWindow::ResetBrowserViews();
|
||||
|
||||
// Destroy the native class when window is closed.
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
|
||||
|
@ -311,8 +311,7 @@ void BaseWindow::OnWindowMessage(UINT message, WPARAM w_param, LPARAM l_param) {
|
|||
#endif
|
||||
|
||||
void BaseWindow::SetContentView(gin::Handle<View> view) {
|
||||
ResetBrowserViews();
|
||||
content_view_.Reset(isolate(), view.ToV8());
|
||||
content_view_.Reset(JavascriptEnvironment::GetIsolate(), view.ToV8());
|
||||
window_->SetContentView(view->view());
|
||||
}
|
||||
|
||||
|
@ -749,70 +748,6 @@ void BaseWindow::SetParentWindow(v8::Local<v8::Value> value,
|
|||
}
|
||||
}
|
||||
|
||||
void BaseWindow::SetBrowserView(
|
||||
absl::optional<gin::Handle<BrowserView>> browser_view) {
|
||||
ResetBrowserViews();
|
||||
if (browser_view)
|
||||
AddBrowserView(*browser_view);
|
||||
}
|
||||
|
||||
void BaseWindow::AddBrowserView(gin::Handle<BrowserView> browser_view) {
|
||||
if (!base::Contains(browser_views_, browser_view.ToV8())) {
|
||||
// If we're reparenting a BrowserView, ensure that it's detached from
|
||||
// its previous owner window.
|
||||
BaseWindow* owner_window = browser_view->owner_window();
|
||||
if (owner_window) {
|
||||
// iter == browser_views_.end() should imply owner_window != this.
|
||||
DCHECK_NE(owner_window, this);
|
||||
owner_window->RemoveBrowserView(browser_view);
|
||||
browser_view->SetOwnerWindow(nullptr);
|
||||
}
|
||||
|
||||
// If the user set the BrowserView's bounds before adding it to the window,
|
||||
// we need to get those initial bounds *before* adding it to the window
|
||||
// so bounds isn't returned relative despite not being correctly positioned
|
||||
// relative to the window.
|
||||
auto bounds = browser_view->GetBounds();
|
||||
|
||||
window_->AddBrowserView(browser_view->view());
|
||||
window_->AddDraggableRegionProvider(browser_view.get());
|
||||
browser_view->SetOwnerWindow(this);
|
||||
browser_views_.emplace_back().Reset(isolate(), browser_view.ToV8());
|
||||
|
||||
// Recalibrate bounds relative to the containing window.
|
||||
if (!bounds.IsEmpty())
|
||||
browser_view->SetBounds(bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseWindow::RemoveBrowserView(gin::Handle<BrowserView> browser_view) {
|
||||
auto iter = std::find(browser_views_.begin(), browser_views_.end(),
|
||||
browser_view.ToV8());
|
||||
|
||||
if (iter != browser_views_.end()) {
|
||||
window_->RemoveDraggableRegionProvider(browser_view.get());
|
||||
window_->RemoveBrowserView(browser_view->view());
|
||||
browser_view->SetOwnerWindow(nullptr);
|
||||
iter->Reset();
|
||||
browser_views_.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseWindow::SetTopBrowserView(gin::Handle<BrowserView> browser_view,
|
||||
gin_helper::Arguments* args) {
|
||||
BaseWindow* owner_window = browser_view->owner_window();
|
||||
auto iter = std::find(browser_views_.begin(), browser_views_.end(),
|
||||
browser_view.ToV8());
|
||||
if (iter == browser_views_.end() || (owner_window && owner_window != this)) {
|
||||
args->ThrowError("Given BrowserView is not attached to the window");
|
||||
return;
|
||||
}
|
||||
|
||||
browser_views_.erase(iter);
|
||||
browser_views_.emplace_back().Reset(isolate(), browser_view.ToV8());
|
||||
window_->SetTopBrowserView(browser_view->view());
|
||||
}
|
||||
|
||||
std::string BaseWindow::GetMediaSourceId() const {
|
||||
return window_->GetDesktopMediaID().ToString();
|
||||
}
|
||||
|
@ -1018,31 +953,6 @@ std::vector<v8::Local<v8::Object>> BaseWindow::GetChildWindows() const {
|
|||
return child_windows_.Values(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> BaseWindow::GetBrowserView(
|
||||
gin_helper::Arguments* args) const {
|
||||
if (browser_views_.empty()) {
|
||||
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);
|
||||
} else {
|
||||
args->ThrowError(
|
||||
"BrowserWindow have multiple BrowserViews, "
|
||||
"Use getBrowserViews() instead");
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<v8::Local<v8::Value>> BaseWindow::GetBrowserViews() const {
|
||||
std::vector<v8::Local<v8::Value>> ret;
|
||||
|
||||
for (auto const& browser_view : browser_views_) {
|
||||
ret.push_back(v8::Local<v8::Value>::New(isolate(), browser_view));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool BaseWindow::IsModal() const {
|
||||
return window_->is_modal();
|
||||
}
|
||||
|
@ -1140,31 +1050,6 @@ int32_t BaseWindow::GetID() const {
|
|||
return weak_map_id();
|
||||
}
|
||||
|
||||
void BaseWindow::ResetBrowserViews() {
|
||||
v8::HandleScope scope(isolate());
|
||||
|
||||
for (auto& item : browser_views_) {
|
||||
gin::Handle<BrowserView> browser_view;
|
||||
if (gin::ConvertFromV8(isolate(),
|
||||
v8::Local<v8::Value>::New(isolate(), item),
|
||||
&browser_view) &&
|
||||
!browser_view.IsEmpty()) {
|
||||
// There's a chance that the BrowserView may have been reparented - only
|
||||
// reset if the owner window is *this* window.
|
||||
BaseWindow* owner_window = browser_view->owner_window();
|
||||
DCHECK_EQ(owner_window, this);
|
||||
browser_view->SetOwnerWindow(nullptr);
|
||||
window_->RemoveBrowserView(browser_view->view());
|
||||
window_->RemoveDraggableRegionProvider(browser_view.get());
|
||||
browser_view->SetOwnerWindow(nullptr);
|
||||
}
|
||||
|
||||
item.Reset();
|
||||
}
|
||||
|
||||
browser_views_.clear();
|
||||
}
|
||||
|
||||
void BaseWindow::RemoveFromParentChildWindows() {
|
||||
if (parent_window_.IsEmpty())
|
||||
return;
|
||||
|
@ -1274,10 +1159,6 @@ void BaseWindow::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetMethod("setMenu", &BaseWindow::SetMenu)
|
||||
.SetMethod("removeMenu", &BaseWindow::RemoveMenu)
|
||||
.SetMethod("setParentWindow", &BaseWindow::SetParentWindow)
|
||||
.SetMethod("setBrowserView", &BaseWindow::SetBrowserView)
|
||||
.SetMethod("addBrowserView", &BaseWindow::AddBrowserView)
|
||||
.SetMethod("removeBrowserView", &BaseWindow::RemoveBrowserView)
|
||||
.SetMethod("setTopBrowserView", &BaseWindow::SetTopBrowserView)
|
||||
.SetMethod("getMediaSourceId", &BaseWindow::GetMediaSourceId)
|
||||
.SetMethod("getNativeWindowHandle", &BaseWindow::GetNativeWindowHandle)
|
||||
.SetMethod("setProgressBar", &BaseWindow::SetProgressBar)
|
||||
|
@ -1333,10 +1214,10 @@ void BaseWindow::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetMethod("previewFile", &BaseWindow::PreviewFile)
|
||||
.SetMethod("closeFilePreview", &BaseWindow::CloseFilePreview)
|
||||
.SetMethod("getContentView", &BaseWindow::GetContentView)
|
||||
.SetProperty("contentView", &BaseWindow::GetContentView,
|
||||
&BaseWindow::SetContentView)
|
||||
.SetMethod("getParentWindow", &BaseWindow::GetParentWindow)
|
||||
.SetMethod("getChildWindows", &BaseWindow::GetChildWindows)
|
||||
.SetMethod("getBrowserView", &BaseWindow::GetBrowserView)
|
||||
.SetMethod("getBrowserViews", &BaseWindow::GetBrowserViews)
|
||||
.SetMethod("isModal", &BaseWindow::IsModal)
|
||||
.SetMethod("setThumbarButtons", &BaseWindow::SetThumbarButtons)
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
namespace electron::api {
|
||||
|
||||
class View;
|
||||
class BrowserView;
|
||||
|
||||
class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
||||
public NativeWindowObserver {
|
||||
|
@ -173,14 +172,6 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
|||
void SetMenu(v8::Isolate* isolate, v8::Local<v8::Value> menu);
|
||||
void RemoveMenu();
|
||||
void SetParentWindow(v8::Local<v8::Value> value, gin_helper::Arguments* args);
|
||||
virtual void SetBrowserView(
|
||||
absl::optional<gin::Handle<BrowserView>> browser_view);
|
||||
virtual void AddBrowserView(gin::Handle<BrowserView> browser_view);
|
||||
virtual void RemoveBrowserView(gin::Handle<BrowserView> browser_view);
|
||||
virtual void SetTopBrowserView(gin::Handle<BrowserView> browser_view,
|
||||
gin_helper::Arguments* args);
|
||||
virtual std::vector<v8::Local<v8::Value>> GetBrowserViews() const;
|
||||
virtual void ResetBrowserViews();
|
||||
std::string GetMediaSourceId() const;
|
||||
v8::Local<v8::Value> GetNativeWindowHandle();
|
||||
void SetProgressBar(double progress, gin_helper::Arguments* args);
|
||||
|
@ -227,7 +218,6 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
|||
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(gin_helper::Arguments* args) const;
|
||||
bool IsModal() const;
|
||||
|
||||
// Extra APIs added in JS.
|
||||
|
@ -254,9 +244,6 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
|||
|
||||
// Helpers.
|
||||
|
||||
// Remove BrowserView.
|
||||
void ResetBrowserView();
|
||||
|
||||
// Remove this window from parent window's |child_windows_|.
|
||||
void RemoveFromParentChildWindows();
|
||||
|
||||
|
@ -274,7 +261,6 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
|||
#endif
|
||||
|
||||
v8::Global<v8::Value> content_view_;
|
||||
std::vector<v8::Global<v8::Value>> browser_views_;
|
||||
v8::Global<v8::Value> menu_;
|
||||
v8::Global<v8::Value> parent_window_;
|
||||
KeyWeakMap<int> child_windows_;
|
||||
|
|
|
@ -1,231 +0,0 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/api/electron_api_browser_view.h"
|
||||
|
||||
#include "content/browser/renderer_host/render_widget_host_view_base.h" // nogncheck
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "shell/browser/api/electron_api_base_window.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
#include "shell/browser/ui/drag_util.h"
|
||||
#include "shell/browser/web_contents_preferences.h"
|
||||
#include "shell/common/color_util.h"
|
||||
#include "shell/common/gin_converters/gfx_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/object_template_builder.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "shell/common/options_switches.h"
|
||||
#include "ui/base/hit_test.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
||||
namespace gin {
|
||||
|
||||
template <>
|
||||
struct Converter<electron::AutoResizeFlags> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
electron::AutoResizeFlags* auto_resize_flags) {
|
||||
gin_helper::Dictionary params;
|
||||
if (!ConvertFromV8(isolate, val, ¶ms)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t flags = 0;
|
||||
bool width = false;
|
||||
if (params.Get("width", &width) && width) {
|
||||
flags |= electron::kAutoResizeWidth;
|
||||
}
|
||||
bool height = false;
|
||||
if (params.Get("height", &height) && height) {
|
||||
flags |= electron::kAutoResizeHeight;
|
||||
}
|
||||
bool horizontal = false;
|
||||
if (params.Get("horizontal", &horizontal) && horizontal) {
|
||||
flags |= electron::kAutoResizeHorizontal;
|
||||
}
|
||||
bool vertical = false;
|
||||
if (params.Get("vertical", &vertical) && vertical) {
|
||||
flags |= electron::kAutoResizeVertical;
|
||||
}
|
||||
|
||||
*auto_resize_flags = static_cast<electron::AutoResizeFlags>(flags);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gin
|
||||
|
||||
namespace {
|
||||
|
||||
int32_t GetNextId() {
|
||||
static int32_t next_id = 1;
|
||||
return next_id++;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
gin::WrapperInfo BrowserView::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
|
||||
BrowserView::BrowserView(gin::Arguments* args,
|
||||
const gin_helper::Dictionary& options)
|
||||
: id_(GetNextId()) {
|
||||
auto web_preferences = gin_helper::Dictionary::CreateEmpty(args->isolate());
|
||||
options.Get(options::kWebPreferences, &web_preferences);
|
||||
web_preferences.Set("type", "browserView");
|
||||
|
||||
v8::Local<v8::Value> value;
|
||||
|
||||
// Copy the webContents option to webPreferences.
|
||||
if (options.Get("webContents", &value)) {
|
||||
web_preferences.SetHidden("webContents", value);
|
||||
}
|
||||
|
||||
auto web_contents =
|
||||
WebContents::CreateFromWebPreferences(args->isolate(), web_preferences);
|
||||
|
||||
web_contents_.Reset(args->isolate(), web_contents.ToV8());
|
||||
api_web_contents_ = web_contents.get();
|
||||
api_web_contents_->AddObserver(this);
|
||||
Observe(web_contents->web_contents());
|
||||
|
||||
view_.reset(
|
||||
NativeBrowserView::Create(api_web_contents_->inspectable_web_contents()));
|
||||
}
|
||||
|
||||
void BrowserView::SetOwnerWindow(BaseWindow* window) {
|
||||
// Ensure WebContents and BrowserView owner windows are in sync.
|
||||
if (web_contents())
|
||||
web_contents()->SetOwnerWindow(window ? window->window() : nullptr);
|
||||
|
||||
owner_window_ = window ? window->GetWeakPtr() : nullptr;
|
||||
}
|
||||
|
||||
int BrowserView::NonClientHitTest(const gfx::Point& point) {
|
||||
gfx::Rect bounds = GetBounds();
|
||||
gfx::Point local_point(point.x() - bounds.x(), point.y() - bounds.y());
|
||||
SkRegion* region = api_web_contents_->draggable_region();
|
||||
if (region && region->contains(local_point.x(), local_point.y()))
|
||||
return HTCAPTION;
|
||||
return HTNOWHERE;
|
||||
}
|
||||
|
||||
BrowserView::~BrowserView() {
|
||||
if (web_contents()) { // destroy() called without closing WebContents
|
||||
web_contents()->RemoveObserver(this);
|
||||
web_contents()->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void BrowserView::WebContentsDestroyed() {
|
||||
if (owner_window())
|
||||
owner_window()->window()->RemoveDraggableRegionProvider(this);
|
||||
|
||||
api_web_contents_ = nullptr;
|
||||
web_contents_.Reset();
|
||||
Unpin();
|
||||
}
|
||||
|
||||
void BrowserView::OnCloseContents() {
|
||||
api_web_contents_ = nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<BrowserView> BrowserView::New(gin_helper::ErrorThrower thrower,
|
||||
gin::Arguments* args) {
|
||||
if (!Browser::Get()->is_ready()) {
|
||||
thrower.ThrowError("Cannot create BrowserView before app is ready");
|
||||
return gin::Handle<BrowserView>();
|
||||
}
|
||||
|
||||
auto options = gin::Dictionary::CreateEmpty(args->isolate());
|
||||
args->GetNext(&options);
|
||||
|
||||
auto handle =
|
||||
gin::CreateHandle(args->isolate(), new BrowserView(args, options));
|
||||
handle->Pin(args->isolate());
|
||||
return handle;
|
||||
}
|
||||
|
||||
void BrowserView::SetAutoResize(AutoResizeFlags flags) {
|
||||
view_->SetAutoResizeFlags(flags);
|
||||
}
|
||||
|
||||
void BrowserView::SetBounds(const gfx::Rect& bounds) {
|
||||
view_->SetBounds(bounds);
|
||||
}
|
||||
|
||||
gfx::Rect BrowserView::GetBounds() {
|
||||
return view_->GetBounds();
|
||||
}
|
||||
|
||||
void BrowserView::SetBackgroundColor(const std::string& color_name) {
|
||||
SkColor color = ParseCSSColor(color_name);
|
||||
view_->SetBackgroundColor(color);
|
||||
|
||||
if (web_contents()) {
|
||||
auto* wc = web_contents()->web_contents();
|
||||
wc->SetPageBaseBackgroundColor(ParseCSSColor(color_name));
|
||||
|
||||
auto* const rwhv = wc->GetRenderWidgetHostView();
|
||||
if (rwhv) {
|
||||
rwhv->SetBackgroundColor(color);
|
||||
static_cast<content::RenderWidgetHostViewBase*>(rwhv)
|
||||
->SetContentBackgroundColor(color);
|
||||
}
|
||||
|
||||
// Ensure new color is stored in webPreferences, otherwise
|
||||
// the color will be reset on the next load via HandleNewRenderFrame.
|
||||
auto* web_preferences = WebContentsPreferences::From(wc);
|
||||
if (web_preferences)
|
||||
web_preferences->SetBackgroundColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> BrowserView::GetWebContents(v8::Isolate* isolate) {
|
||||
if (web_contents_.IsEmpty()) {
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
return v8::Local<v8::Value>::New(isolate, web_contents_);
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserView::FillObjectTemplate(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> templ) {
|
||||
gin::ObjectTemplateBuilder(isolate, GetClassName(), templ)
|
||||
.SetMethod("setAutoResize", &BrowserView::SetAutoResize)
|
||||
.SetMethod("setBounds", &BrowserView::SetBounds)
|
||||
.SetMethod("getBounds", &BrowserView::GetBounds)
|
||||
.SetMethod("setBackgroundColor", &BrowserView::SetBackgroundColor)
|
||||
.SetProperty("webContents", &BrowserView::GetWebContents)
|
||||
.Build();
|
||||
}
|
||||
|
||||
const char* BrowserView::GetTypeName() {
|
||||
return GetClassName();
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
namespace {
|
||||
|
||||
using electron::api::BrowserView;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
|
||||
gin_helper::Dictionary dict(isolate, exports);
|
||||
dict.Set("BrowserView", BrowserView::GetConstructor(context));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_browser_view, Initialize)
|
|
@ -1,98 +0,0 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_BROWSER_VIEW_H_
|
||||
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_BROWSER_VIEW_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "gin/handle.h"
|
||||
#include "gin/wrappable.h"
|
||||
#include "shell/browser/draggable_region_provider.h"
|
||||
#include "shell/browser/extended_web_contents_observer.h"
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/common/api/api.mojom.h"
|
||||
#include "shell/common/gin_helper/constructible.h"
|
||||
#include "shell/common/gin_helper/error_thrower.h"
|
||||
#include "shell/common/gin_helper/pinnable.h"
|
||||
|
||||
namespace gfx {
|
||||
class Rect;
|
||||
}
|
||||
|
||||
namespace gin_helper {
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
class WebContents;
|
||||
class BaseWindow;
|
||||
|
||||
class BrowserView : public gin::Wrappable<BrowserView>,
|
||||
public gin_helper::Constructible<BrowserView>,
|
||||
public gin_helper::Pinnable<BrowserView>,
|
||||
public content::WebContentsObserver,
|
||||
public ExtendedWebContentsObserver,
|
||||
public DraggableRegionProvider {
|
||||
public:
|
||||
// gin_helper::Constructible
|
||||
static gin::Handle<BrowserView> New(gin_helper::ErrorThrower thrower,
|
||||
gin::Arguments* args);
|
||||
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
|
||||
static const char* GetClassName() { return "BrowserView"; }
|
||||
|
||||
// gin::Wrappable
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
const char* GetTypeName() override;
|
||||
|
||||
WebContents* web_contents() const { return api_web_contents_; }
|
||||
NativeBrowserView* view() const { return view_.get(); }
|
||||
|
||||
BaseWindow* owner_window() const { return owner_window_.get(); }
|
||||
|
||||
void SetOwnerWindow(BaseWindow* window);
|
||||
|
||||
int32_t ID() const { return id_; }
|
||||
|
||||
int NonClientHitTest(const gfx::Point& point) override;
|
||||
|
||||
// disable copy
|
||||
BrowserView(const BrowserView&) = delete;
|
||||
BrowserView& operator=(const BrowserView&) = delete;
|
||||
|
||||
gfx::Rect GetBounds();
|
||||
void SetBounds(const gfx::Rect& bounds);
|
||||
|
||||
protected:
|
||||
BrowserView(gin::Arguments* args, const gin_helper::Dictionary& options);
|
||||
~BrowserView() override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void WebContentsDestroyed() override;
|
||||
|
||||
// ExtendedWebContentsObserver:
|
||||
void OnCloseContents() override;
|
||||
|
||||
private:
|
||||
void SetAutoResize(AutoResizeFlags flags);
|
||||
void SetBackgroundColor(const std::string& color_name);
|
||||
v8::Local<v8::Value> GetWebContents(v8::Isolate*);
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
class raw_ptr<WebContents> api_web_contents_ = nullptr;
|
||||
|
||||
std::unique_ptr<NativeBrowserView> view_;
|
||||
base::WeakPtr<BaseWindow> owner_window_;
|
||||
|
||||
int32_t id_;
|
||||
};
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_API_ELECTRON_API_BROWSER_VIEW_H_
|
|
@ -13,7 +13,6 @@
|
|||
#include "content/public/common/color_parser.h"
|
||||
#include "shell/browser/api/electron_api_web_contents_view.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
#include "shell/browser/web_contents_preferences.h"
|
||||
#include "shell/browser/window_list.h"
|
||||
#include "shell/common/color_util.h"
|
||||
|
@ -70,6 +69,9 @@ BrowserWindow::BrowserWindow(gin::Arguments* args,
|
|||
web_preferences.SetHidden("webContents", value);
|
||||
}
|
||||
|
||||
if (!web_preferences.Has(options::kShow))
|
||||
web_preferences.Set(options::kShow, true);
|
||||
|
||||
// Creates the WebContentsView.
|
||||
gin::Handle<WebContentsView> web_contents_view =
|
||||
WebContentsView::Create(isolate, web_preferences);
|
||||
|
@ -101,8 +103,6 @@ BrowserWindow::~BrowserWindow() {
|
|||
// Cleanup the observers if user destroyed this instance directly instead of
|
||||
// gracefully closing content::WebContents.
|
||||
api_web_contents_->RemoveObserver(this);
|
||||
// Destroy the WebContents.
|
||||
OnCloseContents();
|
||||
api_web_contents_->Destroy();
|
||||
}
|
||||
}
|
||||
|
@ -129,10 +129,6 @@ void BrowserWindow::WebContentsDestroyed() {
|
|||
CloseImmediately();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnCloseContents() {
|
||||
BaseWindow::ResetBrowserViews();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererResponsive(content::RenderProcessHost*) {
|
||||
window_unresponsive_closure_.Cancel();
|
||||
Emit("responsive");
|
||||
|
@ -187,26 +183,6 @@ void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
|
|||
// Required to make beforeunload handler work.
|
||||
api_web_contents_->NotifyUserActivation();
|
||||
|
||||
// Trigger beforeunload events for associated BrowserViews.
|
||||
for (NativeBrowserView* view : window_->browser_views()) {
|
||||
auto* iwc = view->GetInspectableWebContents();
|
||||
if (!iwc)
|
||||
continue;
|
||||
|
||||
auto* vwc = iwc->GetWebContents();
|
||||
auto* api_web_contents = api::WebContents::From(vwc);
|
||||
|
||||
// Required to make beforeunload handler work.
|
||||
if (api_web_contents)
|
||||
api_web_contents->NotifyUserActivation();
|
||||
|
||||
if (vwc) {
|
||||
if (vwc->NeedToFireBeforeUnloadOrUnloadEvents()) {
|
||||
vwc->DispatchBeforeUnload(false /* auto_cancel */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (web_contents()->NeedToFireBeforeUnloadOrUnloadEvents()) {
|
||||
web_contents()->DispatchBeforeUnload(false /* auto_cancel */);
|
||||
} else {
|
||||
|
@ -288,16 +264,10 @@ void BrowserWindow::Blur() {
|
|||
void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
|
||||
BaseWindow::SetBackgroundColor(color_name);
|
||||
SkColor color = ParseCSSColor(color_name);
|
||||
web_contents()->SetPageBaseBackgroundColor(color);
|
||||
auto* rwhv = web_contents()->GetRenderWidgetHostView();
|
||||
if (rwhv) {
|
||||
rwhv->SetBackgroundColor(color);
|
||||
static_cast<content::RenderWidgetHostViewBase*>(rwhv)
|
||||
->SetContentBackgroundColor(color);
|
||||
}
|
||||
// Also update the web preferences object otherwise the view will be reset on
|
||||
// the next load URL call
|
||||
if (api_web_contents_) {
|
||||
api_web_contents_->SetBackgroundColor(color);
|
||||
// Also update the web preferences object otherwise the view will be reset
|
||||
// on the next load URL call
|
||||
auto* web_preferences =
|
||||
WebContentsPreferences::From(api_web_contents_->web_contents());
|
||||
if (web_preferences) {
|
||||
|
@ -306,13 +276,6 @@ void BrowserWindow::SetBackgroundColor(const std::string& color_name) {
|
|||
}
|
||||
}
|
||||
|
||||
void BrowserWindow::SetBrowserView(
|
||||
absl::optional<gin::Handle<BrowserView>> browser_view) {
|
||||
BaseWindow::ResetBrowserViews();
|
||||
if (browser_view)
|
||||
BaseWindow::AddBrowserView(*browser_view);
|
||||
}
|
||||
|
||||
void BrowserWindow::FocusOnWebView() {
|
||||
web_contents()->GetRenderViewHost()->GetWidget()->Focus();
|
||||
}
|
||||
|
|
|
@ -49,7 +49,6 @@ class BrowserWindow : public BaseWindow,
|
|||
void WebContentsDestroyed() override;
|
||||
|
||||
// ExtendedWebContentsObserver:
|
||||
void OnCloseContents() override;
|
||||
void OnSetContentBounds(const gfx::Rect& rect) override;
|
||||
void OnActivateContents() override;
|
||||
void OnPageTitleUpdated(const std::u16string& title,
|
||||
|
@ -69,8 +68,6 @@ class BrowserWindow : public BaseWindow,
|
|||
void Focus() override;
|
||||
void Blur() override;
|
||||
void SetBackgroundColor(const std::string& color_name) override;
|
||||
void SetBrowserView(
|
||||
absl::optional<gin::Handle<BrowserView>> browser_view) override;
|
||||
void OnWindowShow() override;
|
||||
void OnWindowHide() override;
|
||||
|
||||
|
|
|
@ -4,34 +4,357 @@
|
|||
|
||||
#include "shell/browser/api/electron_api_view.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "gin/data_object_builder.h"
|
||||
#include "gin/wrappable.h"
|
||||
#include "shell/browser/javascript_environment.h"
|
||||
#include "shell/common/gin_converters/callback_converter.h"
|
||||
#include "shell/common/gin_converters/gfx_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/object_template_builder.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/layout/flex_layout.h"
|
||||
#include "ui/views/layout/layout_manager_base.h"
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
#include "shell/browser/animation_util.h"
|
||||
#endif
|
||||
|
||||
namespace gin {
|
||||
|
||||
template <>
|
||||
struct Converter<views::ChildLayout> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
views::ChildLayout* out) {
|
||||
gin_helper::Dictionary dict;
|
||||
if (!gin::ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
gin::Handle<electron::api::View> view;
|
||||
if (!dict.Get("view", &view))
|
||||
return false;
|
||||
out->child_view = view->view();
|
||||
if (dict.Has("bounds"))
|
||||
dict.Get("bounds", &out->bounds);
|
||||
out->visible = true;
|
||||
if (dict.Has("visible"))
|
||||
dict.Get("visible", &out->visible);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<views::ProposedLayout> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
views::ProposedLayout* out) {
|
||||
gin_helper::Dictionary dict;
|
||||
if (!gin::ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
if (!dict.Get("size", &out->host_size))
|
||||
return false;
|
||||
if (!dict.Get("layouts", &out->child_layouts))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<views::LayoutOrientation> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
views::LayoutOrientation* out) {
|
||||
std::string orientation = base::ToLowerASCII(gin::V8ToString(isolate, val));
|
||||
if (orientation == "horizontal") {
|
||||
*out = views::LayoutOrientation::kHorizontal;
|
||||
} else if (orientation == "vertical") {
|
||||
*out = views::LayoutOrientation::kVertical;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<views::LayoutAlignment> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
views::LayoutAlignment* out) {
|
||||
std::string orientation = base::ToLowerASCII(gin::V8ToString(isolate, val));
|
||||
if (orientation == "start") {
|
||||
*out = views::LayoutAlignment::kStart;
|
||||
} else if (orientation == "center") {
|
||||
*out = views::LayoutAlignment::kCenter;
|
||||
} else if (orientation == "end") {
|
||||
*out = views::LayoutAlignment::kEnd;
|
||||
} else if (orientation == "stretch") {
|
||||
*out = views::LayoutAlignment::kStretch;
|
||||
} else if (orientation == "baseline") {
|
||||
*out = views::LayoutAlignment::kBaseline;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<views::FlexAllocationOrder> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
views::FlexAllocationOrder* out) {
|
||||
std::string orientation = base::ToLowerASCII(gin::V8ToString(isolate, val));
|
||||
if (orientation == "normal") {
|
||||
*out = views::FlexAllocationOrder::kNormal;
|
||||
} else if (orientation == "reverse") {
|
||||
*out = views::FlexAllocationOrder::kReverse;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<views::SizeBound> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const views::SizeBound& in) {
|
||||
if (in.is_bounded())
|
||||
return v8::Integer::New(isolate, in.value());
|
||||
return v8::Number::New(isolate, std::numeric_limits<double>::infinity());
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<views::SizeBounds> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const views::SizeBounds& in) {
|
||||
return gin::DataObjectBuilder(isolate)
|
||||
.Set("width", in.width())
|
||||
.Set("height", in.height())
|
||||
.Build();
|
||||
}
|
||||
};
|
||||
} // namespace gin
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
using LayoutCallback = base::RepeatingCallback<views::ProposedLayout(
|
||||
const views::SizeBounds& size_bounds)>;
|
||||
|
||||
class JSLayoutManager : public views::LayoutManagerBase {
|
||||
public:
|
||||
explicit JSLayoutManager(LayoutCallback layout_callback)
|
||||
: layout_callback_(std::move(layout_callback)) {}
|
||||
~JSLayoutManager() override {}
|
||||
|
||||
views::ProposedLayout CalculateProposedLayout(
|
||||
const views::SizeBounds& size_bounds) const override {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
return layout_callback_.Run(size_bounds);
|
||||
}
|
||||
|
||||
private:
|
||||
LayoutCallback layout_callback_;
|
||||
};
|
||||
|
||||
View::View(views::View* view) : view_(view) {
|
||||
view_->set_owned_by_client();
|
||||
view_->AddObserver(this);
|
||||
}
|
||||
|
||||
View::View() : View(new views::View()) {}
|
||||
|
||||
View::~View() {
|
||||
if (!view_)
|
||||
return;
|
||||
view_->RemoveObserver(this);
|
||||
if (delete_view_)
|
||||
delete view_;
|
||||
}
|
||||
|
||||
void View::AddChildViewAt(gin::Handle<View> child,
|
||||
absl::optional<size_t> maybe_index) {
|
||||
// TODO(nornagon): !view_ is only for supporting the weird case of
|
||||
// WebContentsView's view being deleted when the underlying WebContents is
|
||||
// destroyed (on non-Mac). We should fix that so that WebContentsView always
|
||||
// has a View, possibly a wrapper view around the underlying platform View.
|
||||
if (!view_)
|
||||
return;
|
||||
size_t index =
|
||||
std::min(child_views_.size(), maybe_index.value_or(child_views_.size()));
|
||||
child_views_.emplace(child_views_.begin() + index, // index
|
||||
isolate(), child->GetWrapper()); // v8::Global(args...)
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
// Disable the implicit CALayer animations that happen by default when adding
|
||||
// or removing sublayers.
|
||||
// See
|
||||
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/ReactingtoLayerChanges/ReactingtoLayerChanges.html
|
||||
// and https://github.com/electron/electron/pull/14911
|
||||
// TODO(nornagon): Disabling these CALayer animations (which are specific to
|
||||
// WebContentsView, I think) seems like this is something that remote_cocoa
|
||||
// or views should be taking care of, but isn't. This should be pushed
|
||||
// upstream.
|
||||
ScopedCAActionDisabler disable_animations;
|
||||
#endif
|
||||
view_->AddChildViewAt(child->view(), index);
|
||||
}
|
||||
|
||||
void View::RemoveChildView(gin::Handle<View> child) {
|
||||
if (!view_)
|
||||
return;
|
||||
if (!child->view())
|
||||
return;
|
||||
auto it = std::find(child_views_.begin(), child_views_.end(), child.ToV8());
|
||||
if (it != child_views_.end()) {
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
ScopedCAActionDisabler disable_animations;
|
||||
#endif
|
||||
view_->RemoveChildView(child->view());
|
||||
child_views_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void View::SetBounds(const gfx::Rect& bounds) {
|
||||
if (!view_)
|
||||
return;
|
||||
view_->SetBoundsRect(bounds);
|
||||
}
|
||||
|
||||
gfx::Rect View::GetBounds() {
|
||||
if (!view_)
|
||||
return gfx::Rect();
|
||||
return view_->bounds();
|
||||
}
|
||||
|
||||
void View::SetLayout(v8::Isolate* isolate, v8::Local<v8::Object> value) {
|
||||
if (!view_)
|
||||
return;
|
||||
gin_helper::Dictionary dict(isolate, value);
|
||||
LayoutCallback calculate_proposed_layout;
|
||||
if (dict.Get("calculateProposedLayout", &calculate_proposed_layout)) {
|
||||
view_->SetLayoutManager(std::make_unique<JSLayoutManager>(
|
||||
std::move(calculate_proposed_layout)));
|
||||
} else {
|
||||
auto* layout =
|
||||
view_->SetLayoutManager(std::make_unique<views::FlexLayout>());
|
||||
views::LayoutOrientation orientation;
|
||||
if (dict.Get("orientation", &orientation))
|
||||
layout->SetOrientation(orientation);
|
||||
views::LayoutAlignment main_axis_alignment;
|
||||
if (dict.Get("mainAxisAlignment", &main_axis_alignment))
|
||||
layout->SetMainAxisAlignment(main_axis_alignment);
|
||||
views::LayoutAlignment cross_axis_alignment;
|
||||
if (dict.Get("crossAxisAlignment", &cross_axis_alignment))
|
||||
layout->SetCrossAxisAlignment(cross_axis_alignment);
|
||||
gfx::Insets interior_margin;
|
||||
if (dict.Get("interiorMargin", &interior_margin))
|
||||
layout->SetInteriorMargin(interior_margin);
|
||||
int minimum_cross_axis_size;
|
||||
if (dict.Get("minimumCrossAxisSize", &minimum_cross_axis_size))
|
||||
layout->SetMinimumCrossAxisSize(minimum_cross_axis_size);
|
||||
bool collapse_margins;
|
||||
if (dict.Has("collapseMargins") &&
|
||||
dict.Get("collapseMargins", &collapse_margins))
|
||||
layout->SetCollapseMargins(collapse_margins);
|
||||
bool include_host_insets_in_layout;
|
||||
if (dict.Has("includeHostInsetsInLayout") &&
|
||||
dict.Get("includeHostInsetsInLayout", &include_host_insets_in_layout))
|
||||
layout->SetIncludeHostInsetsInLayout(include_host_insets_in_layout);
|
||||
bool ignore_default_main_axis_margins;
|
||||
if (dict.Has("ignoreDefaultMainAxisMargins") &&
|
||||
dict.Get("ignoreDefaultMainAxisMargins",
|
||||
&ignore_default_main_axis_margins))
|
||||
layout->SetIgnoreDefaultMainAxisMargins(ignore_default_main_axis_margins);
|
||||
views::FlexAllocationOrder flex_allocation_order;
|
||||
if (dict.Get("flexAllocationOrder", &flex_allocation_order))
|
||||
layout->SetFlexAllocationOrder(flex_allocation_order);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<v8::Local<v8::Value>> View::GetChildren() {
|
||||
std::vector<v8::Local<v8::Value>> ret;
|
||||
ret.reserve(child_views_.size());
|
||||
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
|
||||
for (auto& child_view : child_views_)
|
||||
ret.push_back(child_view.Get(isolate));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void View::SetBackgroundColor(absl::optional<WrappedSkColor> color) {
|
||||
if (!view_)
|
||||
return;
|
||||
view_->SetBackground(color ? views::CreateSolidBackground(*color) : nullptr);
|
||||
}
|
||||
|
||||
void View::SetVisible(bool visible) {
|
||||
if (!view_)
|
||||
return;
|
||||
view_->SetVisible(visible);
|
||||
}
|
||||
|
||||
void View::OnViewBoundsChanged(views::View* observed_view) {
|
||||
Emit("bounds-changed");
|
||||
}
|
||||
|
||||
void View::OnViewIsDeleting(views::View* observed_view) {
|
||||
DCHECK_EQ(observed_view, view_);
|
||||
view_ = nullptr;
|
||||
}
|
||||
|
||||
// static
|
||||
gin_helper::WrappableBase* View::New(gin::Arguments* args) {
|
||||
auto* view = new View();
|
||||
View* view = new View();
|
||||
view->InitWithArgs(args);
|
||||
return view;
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Function> View::GetConstructor(v8::Isolate* isolate) {
|
||||
static base::NoDestructor<v8::Global<v8::Function>> constructor;
|
||||
if (constructor.get()->IsEmpty()) {
|
||||
constructor->Reset(isolate, gin_helper::CreateConstructor<View>(
|
||||
isolate, base::BindRepeating(&View::New)));
|
||||
}
|
||||
return v8::Local<v8::Function>::New(isolate, *constructor.get());
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<View> View::Create(v8::Isolate* isolate) {
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
v8::Local<v8::Object> obj;
|
||||
if (GetConstructor(isolate)->NewInstance(context, 0, nullptr).ToLocal(&obj)) {
|
||||
gin::Handle<View> view;
|
||||
if (gin::ConvertFromV8(isolate, obj, &view))
|
||||
return view;
|
||||
}
|
||||
return gin::Handle<View>();
|
||||
}
|
||||
|
||||
// static
|
||||
void View::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(gin::StringToV8(isolate, "View"));
|
||||
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("addChildView", &View::AddChildViewAt)
|
||||
.SetMethod("removeChildView", &View::RemoveChildView)
|
||||
.SetProperty("children", &View::GetChildren)
|
||||
.SetMethod("setBounds", &View::SetBounds)
|
||||
.SetMethod("getBounds", &View::GetBounds)
|
||||
.SetMethod("setBackgroundColor", &View::SetBackgroundColor)
|
||||
.SetMethod("setLayout", &View::SetLayout)
|
||||
.SetMethod("setVisible", &View::SetVisible);
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
|
@ -45,14 +368,9 @@ void Initialize(v8::Local<v8::Object> exports,
|
|||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
View::SetConstructor(isolate, base::BindRepeating(&View::New));
|
||||
|
||||
gin_helper::Dictionary constructor(
|
||||
isolate,
|
||||
View::GetConstructor(isolate)->GetFunction(context).ToLocalChecked());
|
||||
|
||||
gin_helper::Dictionary dict(isolate, exports);
|
||||
dict.Set("View", constructor);
|
||||
dict.Set("View", View::GetConstructor(isolate));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
@ -7,18 +7,39 @@
|
|||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "gin/handle.h"
|
||||
#include "shell/common/gin_helper/wrappable.h"
|
||||
#include "shell/common/color_util.h"
|
||||
#include "shell/common/gin_helper/event_emitter.h"
|
||||
#include "ui/views/view.h"
|
||||
#include "ui/views/view_observer.h"
|
||||
#include "v8/include/v8-value.h"
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
class View : public gin_helper::Wrappable<View> {
|
||||
class View : public gin_helper::EventEmitter<View>, public views::ViewObserver {
|
||||
public:
|
||||
static gin_helper::WrappableBase* New(gin::Arguments* args);
|
||||
static gin::Handle<View> Create(v8::Isolate* isolate);
|
||||
|
||||
// Return the cached constructor function.
|
||||
static v8::Local<v8::Function> GetConstructor(v8::Isolate* isolate);
|
||||
|
||||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::FunctionTemplate> prototype);
|
||||
|
||||
void AddChildViewAt(gin::Handle<View> child, absl::optional<size_t> index);
|
||||
void RemoveChildView(gin::Handle<View> child);
|
||||
|
||||
void SetBounds(const gfx::Rect& bounds);
|
||||
gfx::Rect GetBounds();
|
||||
void SetLayout(v8::Isolate* isolate, v8::Local<v8::Object> value);
|
||||
std::vector<v8::Local<v8::Value>> GetChildren();
|
||||
void SetBackgroundColor(absl::optional<WrappedSkColor> color);
|
||||
void SetVisible(bool visible);
|
||||
|
||||
// views::ViewObserver
|
||||
void OnViewBoundsChanged(views::View* observed_view) override;
|
||||
void OnViewIsDeleting(views::View* observed_view) override;
|
||||
|
||||
views::View* view() const { return view_; }
|
||||
|
||||
// disable copy
|
||||
|
@ -34,6 +55,8 @@ class View : public gin_helper::Wrappable<View> {
|
|||
void set_delete_view(bool should) { delete_view_ = should; }
|
||||
|
||||
private:
|
||||
std::vector<v8::Global<v8::Object>> child_views_;
|
||||
|
||||
bool delete_view_ = true;
|
||||
raw_ptr<views::View> view_ = nullptr;
|
||||
};
|
||||
|
|
|
@ -717,12 +717,6 @@ bool IsDevToolsFileSystemAdded(content::WebContents* web_contents,
|
|||
file_system_path);
|
||||
}
|
||||
|
||||
void SetBackgroundColor(content::RenderWidgetHostView* rwhv, SkColor color) {
|
||||
rwhv->SetBackgroundColor(color);
|
||||
static_cast<content::RenderWidgetHostViewBase*>(rwhv)
|
||||
->SetContentBackgroundColor(color);
|
||||
}
|
||||
|
||||
content::RenderFrameHost* GetRenderFrameHost(
|
||||
content::NavigationHandle* navigation_handle) {
|
||||
int frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
|
||||
|
@ -739,7 +733,6 @@ content::RenderFrameHost* GetRenderFrameHost(
|
|||
|
||||
return frame_host;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
||||
|
@ -839,10 +832,7 @@ WebContents::WebContents(v8::Isolate* isolate,
|
|||
// Whether to enable DevTools.
|
||||
options.Get("devTools", &enable_devtools_);
|
||||
|
||||
// BrowserViews are not attached to a window initially so they should start
|
||||
// off as hidden. This is also important for compositor recycling. See:
|
||||
// https://github.com/electron/electron/pull/21372
|
||||
bool initially_shown = type_ != Type::kBrowserView;
|
||||
bool initially_shown = true;
|
||||
options.Get(options::kShow, &initially_shown);
|
||||
|
||||
// Obtain the session.
|
||||
|
@ -1287,13 +1277,11 @@ content::WebContents* WebContents::OpenURLFromTab(
|
|||
void WebContents::BeforeUnloadFired(content::WebContents* tab,
|
||||
bool proceed,
|
||||
bool* proceed_to_fire_unload) {
|
||||
if (type_ == Type::kBrowserWindow || type_ == Type::kOffScreen ||
|
||||
type_ == Type::kBrowserView)
|
||||
*proceed_to_fire_unload = proceed;
|
||||
else
|
||||
*proceed_to_fire_unload = true;
|
||||
// Note that Chromium does not emit this for navigations.
|
||||
Emit("before-unload-fired", proceed);
|
||||
|
||||
// Emit returns true if preventDefault() was called, so !Emit will be true if
|
||||
// the event should proceed.
|
||||
*proceed_to_fire_unload = !Emit("-before-unload-fired", proceed);
|
||||
}
|
||||
|
||||
void WebContents::SetContentsBounds(content::WebContents* source,
|
||||
|
@ -1312,12 +1300,7 @@ void WebContents::CloseContents(content::WebContents* source) {
|
|||
autofill_driver_factory->CloseAllPopups();
|
||||
}
|
||||
|
||||
for (ExtendedWebContentsObserver& observer : observers_)
|
||||
observer.OnCloseContents();
|
||||
|
||||
// This is handled by the embedder frame.
|
||||
if (!IsGuest())
|
||||
Destroy();
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void WebContents::ActivateContents(content::WebContents* source) {
|
||||
|
@ -1599,9 +1582,53 @@ void WebContents::RequestMediaAccessPermission(
|
|||
permission_helper->RequestMediaAccessPermission(request, std::move(callback));
|
||||
}
|
||||
|
||||
const void* const kJavaScriptDialogManagerKey = &kJavaScriptDialogManagerKey;
|
||||
|
||||
content::JavaScriptDialogManager* WebContents::GetJavaScriptDialogManager(
|
||||
content::WebContents* source) {
|
||||
return this;
|
||||
// Indirect these delegate methods through a helper object whose lifetime is
|
||||
// bound to that of the content::WebContents. This prevents the
|
||||
// content::WebContents from calling methods on the Electron WebContents in
|
||||
// the event that the Electron one is destroyed before the content one, as
|
||||
// happens sometimes during shutdown or when webviews are involved.
|
||||
class JSDialogManagerHelper : public content::JavaScriptDialogManager,
|
||||
public base::SupportsUserData::Data {
|
||||
public:
|
||||
void RunJavaScriptDialog(content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
content::JavaScriptDialogType dialog_type,
|
||||
const std::u16string& message_text,
|
||||
const std::u16string& default_prompt_text,
|
||||
DialogClosedCallback callback,
|
||||
bool* did_suppress_message) override {
|
||||
auto* wc = WebContents::From(web_contents);
|
||||
if (wc)
|
||||
wc->RunJavaScriptDialog(web_contents, rfh, dialog_type, message_text,
|
||||
default_prompt_text, std::move(callback),
|
||||
did_suppress_message);
|
||||
}
|
||||
void RunBeforeUnloadDialog(content::WebContents* web_contents,
|
||||
content::RenderFrameHost* rfh,
|
||||
bool is_reload,
|
||||
DialogClosedCallback callback) override {
|
||||
auto* wc = WebContents::From(web_contents);
|
||||
if (wc)
|
||||
wc->RunBeforeUnloadDialog(web_contents, rfh, is_reload,
|
||||
std::move(callback));
|
||||
}
|
||||
void CancelDialogs(content::WebContents* web_contents,
|
||||
bool reset_state) override {
|
||||
auto* wc = WebContents::From(web_contents);
|
||||
if (wc)
|
||||
wc->CancelDialogs(web_contents, reset_state);
|
||||
}
|
||||
};
|
||||
if (!source->GetUserData(kJavaScriptDialogManagerKey))
|
||||
source->SetUserData(kJavaScriptDialogManagerKey,
|
||||
std::make_unique<JSDialogManagerHelper>());
|
||||
|
||||
return static_cast<JSDialogManagerHelper*>(
|
||||
source->GetUserData(kJavaScriptDialogManagerKey));
|
||||
}
|
||||
|
||||
void WebContents::OnAudioStateChanged(bool audible) {
|
||||
|
@ -1628,17 +1655,8 @@ void WebContents::HandleNewRenderFrame(
|
|||
|
||||
// Set the background color of RenderWidgetHostView.
|
||||
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
||||
if (web_preferences) {
|
||||
auto maybe_color = web_preferences->GetBackgroundColor();
|
||||
bool guest = IsGuest() || type_ == Type::kBrowserView;
|
||||
|
||||
// If webPreferences has no color stored we need to explicitly set guest
|
||||
// webContents background color to transparent.
|
||||
auto bg_color =
|
||||
maybe_color.value_or(guest ? SK_ColorTRANSPARENT : SK_ColorWHITE);
|
||||
web_contents()->SetPageBaseBackgroundColor(bg_color);
|
||||
SetBackgroundColor(rwhv, bg_color);
|
||||
}
|
||||
if (web_preferences)
|
||||
SetBackgroundColor(web_preferences->GetBackgroundColor());
|
||||
|
||||
if (!background_throttling_)
|
||||
render_frame_host->GetRenderViewHost()->SetSchedulerThrottling(false);
|
||||
|
@ -2245,6 +2263,11 @@ void WebContents::SetOwnerWindow(NativeWindow* owner_window) {
|
|||
SetOwnerWindow(GetWebContents(), owner_window);
|
||||
}
|
||||
|
||||
void WebContents::SetOwnerBaseWindow(absl::optional<BaseWindow*> owner_window) {
|
||||
SetOwnerWindow(GetWebContents(),
|
||||
owner_window ? (*owner_window)->window() : nullptr);
|
||||
}
|
||||
|
||||
void WebContents::SetOwnerWindow(content::WebContents* web_contents,
|
||||
NativeWindow* owner_window) {
|
||||
if (owner_window_) {
|
||||
|
@ -3754,6 +3777,22 @@ void WebContents::SetImageAnimationPolicy(const std::string& new_policy) {
|
|||
web_contents()->OnWebPreferencesChanged();
|
||||
}
|
||||
|
||||
void WebContents::SetBackgroundColor(absl::optional<SkColor> maybe_color) {
|
||||
web_contents()->SetPageBaseBackgroundColor(maybe_color);
|
||||
|
||||
content::RenderFrameHost* rfh = web_contents()->GetPrimaryMainFrame();
|
||||
if (!rfh)
|
||||
return;
|
||||
content::RenderWidgetHostView* rwhv = rfh->GetView();
|
||||
if (rwhv) {
|
||||
SkColor color =
|
||||
maybe_color.value_or(IsGuest() ? SK_ColorTRANSPARENT : SK_ColorWHITE);
|
||||
rwhv->SetBackgroundColor(color);
|
||||
static_cast<content::RenderWidgetHostViewBase*>(rwhv)
|
||||
->SetContentBackgroundColor(color);
|
||||
}
|
||||
}
|
||||
|
||||
void WebContents::OnInputEvent(const blink::WebInputEvent& event) {
|
||||
Emit("input-event", event);
|
||||
}
|
||||
|
@ -4414,6 +4453,7 @@ void WebContents::FillObjectTemplate(v8::Isolate* isolate,
|
|||
.SetProperty("debugger", &WebContents::Debugger)
|
||||
.SetProperty("mainFrame", &WebContents::MainFrame)
|
||||
.SetProperty("opener", &WebContents::Opener)
|
||||
.SetMethod("_setOwnerWindow", &WebContents::SetOwnerBaseWindow)
|
||||
.Build();
|
||||
}
|
||||
|
||||
|
@ -4497,14 +4537,8 @@ gin::Handle<WebContents> WebContents::CreateFromWebPreferences(
|
|||
if (gin::ConvertFromV8(isolate, web_preferences.GetHandle(),
|
||||
&web_preferences_dict)) {
|
||||
existing_preferences->SetFromDictionary(web_preferences_dict);
|
||||
absl::optional<SkColor> color =
|
||||
existing_preferences->GetBackgroundColor();
|
||||
web_contents->web_contents()->SetPageBaseBackgroundColor(color);
|
||||
// Because web preferences don't recognize transparency,
|
||||
// only set rwhv background color if a color exists
|
||||
auto* rwhv = web_contents->web_contents()->GetRenderWidgetHostView();
|
||||
if (rwhv && color.has_value())
|
||||
SetBackgroundColor(rwhv, color.value());
|
||||
web_contents->SetBackgroundColor(
|
||||
existing_preferences->GetBackgroundColor());
|
||||
}
|
||||
} else {
|
||||
// Create one if not.
|
||||
|
|
|
@ -97,6 +97,8 @@ class OffScreenWebContentsView;
|
|||
|
||||
namespace api {
|
||||
|
||||
class BaseWindow;
|
||||
|
||||
// Wrapper around the content::WebContents.
|
||||
class WebContents : public ExclusiveAccessContext,
|
||||
public gin::Wrappable<WebContents>,
|
||||
|
@ -115,7 +117,9 @@ class WebContents : public ExclusiveAccessContext,
|
|||
enum class Type {
|
||||
kBackgroundPage, // An extension background page.
|
||||
kBrowserWindow, // Used by BrowserWindow.
|
||||
kBrowserView, // Used by BrowserView.
|
||||
kBrowserView, // Used by the JS implementation of BrowserView for
|
||||
// backwards compatibility. Otherwise identical to
|
||||
// kBrowserWindow.
|
||||
kRemote, // Thin wrap around an existing WebContents.
|
||||
kWebView, // Used by <webview>.
|
||||
kOffScreen, // Used for offscreen rendering
|
||||
|
@ -399,6 +403,7 @@ class WebContents : public ExclusiveAccessContext,
|
|||
void SetOwnerWindow(NativeWindow* owner_window);
|
||||
void SetOwnerWindow(content::WebContents* web_contents,
|
||||
NativeWindow* owner_window);
|
||||
void SetOwnerBaseWindow(absl::optional<BaseWindow*> owner_window);
|
||||
|
||||
// Returns the WebContents managed by this delegate.
|
||||
content::WebContents* GetWebContents() const;
|
||||
|
@ -469,6 +474,8 @@ class WebContents : public ExclusiveAccessContext,
|
|||
void CancelDialogs(content::WebContents* web_contents,
|
||||
bool reset_state) override;
|
||||
|
||||
void SetBackgroundColor(absl::optional<SkColor> color);
|
||||
|
||||
SkRegion* draggable_region() {
|
||||
return force_non_draggable_ ? nullptr : draggable_region_.get();
|
||||
}
|
||||
|
|
|
@ -5,17 +5,24 @@
|
|||
#include "shell/browser/api/electron_api_web_contents_view.h"
|
||||
|
||||
#include "base/no_destructor.h"
|
||||
#include "gin/data_object_builder.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||
#include "shell/browser/web_contents_preferences.h"
|
||||
#include "shell/common/gin_converters/gfx_converter.h"
|
||||
#include "shell/common/gin_converters/value_converter.h"
|
||||
#include "shell/common/gin_helper/constructor.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/object_template_builder.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "shell/common/options_switches.h"
|
||||
#include "third_party/skia/include/core/SkRegion.h"
|
||||
#include "ui/base/hit_test.h"
|
||||
#include "ui/views/layout/flex_layout_types.h"
|
||||
#include "ui/views/view_class_properties.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
#include "shell/browser/ui/cocoa/delayed_native_view_host.h"
|
||||
|
@ -40,6 +47,10 @@ WebContentsView::WebContentsView(v8::Isolate* isolate,
|
|||
// managed by InspectableWebContents.
|
||||
set_delete_view(false);
|
||||
#endif
|
||||
view()->SetProperty(
|
||||
views::kFlexBehaviorKey,
|
||||
views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
|
||||
views::MaximumFlexSizeRule::kUnbounded));
|
||||
Observe(web_contents->web_contents());
|
||||
}
|
||||
|
||||
|
@ -49,7 +60,24 @@ WebContentsView::~WebContentsView() {
|
|||
}
|
||||
|
||||
gin::Handle<WebContents> WebContentsView::GetWebContents(v8::Isolate* isolate) {
|
||||
return gin::CreateHandle(isolate, api_web_contents_.get());
|
||||
if (api_web_contents_)
|
||||
return gin::CreateHandle(isolate, api_web_contents_.get());
|
||||
else
|
||||
return gin::Handle<WebContents>();
|
||||
}
|
||||
|
||||
void WebContentsView::SetBackgroundColor(absl::optional<WrappedSkColor> color) {
|
||||
View::SetBackgroundColor(color);
|
||||
if (api_web_contents_) {
|
||||
api_web_contents_->SetBackgroundColor(color);
|
||||
// Also update the web preferences object otherwise the view will be reset
|
||||
// on the next load URL call
|
||||
auto* web_preferences =
|
||||
WebContentsPreferences::From(api_web_contents_->web_contents());
|
||||
if (web_preferences) {
|
||||
web_preferences->SetBackgroundColor(color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int WebContentsView::NonClientHitTest(const gfx::Point& point) {
|
||||
|
@ -66,16 +94,40 @@ void WebContentsView::WebContentsDestroyed() {
|
|||
web_contents_.Reset();
|
||||
}
|
||||
|
||||
void WebContentsView::OnViewAddedToWidget(views::View* observed_view) {
|
||||
DCHECK_EQ(observed_view, view());
|
||||
views::Widget* widget = view()->GetWidget();
|
||||
auto* native_window = static_cast<NativeWindow*>(
|
||||
widget->GetNativeWindowProperty(electron::kElectronNativeWindowKey));
|
||||
if (!native_window)
|
||||
return;
|
||||
native_window->AddDraggableRegionProvider(this);
|
||||
}
|
||||
|
||||
void WebContentsView::OnViewRemovedFromWidget(views::View* observed_view) {
|
||||
DCHECK_EQ(observed_view, view());
|
||||
views::Widget* widget = view()->GetWidget();
|
||||
auto* native_window = static_cast<NativeWindow*>(
|
||||
widget->GetNativeWindowProperty(kElectronNativeWindowKey));
|
||||
if (!native_window)
|
||||
return;
|
||||
native_window->RemoveDraggableRegionProvider(this);
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<WebContentsView> WebContentsView::Create(
|
||||
v8::Isolate* isolate,
|
||||
const gin_helper::Dictionary& web_preferences) {
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
v8::Local<v8::Value> arg = gin::ConvertToV8(isolate, web_preferences);
|
||||
v8::Local<v8::Object> obj;
|
||||
if (GetConstructor(isolate)->NewInstance(context, 1, &arg).ToLocal(&obj)) {
|
||||
v8::Local<v8::Value> arg = gin::DataObjectBuilder(isolate)
|
||||
.Set("webPreferences", web_preferences)
|
||||
.Build();
|
||||
v8::Local<v8::Object> web_contents_view_obj;
|
||||
if (GetConstructor(isolate)
|
||||
->NewInstance(context, 1, &arg)
|
||||
.ToLocal(&web_contents_view_obj)) {
|
||||
gin::Handle<WebContentsView> web_contents_view;
|
||||
if (gin::ConvertFromV8(isolate, obj, &web_contents_view))
|
||||
if (gin::ConvertFromV8(isolate, web_contents_view_obj, &web_contents_view))
|
||||
return web_contents_view;
|
||||
}
|
||||
return gin::Handle<WebContentsView>();
|
||||
|
@ -93,9 +145,30 @@ v8::Local<v8::Function> WebContentsView::GetConstructor(v8::Isolate* isolate) {
|
|||
}
|
||||
|
||||
// static
|
||||
gin_helper::WrappableBase* WebContentsView::New(
|
||||
gin_helper::Arguments* args,
|
||||
const gin_helper::Dictionary& web_preferences) {
|
||||
gin_helper::WrappableBase* WebContentsView::New(gin_helper::Arguments* args) {
|
||||
gin_helper::Dictionary web_preferences;
|
||||
{
|
||||
v8::Local<v8::Value> options_value;
|
||||
if (args->GetNext(&options_value)) {
|
||||
gin_helper::Dictionary options;
|
||||
if (!gin::ConvertFromV8(args->isolate(), options_value, &options)) {
|
||||
args->ThrowError("options must be an object");
|
||||
return nullptr;
|
||||
}
|
||||
v8::Local<v8::Value> web_preferences_value;
|
||||
if (options.Get("webPreferences", &web_preferences_value)) {
|
||||
if (!gin::ConvertFromV8(args->isolate(), web_preferences_value,
|
||||
&web_preferences)) {
|
||||
args->ThrowError("options.webPreferences must be an object");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (web_preferences.IsEmpty())
|
||||
web_preferences = gin_helper::Dictionary::CreateEmpty(args->isolate());
|
||||
if (!web_preferences.Has(options::kShow))
|
||||
web_preferences.Set(options::kShow, false);
|
||||
auto web_contents =
|
||||
WebContents::CreateFromWebPreferences(args->isolate(), web_preferences);
|
||||
|
||||
|
@ -111,6 +184,7 @@ void WebContentsView::BuildPrototype(
|
|||
v8::Local<v8::FunctionTemplate> prototype) {
|
||||
prototype->SetClassName(gin::StringToV8(isolate, "WebContentsView"));
|
||||
gin_helper::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
|
||||
.SetMethod("setBackgroundColor", &WebContentsView::SetBackgroundColor)
|
||||
.SetProperty("webContents", &WebContentsView::GetWebContents);
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class WebContentsView : public View,
|
|||
|
||||
// Public APIs.
|
||||
gin::Handle<WebContents> GetWebContents(v8::Isolate* isolate);
|
||||
void SetBackgroundColor(absl::optional<WrappedSkColor> color);
|
||||
|
||||
int NonClientHitTest(const gfx::Point& point) override;
|
||||
|
||||
|
@ -47,10 +48,12 @@ class WebContentsView : public View,
|
|||
// content::WebContentsObserver:
|
||||
void WebContentsDestroyed() override;
|
||||
|
||||
// views::ViewObserver
|
||||
void OnViewAddedToWidget(views::View* view) override;
|
||||
void OnViewRemovedFromWidget(views::View* view) override;
|
||||
|
||||
private:
|
||||
static gin_helper::WrappableBase* New(
|
||||
gin_helper::Arguments* args,
|
||||
const gin_helper::Dictionary& web_preferences);
|
||||
static gin_helper::WrappableBase* New(gin_helper::Arguments* args);
|
||||
|
||||
// Keep a reference to v8 wrapper.
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/javascript_environment.h"
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
#include "shell/browser/native_window.h"
|
||||
|
||||
namespace electron {
|
||||
|
@ -60,21 +59,6 @@ void AutofillDriver::ShowAutofillPopup(
|
|||
embedder_frame_host = embedder->web_contents()->GetPrimaryMainFrame();
|
||||
}
|
||||
|
||||
// Ensure that if the WebContents belongs to a BrowserView,
|
||||
// the popup is positioned relative to the BrowserView's bounds.
|
||||
for (NativeBrowserView* bv : owner_window->browser_views()) {
|
||||
auto* iwc = bv->GetInspectableWebContents();
|
||||
if (!iwc)
|
||||
continue;
|
||||
|
||||
auto* awc = api::WebContents::From(iwc->GetWebContents());
|
||||
if (awc == web_contents) {
|
||||
auto bv_origin = bv->GetBounds().origin();
|
||||
popup_bounds.Offset(gfx::Vector2dF(bv_origin.x(), bv_origin.y()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
autofill_popup_->CreateView(render_frame_host_, embedder_frame_host, osr,
|
||||
owner_window->content_view(), popup_bounds);
|
||||
autofill_popup_->SetItems(values, labels);
|
||||
|
|
|
@ -18,7 +18,6 @@ namespace electron {
|
|||
// Observer to dispatch those events.
|
||||
class ExtendedWebContentsObserver : public base::CheckedObserver {
|
||||
public:
|
||||
virtual void OnCloseContents() {}
|
||||
virtual void OnDraggableRegionsUpdated(
|
||||
const std::vector<mojom::DraggableRegionPtr>& regions) {}
|
||||
virtual void OnSetContentBounds(const gfx::Rect& rect) {}
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
NativeBrowserView::NativeBrowserView(
|
||||
InspectableWebContents* inspectable_web_contents)
|
||||
: inspectable_web_contents_(inspectable_web_contents) {
|
||||
Observe(inspectable_web_contents_->GetWebContents());
|
||||
}
|
||||
|
||||
NativeBrowserView::~NativeBrowserView() = default;
|
||||
|
||||
InspectableWebContentsView* NativeBrowserView::GetInspectableWebContentsView() {
|
||||
if (!inspectable_web_contents_)
|
||||
return nullptr;
|
||||
return inspectable_web_contents_->GetView();
|
||||
}
|
||||
|
||||
void NativeBrowserView::WebContentsDestroyed() {
|
||||
inspectable_web_contents_ = nullptr;
|
||||
}
|
||||
|
||||
} // namespace electron
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_NATIVE_BROWSER_VIEW_H_
|
||||
#define ELECTRON_SHELL_BROWSER_NATIVE_BROWSER_VIEW_H_
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
|
||||
namespace gfx {
|
||||
class Rect;
|
||||
}
|
||||
|
||||
namespace electron {
|
||||
|
||||
enum AutoResizeFlags {
|
||||
kAutoResizeWidth = 0x1,
|
||||
kAutoResizeHeight = 0x2,
|
||||
kAutoResizeHorizontal = 0x4,
|
||||
kAutoResizeVertical = 0x8,
|
||||
};
|
||||
|
||||
class InspectableWebContents;
|
||||
class InspectableWebContentsView;
|
||||
|
||||
class NativeBrowserView : public content::WebContentsObserver {
|
||||
public:
|
||||
~NativeBrowserView() override;
|
||||
|
||||
// disable copy
|
||||
NativeBrowserView(const NativeBrowserView&) = delete;
|
||||
NativeBrowserView& operator=(const NativeBrowserView&) = delete;
|
||||
|
||||
static NativeBrowserView* Create(
|
||||
InspectableWebContents* inspectable_web_contents);
|
||||
|
||||
InspectableWebContents* GetInspectableWebContents() {
|
||||
return inspectable_web_contents_;
|
||||
}
|
||||
|
||||
InspectableWebContentsView* GetInspectableWebContentsView();
|
||||
|
||||
virtual void SetAutoResizeFlags(uint8_t flags) = 0;
|
||||
virtual void SetBounds(const gfx::Rect& bounds) = 0;
|
||||
virtual gfx::Rect GetBounds() = 0;
|
||||
virtual void SetBackgroundColor(SkColor color) = 0;
|
||||
|
||||
protected:
|
||||
explicit NativeBrowserView(InspectableWebContents* inspectable_web_contents);
|
||||
// content::WebContentsObserver:
|
||||
void WebContentsDestroyed() override;
|
||||
|
||||
raw_ptr<InspectableWebContents> inspectable_web_contents_;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_NATIVE_BROWSER_VIEW_H_
|
|
@ -1,28 +0,0 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_NATIVE_BROWSER_VIEW_MAC_H_
|
||||
#define ELECTRON_SHELL_BROWSER_NATIVE_BROWSER_VIEW_MAC_H_
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
class NativeBrowserViewMac : public NativeBrowserView {
|
||||
public:
|
||||
explicit NativeBrowserViewMac(
|
||||
InspectableWebContents* inspectable_web_contents);
|
||||
~NativeBrowserViewMac() override;
|
||||
|
||||
void SetAutoResizeFlags(uint8_t flags) override;
|
||||
void SetBounds(const gfx::Rect& bounds) override;
|
||||
gfx::Rect GetBounds() override;
|
||||
void SetBackgroundColor(SkColor color) override;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_NATIVE_BROWSER_VIEW_MAC_H_
|
|
@ -1,96 +0,0 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/native_browser_view_mac.h"
|
||||
|
||||
#include "shell/browser/ui/inspectable_web_contents.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||
#include "skia/ext/skia_utils_mac.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
||||
// Match view::Views behavior where the view sticks to the top-left origin.
|
||||
const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
|
||||
NSViewMaxXMargin | NSViewMinYMargin;
|
||||
|
||||
namespace electron {
|
||||
|
||||
NativeBrowserViewMac::NativeBrowserViewMac(
|
||||
InspectableWebContents* inspectable_web_contents)
|
||||
: NativeBrowserView(inspectable_web_contents) {
|
||||
auto* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetNativeView().GetNativeNSView();
|
||||
view.autoresizingMask = kDefaultAutoResizingMask;
|
||||
}
|
||||
|
||||
NativeBrowserViewMac::~NativeBrowserViewMac() = default;
|
||||
|
||||
void NativeBrowserViewMac::SetAutoResizeFlags(uint8_t flags) {
|
||||
NSAutoresizingMaskOptions autoresizing_mask = kDefaultAutoResizingMask;
|
||||
if (flags & kAutoResizeWidth) {
|
||||
autoresizing_mask |= NSViewWidthSizable;
|
||||
}
|
||||
if (flags & kAutoResizeHeight) {
|
||||
autoresizing_mask |= NSViewHeightSizable;
|
||||
}
|
||||
if (flags & kAutoResizeHorizontal) {
|
||||
autoresizing_mask |=
|
||||
NSViewMaxXMargin | NSViewMinXMargin | NSViewWidthSizable;
|
||||
}
|
||||
if (flags & kAutoResizeVertical) {
|
||||
autoresizing_mask |=
|
||||
NSViewMaxYMargin | NSViewMinYMargin | NSViewHeightSizable;
|
||||
}
|
||||
|
||||
auto* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetNativeView().GetNativeNSView();
|
||||
view.autoresizingMask = autoresizing_mask;
|
||||
}
|
||||
|
||||
void NativeBrowserViewMac::SetBounds(const gfx::Rect& bounds) {
|
||||
auto* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return;
|
||||
|
||||
auto* view = iwc_view->GetNativeView().GetNativeNSView();
|
||||
const auto superview_height =
|
||||
view.superview ? view.superview.frame.size.height : 0;
|
||||
int y_coord = superview_height - bounds.y() - bounds.height();
|
||||
|
||||
view.frame = NSMakeRect(bounds.x(), y_coord, bounds.width(), bounds.height());
|
||||
}
|
||||
|
||||
gfx::Rect NativeBrowserViewMac::GetBounds() {
|
||||
auto* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return gfx::Rect();
|
||||
|
||||
NSView* view = iwc_view->GetNativeView().GetNativeNSView();
|
||||
const int superview_height =
|
||||
view.superview ? view.superview.frame.size.height : 0;
|
||||
int y_coord = superview_height - view.frame.origin.y - view.frame.size.height;
|
||||
|
||||
return gfx::Rect(view.frame.origin.x, y_coord, view.frame.size.width,
|
||||
view.frame.size.height);
|
||||
}
|
||||
|
||||
void NativeBrowserViewMac::SetBackgroundColor(SkColor color) {
|
||||
auto* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetNativeView().GetNativeNSView();
|
||||
view.wantsLayer = YES;
|
||||
view.layer.backgroundColor = skia::CGColorCreateFromSkColor(color).get();
|
||||
}
|
||||
|
||||
// static
|
||||
NativeBrowserView* NativeBrowserView::Create(
|
||||
InspectableWebContents* inspectable_web_contents) {
|
||||
return new NativeBrowserViewMac(inspectable_web_contents);
|
||||
}
|
||||
|
||||
} // namespace electron
|
|
@ -1,143 +0,0 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/native_browser_view_views.h"
|
||||
|
||||
#include "shell/browser/ui/views/inspectable_web_contents_view_views.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
NativeBrowserViewViews::NativeBrowserViewViews(
|
||||
InspectableWebContents* inspectable_web_contents)
|
||||
: NativeBrowserView(inspectable_web_contents) {}
|
||||
|
||||
NativeBrowserViewViews::~NativeBrowserViewViews() = default;
|
||||
|
||||
void NativeBrowserViewViews::SetAutoResizeFlags(uint8_t flags) {
|
||||
auto_resize_flags_ = flags;
|
||||
ResetAutoResizeProportions();
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::SetAutoResizeProportions(
|
||||
const gfx::Size& window_size) {
|
||||
if ((auto_resize_flags_ & AutoResizeFlags::kAutoResizeHorizontal) &&
|
||||
!auto_horizontal_proportion_set_) {
|
||||
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetView();
|
||||
auto view_bounds = view->bounds();
|
||||
auto_horizontal_proportion_width_ =
|
||||
static_cast<float>(window_size.width()) /
|
||||
static_cast<float>(view_bounds.width());
|
||||
auto_horizontal_proportion_left_ = static_cast<float>(window_size.width()) /
|
||||
static_cast<float>(view_bounds.x());
|
||||
auto_horizontal_proportion_set_ = true;
|
||||
}
|
||||
if ((auto_resize_flags_ & AutoResizeFlags::kAutoResizeVertical) &&
|
||||
!auto_vertical_proportion_set_) {
|
||||
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetView();
|
||||
auto view_bounds = view->bounds();
|
||||
auto_vertical_proportion_height_ =
|
||||
static_cast<float>(window_size.height()) /
|
||||
static_cast<float>(view_bounds.height());
|
||||
auto_vertical_proportion_top_ = static_cast<float>(window_size.height()) /
|
||||
static_cast<float>(view_bounds.y());
|
||||
auto_vertical_proportion_set_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::AutoResize(const gfx::Rect& new_window,
|
||||
int width_delta,
|
||||
int height_delta) {
|
||||
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetView();
|
||||
const auto flags = GetAutoResizeFlags();
|
||||
if (!(flags & kAutoResizeWidth)) {
|
||||
width_delta = 0;
|
||||
}
|
||||
if (!(flags & kAutoResizeHeight)) {
|
||||
height_delta = 0;
|
||||
}
|
||||
if (height_delta || width_delta) {
|
||||
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);
|
||||
}
|
||||
auto new_view_bounds = view->bounds();
|
||||
if (flags & kAutoResizeHorizontal) {
|
||||
new_view_bounds.set_width(new_window.width() /
|
||||
auto_horizontal_proportion_width_);
|
||||
new_view_bounds.set_x(new_window.width() /
|
||||
auto_horizontal_proportion_left_);
|
||||
}
|
||||
if (flags & kAutoResizeVertical) {
|
||||
new_view_bounds.set_height(new_window.height() /
|
||||
auto_vertical_proportion_height_);
|
||||
new_view_bounds.set_y(new_window.height() / auto_vertical_proportion_top_);
|
||||
}
|
||||
if ((flags & kAutoResizeHorizontal) || (flags & kAutoResizeVertical)) {
|
||||
view->SetBoundsRect(new_view_bounds);
|
||||
}
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::ResetAutoResizeProportions() {
|
||||
if (auto_resize_flags_ & AutoResizeFlags::kAutoResizeHorizontal) {
|
||||
auto_horizontal_proportion_set_ = false;
|
||||
}
|
||||
if (auto_resize_flags_ & AutoResizeFlags::kAutoResizeVertical) {
|
||||
auto_vertical_proportion_set_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::SetBounds(const gfx::Rect& bounds) {
|
||||
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetView();
|
||||
view->SetBoundsRect(bounds);
|
||||
ResetAutoResizeProportions();
|
||||
|
||||
view->InvalidateLayout();
|
||||
view->SchedulePaint();
|
||||
}
|
||||
|
||||
gfx::Rect NativeBrowserViewViews::GetBounds() {
|
||||
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return gfx::Rect();
|
||||
return iwc_view->GetView()->bounds();
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::RenderViewReady() {
|
||||
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
|
||||
if (iwc_view)
|
||||
iwc_view->GetView()->Layout();
|
||||
}
|
||||
|
||||
void NativeBrowserViewViews::SetBackgroundColor(SkColor color) {
|
||||
InspectableWebContentsView* iwc_view = GetInspectableWebContentsView();
|
||||
if (!iwc_view)
|
||||
return;
|
||||
auto* view = iwc_view->GetView();
|
||||
view->SetBackground(views::CreateSolidBackground(color));
|
||||
view->SchedulePaint();
|
||||
}
|
||||
|
||||
// static
|
||||
NativeBrowserView* NativeBrowserView::Create(
|
||||
InspectableWebContents* inspectable_web_contents) {
|
||||
return new NativeBrowserViewViews(inspectable_web_contents);
|
||||
}
|
||||
|
||||
} // namespace electron
|
|
@ -1,49 +0,0 @@
|
|||
// Copyright (c) 2017 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_NATIVE_BROWSER_VIEW_VIEWS_H_
|
||||
#define ELECTRON_SHELL_BROWSER_NATIVE_BROWSER_VIEW_VIEWS_H_
|
||||
|
||||
#include "shell/browser/native_browser_view.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
class NativeBrowserViewViews : public NativeBrowserView {
|
||||
public:
|
||||
explicit NativeBrowserViewViews(
|
||||
InspectableWebContents* inspectable_web_contents);
|
||||
~NativeBrowserViewViews() override;
|
||||
|
||||
void SetAutoResizeProportions(const gfx::Size& window_size);
|
||||
void AutoResize(const gfx::Rect& new_window,
|
||||
int width_delta,
|
||||
int height_delta);
|
||||
uint8_t GetAutoResizeFlags() { return auto_resize_flags_; }
|
||||
|
||||
// NativeBrowserView:
|
||||
void SetAutoResizeFlags(uint8_t flags) override;
|
||||
void SetBounds(const gfx::Rect& bounds) override;
|
||||
gfx::Rect GetBounds() override;
|
||||
void SetBackgroundColor(SkColor color) override;
|
||||
|
||||
// WebContentsObserver:
|
||||
void RenderViewReady() override;
|
||||
|
||||
private:
|
||||
void ResetAutoResizeProportions();
|
||||
|
||||
uint8_t auto_resize_flags_ = 0;
|
||||
|
||||
bool auto_horizontal_proportion_set_ = false;
|
||||
float auto_horizontal_proportion_width_ = 0.;
|
||||
float auto_horizontal_proportion_left_ = 0.;
|
||||
|
||||
bool auto_vertical_proportion_set_ = false;
|
||||
float auto_vertical_proportion_height_ = 0.;
|
||||
float auto_vertical_proportion_top_ = 0.;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_NATIVE_BROWSER_VIEW_VIEWS_H_
|
|
@ -92,6 +92,8 @@ gfx::Size GetExpandedWindowSize(const NativeWindow* window, gfx::Size size) {
|
|||
|
||||
} // namespace
|
||||
|
||||
const char kElectronNativeWindowKey[] = "__ELECTRON_NATIVE_WINDOW__";
|
||||
|
||||
NativeWindow::NativeWindow(const gin_helper::Dictionary& options,
|
||||
NativeWindow* parent)
|
||||
: widget_(std::make_unique<views::Widget>()), parent_(parent) {
|
||||
|
|
|
@ -46,9 +46,10 @@ class PersistentDictionary;
|
|||
|
||||
namespace electron {
|
||||
|
||||
extern const char kElectronNativeWindowKey[];
|
||||
|
||||
class ElectronMenuModel;
|
||||
class BackgroundThrottlingSource;
|
||||
class NativeBrowserView;
|
||||
|
||||
namespace api {
|
||||
class BrowserView;
|
||||
|
@ -186,9 +187,6 @@ class NativeWindow : public base::SupportsUserData,
|
|||
virtual bool IsFocusable();
|
||||
virtual void SetMenu(ElectronMenuModel* menu);
|
||||
virtual void SetParentWindow(NativeWindow* parent);
|
||||
virtual void AddBrowserView(NativeBrowserView* browser_view) = 0;
|
||||
virtual void RemoveBrowserView(NativeBrowserView* browser_view) = 0;
|
||||
virtual void SetTopBrowserView(NativeBrowserView* browser_view) = 0;
|
||||
virtual content::DesktopMediaID GetDesktopMediaID() const = 0;
|
||||
virtual gfx::NativeView GetNativeView() const = 0;
|
||||
virtual gfx::NativeWindow GetNativeWindow() const = 0;
|
||||
|
@ -389,8 +387,6 @@ class NativeWindow : public base::SupportsUserData,
|
|||
NativeWindow* parent() const { return parent_; }
|
||||
bool is_modal() const { return is_modal_; }
|
||||
|
||||
std::list<NativeBrowserView*> browser_views() const { return browser_views_; }
|
||||
|
||||
int32_t window_id() const { return next_id_; }
|
||||
|
||||
void add_child_window(NativeWindow* child) {
|
||||
|
@ -426,14 +422,6 @@ class NativeWindow : public base::SupportsUserData,
|
|||
|
||||
void set_content_view(views::View* view) { content_view_ = 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); });
|
||||
}
|
||||
|
||||
// The boolean parsing of the "titleBarOverlay" option
|
||||
bool titlebar_overlay_ = false;
|
||||
|
||||
|
@ -500,9 +488,6 @@ class NativeWindow : public base::SupportsUserData,
|
|||
// Is this a modal window.
|
||||
bool is_modal_ = false;
|
||||
|
||||
// The browser view layer.
|
||||
std::list<NativeBrowserView*> browser_views_;
|
||||
|
||||
std::list<DraggableRegionProvider*> draggable_region_providers_;
|
||||
|
||||
// Observers of this window.
|
||||
|
|
|
@ -110,9 +110,6 @@ class NativeWindowMac : public NativeWindow,
|
|||
void SetContentProtection(bool enable) override;
|
||||
void SetFocusable(bool focusable) override;
|
||||
bool IsFocusable() override;
|
||||
void AddBrowserView(NativeBrowserView* browser_view) override;
|
||||
void RemoveBrowserView(NativeBrowserView* browser_view) override;
|
||||
void SetTopBrowserView(NativeBrowserView* browser_view) override;
|
||||
void SetParentWindow(NativeWindow* parent) override;
|
||||
content::DesktopMediaID GetDesktopMediaID() const override;
|
||||
gfx::NativeView GetNativeView() const override;
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "content/public/browser/desktop_media_id.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/javascript_environment.h"
|
||||
#include "shell/browser/native_browser_view_mac.h"
|
||||
#include "shell/browser/ui/cocoa/electron_native_widget_mac.h"
|
||||
#include "shell/browser/ui/cocoa/electron_ns_window.h"
|
||||
#include "shell/browser/ui/cocoa/electron_ns_window_delegate.h"
|
||||
|
@ -206,14 +205,6 @@ void ReorderChildWindowAbove(NSWindow* child_window, NSWindow* other_window) {
|
|||
}
|
||||
}
|
||||
|
||||
NSView* GetNativeNSView(NativeBrowserView* view) {
|
||||
if (auto* inspectable = view->GetInspectableWebContentsView()) {
|
||||
return inspectable->GetNativeView().GetNativeNSView();
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
|
||||
|
@ -296,6 +287,7 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
|
|||
params.native_widget =
|
||||
new ElectronNativeWidgetMac(this, windowType, styleMask, widget());
|
||||
widget()->Init(std::move(params));
|
||||
widget()->SetNativeWindowProperty(kElectronNativeWindowKey, this);
|
||||
SetCanResize(resizable);
|
||||
window_ = static_cast<ElectronNSWindow*>(
|
||||
widget()->GetNativeWindow().GetNativeNSWindow());
|
||||
|
@ -1285,64 +1277,6 @@ bool NativeWindowMac::IsFocusable() {
|
|||
return ![window_ disableKeyOrMainWindow];
|
||||
}
|
||||
|
||||
void NativeWindowMac::AddBrowserView(NativeBrowserView* view) {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
|
||||
if (!view) {
|
||||
[CATransaction commit];
|
||||
return;
|
||||
}
|
||||
|
||||
add_browser_view(view);
|
||||
if (auto* native_view = GetNativeNSView(view)) {
|
||||
[[window_ contentView] addSubview:native_view
|
||||
positioned:NSWindowAbove
|
||||
relativeTo:nil];
|
||||
native_view.hidden = NO;
|
||||
}
|
||||
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
void NativeWindowMac::RemoveBrowserView(NativeBrowserView* view) {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
|
||||
if (!view) {
|
||||
[CATransaction commit];
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto* native_view = GetNativeNSView(view)) {
|
||||
[native_view removeFromSuperview];
|
||||
}
|
||||
remove_browser_view(view);
|
||||
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetTopBrowserView(NativeBrowserView* view) {
|
||||
[CATransaction begin];
|
||||
[CATransaction setDisableActions:YES];
|
||||
|
||||
if (!view) {
|
||||
[CATransaction commit];
|
||||
return;
|
||||
}
|
||||
|
||||
remove_browser_view(view);
|
||||
add_browser_view(view);
|
||||
if (auto* native_view = GetNativeNSView(view)) {
|
||||
[[window_ contentView] addSubview:native_view
|
||||
positioned:NSWindowAbove
|
||||
relativeTo:nil];
|
||||
native_view.hidden = NO;
|
||||
}
|
||||
|
||||
[CATransaction commit];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetParentWindow(NativeWindow* parent) {
|
||||
InternalSetParentWindow(parent, IsVisible());
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/desktop_media_id.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/native_browser_view_views.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents.h"
|
||||
#include "shell/browser/ui/views/inspectable_web_contents_view_views.h"
|
||||
#include "shell/browser/ui/views/root_view.h"
|
||||
|
@ -333,6 +332,7 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options,
|
|||
#endif
|
||||
|
||||
widget()->Init(std::move(params));
|
||||
widget()->SetNativeWindowProperty(kElectronNativeWindowKey, this);
|
||||
SetCanResize(resizable_);
|
||||
|
||||
bool fullscreen = false;
|
||||
|
@ -1361,50 +1361,6 @@ void NativeWindowViews::SetMenu(ElectronMenuModel* menu_model) {
|
|||
}
|
||||
}
|
||||
|
||||
void NativeWindowViews::AddBrowserView(NativeBrowserView* view) {
|
||||
if (!content_view())
|
||||
return;
|
||||
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_browser_view(view);
|
||||
if (view->GetInspectableWebContentsView())
|
||||
content_view()->AddChildView(
|
||||
view->GetInspectableWebContentsView()->GetView());
|
||||
}
|
||||
|
||||
void NativeWindowViews::RemoveBrowserView(NativeBrowserView* view) {
|
||||
if (!content_view())
|
||||
return;
|
||||
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (view->GetInspectableWebContentsView())
|
||||
content_view()->RemoveChildView(
|
||||
view->GetInspectableWebContentsView()->GetView());
|
||||
remove_browser_view(view);
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetTopBrowserView(NativeBrowserView* view) {
|
||||
if (!content_view())
|
||||
return;
|
||||
|
||||
if (!view) {
|
||||
return;
|
||||
}
|
||||
|
||||
remove_browser_view(view);
|
||||
add_browser_view(view);
|
||||
|
||||
if (view->GetInspectableWebContentsView())
|
||||
content_view()->ReorderChildView(
|
||||
view->GetInspectableWebContentsView()->GetView(), -1);
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
|
||||
NativeWindow::SetParentWindow(parent);
|
||||
|
||||
|
@ -1698,14 +1654,6 @@ void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
|
|||
// handle minimized windows on Windows.
|
||||
const auto new_bounds = GetBounds();
|
||||
if (widget_size_ != new_bounds.size()) {
|
||||
int width_delta = new_bounds.width() - widget_size_.width();
|
||||
int height_delta = new_bounds.height() - widget_size_.height();
|
||||
for (NativeBrowserView* item : browser_views()) {
|
||||
auto* native_view = static_cast<NativeBrowserViewViews*>(item);
|
||||
native_view->SetAutoResizeProportions(widget_size_);
|
||||
native_view->AutoResize(new_bounds, width_delta, height_delta);
|
||||
}
|
||||
|
||||
NotifyWindowResize();
|
||||
widget_size_ = new_bounds.size();
|
||||
}
|
||||
|
|
|
@ -124,9 +124,6 @@ class NativeWindowViews : public NativeWindow,
|
|||
void SetFocusable(bool focusable) override;
|
||||
bool IsFocusable() override;
|
||||
void SetMenu(ElectronMenuModel* menu_model) override;
|
||||
void AddBrowserView(NativeBrowserView* browser_view) override;
|
||||
void RemoveBrowserView(NativeBrowserView* browser_view) override;
|
||||
void SetTopBrowserView(NativeBrowserView* browser_view) override;
|
||||
void SetParentWindow(NativeWindow* parent) override;
|
||||
gfx::NativeView GetNativeView() const override;
|
||||
gfx::NativeWindow GetNativeWindow() const override;
|
||||
|
|
|
@ -15,9 +15,13 @@ DelayedNativeViewHost::~DelayedNativeViewHost() = default;
|
|||
|
||||
void DelayedNativeViewHost::ViewHierarchyChanged(
|
||||
const views::ViewHierarchyChangedDetails& details) {
|
||||
NativeViewHost::ViewHierarchyChanged(details);
|
||||
if (details.is_add && GetWidget())
|
||||
Attach(native_view_);
|
||||
// NativeViewHost doesn't expect to have children, so filter the
|
||||
// ViewHierarchyChanged events before passing them on.
|
||||
if (details.child == this) {
|
||||
NativeViewHost::ViewHierarchyChanged(details);
|
||||
if (details.is_add && GetWidget() && !native_view())
|
||||
Attach(native_view_);
|
||||
}
|
||||
}
|
||||
|
||||
bool DelayedNativeViewHost::OnMousePressed(const ui::MouseEvent& ui_event) {
|
||||
|
|
|
@ -22,7 +22,6 @@ class RootViewMac : public views::View {
|
|||
RootViewMac& operator=(const RootViewMac&) = delete;
|
||||
|
||||
// views::View:
|
||||
void Layout() override;
|
||||
gfx::Size GetMinimumSize() const override;
|
||||
gfx::Size GetMaximumSize() const override;
|
||||
|
||||
|
|
|
@ -4,23 +4,20 @@
|
|||
|
||||
#include "shell/browser/ui/cocoa/root_view_mac.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "shell/browser/native_window.h"
|
||||
#include "ui/views/layout/fill_layout.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
RootViewMac::RootViewMac(NativeWindow* window) : window_(window) {
|
||||
set_owned_by_client();
|
||||
SetLayoutManager(std::make_unique<views::FillLayout>());
|
||||
}
|
||||
|
||||
RootViewMac::~RootViewMac() = default;
|
||||
|
||||
void RootViewMac::Layout() {
|
||||
if (!window_->content_view()) // Not ready yet.
|
||||
return;
|
||||
|
||||
window_->content_view()->SetBoundsRect(gfx::Rect(gfx::Point(), size()));
|
||||
}
|
||||
|
||||
gfx::Size RootViewMac::GetMinimumSize() const {
|
||||
return window_->GetMinimumSize();
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include "shell/browser/ui/views/frameless_view.h"
|
||||
|
||||
#include "shell/browser/native_browser_view_views.h"
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#include "shell/browser/ui/views/inspectable_web_contents_view_views.h"
|
||||
#include "ui/aura/window.h"
|
||||
|
|
|
@ -21,10 +21,6 @@ bool IsFakeLocationProviderEnabled() {
|
|||
return BUILDFLAG(OVERRIDE_LOCATION_PROVIDER);
|
||||
}
|
||||
|
||||
bool IsViewApiEnabled() {
|
||||
return BUILDFLAG(ENABLE_VIEWS_API);
|
||||
}
|
||||
|
||||
bool IsPrintingEnabled() {
|
||||
return BUILDFLAG(ENABLE_PRINTING);
|
||||
}
|
||||
|
@ -50,7 +46,6 @@ void Initialize(v8::Local<v8::Object> exports,
|
|||
dict.SetMethod("isPDFViewerEnabled", &IsPDFViewerEnabled);
|
||||
dict.SetMethod("isFakeLocationProviderEnabled",
|
||||
&IsFakeLocationProviderEnabled);
|
||||
dict.SetMethod("isViewApiEnabled", &IsViewApiEnabled);
|
||||
dict.SetMethod("isPrintingEnabled", &IsPrintingEnabled);
|
||||
dict.SetMethod("isComponentBuild", &IsComponentBuild);
|
||||
dict.SetMethod("isExtensionsEnabled", &IsExtensionsEnabled);
|
||||
|
|
|
@ -9,6 +9,15 @@
|
|||
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
|
||||
// SkColor is a typedef for uint32_t, this wrapper is to tag an SkColor for
|
||||
// ease of use in gin converters.
|
||||
struct WrappedSkColor {
|
||||
WrappedSkColor() {}
|
||||
WrappedSkColor(SkColor c) : value(c) {} // NOLINT(runtime/explicit)
|
||||
SkColor value;
|
||||
operator SkColor() const { return value; }
|
||||
};
|
||||
|
||||
namespace electron {
|
||||
|
||||
// Parses a CSS-style color string from hex, rgb(), rgba(),
|
||||
|
|
|
@ -4,9 +4,14 @@
|
|||
|
||||
#include "shell/common/gin_converters/gfx_converter.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "gin/data_object_builder.h"
|
||||
#include "shell/common/color_util.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "ui/display/display.h"
|
||||
#include "ui/display/screen.h"
|
||||
#include "ui/gfx/geometry/insets.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
#include "ui/gfx/geometry/point_f.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
|
@ -103,6 +108,35 @@ bool Converter<gfx::Rect>::FromV8(v8::Isolate* isolate,
|
|||
return true;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Converter<gfx::Insets>::ToV8(v8::Isolate* isolate,
|
||||
const gfx::Insets& val) {
|
||||
return gin::DataObjectBuilder(isolate)
|
||||
.Set("top", val.top())
|
||||
.Set("left", val.left())
|
||||
.Set("bottom", val.bottom())
|
||||
.Set("right", val.right())
|
||||
.Build();
|
||||
}
|
||||
|
||||
bool Converter<gfx::Insets>::FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
gfx::Insets* out) {
|
||||
gin::Dictionary dict(isolate);
|
||||
if (!gin::ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
double top, left, right, bottom;
|
||||
if (!dict.Get("top", &top))
|
||||
return false;
|
||||
if (!dict.Get("left", &left))
|
||||
return false;
|
||||
if (!dict.Get("bottom", &bottom))
|
||||
return false;
|
||||
if (!dict.Get("right", &right))
|
||||
return false;
|
||||
*out = gfx::Insets::TLBR(top, left, bottom, right);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
struct Converter<display::Display::AccelerometerSupport> {
|
||||
static v8::Local<v8::Value> ToV8(
|
||||
|
@ -185,4 +219,14 @@ v8::Local<v8::Value> Converter<gfx::ResizeEdge>::ToV8(
|
|||
}
|
||||
}
|
||||
|
||||
bool Converter<WrappedSkColor>::FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
WrappedSkColor* out) {
|
||||
std::string str;
|
||||
if (!gin::ConvertFromV8(isolate, val, &str))
|
||||
return false;
|
||||
*out = electron::ParseCSSColor(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace gin
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#define ELECTRON_SHELL_COMMON_GIN_CONVERTERS_GFX_CONVERTER_H_
|
||||
|
||||
#include "gin/converter.h"
|
||||
#include "shell/common/color_util.h"
|
||||
|
||||
namespace display {
|
||||
class Display;
|
||||
|
@ -16,6 +17,7 @@ class Point;
|
|||
class PointF;
|
||||
class Size;
|
||||
class Rect;
|
||||
class Insets;
|
||||
enum class ResizeEdge;
|
||||
} // namespace gfx
|
||||
|
||||
|
@ -54,6 +56,15 @@ struct Converter<gfx::Rect> {
|
|||
gfx::Rect* out);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<gfx::Insets> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const gfx::Insets& val);
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
gfx::Insets* out);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<display::Display> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
|
@ -69,6 +80,13 @@ struct Converter<gfx::ResizeEdge> {
|
|||
const gfx::ResizeEdge& val);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<WrappedSkColor> {
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
WrappedSkColor* out);
|
||||
};
|
||||
|
||||
} // namespace gin
|
||||
|
||||
#endif // ELECTRON_SHELL_COMMON_GIN_CONVERTERS_GFX_CONVERTER_H_
|
||||
|
|
|
@ -23,7 +23,7 @@ class EventEmitterMixin;
|
|||
// class Example : public gin::Wrappable<Example>,
|
||||
// public gin_helper::Constructible<Example> {
|
||||
// public:
|
||||
// static gin::Handle<Tray> New(...usual gin method arguments...);
|
||||
// static gin::Handle<Example> New(...usual gin method arguments...);
|
||||
// static void FillObjectTemplate(
|
||||
// v8::Isolate*,
|
||||
// v8::Local<v8::ObjectTemplate>);
|
||||
|
|
|
@ -46,13 +46,13 @@
|
|||
#define ELECTRON_BROWSER_BINDINGS(V) \
|
||||
V(electron_browser_app) \
|
||||
V(electron_browser_auto_updater) \
|
||||
V(electron_browser_browser_view) \
|
||||
V(electron_browser_content_tracing) \
|
||||
V(electron_browser_crash_reporter) \
|
||||
V(electron_browser_desktop_capturer) \
|
||||
V(electron_browser_dialog) \
|
||||
V(electron_browser_event_emitter) \
|
||||
V(electron_browser_global_shortcut) \
|
||||
V(electron_browser_image_view) \
|
||||
V(electron_browser_in_app_purchase) \
|
||||
V(electron_browser_menu) \
|
||||
V(electron_browser_message_port) \
|
||||
|
@ -98,8 +98,6 @@
|
|||
|
||||
#define ELECTRON_UTILITY_BINDINGS(V) V(electron_utility_parent_port)
|
||||
|
||||
#define ELECTRON_VIEWS_BINDINGS(V) V(electron_browser_image_view)
|
||||
|
||||
#define ELECTRON_TESTING_BINDINGS(V) V(electron_common_testing)
|
||||
|
||||
// This is used to load built-in bindings. Instead of using
|
||||
|
@ -112,9 +110,6 @@ ELECTRON_BROWSER_BINDINGS(V)
|
|||
ELECTRON_COMMON_BINDINGS(V)
|
||||
ELECTRON_RENDERER_BINDINGS(V)
|
||||
ELECTRON_UTILITY_BINDINGS(V)
|
||||
#if BUILDFLAG(ENABLE_VIEWS_API)
|
||||
ELECTRON_VIEWS_BINDINGS(V)
|
||||
#endif
|
||||
#if DCHECK_IS_ON()
|
||||
ELECTRON_TESTING_BINDINGS(V)
|
||||
#endif
|
||||
|
@ -441,9 +436,6 @@ void NodeBindings::RegisterBuiltinBindings() {
|
|||
#define V(modname) _register_##modname();
|
||||
if (IsBrowserProcess()) {
|
||||
ELECTRON_BROWSER_BINDINGS(V)
|
||||
#if BUILDFLAG(ENABLE_VIEWS_API)
|
||||
ELECTRON_VIEWS_BINDINGS(V)
|
||||
#endif
|
||||
}
|
||||
ELECTRON_COMMON_BINDINGS(V)
|
||||
if (IsRendererProcess()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue