Browse Source

feat: flexible autoresize for BrowserViews (#16184)

* feat: flexible autoresize for BrowserViews

* fix: change to static_cast

* Slight format code
Vladimir 6 years ago
parent
commit
49ec7e1582

+ 8 - 0
atom/browser/api/atom_api_browser_view.cc

@@ -37,6 +37,14 @@ struct Converter<atom::AutoResizeFlags> {
     if (params.Get("height", &height) && height) {
       flags |= atom::kAutoResizeHeight;
     }
+    bool horizontal = false;
+    if (params.Get("horizontal", &horizontal) && horizontal) {
+      flags |= atom::kAutoResizeHorizontal;
+    }
+    bool vertical = false;
+    if (params.Get("vertical", &vertical) && vertical) {
+      flags |= atom::kAutoResizeVertical;
+    }
 
     *auto_resize_flags = static_cast<atom::AutoResizeFlags>(flags);
     return true;

+ 2 - 0
atom/browser/native_browser_view.h

@@ -21,6 +21,8 @@ namespace atom {
 enum AutoResizeFlags {
   kAutoResizeWidth = 0x1,
   kAutoResizeHeight = 0x2,
+  kAutoResizeHorizontal = 0x4,
+  kAutoResizeVertical = 0x8,
 };
 
 class InspectableWebContents;

+ 8 - 0
atom/browser/native_browser_view_mac.mm

@@ -175,6 +175,14 @@ void NativeBrowserViewMac::SetAutoResizeFlags(uint8_t flags) {
   if (flags & kAutoResizeHeight) {
     autoresizing_mask |= NSViewHeightSizable;
   }
+  if (flags & kAutoResizeHorizontal) {
+    autoresizing_mask |=
+        NSViewMaxXMargin | NSViewMinXMargin | NSViewWidthSizable;
+  }
+  if (flags & kAutoResizeVertical) {
+    autoresizing_mask |=
+        NSViewMaxYMargin | NSViewMinYMargin | NSViewHeightSizable;
+  }
 
   auto* view =
       GetInspectableWebContentsView()->GetNativeView().GetNativeNSView();

+ 71 - 0
atom/browser/native_browser_view_views.cc

@@ -19,11 +19,82 @@ NativeBrowserViewViews::~NativeBrowserViewViews() {}
 
 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_) {
+    auto* view = GetInspectableWebContentsView()->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_) {
+    auto* view = GetInspectableWebContentsView()->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) {
+  auto* view = GetInspectableWebContentsView()->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) {
   auto* view = GetInspectableWebContentsView()->GetView();
   view->SetBoundsRect(bounds);
+  ResetAutoResizeProportions();
 }
 
 void NativeBrowserViewViews::SetBackgroundColor(SkColor color) {

+ 17 - 1
atom/browser/native_browser_view_views.h

@@ -15,13 +15,29 @@ class NativeBrowserViewViews : public NativeBrowserView {
       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;
   void SetBackgroundColor(SkColor color) override;
 
  private:
-  uint8_t auto_resize_flags_;
+  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.;
 
   DISALLOW_COPY_AND_ASSIGN(NativeBrowserViewViews);
 };

+ 4 - 21
atom/browser/native_window_views.cc

@@ -1176,26 +1176,6 @@ void NativeWindowViews::OnWidgetActivationChanged(views::Widget* changed_widget,
   root_view_->ResetAltState();
 }
 
-void NativeWindowViews::AutoresizeBrowserView(int width_delta,
-                                              int height_delta,
-                                              NativeBrowserView* browser_view) {
-  const auto flags =
-      static_cast<NativeBrowserViewViews*>(browser_view)->GetAutoResizeFlags();
-  if (!(flags & kAutoResizeWidth)) {
-    width_delta = 0;
-  }
-  if (!(flags & kAutoResizeHeight)) {
-    height_delta = 0;
-  }
-  if (height_delta || width_delta) {
-    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);
-  }
-}
-
 void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
                                               const gfx::Rect& bounds) {
   if (changed_widget != widget())
@@ -1208,7 +1188,10 @@ void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget,
     int width_delta = new_bounds.width() - widget_size_.width();
     int height_delta = new_bounds.height() - widget_size_.height();
     for (NativeBrowserView* item : browser_views()) {
-      AutoresizeBrowserView(width_delta, height_delta, item);
+      NativeBrowserViewViews* native_view =
+          static_cast<NativeBrowserViewViews*>(item);
+      native_view->SetAutoResizeProportions(widget_size_);
+      native_view->AutoResize(new_bounds, width_delta, height_delta);
     }
 
     NotifyWindowResize();

+ 1 - 3
atom/browser/native_window_views.h

@@ -158,10 +158,8 @@ class NativeWindowViews : public NativeWindow,
   void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
   void OnWidgetBoundsChanged(views::Widget* widget,
                              const gfx::Rect& bounds) override;
-  void AutoresizeBrowserView(int width_delta,
-                             int height_delta,
-                             NativeBrowserView* browser_view);
   void OnWidgetDestroying(views::Widget* widget) override;
+
   // views::WidgetDelegate:
   void DeleteDelegate() override;
   views::View* GetInitiallyFocusedView() override;

+ 4 - 0
docs/api/browser-view.md

@@ -83,6 +83,10 @@ Returns `Boolean` - Whether the view is destroyed.
     with the window. `false` by default.
   * `height` Boolean - If `true`, the view's height will grow and shrink
     together with the window. `false` by default.
+  * `horizontal` Boolean - If `true`, the view's x position and width will grow
+    and shrink proportionly with the window. `false` by default.
+  * `vertical` Boolean - If `true`, the view's y position and height will grow
+    and shrink proportinaly with the window. `false` by default.
 
 #### `view.setBounds(bounds)` _Experimental_