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

@ -124,7 +124,6 @@ filenames = {
"shell/app/electron_main_delegate_mac.h", "shell/app/electron_main_delegate_mac.h",
"shell/app/electron_main_delegate_mac.mm", "shell/app/electron_main_delegate_mac.mm",
"shell/browser/api/electron_api_app_mac.mm", "shell/browser/api/electron_api_app_mac.mm",
"shell/browser/api/electron_api_browser_window_mac.mm",
"shell/browser/api/electron_api_menu_mac.h", "shell/browser/api/electron_api_menu_mac.h",
"shell/browser/api/electron_api_menu_mac.mm", "shell/browser/api/electron_api_menu_mac.mm",
"shell/browser/api/electron_api_native_theme_mac.mm", "shell/browser/api/electron_api_native_theme_mac.mm",
@ -211,7 +210,6 @@ filenames = {
] ]
lib_sources_views = [ lib_sources_views = [
"shell/browser/api/electron_api_browser_window_views.cc",
"shell/browser/api/electron_api_menu_views.cc", "shell/browser/api/electron_api_menu_views.cc",
"shell/browser/api/electron_api_menu_views.h", "shell/browser/api/electron_api_menu_views.h",
"shell/browser/native_browser_view_views.cc", "shell/browser/native_browser_view_views.cc",

View file

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

View file

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

7
shell/browser/native_window.cc Executable file → Normal file
View file

@ -14,11 +14,13 @@
#include "content/public/browser/web_contents_user_data.h" #include "content/public/browser/web_contents_user_data.h"
#include "shell/browser/browser.h" #include "shell/browser/browser.h"
#include "shell/browser/native_window_features.h" #include "shell/browser/native_window_features.h"
#include "shell/browser/ui/drag_util.h"
#include "shell/browser/window_list.h" #include "shell/browser/window_list.h"
#include "shell/common/color_util.h" #include "shell/common/color_util.h"
#include "shell/common/gin_helper/dictionary.h" #include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/persistent_dictionary.h" #include "shell/common/gin_helper/persistent_dictionary.h"
#include "shell/common/options_switches.h" #include "shell/common/options_switches.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
@ -683,6 +685,11 @@ void NativeWindow::NotifyWindowMessage(UINT message,
} }
#endif #endif
void NativeWindow::UpdateDraggableRegions(
const std::vector<mojom::DraggableRegionPtr>& regions) {
draggable_region_ = DraggableRegionsToSkRegion(regions);
}
views::Widget* NativeWindow::GetWidget() { views::Widget* NativeWindow::GetWidget() {
return widget(); return widget();
} }

View file

@ -18,9 +18,12 @@
#include "content/public/browser/web_contents_user_data.h" #include "content/public/browser/web_contents_user_data.h"
#include "extensions/browser/app_window/size_constraints.h" #include "extensions/browser/app_window/size_constraints.h"
#include "shell/browser/native_window_observer.h" #include "shell/browser/native_window_observer.h"
#include "shell/common/api/api.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/optional.h"
#include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_delegate.h"
class SkRegion;
namespace base { namespace base {
class DictionaryValue; class DictionaryValue;
} }
@ -337,6 +340,11 @@ class NativeWindow : public base::SupportsUserData,
return fullscreen_transition_type_; return fullscreen_transition_type_;
} }
SkRegion const* draggable_region() const { return draggable_region_.get(); }
void UpdateDraggableRegions(
const std::vector<mojom::DraggableRegionPtr>& regions);
views::Widget* widget() const { return widget_.get(); } views::Widget* widget() const { return widget_.get(); }
views::View* content_view() const { return content_view_; } views::View* content_view() const { return content_view_; }
@ -456,6 +464,10 @@ class NativeWindow : public base::SupportsUserData,
gfx::Rect overlay_rect_; gfx::Rect overlay_rect_;
// For custom drag, the whole window is non-draggable and the draggable region
// has to been explicitly provided.
std::unique_ptr<SkRegion> draggable_region_; // used in custom drag.
base::WeakPtrFactory<NativeWindow> weak_factory_{this}; base::WeakPtrFactory<NativeWindow> weak_factory_{this};
}; };

View file

@ -13,6 +13,7 @@
#include "base/mac/scoped_nsobject.h" #include "base/mac/scoped_nsobject.h"
#include "shell/browser/native_window.h" #include "shell/browser/native_window.h"
#include "shell/common/api/api.mojom.h"
#include "ui/display/display_observer.h" #include "ui/display/display_observer.h"
#include "ui/native_theme/native_theme_observer.h" #include "ui/native_theme/native_theme_observer.h"
#include "ui/views/controls/native/native_view_host.h" #include "ui/views/controls/native/native_view_host.h"
@ -160,9 +161,6 @@ class NativeWindowMac : public NativeWindow,
// cleanup in destructor. // cleanup in destructor.
void Cleanup(); void Cleanup();
// Use a custom content view instead of Chromium's BridgedContentView.
void OverrideNSWindowContentView();
void UpdateVibrancyRadii(bool fullscreen); void UpdateVibrancyRadii(bool fullscreen);
void UpdateWindowOriginalFrame(); void UpdateWindowOriginalFrame();
@ -206,6 +204,8 @@ class NativeWindowMac : public NativeWindow,
// views::WidgetDelegate: // views::WidgetDelegate:
views::View* GetContentsView() override; views::View* GetContentsView() override;
bool CanMaximize() const override; bool CanMaximize() const override;
std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
views::Widget* widget) override;
// ui::NativeThemeObserver: // ui::NativeThemeObserver:
void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override; void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override;
@ -228,11 +228,6 @@ class NativeWindowMac : public NativeWindow,
base::scoped_nsobject<ElectronPreviewItem> preview_item_; base::scoped_nsobject<ElectronPreviewItem> preview_item_;
base::scoped_nsobject<ElectronTouchBar> touch_bar_; base::scoped_nsobject<ElectronTouchBar> touch_bar_;
// The NSView that used as contentView of window.
//
// For frameless window it would fill the whole window.
base::scoped_nsobject<NSView> container_view_;
// The views::View that fills the client area. // The views::View that fills the client area.
std::unique_ptr<RootViewMac> root_view_; std::unique_ptr<RootViewMac> root_view_;
@ -261,6 +256,8 @@ class NativeWindowMac : public NativeWindow,
// Controls the position and visibility of window buttons. // Controls the position and visibility of window buttons.
base::scoped_nsobject<WindowButtonsProxy> buttons_proxy_; base::scoped_nsobject<WindowButtonsProxy> buttons_proxy_;
std::unique_ptr<SkRegion> draggable_region_;
// Maximizable window state; necessary for persistence through redraws. // Maximizable window state; necessary for persistence through redraws.
bool maximizable_ = true; bool maximizable_ = true;

View file

@ -8,6 +8,7 @@
#include <objc/objc-runtime.h> #include <objc/objc-runtime.h>
#include <algorithm> #include <algorithm>
#include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -31,6 +32,7 @@
#include "shell/browser/ui/cocoa/electron_touch_bar.h" #include "shell/browser/ui/cocoa/electron_touch_bar.h"
#include "shell/browser/ui/cocoa/root_view_mac.h" #include "shell/browser/ui/cocoa/root_view_mac.h"
#include "shell/browser/ui/cocoa/window_buttons_proxy.h" #include "shell/browser/ui/cocoa/window_buttons_proxy.h"
#include "shell/browser/ui/drag_util.h"
#include "shell/browser/ui/inspectable_web_contents.h" #include "shell/browser/ui/inspectable_web_contents.h"
#include "shell/browser/ui/inspectable_web_contents_view.h" #include "shell/browser/ui/inspectable_web_contents_view.h"
#include "shell/browser/window_list.h" #include "shell/browser/window_list.h"
@ -40,88 +42,16 @@
#include "shell/common/options_switches.h" #include "shell/common/options_switches.h"
#include "shell/common/process_util.h" #include "shell/common/process_util.h"
#include "skia/ext/skia_utils_mac.h" #include "skia/ext/skia_utils_mac.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "third_party/webrtc/modules/desktop_capture/mac/window_list_utils.h" #include "third_party/webrtc/modules/desktop_capture/mac/window_list_utils.h"
#include "ui/base/hit_test.h"
#include "ui/display/screen.h" #include "ui/display/screen.h"
#include "ui/gfx/skia_util.h" #include "ui/gfx/skia_util.h"
#include "ui/gl/gpu_switching_manager.h" #include "ui/gl/gpu_switching_manager.h"
#include "ui/views/background.h" #include "ui/views/background.h"
#include "ui/views/cocoa/native_widget_mac_ns_window_host.h" #include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
#include "ui/views/window/native_frame_view_mac.h"
// This view would inform Chromium to resize the hosted views::View.
//
// The overridden methods should behave the same with BridgedContentView.
@interface ElectronAdaptedContentView : NSView {
@private
views::NativeWidgetMacNSWindowHost* bridge_host_;
}
@end
@implementation ElectronAdaptedContentView
- (id)initWithShell:(electron::NativeWindowMac*)shell {
if ((self = [self init])) {
bridge_host_ = views::NativeWidgetMacNSWindowHost::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_->GetInProcessNSWindowBridge()->UpdateWindowGeometry();
}
[super setFrameSize:newSize];
// The OnViewSizeChanged is marked private in derived class.
static_cast<remote_cocoa::mojom::NativeWidgetNSWindowHost*>(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.
@interface FullSizeContentView : NSView
@end
@implementation FullSizeContentView
// This method is directly called by NSWindow during a window resize on OSX
// 10.10.0, beta 2. We must override it to prevent the content view from
// shrinking.
- (void)setFrameSize:(NSSize)size {
if ([self superview])
size = [[self superview] bounds].size;
[super setFrameSize:size];
}
// The contentView gets moved around during certain full-screen operations.
// This is less than ideal, and should eventually be removed.
- (void)viewDidMoveToSuperview {
[self setFrame:[[self superview] bounds]];
}
@end
@interface ElectronProgressBar : NSProgressIndicator @interface ElectronProgressBar : NSProgressIndicator
@end @end
@ -1701,22 +1631,42 @@ void NativeWindowMac::Cleanup() {
display::Screen::GetScreen()->RemoveObserver(this); display::Screen::GetScreen()->RemoveObserver(this);
} }
void NativeWindowMac::OverrideNSWindowContentView() { class NativeAppWindowFrameViewMac : public views::NativeFrameViewMac {
// When using `views::Widget` to hold WebContents, Chromium would use public:
// `BridgedContentView` as content view, which does not support draggable NativeAppWindowFrameViewMac(views::Widget* frame, NativeWindowMac* window)
// regions. In order to make draggable regions work, we have to replace the : views::NativeFrameViewMac(frame), native_window_(window) {}
// content view with a simple NSView.
if (has_frame()) { NativeAppWindowFrameViewMac(const NativeAppWindowFrameViewMac&) = delete;
container_view_.reset( NativeAppWindowFrameViewMac& operator=(const NativeAppWindowFrameViewMac&) =
[[ElectronAdaptedContentView alloc] initWithShell:this]); delete;
} else {
container_view_.reset([[FullSizeContentView alloc] init]); ~NativeAppWindowFrameViewMac() override = default;
[container_view_ setFrame:[[[window_ contentView] superview] bounds]];
// NonClientFrameView:
int NonClientHitTest(const gfx::Point& point) override {
if (!bounds().Contains(point))
return HTNOWHERE;
if (GetWidget()->IsFullscreen())
return HTCLIENT;
// Check for possible draggable region in the client area for the frameless
// window.
SkRegion const* draggable_region = native_window_->draggable_region();
if (draggable_region && draggable_region->contains(point.x(), point.y()))
return HTCAPTION;
return HTCLIENT;
} }
[container_view_
setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; private:
[window_ setContentView:container_view_]; // Weak.
AddContentViewLayers(); raw_ptr<NativeWindowMac> const native_window_;
};
std::unique_ptr<views::NonClientFrameView>
NativeWindowMac::CreateNonClientFrameView(views::Widget* widget) {
return std::make_unique<NativeAppWindowFrameViewMac>(widget, this);
} }
bool NativeWindowMac::HasStyleMask(NSUInteger flag) const { bool NativeWindowMac::HasStyleMask(NSUInteger flag) const {
@ -1779,22 +1729,6 @@ void NativeWindowMac::AddContentViewLayers() {
} }
[[window_ contentView] setWantsLayer:YES]; [[window_ contentView] setWantsLayer:YES];
} }
if (!has_frame()) {
// In OSX 10.10, adding subviews to the root view for the NSView hierarchy
// produces warnings. To eliminate the warnings, we resize the contentView
// to fill the window, and add subviews to that.
// http://crbug.com/380412
if (!original_set_frame_size) {
Class cl = [[window_ contentView] class];
original_set_frame_size = class_replaceMethod(
cl, @selector(setFrameSize:), (IMP)SetFrameSize, "v@:{_NSSize=ff}");
original_view_did_move_to_superview =
class_replaceMethod(cl, @selector(viewDidMoveToSuperview),
(IMP)ViewDidMoveToSuperview, "v@:");
[[window_ contentView] viewDidMoveToWindow];
}
}
} }
void NativeWindowMac::InternalSetWindowButtonVisibility(bool visible) { void NativeWindowMac::InternalSetWindowButtonVisibility(bool visible) {

View file

@ -19,7 +19,6 @@
#include "content/public/browser/desktop_media_id.h" #include "content/public/browser/desktop_media_id.h"
#include "shell/browser/api/electron_api_web_contents.h" #include "shell/browser/api/electron_api_web_contents.h"
#include "shell/browser/native_browser_view_views.h" #include "shell/browser/native_browser_view_views.h"
#include "shell/browser/ui/drag_util.h"
#include "shell/browser/ui/inspectable_web_contents.h" #include "shell/browser/ui/inspectable_web_contents.h"
#include "shell/browser/ui/inspectable_web_contents_view.h" #include "shell/browser/ui/inspectable_web_contents_view.h"
#include "shell/browser/ui/views/root_view.h" #include "shell/browser/ui/views/root_view.h"
@ -1512,11 +1511,6 @@ gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
return content_bounds; return content_bounds;
} }
void NativeWindowViews::UpdateDraggableRegions(
const std::vector<mojom::DraggableRegionPtr>& regions) {
draggable_region_ = DraggableRegionsToSkRegion(regions);
}
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
void NativeWindowViews::SetIcon(HICON window_icon, HICON app_icon) { void NativeWindowViews::SetIcon(HICON window_icon, HICON app_icon) {
// We are responsible for storing the images. // We are responsible for storing the images.

View file

@ -12,8 +12,6 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "shell/common/api/api.mojom.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/views/widget/widget_observer.h" #include "ui/views/widget/widget_observer.h"
#if defined(USE_OZONE) #if defined(USE_OZONE)
@ -155,9 +153,6 @@ class NativeWindowViews : public NativeWindow,
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override; gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override; gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override;
void UpdateDraggableRegions(
const std::vector<mojom::DraggableRegionPtr>& regions);
void IncrementChildModals(); void IncrementChildModals();
void DecrementChildModals(); void DecrementChildModals();
@ -177,8 +172,6 @@ class NativeWindowViews : public NativeWindow,
void SetIcon(const gfx::ImageSkia& icon); void SetIcon(const gfx::ImageSkia& icon);
#endif #endif
SkRegion* draggable_region() const { return draggable_region_.get(); }
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
TaskbarHost& taskbar_host() { return taskbar_host_; } TaskbarHost& taskbar_host() { return taskbar_host_; }
#endif #endif
@ -329,10 +322,6 @@ class NativeWindowViews : public NativeWindow,
// Handles unhandled keyboard messages coming back from the renderer process. // Handles unhandled keyboard messages coming back from the renderer process.
std::unique_ptr<views::UnhandledKeyboardEventHandler> keyboard_event_handler_; std::unique_ptr<views::UnhandledKeyboardEventHandler> keyboard_event_handler_;
// For custom drag, the whole window is non-draggable and the draggable region
// has to been explicitly provided.
std::unique_ptr<SkRegion> draggable_region_; // used in custom drag.
// Whether the window should be enabled based on user calls to SetEnabled() // Whether the window should be enabled based on user calls to SetEnabled()
bool is_enabled_ = true; bool is_enabled_ = true;
// How many modal children this window has; // How many modal children this window has;

View file

@ -21,16 +21,12 @@ using electron::InspectableWebContentsViewMac;
- (void)setMouseDownCanMoveWindow:(BOOL)can_move; - (void)setMouseDownCanMoveWindow:(BOOL)can_move;
@end @end
@interface ControlRegionView : NSView
@end
@interface ElectronInspectableWebContentsView : BaseView <NSWindowDelegate> { @interface ElectronInspectableWebContentsView : BaseView <NSWindowDelegate> {
@private @private
electron::InspectableWebContentsViewMac* inspectableWebContentsView_; electron::InspectableWebContentsViewMac* inspectableWebContentsView_;
base::scoped_nsobject<NSView> fake_view_; base::scoped_nsobject<NSView> fake_view_;
base::scoped_nsobject<NSWindow> devtools_window_; base::scoped_nsobject<NSWindow> devtools_window_;
base::scoped_nsobject<ControlRegionView> devtools_mask_;
BOOL devtools_visible_; BOOL devtools_visible_;
BOOL devtools_docked_; BOOL devtools_docked_;
BOOL devtools_is_first_responder_; BOOL devtools_is_first_responder_;

View file

@ -11,18 +11,6 @@
#include "shell/browser/ui/inspectable_web_contents_view_mac.h" #include "shell/browser/ui/inspectable_web_contents_view_mac.h"
#include "ui/gfx/mac/scoped_cocoa_disable_screen_updates.h" #include "ui/gfx/mac/scoped_cocoa_disable_screen_updates.h"
@implementation ControlRegionView
- (BOOL)mouseDownCanMoveWindow {
return NO;
}
- (NSView*)hitTest:(NSPoint)aPoint {
return nil;
}
@end
@implementation ElectronInspectableWebContentsView @implementation ElectronInspectableWebContentsView
- (instancetype)initWithInspectableWebContentsViewMac: - (instancetype)initWithInspectableWebContentsViewMac:
@ -49,9 +37,6 @@
[self addSubview:contentsView]; [self addSubview:contentsView];
} }
// This will float above devtools to exclude it from dragging.
devtools_mask_.reset([[ControlRegionView alloc] initWithFrame:NSZeroRect]);
// See https://code.google.com/p/chromium/issues/detail?id=348490. // See https://code.google.com/p/chromium/issues/detail?id=348490.
[self setWantsLayer:YES]; [self setWantsLayer:YES];
@ -116,12 +101,6 @@
devtools_visible_ = visible; devtools_visible_ = visible;
if (devtools_docked_) { if (devtools_docked_) {
if (visible) { if (visible) {
// The devToolsView is placed under the contentsView, so it has to be
// draggable to make draggable region of contentsView work.
[devToolsView setMouseDownCanMoveWindow:YES];
// This view will exclude the actual devtools part from dragging.
[self addSubview:devtools_mask_.get()];
// Place the devToolsView under contentsView, notice that we didn't set // Place the devToolsView under contentsView, notice that we didn't set
// sizes for them until the setContentsResizingStrategy message. // sizes for them until the setContentsResizingStrategy message.
[self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil]; [self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil];
@ -132,7 +111,6 @@
} else { } else {
gfx::ScopedCocoaDisableScreenUpdates disabler; gfx::ScopedCocoaDisableScreenUpdates disabler;
[devToolsView removeFromSuperview]; [devToolsView removeFromSuperview];
[devtools_mask_ removeFromSuperview];
[self adjustSubviews]; [self adjustSubviews];
[self notifyDevToolsResized]; [self notifyDevToolsResized];
} }
@ -225,7 +203,7 @@
NSView* devToolsView = [[self subviews] objectAtIndex:0]; NSView* devToolsView = [[self subviews] objectAtIndex:0];
NSView* contentsView = [[self subviews] objectAtIndex:1]; NSView* contentsView = [[self subviews] objectAtIndex:1];
DCHECK_EQ(3u, [[self subviews] count]); DCHECK_EQ(2u, [[self subviews] count]);
gfx::Rect new_devtools_bounds; gfx::Rect new_devtools_bounds;
gfx::Rect new_contents_bounds; gfx::Rect new_contents_bounds;
@ -253,7 +231,6 @@
devtools_frame.size.width = sb.size.width - cf.size.width; devtools_frame.size.width = sb.size.width - cf.size.width;
devtools_frame.size.height = sb.size.height; devtools_frame.size.height = sb.size.height;
} }
[devtools_mask_ setFrame:devtools_frame];
[self notifyDevToolsResized]; [self notifyDevToolsResized];
} }

View file

@ -95,7 +95,7 @@ int FramelessView::NonClientHitTest(const gfx::Point& cursor) {
// Check for possible draggable region in the client area for the frameless // Check for possible draggable region in the client area for the frameless
// window. // window.
SkRegion* draggable_region = window_->draggable_region(); const SkRegion* draggable_region = window_->draggable_region();
if (draggable_region && draggable_region->contains(cursor.x(), cursor.y())) if (draggable_region && draggable_region->contains(cursor.x(), cursor.y()))
return HTCAPTION; return HTCAPTION;

View file

@ -897,28 +897,6 @@ describe('webContents module', () => {
w.webContents.focus(); w.webContents.focus();
await expect(focusPromise).to.eventually.be.fulfilled(); await expect(focusPromise).to.eventually.be.fulfilled();
}); });
it('is triggered when BrowserWindow is focused', async () => {
const window1 = new BrowserWindow({ show: false });
const window2 = new BrowserWindow({ show: false });
await Promise.all([
window1.loadURL('about:blank'),
window2.loadURL('about:blank')
]);
const focusPromise1 = emittedOnce(window1.webContents, 'focus');
const focusPromise2 = emittedOnce(window2.webContents, 'focus');
window1.showInactive();
window2.showInactive();
window1.focus();
await expect(focusPromise1).to.eventually.be.fulfilled();
window2.focus();
await expect(focusPromise2).to.eventually.be.fulfilled();
});
}); });
describe('blur event', () => { describe('blur event', () => {