Browse Source

Backport (2-0-x) - Update draggable regions when changing BrowserView (#12370)

* Store InspectableWebContents instead of InspectableWebContentsView in NativeBrowserView

* Rename system_drag_exclude_areas => drag_exclude_rects

* Use NSView convertRect:toView: for BrowserView DragRegionView positioning

* Make BrowserView DragRegionViews children of the WebContents view

Previously they were children of the `InspectableWebContentsView` view,
which caused this assertion to fail:

https://github.com/electron/electron/blob/f9938884248627335c59da6b3b0ff0dc7df3b258/brightray/browser/mac/bry_inspectable_web_contents_view.mm#L162

* Update draggable regions when changing BrowserView

Fixes #12150.
Birunthan Mohanathas 7 years ago
parent
commit
8991ad31d8

+ 2 - 2
atom/browser/api/atom_api_browser_view.cc

@@ -68,8 +68,8 @@ void BrowserView::Init(v8::Isolate* isolate,
   web_contents_.Reset(isolate, web_contents.ToV8());
   api_web_contents_ = web_contents.get();
 
-  view_.reset(NativeBrowserView::Create(
-      api_web_contents_->managed_web_contents()->GetView()));
+  view_.reset(
+      NativeBrowserView::Create(api_web_contents_->managed_web_contents()));
 
   InitWith(isolate, wrapper);
 }

+ 2 - 0
atom/browser/api/atom_api_window.cc

@@ -893,6 +893,8 @@ void Window::SetBrowserView(v8::Local<v8::Value> value) {
     window_->SetBrowserView(browser_view->view());
     browser_view->web_contents()->SetOwnerWindow(window_.get());
     browser_view_.Reset(isolate(), value);
+
+    window_->UpdateDraggableRegionViews();
   }
 }
 

+ 12 - 3
atom/browser/native_browser_view.cc

@@ -7,14 +7,23 @@
 #include "atom/browser/native_browser_view.h"
 
 #include "atom/browser/api/atom_api_web_contents.h"
-#include "brightray/browser/inspectable_web_contents_view.h"
+#include "brightray/browser/inspectable_web_contents.h"
 
 namespace atom {
 
 NativeBrowserView::NativeBrowserView(
-    brightray::InspectableWebContentsView* web_contents_view)
-    : web_contents_view_(web_contents_view) {}
+    brightray::InspectableWebContents* inspectable_web_contents)
+    : inspectable_web_contents_(inspectable_web_contents) {}
 
 NativeBrowserView::~NativeBrowserView() {}
 
+brightray::InspectableWebContentsView*
+NativeBrowserView::GetInspectableWebContentsView() {
+  return inspectable_web_contents_->GetView();
+}
+
+content::WebContents* NativeBrowserView::GetWebContents() {
+  return inspectable_web_contents_->GetWebContents();
+}
+
 }  // namespace atom

+ 10 - 5
atom/browser/native_browser_view.h

@@ -9,9 +9,11 @@
 
 #include "atom/common/draggable_region.h"
 #include "base/macros.h"
+#include "content/public/browser/web_contents.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace brightray {
+class InspectableWebContents;
 class InspectableWebContentsView;
 }
 
@@ -31,12 +33,15 @@ class NativeBrowserView {
   virtual ~NativeBrowserView();
 
   static NativeBrowserView* Create(
-      brightray::InspectableWebContentsView* web_contents_view);
+      brightray::InspectableWebContents* inspectable_web_contents);
 
-  brightray::InspectableWebContentsView* GetInspectableWebContentsView() {
-    return web_contents_view_;
+  brightray::InspectableWebContents* GetInspectableWebContents() {
+    return inspectable_web_contents_;
   }
 
+  brightray::InspectableWebContentsView* GetInspectableWebContentsView();
+  content::WebContents* GetWebContents();
+
   virtual void SetAutoResizeFlags(uint8_t flags) = 0;
   virtual void SetBounds(const gfx::Rect& bounds) = 0;
   virtual void SetBackgroundColor(SkColor color) = 0;
@@ -47,9 +52,9 @@ class NativeBrowserView {
 
  protected:
   explicit NativeBrowserView(
-      brightray::InspectableWebContentsView* web_contents_view);
+      brightray::InspectableWebContents* inspectable_web_contents);
 
-  brightray::InspectableWebContentsView* web_contents_view_;
+  brightray::InspectableWebContents* inspectable_web_contents_;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(NativeBrowserView);

+ 2 - 1
atom/browser/native_browser_view_mac.h

@@ -17,12 +17,13 @@ namespace atom {
 class NativeBrowserViewMac : public NativeBrowserView {
  public:
   explicit NativeBrowserViewMac(
-      brightray::InspectableWebContentsView* web_contents_view);
+      brightray::InspectableWebContents* inspectable_web_contents);
   ~NativeBrowserViewMac() override;
 
   void SetAutoResizeFlags(uint8_t flags) override;
   void SetBounds(const gfx::Rect& bounds) override;
   void SetBackgroundColor(SkColor color) override;
+
   void UpdateDraggableRegions(
       const std::vector<gfx::Rect>& system_drag_exclude_areas) override;
 

+ 33 - 48
atom/browser/native_browser_view_mac.mm

@@ -4,6 +4,7 @@
 
 #include "atom/browser/native_browser_view_mac.h"
 
+#include "brightray/browser/inspectable_web_contents.h"
 #include "brightray/browser/inspectable_web_contents_view.h"
 #include "skia/ext/skia_utils_mac.h"
 #include "ui/gfx/geometry/rect.h"
@@ -156,8 +157,8 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask =
 namespace atom {
 
 NativeBrowserViewMac::NativeBrowserViewMac(
-    brightray::InspectableWebContentsView* web_contents_view)
-    : NativeBrowserView(web_contents_view) {
+    brightray::InspectableWebContents* inspectable_web_contents)
+    : NativeBrowserView(inspectable_web_contents) {
   auto* view = GetInspectableWebContentsView()->GetNativeView();
   view.autoresizingMask = kDefaultAutoResizingMask;
 }
@@ -193,62 +194,46 @@ void NativeBrowserViewMac::SetBackgroundColor(SkColor color) {
 }
 
 void NativeBrowserViewMac::UpdateDraggableRegions(
-    const std::vector<gfx::Rect>& system_drag_exclude_areas) {
-  NSView* webView = GetInspectableWebContentsView()->GetNativeView();
-
-  NSInteger superViewHeight = NSHeight([webView.superview bounds]);
-  NSInteger webViewHeight = NSHeight([webView bounds]);
-  NSInteger webViewWidth = NSWidth([webView bounds]);
-  NSInteger webViewX = NSMinX([webView frame]);
-  NSInteger webViewY = 0;
-
-  // Apple's NSViews have their coordinate system originate at the bottom left,
-  // meaning that we need to be a bit smarter when it comes to calculating our
-  // current top offset
-  if (webViewHeight > superViewHeight) {
-    webViewY = std::abs(webViewHeight - superViewHeight - (std::abs(NSMinY([webView frame]))));
-  } else {
-    webViewY = superViewHeight - NSMaxY([webView frame]);
-  }
-
-  // Remove all DraggableRegionViews that are added last time.
-  // Note that [webView subviews] returns the view's mutable internal array and
-  // it should be copied to avoid mutating the original array while enumerating
-  // it.
-  base::scoped_nsobject<NSArray> subviews([[webView subviews] copy]);
-  for (NSView* subview in subviews.get())
-    if ([subview isKindOfClass:[DragRegionView class]])
+    const std::vector<gfx::Rect>& drag_exclude_rects) {
+  NSView* web_view = GetWebContents()->GetNativeView();
+  NSView* inspectable_view = GetInspectableWebContentsView()->GetNativeView();
+  NSView* window_content_view = inspectable_view.superview;
+  const auto window_content_view_height = NSHeight(window_content_view.bounds);
+
+  // Remove all DragRegionViews that were added last time. Note that we need
+  // to copy the `subviews` array to avoid mutation during iteration.
+  base::scoped_nsobject<NSArray> subviews([[web_view subviews] copy]);
+  for (NSView* subview in subviews.get()) {
+    if ([subview isKindOfClass:[DragRegionView class]]) {
       [subview removeFromSuperview];
+    }
+  }
 
   // Create one giant NSView that is draggable.
-  base::scoped_nsobject<NSView> dragRegion(
-        [[DragRegionView alloc] initWithFrame:NSZeroRect]);
-    [dragRegion setFrame:NSMakeRect(0,
-                                    0,
-                                    webViewWidth,
-                                    webViewHeight)];
+  base::scoped_nsobject<NSView> drag_region_view(
+      [[DragRegionView alloc] initWithFrame:web_view.bounds]);
+  [web_view addSubview:drag_region_view];
 
   // Then, on top of that, add "exclusion zones"
-  for (auto iter = system_drag_exclude_areas.begin();
-       iter != system_drag_exclude_areas.end();
-       ++iter) {
-    base::scoped_nsobject<NSView> controlRegion(
-        [[ExcludeDragRegionView alloc] initWithFrame:NSZeroRect]);
-    [controlRegion setFrame:NSMakeRect(iter->x() - webViewX,
-                                       webViewHeight - iter->bottom() + webViewY,
-                                       iter->width(),
-                                       iter->height())];
-    [dragRegion addSubview:controlRegion];
+  for (const auto& rect : drag_exclude_rects) {
+    const auto window_content_view_exclude_rect =
+        NSMakeRect(rect.x(), window_content_view_height - rect.bottom(),
+                   rect.width(), rect.height());
+    const auto drag_region_view_exclude_rect =
+        [window_content_view convertRect:window_content_view_exclude_rect
+                                  toView:drag_region_view];
+
+    base::scoped_nsobject<NSView> exclude_drag_region_view(
+        [[ExcludeDragRegionView alloc]
+            initWithFrame:drag_region_view_exclude_rect]);
+    [drag_region_view addSubview:exclude_drag_region_view];
   }
-
-  // Add the DragRegion to the WebView
-  [webView addSubview:dragRegion];
 }
 
 // static
 NativeBrowserView* NativeBrowserView::Create(
-    brightray::InspectableWebContentsView* web_contents_view) {
-  return new NativeBrowserViewMac(web_contents_view);
+    brightray::InspectableWebContents* inspectable_web_contents) {
+  return new NativeBrowserViewMac(inspectable_web_contents);
 }
 
 }  // namespace atom

+ 4 - 4
atom/browser/native_browser_view_views.cc

@@ -12,8 +12,8 @@
 namespace atom {
 
 NativeBrowserViewViews::NativeBrowserViewViews(
-    brightray::InspectableWebContentsView* web_contents_view)
-    : NativeBrowserView(web_contents_view) {}
+    brightray::InspectableWebContents* inspectable_web_contents)
+    : NativeBrowserView(inspectable_web_contents) {}
 
 NativeBrowserViewViews::~NativeBrowserViewViews() {}
 
@@ -29,8 +29,8 @@ void NativeBrowserViewViews::SetBackgroundColor(SkColor color) {
 
 // static
 NativeBrowserView* NativeBrowserView::Create(
-    brightray::InspectableWebContentsView* web_contents_view) {
-  return new NativeBrowserViewViews(web_contents_view);
+    brightray::InspectableWebContents* inspectable_web_contents) {
+  return new NativeBrowserViewViews(inspectable_web_contents);
 }
 
 }  // namespace atom

+ 1 - 1
atom/browser/native_browser_view_views.h

@@ -12,7 +12,7 @@ namespace atom {
 class NativeBrowserViewViews : public NativeBrowserView {
  public:
   explicit NativeBrowserViewViews(
-      brightray::InspectableWebContentsView* web_contents_view);
+      brightray::InspectableWebContents* inspectable_web_contents);
   ~NativeBrowserViewViews() override;
 
   uint8_t GetAutoResizeFlags() { return auto_resize_flags_; }

+ 2 - 0
atom/browser/native_window.h

@@ -238,6 +238,8 @@ class NativeWindow : public base::SupportsUserData,
     const std::vector<base::string16>& labels) {}
   virtual void HideAutofillPopup(content::RenderFrameHost* frame_host) {}
 
+  virtual void UpdateDraggableRegionViews() {}
+
   // Public API used by platform-dependent delegates and observers to send UI
   // related notifications.
   void NotifyWindowClosed();

+ 1 - 1
atom/browser/native_window_mac.h

@@ -127,7 +127,7 @@ class NativeWindowMac : public NativeWindow,
                              content::RenderViewHost* new_host) override;
 
   // Refresh the DraggableRegion views.
-  void UpdateDraggableRegionViews() {
+  void UpdateDraggableRegionViews() override {
     UpdateDraggableRegionViews(draggable_regions_);
   }
 

+ 5 - 10
atom/browser/native_window_mac.mm

@@ -1980,25 +1980,20 @@ void NativeWindowMac::UpdateDraggableRegionViews(
 
   // Draggable regions is implemented by having the whole web view draggable
   // (mouseDownCanMoveWindow) and overlaying regions that are not draggable.
-  std::vector<gfx::Rect> system_drag_exclude_areas =
+  std::vector<gfx::Rect> drag_exclude_rects =
       CalculateNonDraggableRegions(regions, webViewWidth, webViewHeight);
 
   if (browser_view_) {
-    browser_view_->UpdateDraggableRegions(system_drag_exclude_areas);
+    browser_view_->UpdateDraggableRegions(drag_exclude_rects);
   }
 
   // Create and add a ControlRegionView for each region that needs to be
   // excluded from the dragging.
-  for (std::vector<gfx::Rect>::const_iterator iter =
-           system_drag_exclude_areas.begin();
-       iter != system_drag_exclude_areas.end();
-       ++iter) {
+  for (const auto& rect : drag_exclude_rects) {
     base::scoped_nsobject<NSView> controlRegion(
         [[ControlRegionView alloc] initWithFrame:NSZeroRect]);
-    [controlRegion setFrame:NSMakeRect(iter->x(),
-                                       webViewHeight - iter->bottom(),
-                                       iter->width(),
-                                       iter->height())];
+    [controlRegion setFrame:NSMakeRect(rect.x(), webViewHeight - rect.bottom(),
+                                       rect.width(), rect.height())];
     [webView addSubview:controlRegion];
   }