Merge pull request #12696 from electron/mac-use-widget
Refactor NativeWindow (Part 9): Use views::Widget on macOS
This commit is contained in:
commit
152422af81
8 changed files with 104 additions and 46 deletions
|
@ -23,7 +23,8 @@
|
|||
|
||||
namespace atom {
|
||||
|
||||
class NativeWindowMac : public NativeWindow {
|
||||
class NativeWindowMac : public NativeWindow,
|
||||
public views::WidgetDelegate {
|
||||
public:
|
||||
NativeWindowMac(const mate::Dictionary& options, NativeWindow* parent);
|
||||
~NativeWindowMac() override;
|
||||
|
@ -144,19 +145,25 @@ class NativeWindowMac : public NativeWindow {
|
|||
bool fullscreen_window_title() const { return fullscreen_window_title_; }
|
||||
bool simple_fullscreen() const { return always_simple_fullscreen_; }
|
||||
|
||||
protected:
|
||||
// views::WidgetDelegate:
|
||||
views::Widget* GetWidget() override;
|
||||
const views::Widget* GetWidget() const override;
|
||||
bool CanResize() const override;
|
||||
|
||||
private:
|
||||
void InternalSetParentWindow(NativeWindow* parent, bool attach);
|
||||
void ShowWindowButton(NSWindowButton button);
|
||||
|
||||
void SetForwardMouseMessages(bool forward);
|
||||
|
||||
base::scoped_nsobject<AtomNSWindow> window_;
|
||||
std::unique_ptr<views::Widget> widget_;
|
||||
AtomNSWindow* window_; // Weak ref, managed by widget_.
|
||||
|
||||
base::scoped_nsobject<AtomNSWindowDelegate> window_delegate_;
|
||||
base::scoped_nsobject<AtomPreviewItem> preview_item_;
|
||||
base::scoped_nsobject<AtomTouchBar> touch_bar_;
|
||||
|
||||
std::unique_ptr<views::Widget> widget_;
|
||||
|
||||
// Event monitor for scroll wheel event.
|
||||
id wheel_event_monitor_;
|
||||
|
||||
|
@ -167,12 +174,10 @@ class NativeWindowMac : public NativeWindow {
|
|||
NSView* content_view_;
|
||||
|
||||
bool is_kiosk_;
|
||||
|
||||
bool was_fullscreen_;
|
||||
|
||||
bool zoom_to_page_width_;
|
||||
|
||||
bool fullscreen_window_title_;
|
||||
bool resizable_;
|
||||
|
||||
NSInteger attention_request_id_; // identifier from requestUserAttention
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <string>
|
||||
|
||||
#include "atom/browser/native_browser_view_mac.h"
|
||||
#include "atom/browser/ui/cocoa/atom_native_widget_mac.h"
|
||||
#include "atom/browser/ui/cocoa/atom_ns_window.h"
|
||||
#include "atom/browser/ui/cocoa/atom_ns_window_delegate.h"
|
||||
#include "atom/browser/ui/cocoa/atom_preview_item.h"
|
||||
|
@ -25,6 +26,8 @@
|
|||
#include "skia/ext/skia_utils_mac.h"
|
||||
#include "ui/gfx/skia_util.h"
|
||||
#include "ui/gl/gpu_switching_manager.h"
|
||||
#include "ui/views/background.h"
|
||||
#include "ui/views/cocoa/bridged_native_widget.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
|
||||
// Custom Quit, Minimize and Full Screen button container for frameless
|
||||
|
@ -238,6 +241,7 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
was_fullscreen_(false),
|
||||
zoom_to_page_width_(false),
|
||||
fullscreen_window_title_(false),
|
||||
resizable_(true),
|
||||
attention_request_id_(0),
|
||||
title_bar_style_(NORMAL),
|
||||
always_simple_fullscreen_(false),
|
||||
|
@ -247,12 +251,16 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
options.Get(options::kHeight, &height);
|
||||
|
||||
NSRect main_screen_rect = [[[NSScreen screens] firstObject] frame];
|
||||
NSRect cocoa_bounds = NSMakeRect(
|
||||
round((NSWidth(main_screen_rect) - width) / 2),
|
||||
round((NSHeight(main_screen_rect) - height) / 2), width, height);
|
||||
gfx::Rect bounds(round((NSWidth(main_screen_rect) - width) / 2),
|
||||
round((NSHeight(main_screen_rect) - height) / 2),
|
||||
width,
|
||||
height);
|
||||
|
||||
bool resizable = true;
|
||||
options.Get(options::kResizable, &resizable);
|
||||
options.Get(options::kResizable, &resizable_);
|
||||
options.Get(options::kTitleBarStyle, &title_bar_style_);
|
||||
options.Get(options::kZoomToPageWidth, &zoom_to_page_width_);
|
||||
options.Get(options::kFullscreenWindowTitle, &fullscreen_window_title_);
|
||||
options.Get(options::kSimpleFullScreen, &always_simple_fullscreen_);
|
||||
|
||||
bool minimizable = true;
|
||||
options.Get(options::kMinimizable, &minimizable);
|
||||
|
@ -263,8 +271,6 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
bool closable = true;
|
||||
options.Get(options::kClosable, &closable);
|
||||
|
||||
options.Get(options::kTitleBarStyle, &title_bar_style_);
|
||||
|
||||
std::string tabbingIdentifier;
|
||||
options.Get(options::kTabbingIdentifier, &tabbingIdentifier);
|
||||
|
||||
|
@ -299,14 +305,19 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
if (!useStandardWindow || transparent() || !has_frame()) {
|
||||
styleMask |= NSTexturedBackgroundWindowMask;
|
||||
}
|
||||
if (resizable) {
|
||||
styleMask |= NSResizableWindowMask;
|
||||
}
|
||||
|
||||
window_.reset([[AtomNSWindow alloc] initWithContentRect:cocoa_bounds
|
||||
styleMask:styleMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:YES]);
|
||||
// Create views::Widget and assign window_ with it.
|
||||
// TODO(zcbenz): Get rid of the window_ in future.
|
||||
widget_.reset(new views::Widget());
|
||||
views::Widget::InitParams params;
|
||||
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
||||
params.bounds = bounds;
|
||||
params.delegate = this;
|
||||
params.type = views::Widget::InitParams::TYPE_WINDOW;
|
||||
params.native_widget = new AtomNativeWidgetMac(styleMask, widget_.get());
|
||||
widget_->Init(params);
|
||||
window_ = static_cast<AtomNSWindow*>(widget_->GetNativeWindow());
|
||||
|
||||
[window_ setShell:this];
|
||||
[window_ setEnableLargerThanScreen:enable_larger_than_screen()];
|
||||
|
||||
|
@ -357,9 +368,6 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
}
|
||||
}
|
||||
|
||||
// We will manage window's lifetime ourselves.
|
||||
[window_ setReleasedWhenClosed:NO];
|
||||
|
||||
// Hide the title bar background
|
||||
if (title_bar_style_ != NORMAL) {
|
||||
if (@available(macOS 10.10, *)) {
|
||||
|
@ -380,17 +388,11 @@ NativeWindowMac::NativeWindowMac(const mate::Dictionary& options,
|
|||
}
|
||||
}
|
||||
|
||||
// On macOS the initial window size doesn't include window frame.
|
||||
// Resize to content bounds.
|
||||
bool use_content_size = false;
|
||||
options.Get(options::kUseContentSize, &use_content_size);
|
||||
if (!has_frame() || !use_content_size)
|
||||
SetSize(gfx::Size(width, height));
|
||||
|
||||
options.Get(options::kZoomToPageWidth, &zoom_to_page_width_);
|
||||
|
||||
options.Get(options::kFullscreenWindowTitle, &fullscreen_window_title_);
|
||||
|
||||
options.Get(options::kSimpleFullScreen, &always_simple_fullscreen_);
|
||||
if (!has_frame() || use_content_size)
|
||||
SetContentSize(gfx::Size(width, height));
|
||||
|
||||
// Enable the NSView to accept first mouse event.
|
||||
bool acceptsFirstMouse = false;
|
||||
|
@ -448,8 +450,13 @@ void NativeWindowMac::SetContentView(
|
|||
// 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())
|
||||
if (!(transparent() && base::mac::IsOS10_9()) && !is_modal()) {
|
||||
base::scoped_nsobject<CALayer> background_layer([[CALayer alloc] init]);
|
||||
[background_layer
|
||||
setAutoresizingMask:kCALayerWidthSizable | kCALayerHeightSizable];
|
||||
[[window_ contentView] setLayer:background_layer];
|
||||
[[window_ contentView] setWantsLayer:YES];
|
||||
}
|
||||
|
||||
if (has_frame()) {
|
||||
[content_view_ setFrame:[[window_ contentView] bounds]];
|
||||
|
@ -712,6 +719,7 @@ void NativeWindowMac::SetContentSizeConstraints(
|
|||
void NativeWindowMac::MoveTop() {
|
||||
[window_ orderWindow:NSWindowAbove relativeTo:0];
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetResizable(bool resizable) {
|
||||
SetStyleMask(resizable, NSResizableWindowMask);
|
||||
}
|
||||
|
@ -974,6 +982,14 @@ bool NativeWindowMac::IsKiosk() {
|
|||
void NativeWindowMac::SetBackgroundColor(SkColor color) {
|
||||
base::ScopedCFTypeRef<CGColorRef> cgcolor(
|
||||
skia::CGColorCreateFromSkColor(color));
|
||||
// views::Widget adds a layer for the content view.
|
||||
auto* bridge = views::NativeWidgetMac::GetBridgeForNativeWindow(window_);
|
||||
NSView* compositor_superview =
|
||||
static_cast<ui::AcceleratedWidgetMacNSView*>(bridge)->
|
||||
AcceleratedWidgetGetNSView();
|
||||
[[compositor_superview layer] setBackgroundColor:cgcolor];
|
||||
// When using WebContents as content view, the contentView also has layer.
|
||||
if ([[window_ contentView] wantsLayer])
|
||||
[[[window_ contentView] layer] setBackgroundColor:cgcolor];
|
||||
}
|
||||
|
||||
|
@ -1145,7 +1161,7 @@ void NativeWindowMac::ToggleTabBar() {
|
|||
}
|
||||
|
||||
bool NativeWindowMac::AddTabbedWindow(NativeWindow* window) {
|
||||
if (window_.get() == window->GetNativeWindow()) {
|
||||
if (window_ == window->GetNativeWindow()) {
|
||||
return false;
|
||||
} else {
|
||||
if (@available(macOS 10.12, *))
|
||||
|
@ -1289,6 +1305,18 @@ gfx::Rect NativeWindowMac::WindowBoundsToContentBounds(
|
|||
}
|
||||
}
|
||||
|
||||
views::Widget* NativeWindowMac::GetWidget() {
|
||||
return widget_.get();
|
||||
}
|
||||
|
||||
const views::Widget* NativeWindowMac::GetWidget() const {
|
||||
return widget_.get();
|
||||
}
|
||||
|
||||
bool NativeWindowMac::CanResize() const {
|
||||
return resizable_;
|
||||
}
|
||||
|
||||
void NativeWindowMac::InternalSetParentWindow(NativeWindow* parent,
|
||||
bool attach) {
|
||||
if (is_modal())
|
||||
|
|
|
@ -11,7 +11,8 @@ namespace atom {
|
|||
|
||||
class AtomNativeWidgetMac : public views::NativeWidgetMac {
|
||||
public:
|
||||
explicit AtomNativeWidgetMac(views::internal::NativeWidgetDelegate* delegate);
|
||||
AtomNativeWidgetMac(NSUInteger style_mask,
|
||||
views::internal::NativeWidgetDelegate* delegate);
|
||||
~AtomNativeWidgetMac() override;
|
||||
|
||||
protected:
|
||||
|
@ -20,6 +21,8 @@ class AtomNativeWidgetMac : public views::NativeWidgetMac {
|
|||
const views::Widget::InitParams& params) override;
|
||||
|
||||
private:
|
||||
NSUInteger style_mask_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomNativeWidgetMac);
|
||||
};
|
||||
|
||||
|
|
|
@ -4,17 +4,26 @@
|
|||
|
||||
#include "atom/browser/ui/cocoa/atom_native_widget_mac.h"
|
||||
|
||||
#include "atom/browser/ui/cocoa/atom_ns_window.h"
|
||||
#include "ui/base/cocoa/window_size_constants.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomNativeWidgetMac::AtomNativeWidgetMac(
|
||||
NSUInteger style_mask,
|
||||
views::internal::NativeWidgetDelegate* delegate)
|
||||
: views::NativeWidgetMac(delegate) {}
|
||||
: views::NativeWidgetMac(delegate),
|
||||
style_mask_(style_mask) {}
|
||||
|
||||
AtomNativeWidgetMac::~AtomNativeWidgetMac() {}
|
||||
|
||||
NativeWidgetMacNSWindow* AtomNativeWidgetMac::CreateNSWindow(
|
||||
const views::Widget::InitParams& params) {
|
||||
return views::NativeWidgetMac::CreateNSWindow(params);
|
||||
return [[[AtomNSWindow alloc]
|
||||
initWithContentRect:ui::kWindowSizeDeterminedLater
|
||||
styleMask:style_mask_
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:YES] autorelease];
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
|
|
@ -26,7 +26,7 @@ class ScopedDisableResize {
|
|||
|
||||
} // namespace atom
|
||||
|
||||
@interface AtomNSWindow : EventDispatchingWindow {
|
||||
@interface AtomNSWindow : NativeWidgetMacNSWindow {
|
||||
@private
|
||||
atom::NativeWindowMac* shell_;
|
||||
CGFloat windowButtonsInterButtonSpacing_;
|
||||
|
|
|
@ -13,8 +13,8 @@ namespace atom {
|
|||
class NativeWindowMac;
|
||||
}
|
||||
|
||||
@interface AtomNSWindowDelegate : NSObject<NSWindowDelegate,
|
||||
NSTouchBarDelegate,
|
||||
@interface AtomNSWindowDelegate :
|
||||
ViewsNSWindowDelegate<NSTouchBarDelegate,
|
||||
QLPreviewPanelDataSource> {
|
||||
@private
|
||||
atom::NativeWindowMac* shell_;
|
||||
|
|
|
@ -9,11 +9,21 @@
|
|||
#include "atom/browser/ui/cocoa/atom_preview_item.h"
|
||||
#include "atom/browser/ui/cocoa/atom_touch_bar.h"
|
||||
#include "base/mac/mac_util.h"
|
||||
#include "ui/views/widget/native_widget_mac.h"
|
||||
|
||||
@implementation AtomNSWindowDelegate
|
||||
|
||||
- (id)initWithShell:(atom::NativeWindowMac*)shell {
|
||||
if ((self = [super init])) {
|
||||
// The views library assumes the window delegate must be an instance of
|
||||
// ViewsNSWindowDelegate, since we don't have a way to override the creation
|
||||
// of NSWindowDelegate, we have to dynamically replace the window delegate
|
||||
// on the fly.
|
||||
// TODO(zcbenz): Add interface in NativeWidgetMac to allow overriding creating
|
||||
// window delegate.
|
||||
views::BridgedNativeWidget* bridged_view =
|
||||
views::NativeWidgetMac::GetBridgeForNativeWindow(
|
||||
shell->GetNativeWindow());
|
||||
if ((self = [super initWithBridgedNativeWidget:bridged_view])) {
|
||||
shell_ = shell;
|
||||
is_zooming_ = false;
|
||||
level_ = [shell_->GetNativeWindow() level];
|
||||
|
@ -106,10 +116,12 @@
|
|||
}
|
||||
|
||||
- (void)windowDidResize:(NSNotification*)notification {
|
||||
[super windowDidResize:notification];
|
||||
shell_->NotifyWindowResize();
|
||||
}
|
||||
|
||||
- (void)windowDidMove:(NSNotification*)notification {
|
||||
[super windowDidMove:notification];
|
||||
// TODO(zcbenz): Remove the alias after figuring out a proper
|
||||
// way to dispatch move.
|
||||
shell_->NotifyWindowMove();
|
||||
|
@ -125,10 +137,12 @@
|
|||
}
|
||||
|
||||
- (void)windowDidMiniaturize:(NSNotification*)notification {
|
||||
[super windowDidMiniaturize:notification];
|
||||
shell_->NotifyWindowMinimize();
|
||||
}
|
||||
|
||||
- (void)windowDidDeminiaturize:(NSNotification*)notification {
|
||||
[super windowDidDeminiaturize:notification];
|
||||
[shell_->GetNativeWindow() setLevel:level_];
|
||||
shell_->NotifyWindowRestore();
|
||||
}
|
||||
|
|
|
@ -16,8 +16,7 @@ ViewsDelegateMac::~ViewsDelegateMac() {}
|
|||
void ViewsDelegateMac::OnBeforeWidgetInit(
|
||||
views::Widget::InitParams* params,
|
||||
views::internal::NativeWidgetDelegate* delegate) {
|
||||
if (!params->native_widget)
|
||||
params->native_widget = new views::NativeWidgetMac(delegate);
|
||||
DCHECK(params->native_widget);
|
||||
}
|
||||
|
||||
ui::ContextFactory* ViewsDelegateMac::GetContextFactory() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue