refactor: use views NonClientHitTest for draggable regions on mac (#35603)

* refactor: use views NonClientHitTest for draggable regions on mac

* iwyu

* add backport of 9bb5f0316

* chore: update patches

* remove some unneeded functions

* remove test for triggering when BW is focused

* chore: update patches

* simplify views/mac split now that the draggable logic is the same

* Apply suggestions from code review

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* Update shell/browser/native_window.h

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* fix build

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
This commit is contained in:
Jeremy Rose 2022-10-12 09:05:45 -07:00 committed by GitHub
parent 7ce94eb0b4
commit 8a926ffde4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 70 additions and 392 deletions

View file

@ -111,11 +111,6 @@ BrowserWindow::BrowserWindow(gin::Arguments* args,
// Install the content view after BaseWindow's JS code is initialized.
SetContentView(gin::CreateHandle<View>(isolate, web_contents_view.get()));
#if BUILDFLAG(IS_MAC)
OverrideNSWindowContentView(
web_contents->inspectable_web_contents()->GetView());
#endif
// Init window after everything has been setup.
window()->InitFromOptions(options);
}
@ -164,7 +159,10 @@ void BrowserWindow::OnRendererResponsive(content::RenderProcessHost*) {
void BrowserWindow::OnDraggableRegionsUpdated(
const std::vector<mojom::DraggableRegionPtr>& regions) {
UpdateDraggableRegions(regions);
if (window_->has_frame())
return;
window_->UpdateDraggableRegions(regions);
}
void BrowserWindow::OnSetContentBounds(const gfx::Rect& rect) {
@ -268,19 +266,6 @@ void BrowserWindow::OnWindowIsKeyChanged(bool is_key) {
#endif
}
void BrowserWindow::OnWindowResize() {
#if BUILDFLAG(IS_MAC)
if (!draggable_regions_.empty()) {
UpdateDraggableRegions(draggable_regions_);
} else {
for (NativeBrowserView* view : window_->browser_views()) {
view->UpdateDraggableRegions(view->GetDraggableRegions());
}
}
#endif
BaseWindow::OnWindowResize();
}
void BrowserWindow::OnWindowLeaveFullScreen() {
#if BUILDFLAG(IS_MAC)
if (web_contents()->IsFullscreen())
@ -349,42 +334,6 @@ void BrowserWindow::SetBrowserView(
BaseWindow::ResetBrowserViews();
if (browser_view)
BaseWindow::AddBrowserView(*browser_view);
#if BUILDFLAG(IS_MAC)
UpdateDraggableRegions(draggable_regions_);
#endif
}
void BrowserWindow::AddBrowserView(gin::Handle<BrowserView> browser_view) {
BaseWindow::AddBrowserView(browser_view);
#if BUILDFLAG(IS_MAC)
UpdateDraggableRegions(draggable_regions_);
#endif
}
void BrowserWindow::RemoveBrowserView(gin::Handle<BrowserView> browser_view) {
BaseWindow::RemoveBrowserView(browser_view);
#if BUILDFLAG(IS_MAC)
UpdateDraggableRegions(draggable_regions_);
#endif
}
void BrowserWindow::SetTopBrowserView(gin::Handle<BrowserView> browser_view,
gin_helper::Arguments* args) {
BaseWindow::SetTopBrowserView(browser_view, args);
#if BUILDFLAG(IS_MAC)
UpdateDraggableRegions(draggable_regions_);
#endif
}
void BrowserWindow::ResetBrowserViews() {
BaseWindow::ResetBrowserViews();
#if BUILDFLAG(IS_MAC)
UpdateDraggableRegions(draggable_regions_);
#endif
}
void BrowserWindow::OnDevToolsResized() {
UpdateDraggableRegions(draggable_regions_);
}
void BrowserWindow::FocusOnWebView() {

View file

@ -57,7 +57,6 @@ class BrowserWindow : public BaseWindow,
void OnActivateContents() override;
void OnPageTitleUpdated(const std::u16string& title,
bool explicit_set) override;
void OnDevToolsResized() override;
// NativeWindowObserver:
void RequestPreferredWidth(int* width) override;
@ -68,7 +67,6 @@ class BrowserWindow : public BaseWindow,
// BaseWindow:
void OnWindowBlur() override;
void OnWindowFocus() override;
void OnWindowResize() override;
void OnWindowLeaveFullScreen() override;
void CloseImmediately() override;
void Focus() override;
@ -76,11 +74,6 @@ class BrowserWindow : public BaseWindow,
void SetBackgroundColor(const std::string& color_name) override;
void SetBrowserView(
absl::optional<gin::Handle<BrowserView>> browser_view) override;
void AddBrowserView(gin::Handle<BrowserView> browser_view) override;
void RemoveBrowserView(gin::Handle<BrowserView> browser_view) override;
void SetTopBrowserView(gin::Handle<BrowserView> browser_view,
gin_helper::Arguments* args) override;
void ResetBrowserViews() override;
void OnWindowShow() override;
void OnWindowHide() override;
@ -95,10 +88,6 @@ class BrowserWindow : public BaseWindow,
#endif
private:
#if BUILDFLAG(IS_MAC)
void OverrideNSWindowContentView(InspectableWebContentsView* webView);
#endif
// Helpers.
// Called when the window needs to update its draggable region.
@ -115,8 +104,6 @@ class BrowserWindow : public BaseWindow,
// it should be cancelled when we can prove that the window is responsive.
base::CancelableRepeatingClosure window_unresponsive_closure_;
std::vector<mojom::DraggableRegionPtr> draggable_regions_;
v8::Global<v8::Value> web_contents_;
base::WeakPtr<api::WebContents> api_web_contents_;

View file

@ -1,103 +0,0 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/api/electron_api_browser_window.h"
#include <memory>
#include <vector>
#import <Cocoa/Cocoa.h>
#include "base/mac/scoped_nsobject.h"
#include "shell/browser/native_browser_view.h"
#include "shell/browser/native_window_mac.h"
#include "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h"
#include "shell/browser/ui/inspectable_web_contents_view.h"
namespace electron::api {
void BrowserWindow::OverrideNSWindowContentView(
InspectableWebContentsView* view) {
// Make NativeWindow use a NSView as content view.
static_cast<NativeWindowMac*>(window())->OverrideNSWindowContentView();
// Add webview to contentView.
NSView* webView = view->GetNativeView().GetNativeNSView();
NSView* contentView =
[window()->GetNativeWindow().GetNativeNSWindow() contentView];
[webView setFrame:[contentView bounds]];
// ensure that buttons view is floated to top of view hierarchy
NSArray* subviews = [contentView subviews];
NSView* last = subviews.lastObject;
[contentView addSubview:webView positioned:NSWindowBelow relativeTo:last];
[contentView viewDidMoveToWindow];
}
void BrowserWindow::UpdateDraggableRegions(
const std::vector<mojom::DraggableRegionPtr>& regions) {
if (window_->has_frame() || !web_contents())
return;
// All ControlRegionViews should be added as children of the WebContentsView,
// because WebContentsView will be removed and re-added when entering and
// leaving fullscreen mode.
NSView* webView = web_contents()->GetNativeView().GetNativeNSView();
NSInteger webViewWidth = NSWidth([webView bounds]);
NSInteger webViewHeight = NSHeight([webView bounds]);
if ([webView respondsToSelector:@selector(setMouseDownCanMoveWindow:)]) {
[webView setMouseDownCanMoveWindow:YES];
}
// Remove all ControlRegionViews 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:[ControlRegionView class]])
[subview removeFromSuperview];
// Draggable regions are implemented by having the whole web view draggable
// and overlaying regions that are not draggable.
if (&draggable_regions_ != &regions)
draggable_regions_ = mojo::Clone(regions);
std::vector<gfx::Rect> drag_exclude_rects;
if (regions.empty()) {
drag_exclude_rects.emplace_back(0, 0, webViewWidth, webViewHeight);
} else {
drag_exclude_rects = CalculateNonDraggableRegions(
DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight);
}
// Draggable regions on BrowserViews are independent from those of
// BrowserWindows, so if a BrowserView with different draggable regions than
// the BrowserWindow it belongs to is superimposed on top of that window, the
// draggable regions of the BrowserView take precedence over those of the
// BrowserWindow.
for (NativeBrowserView* view : window_->browser_views()) {
view->UpdateDraggableRegions(view->GetDraggableRegions());
}
// Create and add a ControlRegionView for each region that needs to be
// excluded from the dragging.
for (const auto& rect : drag_exclude_rects) {
base::scoped_nsobject<NSView> controlRegion(
[[ControlRegionView alloc] initWithFrame:NSZeroRect]);
[controlRegion setFrame:NSMakeRect(rect.x(), webViewHeight - rect.bottom(),
rect.width(), rect.height())];
[webView addSubview:controlRegion];
}
// AppKit will not update its cache of mouseDownCanMoveWindow unless something
// changes. Previously we tried adding an NSView and removing it, but for some
// reason it required reposting the mouse-down event, and didn't always work.
// Calling the below seems to be an effective solution.
[[webView window] setMovableByWindowBackground:NO];
[[webView window] setMovableByWindowBackground:YES];
}
} // namespace electron::api

View file

@ -1,37 +0,0 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "shell/browser/api/electron_api_browser_window.h"
#include "content/browser/web_contents/web_contents_impl.h" // nogncheck
#include "shell/browser/native_window_views.h"
#include "ui/aura/window.h"
namespace electron::api {
void BrowserWindow::UpdateDraggableRegions(
const std::vector<mojom::DraggableRegionPtr>& regions) {
if (window_->has_frame())
return;
if (&draggable_regions_ != &regions && web_contents()) {
auto* view =
static_cast<content::WebContentsImpl*>(web_contents())->GetView();
if (view) {
const gfx::NativeView nv = view->GetNativeView();
auto const offset = nv->GetBoundsInRootWindow();
auto snapped_regions = mojo::Clone(regions);
for (auto& snapped_region : snapped_regions) {
snapped_region->bounds.Offset(offset.x(), offset.y());
}
draggable_regions_ = mojo::Clone(snapped_regions);
}
}
static_cast<NativeWindowViews*>(window_.get())
->UpdateDraggableRegions(draggable_regions_);
}
} // namespace electron::api