Browse Source

fix: notify views of content view size change (#19888)

Cheng Zhao 5 years ago
parent
commit
db1395628a
2 changed files with 63 additions and 6 deletions
  1. 5 4
      atom/browser/native_window_mac.h
  2. 58 2
      atom/browser/native_window_mac.mm

+ 5 - 4
atom/browser/native_window_mac.h

@@ -21,7 +21,6 @@
 @class AtomPreviewItem;
 @class AtomTouchBar;
 @class CustomWindowButtonView;
-@class FullSizeContentView;
 
 namespace atom {
 
@@ -182,10 +181,12 @@ class NativeWindowMac : public NativeWindow {
   // Event monitor for scroll wheel event.
   id wheel_event_monitor_;
 
-  // The view that will fill the whole frameless window.
-  base::scoped_nsobject<FullSizeContentView> container_view_;
+  // The NSView that used as contentView of window.
+  //
+  // For frameless window it would fill the whole window.
+  base::scoped_nsobject<NSView> container_view_;
 
-  // The view that fills the client area.
+  // The views::View that fills the client area.
   std::unique_ptr<RootViewMac> root_view_;
 
   bool is_kiosk_ = false;

+ 58 - 2
atom/browser/native_window_mac.mm

@@ -31,8 +31,59 @@
 #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_host_impl.h"
 #include "ui/views/widget/widget.h"
 
+// This view would inform Chromium to resize the hosted views::View.
+//
+// The overrided methods should behave the same with BridgedContentView.
+@interface ElectronAdapatedContentView : NSView {
+ @private
+  views::BridgedNativeWidgetHostImpl* bridge_host_;
+}
+@end
+
+@implementation ElectronAdapatedContentView
+
+- (id)initWithShell:(atom::NativeWindowMac*)shell {
+  if ((self = [self init])) {
+    bridge_host_ = views::BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+        shell->GetNativeWindow());
+  }
+  return self;
+}
+
+- (void)viewDidMoveToWindow {
+  // When this view is added to a window, AppKit calls setFrameSize before it is
+  // added to the window, so the behavior in setFrameSize is not triggered.
+  NSWindow* window = [self window];
+  if (window)
+    [self setFrameSize:NSZeroSize];
+}
+
+- (void)setFrameSize:(NSSize)newSize {
+  // The size passed in here does not always use
+  // -[NSWindow contentRectForFrameRect]. The following ensures that the
+  // contentView for a frameless window can extend over the titlebar of the new
+  // window containing it, since AppKit requires a titlebar to give frameless
+  // windows correct shadows and rounded corners.
+  NSWindow* window = [self window];
+  if (window && [window contentView] == self) {
+    newSize = [window contentRectForFrameRect:[window frame]].size;
+    // Ensure that the window geometry be updated on the host side before the
+    // view size is updated.
+    bridge_host_->bridge_impl()->UpdateWindowGeometry();
+  }
+
+  [super setFrameSize:newSize];
+
+  // The OnViewSizeChanged is marked private in derived class.
+  static_cast<remote_cocoa::mojom::BridgedNativeWidgetHost*>(bridge_host_)
+      ->OnViewSizeChanged(gfx::Size(newSize.width, newSize.height));
+}
+
+@end
+
 // This view always takes the size of its superview. It is intended to be used
 // as a NSWindow's contentView.  It is needed because NSWindow's implementation
 // explicitly resizes the contentView at inopportune times.
@@ -1496,10 +1547,15 @@ void NativeWindowMac::OverrideNSWindowContentView() {
   // `BridgedContentView` as content view, which does not support draggable
   // regions. In order to make draggable regions work, we have to replace the
   // content view with a simple NSView.
-  container_view_.reset([[FullSizeContentView alloc] init]);
+  if (has_frame()) {
+    container_view_.reset(
+        [[ElectronAdapatedContentView alloc] initWithShell:this]);
+  } else {
+    container_view_.reset([[FullSizeContentView alloc] init]);
+    [container_view_ setFrame:[[[window_ contentView] superview] bounds]];
+  }
   [container_view_
       setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
-  [container_view_ setFrame:[[[window_ contentView] superview] bounds]];
   [window_ setContentView:container_view_];
   AddContentViewLayers(IsMinimizable(), IsClosable());
 }