From 06fcf2c19df127078320656dcb2a0a4500f61b8a Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Wed, 12 Apr 2017 14:40:31 +0300 Subject: [PATCH] Add support for BrowserView autoresizing --- atom/browser/api/atom_api_browser_view.cc | 34 +++++++++++++++++++++++ atom/browser/api/atom_api_browser_view.h | 2 ++ atom/browser/native_browser_view.h | 6 ++++ atom/browser/native_browser_view_mac.h | 1 + atom/browser/native_browser_view_mac.mm | 22 ++++++++++++++- atom/browser/native_browser_view_views.h | 6 ++++ atom/browser/native_window_views.cc | 31 +++++++++++++++++++-- docs/api/browser-view.md | 8 ++++++ spec/api-browser-view-spec.js | 15 ++++++++++ 9 files changed, 121 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_browser_view.cc b/atom/browser/api/atom_api_browser_view.cc index 67533e645d..dc17fce9e9 100644 --- a/atom/browser/api/atom_api_browser_view.cc +++ b/atom/browser/api/atom_api_browser_view.cc @@ -16,6 +16,35 @@ #include "native_mate/dictionary.h" #include "ui/gfx/geometry/rect.h" +namespace mate { + +template <> +struct Converter { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + atom::AutoResizeFlags* auto_resize_flags) { + mate::Dictionary params; + if (!ConvertFromV8(isolate, val, ¶ms)) { + return false; + } + + uint8_t flags = 0; + bool width = false; + if (params.Get("width", &width) && width) { + flags |= atom::kAutoResizeWidth; + } + bool height = false; + if (params.Get("height", &height) && height) { + flags |= atom::kAutoResizeHeight; + } + + *auto_resize_flags = static_cast(flags); + return true; + } +}; + +} // namespace mate + namespace atom { namespace api { @@ -73,6 +102,10 @@ int32_t BrowserView::ID() const { return weak_map_id(); } +void BrowserView::SetAutoResize(AutoResizeFlags flags) { + view_->SetAutoResizeFlags(flags); +} + void BrowserView::SetBounds(const gfx::Rect& bounds) { view_->SetBounds(bounds); } @@ -95,6 +128,7 @@ void BrowserView::BuildPrototype(v8::Isolate* isolate, prototype->SetClassName(mate::StringToV8(isolate, "BrowserView")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .MakeDestroyable() + .SetMethod("setAutoResize", &BrowserView::SetAutoResize) .SetMethod("setBounds", &BrowserView::SetBounds) .SetMethod("setBackgroundColor", &BrowserView::SetBackgroundColor) .SetProperty("webContents", &BrowserView::WebContents) diff --git a/atom/browser/api/atom_api_browser_view.h b/atom/browser/api/atom_api_browser_view.h index 875d842898..7531cfcc4a 100644 --- a/atom/browser/api/atom_api_browser_view.h +++ b/atom/browser/api/atom_api_browser_view.h @@ -9,6 +9,7 @@ #include #include "atom/browser/api/trackable_object.h" +#include "atom/browser/native_browser_view.h" #include "native_mate/handle.h" namespace gfx { @@ -50,6 +51,7 @@ class BrowserView : public mate::TrackableObject { v8::Local wrapper, const mate::Dictionary& options); + void SetAutoResize(AutoResizeFlags flags); void SetBounds(const gfx::Rect& bounds); void SetBackgroundColor(const std::string& color_name); diff --git a/atom/browser/native_browser_view.h b/atom/browser/native_browser_view.h index f9af80f65e..4216cc1e34 100644 --- a/atom/browser/native_browser_view.h +++ b/atom/browser/native_browser_view.h @@ -22,6 +22,11 @@ namespace api { class WebContents; } +enum AutoResizeFlags { + kAutoResizeWidth = 0x1, + kAutoResizeHeight = 0x2, +}; + class NativeBrowserView { public: virtual ~NativeBrowserView(); @@ -33,6 +38,7 @@ class NativeBrowserView { return web_contents_view_; } + virtual void SetAutoResizeFlags(uint8_t flags) = 0; virtual void SetBounds(const gfx::Rect& bounds) = 0; virtual void SetBackgroundColor(SkColor color) = 0; diff --git a/atom/browser/native_browser_view_mac.h b/atom/browser/native_browser_view_mac.h index 3053a098fc..4e7aa429ce 100644 --- a/atom/browser/native_browser_view_mac.h +++ b/atom/browser/native_browser_view_mac.h @@ -17,6 +17,7 @@ class NativeBrowserViewMac : public NativeBrowserView { brightray::InspectableWebContentsView* web_contents_view); ~NativeBrowserViewMac() override; + void SetAutoResizeFlags(uint8_t flags) override; void SetBounds(const gfx::Rect& bounds) override; void SetBackgroundColor(SkColor color) override; diff --git a/atom/browser/native_browser_view_mac.mm b/atom/browser/native_browser_view_mac.mm index 73a36cd347..2ce2adc1f4 100644 --- a/atom/browser/native_browser_view_mac.mm +++ b/atom/browser/native_browser_view_mac.mm @@ -8,14 +8,34 @@ #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 atom { NativeBrowserViewMac::NativeBrowserViewMac( brightray::InspectableWebContentsView* web_contents_view) - : NativeBrowserView(web_contents_view) {} + : NativeBrowserView(web_contents_view) { + auto* view = GetInspectableWebContentsView()->GetNativeView(); + view.autoresizingMask = kDefaultAutoResizingMask; +} NativeBrowserViewMac::~NativeBrowserViewMac() {} +void NativeBrowserViewMac::SetAutoResizeFlags(uint8_t flags) { + NSAutoresizingMaskOptions autoresizing_mask = kDefaultAutoResizingMask; + if (flags & kAutoResizeWidth) { + autoresizing_mask |= NSViewWidthSizable; + } + if (flags & kAutoResizeHeight) { + autoresizing_mask |= NSViewHeightSizable; + } + + auto* view = GetInspectableWebContentsView()->GetNativeView(); + view.autoresizingMask = autoresizing_mask; +} + void NativeBrowserViewMac::SetBounds(const gfx::Rect& bounds) { auto* view = GetInspectableWebContentsView()->GetNativeView(); auto* superview = view.superview; diff --git a/atom/browser/native_browser_view_views.h b/atom/browser/native_browser_view_views.h index ecfc6989df..5dcda13447 100644 --- a/atom/browser/native_browser_view_views.h +++ b/atom/browser/native_browser_view_views.h @@ -15,10 +15,16 @@ class NativeBrowserViewViews : public NativeBrowserView { brightray::InspectableWebContentsView* web_contents_view); ~NativeBrowserViewViews() override; + uint8_t GetAutoResizeFlags() { return auto_resize_flags_; } + void SetAutoResizeFlags(uint8_t flags) override { + auto_resize_flags_ = flags; + } void SetBounds(const gfx::Rect& bounds) override; void SetBackgroundColor(SkColor color) override; private: + uint8_t auto_resize_flags_; + DISALLOW_COPY_AND_ASSIGN(NativeBrowserViewViews); }; diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 8f5072931b..615c848daa 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -7,7 +7,7 @@ #include #include -#include "atom/browser/native_browser_view.h" +#include "atom/browser/native_browser_view_views.h" #include "atom/browser/ui/views/menu_bar.h" #include "atom/browser/window_list.h" #include "atom/common/color_util.h" @@ -895,7 +895,8 @@ void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) { void NativeWindowViews::SetBrowserView(NativeBrowserView* browser_view) { if (browser_view_) { - RemoveChildView(browser_view_->GetInspectableWebContentsView()->GetView()); + web_view_->RemoveChildView( + browser_view_->GetInspectableWebContentsView()->GetView()); browser_view_ = nullptr; } @@ -903,8 +904,11 @@ void NativeWindowViews::SetBrowserView(NativeBrowserView* browser_view) { return; } + // Add as child of the main web view to avoid (0, 0) origin from overlapping + // with menu bar. browser_view_ = browser_view; - AddChildView(browser_view->GetInspectableWebContentsView()->GetView()); + web_view_->AddChildView( + browser_view->GetInspectableWebContentsView()->GetView()); } void NativeWindowViews::SetParentWindow(NativeWindow* parent) { @@ -1292,11 +1296,32 @@ void NativeWindowViews::Layout() { menu_bar_->SetBoundsRect(menu_bar_bounds); } + const auto old_web_view_size = web_view_ ? web_view_->size() : gfx::Size(); if (web_view_) { web_view_->SetBoundsRect( gfx::Rect(0, menu_bar_bounds.height(), size.width(), size.height() - menu_bar_bounds.height())); } + const auto new_web_view_size = web_view_ ? web_view_->size() : gfx::Size(); + + if (browser_view_) { + const auto flags = static_cast(browser_view_) + ->GetAutoResizeFlags(); + int width_delta = 0; + int height_delta = 0; + if (flags & kAutoResizeWidth) { + width_delta = new_web_view_size.width() - old_web_view_size.width(); + } + if (flags & kAutoResizeHeight) { + height_delta = new_web_view_size.height() - old_web_view_size.height(); + } + + auto* view = browser_view_->GetInspectableWebContentsView()->GetView(); + auto new_view_size = view->size(); + new_view_size.set_width(new_view_size.width() + width_delta); + new_view_size.set_height(new_view_size.height() + height_delta); + view->SetSize(new_view_size); + } } gfx::Size NativeWindowViews::GetMinimumSize() { diff --git a/docs/api/browser-view.md b/docs/api/browser-view.md index 1fa518fdd7..c6d8fb5904 100644 --- a/docs/api/browser-view.md +++ b/docs/api/browser-view.md @@ -50,6 +50,14 @@ A `Integer` representing the unique ID of the view. Objects created with `new BrowserWindow` have the following instance methods: +#### `win.setAutoResize(options)` _Experimental_ + +* `options` Object + * `width`: If `true`, the view's width will grow and shrink together with + the window. `false` by default. + * `height`: If `true`, the view's height will grow and shrink together with + the window. `false` by default. + #### `win.setBounds(bounds)` _Experimental_ * `bounds` [Rectangle](structures/rectangle.md) diff --git a/spec/api-browser-view-spec.js b/spec/api-browser-view-spec.js index d4ab02a417..fc138b0b6f 100644 --- a/spec/api-browser-view-spec.js +++ b/spec/api-browser-view-spec.js @@ -38,6 +38,21 @@ describe('View module', function () { }) }) + describe('BrowserView.setAutoResize()', function () { + it('does not throw for valid args', function () { + const view = new BrowserView() + view.setAutoResize({}) + view.setAutoResize({ width: true, height: false }) + }) + + it('throws for invalid args', function () { + const view = new BrowserView() + assert.throws(function () { + view.setAutoResize(null) + }, /conversion failure/) + }) + }) + describe('BrowserView.setBounds()', function () { it('does not throw for valid args', function () { const view = new BrowserView()