Merge pull request #12584 from electron/no-webcontents-in-constructor

Refactor NativeWindow (Part 5): Add NativeWindow::SetContentView
This commit is contained in:
Cheng Zhao 2018-04-11 15:34:29 +09:00 committed by GitHub
commit 558d36c1f3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 174 additions and 152 deletions

View file

@ -150,9 +150,9 @@ void BrowserWindow::Init(v8::Isolate* isolate,
// Creates BrowserWindow.
window_.reset(NativeWindow::Create(
web_contents->managed_web_contents(),
options,
parent.IsEmpty() ? nullptr : parent->window_.get()));
window_->SetContentView(web_contents->managed_web_contents());
web_contents->SetOwnerWindow(window_.get());
// Tell the content module to initialize renderer widget with transparent

View file

@ -38,7 +38,7 @@ void CommonWebContentsDelegate::ShowAutofillPopup(
auto* window = static_cast<NativeWindowViews*>(owner_window());
autofill_popup_->CreateView(
frame_host, offscreen, window->web_view(), bounds);
frame_host, offscreen, window->content_view(), bounds);
autofill_popup_->SetItems(values, labels);
}

View file

@ -12,17 +12,14 @@
#include "atom/browser/window_list.h"
#include "atom/common/color_util.h"
#include "atom/common/options_switches.h"
#include "brightray/browser/inspectable_web_contents.h"
#include "native_mate/dictionary.h"
DEFINE_WEB_CONTENTS_USER_DATA_KEY(atom::NativeWindowRelay);
namespace atom {
NativeWindow::NativeWindow(
brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options,
NativeWindow* parent)
NativeWindow::NativeWindow(const mate::Dictionary& options,
NativeWindow* parent)
: has_frame_(true),
transparent_(false),
enable_larger_than_screen_(false),
@ -134,6 +131,12 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
if (options.Get(options::kKiosk, &kiosk) && kiosk) {
SetKiosk(kiosk);
}
#if defined(OS_MACOSX)
std::string type;
if (options.Get(options::kVibrancyType, &type)) {
SetVibrancy(type);
}
#endif
std::string color;
if (options.Get(options::kBackgroundColor, &color)) {
SetBackgroundColor(ParseHexColor(color));

View file

@ -11,13 +11,11 @@
#include <vector>
#include "atom/browser/native_window_observer.h"
#include "atom/browser/ui/atom_menu_model.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/supports_user_data.h"
#include "content/public/browser/web_contents_user_data.h"
#include "extensions/browser/app_window/size_constraints.h"
#include "native_mate/persistent_dictionary.h"
class SkRegion;
@ -39,10 +37,12 @@ class Size;
namespace mate {
class Dictionary;
class PersistentDictionary;
}
namespace atom {
class AtomMenuModel;
class NativeBrowserView;
struct DraggableRegion;
@ -53,13 +53,14 @@ class NativeWindow : public base::SupportsUserData {
// Create window with existing WebContents, the caller is responsible for
// managing the window's live.
static NativeWindow* Create(
brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options,
NativeWindow* parent = nullptr);
static NativeWindow* Create(const mate::Dictionary& options,
NativeWindow* parent = nullptr);
void InitFromOptions(const mate::Dictionary& options);
virtual void SetContentView(
brightray::InspectableWebContents* web_contents) = 0;
virtual void Close() = 0;
virtual void CloseImmediately() = 0;
virtual bool IsClosed() const { return is_closed_; }
@ -272,8 +273,7 @@ class NativeWindow : public base::SupportsUserData {
bool is_modal() const { return is_modal_; }
protected:
NativeWindow(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options,
NativeWindow(const mate::Dictionary& options,
NativeWindow* parent);
void set_browser_view(NativeBrowserView* browser_view) {

View file

@ -21,12 +21,12 @@ namespace atom {
class NativeWindowMac : public NativeWindow {
public:
NativeWindowMac(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options,
NativeWindowMac(const mate::Dictionary& options,
NativeWindow* parent);
~NativeWindowMac() override;
// NativeWindow:
void SetContentView(brightray::InspectableWebContents* web_contents) override;
void Close() override;
void CloseImmediately() override;
void Focus(bool focus) override;
@ -141,8 +141,6 @@ class NativeWindowMac : public NativeWindow {
void InternalSetParentWindow(NativeWindow* parent, bool attach);
void ShowWindowButton(NSWindowButton button);
void InstallView(NSView* view);
void SetForwardMouseMessages(bool forward);
base::scoped_nsobject<AtomNSWindow> window_;
@ -152,7 +150,10 @@ class NativeWindowMac : public NativeWindow {
id wheel_event_monitor_;
// The view that will fill the whole frameless window.
base::scoped_nsobject<FullSizeContentView> content_view_;
base::scoped_nsobject<FullSizeContentView> container_view_;
// The content view passed by SetContentView, weak ref.
NSView* content_view_;
bool is_kiosk_;

View file

@ -776,11 +776,10 @@ struct Converter<atom::NativeWindowMac::TitleBarStyle> {
namespace atom {
NativeWindowMac::NativeWindowMac(
brightray::InspectableWebContents* web_contents,
const mate::Dictionary& options,
NativeWindow* parent)
: NativeWindow(web_contents, options, parent),
NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
NativeWindow* parent)
: NativeWindow(options, parent),
content_view_(nil),
is_kiosk_(false),
was_fullscreen_(false),
zoom_to_page_width_(false),
@ -952,9 +951,6 @@ NativeWindowMac::NativeWindowMac(
options.Get(options::kDisableAutoHideCursor, &disableAutoHideCursor);
[window_ setDisableAutoHideCursor:disableAutoHideCursor];
NSView* view = web_contents->GetView()->GetNativeView();
[view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
// Use an NSEvent monitor to listen for the wheel event.
BOOL __block began = NO;
wheel_event_monitor_ = [NSEvent
@ -975,13 +971,6 @@ NativeWindowMac::NativeWindowMac(
return event;
}];
InstallView(web_contents->GetView()->GetNativeView());
std::string type;
if (options.Get(options::kVibrancyType, &type)) {
SetVibrancy(type);
}
// Set maximizable state last to ensure zoom button does not get reset
// by calls to other APIs.
SetMaximizable(maximizable);
@ -991,6 +980,76 @@ NativeWindowMac::~NativeWindowMac() {
[NSEvent removeMonitor:wheel_event_monitor_];
}
void NativeWindowMac::SetContentView(
brightray::InspectableWebContents* web_contents) {
if (content_view_)
[content_view_ removeFromSuperview];
content_view_ = web_contents->GetView()->GetNativeView();
[content_view_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
// Make sure the bottom corner is rounded for non-modal windows: http://crbug.com/396264.
// But do not enable it on OS X 10.9 for transparent window, otherwise a
// semi-transparent frame would show.
if (!(transparent() && base::mac::IsOS10_9()) && !is_modal())
[[window_ contentView] setWantsLayer:YES];
if (has_frame()) {
[content_view_ setFrame:[[window_ contentView] bounds]];
[[window_ contentView] addSubview:content_view_];
} else {
// In OSX 10.10, adding subviews to the root view for the NSView hierarchy
// produces warnings. To eliminate the warnings, we resize the contentView
// to fill the window, and add subviews to that.
// http://crbug.com/380412
container_view_.reset([[FullSizeContentView alloc] init]);
[container_view_
setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[container_view_ setFrame:[[[window_ contentView] superview] bounds]];
// Move the vibrantView from the old content view.
if ([window_ vibrantView]) {
[[window_ vibrantView] removeFromSuperview];
[container_view_ addSubview:[window_ vibrantView]
positioned:NSWindowBelow
relativeTo:nil];
}
[window_ setContentView:container_view_];
[content_view_ setFrame:[container_view_ bounds]];
[container_view_ addSubview:content_view_];
// The fullscreen button should always be hidden for frameless window.
[[window_ standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
if (title_bar_style_ == CUSTOM_BUTTONS_ON_HOVER) {
NSView* window_button_view = [[[CustomWindowButtonView alloc]
initWithFrame:NSZeroRect] autorelease];
[container_view_ addSubview:window_button_view];
} else {
if (title_bar_style_ != NORMAL) {
if (base::mac::IsOS10_9()) {
ShowWindowButton(NSWindowZoomButton);
ShowWindowButton(NSWindowMiniaturizeButton);
ShowWindowButton(NSWindowCloseButton);
}
return;
}
// Hide the window buttons.
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
}
// Some third-party macOS utilities check the zoom button's enabled state to
// determine whether to show custom UI on hover, so we disable it here to
// prevent them from doing so in a frameless app window.
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
}
}
void NativeWindowMac::Close() {
// When this is a sheet showing, performClose won't work.
if (is_modal() && parent() && IsVisible()) {
@ -1649,7 +1708,7 @@ void NativeWindowMac::SetVibrancy(const std::string& type) {
return;
}
background_color_before_vibrancy_.reset([window_ backgroundColor]);
background_color_before_vibrancy_.reset([[window_ backgroundColor] retain]);
transparency_before_vibrancy_ = [window_ titlebarAppearsTransparent];
ui::GpuSwitchingManager::SetTransparent(true);
@ -1775,60 +1834,6 @@ void NativeWindowMac::ShowWindowButton(NSWindowButton button) {
[view.superview addSubview:view positioned:NSWindowAbove relativeTo:nil];
}
void NativeWindowMac::InstallView(NSView* view) {
// Make sure the bottom corner is rounded for non-modal windows: http://crbug.com/396264.
// But do not enable it on OS X 10.9 for transparent window, otherwise a
// semi-transparent frame would show.
if (!(transparent() && base::mac::IsOS10_9()) && !is_modal())
[[window_ contentView] setWantsLayer:YES];
if (has_frame()) {
[view setFrame:[[window_ contentView] bounds]];
[[window_ contentView] addSubview:view];
} else {
// In OSX 10.10, adding subviews to the root view for the NSView hierarchy
// produces warnings. To eliminate the warnings, we resize the contentView
// to fill the window, and add subviews to that.
// http://crbug.com/380412
content_view_.reset([[FullSizeContentView alloc] init]);
[content_view_
setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
[content_view_ setFrame:[[[window_ contentView] superview] bounds]];
[window_ setContentView:content_view_];
[view setFrame:[content_view_ bounds]];
[content_view_ addSubview:view];
// The fullscreen button should always be hidden for frameless window.
[[window_ standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
if (title_bar_style_ == CUSTOM_BUTTONS_ON_HOVER) {
NSView* window_button_view = [[[CustomWindowButtonView alloc]
initWithFrame:NSZeroRect] autorelease];
[content_view_ addSubview:window_button_view];
} else {
if (title_bar_style_ != NORMAL) {
if (base::mac::IsOS10_9()) {
ShowWindowButton(NSWindowZoomButton);
ShowWindowButton(NSWindowMiniaturizeButton);
ShowWindowButton(NSWindowCloseButton);
}
return;
}
// Hide the window buttons.
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
}
// Some third-party macOS utilities check the zoom button's enabled state to
// determine whether to show custom UI on hover, so we disable it here to
// prevent them from doing so in a frameless app window.
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
}
}
void NativeWindowMac::SetForwardMouseMessages(bool forward) {
[window_ setAcceptsMouseMovedEvents:forward];
}
@ -1860,11 +1865,9 @@ void NativeWindowMac::SetCollectionBehavior(bool on, NSUInteger flag) {
}
// static
NativeWindow* NativeWindow::Create(
brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options,
NativeWindow* parent) {
return new NativeWindowMac(inspectable_web_contents, options, parent);
NativeWindow* NativeWindow::Create(const mate::Dictionary& options,
NativeWindow* parent) {
return new NativeWindowMac(options, parent);
}
} // namespace atom

View file

@ -118,14 +118,12 @@ class NativeWindowClientView : public views::ClientView {
} // namespace
NativeWindowViews::NativeWindowViews(
brightray::InspectableWebContents* web_contents,
const mate::Dictionary& options,
NativeWindow* parent)
: NativeWindow(web_contents, options, parent),
NativeWindowViews::NativeWindowViews(const mate::Dictionary& options,
NativeWindow* parent)
: NativeWindow(options, parent),
window_(new views::Widget),
web_view_(web_contents->GetView()->GetView()),
focused_view_(web_contents->GetView()->GetWebView()),
content_view_(nullptr),
focused_view_(nullptr),
menu_bar_autohide_(false),
menu_bar_visible_(false),
menu_bar_alt_pressed_(false),
@ -266,8 +264,6 @@ NativeWindowViews::NativeWindowViews(
SetWindowType(GetAcceleratedWidget(), window_type);
#endif
AddChildView(web_view_);
#if defined(OS_WIN)
if (!has_frame()) {
// Set Window style so that we get a minimize and maximize animation when
@ -310,7 +306,6 @@ NativeWindowViews::NativeWindowViews(
size = ContentBoundsToWindowBounds(gfx::Rect(size)).size();
window_->CenterWindow(size);
Layout();
#if defined(OS_WIN)
// Save initial window state.
@ -331,6 +326,22 @@ NativeWindowViews::~NativeWindowViews() {
#endif
}
void NativeWindowViews::SetContentView(
brightray::InspectableWebContents* web_contents) {
if (content_view_) {
RemoveChildView(content_view_);
if (browser_view()) {
content_view_->RemoveChildView(
browser_view()->GetInspectableWebContentsView()->GetView());
set_browser_view(nullptr);
}
}
content_view_ = web_contents->GetView()->GetView();
focused_view_ = web_contents->GetView()->GetWebView();
AddChildView(content_view_);
Layout();
}
void NativeWindowViews::Close() {
if (!IsClosable()) {
WindowList::WindowCloseCancelled(this);
@ -412,6 +423,33 @@ bool NativeWindowViews::IsEnabled() {
#endif
}
void NativeWindowViews::SetEnabled(bool enable) {
// Handle multiple calls of SetEnabled correctly.
if (enable) {
--disable_count_;
if (disable_count_ != 0)
return;
} else {
++disable_count_;
if (disable_count_ != 1)
return;
}
#if defined(OS_WIN)
::EnableWindow(GetAcceleratedWidget(), enable);
#elif defined(USE_X11)
views::DesktopWindowTreeHostX11* tree_host =
views::DesktopWindowTreeHostX11::GetHostForXID(GetAcceleratedWidget());
if (enable) {
tree_host->RemoveEventRewriter(event_disabler_.get());
event_disabler_.reset();
} else {
event_disabler_.reset(new EventDisabler);
tree_host->AddEventRewriter(event_disabler_.get());
}
#endif
}
void NativeWindowViews::Maximize() {
#if defined(OS_WIN)
// For window without WS_THICKFRAME style, we can not call Maximize().
@ -544,7 +582,7 @@ gfx::Rect NativeWindowViews::GetBounds() {
}
gfx::Rect NativeWindowViews::GetContentBounds() {
return web_view_->GetBoundsInScreen();
return content_view_ ? content_view_->GetBoundsInScreen() : gfx::Rect();
}
gfx::Size NativeWindowViews::GetContentSize() {
@ -553,7 +591,7 @@ gfx::Size NativeWindowViews::GetContentSize() {
return NativeWindow::GetContentSize();
#endif
return web_view_->size();
return content_view_ ? content_view_->size() : gfx::Size();
}
void NativeWindowViews::SetContentSizeConstraints(
@ -933,8 +971,11 @@ void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) {
}
void NativeWindowViews::SetBrowserView(NativeBrowserView* view) {
if (!content_view_)
return;
if (browser_view()) {
web_view_->RemoveChildView(
content_view_->RemoveChildView(
browser_view()->GetInspectableWebContentsView()->GetView());
set_browser_view(nullptr);
}
@ -946,7 +987,7 @@ void NativeWindowViews::SetBrowserView(NativeBrowserView* view) {
// Add as child of the main web view to avoid (0, 0) origin from overlapping
// with menu bar.
set_browser_view(view);
web_view_->AddChildView(view->GetInspectableWebContentsView()->GetView());
content_view_->AddChildView(view->GetInspectableWebContentsView()->GetView());
}
void NativeWindowViews::SetParentWindow(NativeWindow* parent) {
@ -1129,33 +1170,6 @@ void NativeWindowViews::SetIcon(const gfx::ImageSkia& icon) {
}
#endif
void NativeWindowViews::SetEnabled(bool enable) {
// Handle multiple calls of SetEnabled correctly.
if (enable) {
--disable_count_;
if (disable_count_ != 0)
return;
} else {
++disable_count_;
if (disable_count_ != 1)
return;
}
#if defined(OS_WIN)
::EnableWindow(GetAcceleratedWidget(), enable);
#elif defined(USE_X11)
views::DesktopWindowTreeHostX11* tree_host =
views::DesktopWindowTreeHostX11::GetHostForXID(GetAcceleratedWidget());
if (enable) {
tree_host->RemoveEventRewriter(event_disabler_.get());
event_disabler_.reset();
} else {
event_disabler_.reset(new EventDisabler);
tree_host->AddEventRewriter(event_disabler_.get());
}
#endif
}
void NativeWindowViews::OnWidgetActivationChanged(
views::Widget* widget, bool active) {
if (widget != window_.get())
@ -1346,6 +1360,9 @@ void NativeWindowViews::HandleKeyboardEvent(
}
void NativeWindowViews::Layout() {
if (!content_view_) // Not ready yet.
return;
const auto size = GetContentsBounds().size();
const auto menu_bar_bounds =
menu_bar_visible_ ? gfx::Rect(0, 0, size.width(), kMenuBarHeight)
@ -1354,11 +1371,9 @@ void NativeWindowViews::Layout() {
menu_bar_->SetBoundsRect(menu_bar_bounds);
}
if (web_view_) {
web_view_->SetBoundsRect(
gfx::Rect(0, menu_bar_bounds.height(), size.width(),
size.height() - menu_bar_bounds.height()));
}
content_view_->SetBoundsRect(
gfx::Rect(0, menu_bar_bounds.height(), size.width(),
size.height() - menu_bar_bounds.height()));
}
gfx::Size NativeWindowViews::GetMinimumSize() const {
@ -1398,11 +1413,9 @@ ui::WindowShowState NativeWindowViews::GetRestoredState() {
}
// static
NativeWindow* NativeWindow::Create(
brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options,
NativeWindow* parent) {
return new NativeWindowViews(inspectable_web_contents, options, parent);
NativeWindow* NativeWindow::Create(const mate::Dictionary& options,
NativeWindow* parent) {
return new NativeWindowViews(options, parent);
}
} // namespace atom

View file

@ -46,12 +46,12 @@ class NativeWindowViews : public NativeWindow,
public views::WidgetDelegateView,
public views::WidgetObserver {
public:
NativeWindowViews(brightray::InspectableWebContents* inspectable_web_contents,
const mate::Dictionary& options,
NativeWindowViews(const mate::Dictionary& options,
NativeWindow* parent);
~NativeWindowViews() override;
// NativeWindow:
void SetContentView(brightray::InspectableWebContents* web_contents) override;
void Close() override;
void CloseImmediately() override;
void Focus(bool focus) override;
@ -61,6 +61,7 @@ class NativeWindowViews : public NativeWindow,
void Hide() override;
bool IsVisible() override;
bool IsEnabled() override;
void SetEnabled(bool enable) override;
void Maximize() override;
void Unmaximize() override;
bool IsMaximized() override;
@ -139,10 +140,8 @@ class NativeWindowViews : public NativeWindow,
void SetIcon(const gfx::ImageSkia& icon);
#endif
void SetEnabled(bool enable) override;
views::Widget* widget() const { return window_.get(); }
views::View* web_view() const { return web_view_; }
views::View* content_view() const { return content_view_; }
SkRegion* draggable_region() const { return draggable_region_.get(); }
#if defined(OS_WIN)
@ -209,7 +208,7 @@ class NativeWindowViews : public NativeWindow,
ui::WindowShowState GetRestoredState();
std::unique_ptr<views::Widget> window_;
views::View* web_view_; // Managed by inspectable_web_contents_.
views::View* content_view_; // Weak ref.
views::View* focused_view_; // The view should be focused by default.
std::unique_ptr<MenuBar> menu_bar_;

View file

@ -16,6 +16,7 @@
#include "chrome/browser/ui/libgtkui/gtk_signal.h"
#include "chrome/browser/ui/libgtkui/gtk_util.h"
#include "chrome/browser/ui/libgtkui/skia_utils_gtk.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/widget/desktop_aura/x11_desktop_handler.h"
#define ANSI_FOREGROUND_RED "\x1b[31m"

View file

@ -11,6 +11,7 @@
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
#include "skia/ext/skia_utils_mac.h"
#include "ui/gfx/image/image_skia.h"
@interface ModalDelegate : NSObject {
@private

View file

@ -21,6 +21,7 @@
#include "base/win/scoped_gdi_object.h"
#include "content/public/browser/browser_thread.h"
#include "ui/gfx/icon_util.h"
#include "ui/gfx/image/image_skia.h"
namespace atom {