Browse Source

Add support for BrowserView autoresizing

Birunthan Mohanathas 8 years ago
parent
commit
06fcf2c19d

+ 34 - 0
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<atom::AutoResizeFlags> {
+  static bool FromV8(v8::Isolate* isolate,
+                     v8::Local<v8::Value> val,
+                     atom::AutoResizeFlags* auto_resize_flags) {
+    mate::Dictionary params;
+    if (!ConvertFromV8(isolate, val, &params)) {
+      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<atom::AutoResizeFlags>(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)

+ 2 - 0
atom/browser/api/atom_api_browser_view.h

@@ -9,6 +9,7 @@
 #include <string>
 
 #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<BrowserView> {
             v8::Local<v8::Object> wrapper,
             const mate::Dictionary& options);
 
+  void SetAutoResize(AutoResizeFlags flags);
   void SetBounds(const gfx::Rect& bounds);
   void SetBackgroundColor(const std::string& color_name);
 

+ 6 - 0
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;
 

+ 1 - 0
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;
 

+ 21 - 1
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;

+ 6 - 0
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);
 };
 

+ 28 - 3
atom/browser/native_window_views.cc

@@ -7,7 +7,7 @@
 #include <string>
 #include <vector>
 
-#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<NativeBrowserViewViews*>(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() {

+ 8 - 0
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)

+ 15 - 0
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()