diff --git a/filenames.gni b/filenames.gni index b5acd6776a..b9fe517a3a 100644 --- a/filenames.gni +++ b/filenames.gni @@ -368,6 +368,7 @@ filenames = { "shell/browser/electron_web_ui_controller_factory.h", "shell/browser/event_emitter_mixin.cc", "shell/browser/event_emitter_mixin.h", + "shell/browser/extended_web_contents_observer.h", "shell/browser/feature_list.cc", "shell/browser/feature_list.h", "shell/browser/font_defaults.cc", @@ -452,6 +453,7 @@ filenames = { "shell/browser/ui/devtools_manager_delegate.h", "shell/browser/ui/devtools_ui.cc", "shell/browser/ui/devtools_ui.h", + "shell/browser/ui/drag_util.cc", "shell/browser/ui/drag_util.h", "shell/browser/ui/electron_menu_model.cc", "shell/browser/ui/electron_menu_model.h", diff --git a/shell/browser/api/electron_api_browser_view.cc b/shell/browser/api/electron_api_browser_view.cc index 42ef7cc1b7..b46bff87c5 100644 --- a/shell/browser/api/electron_api_browser_view.cc +++ b/shell/browser/api/electron_api_browser_view.cc @@ -4,9 +4,12 @@ #include "shell/browser/api/electron_api_browser_view.h" +#include + #include "shell/browser/api/electron_api_web_contents.h" #include "shell/browser/browser.h" #include "shell/browser/native_browser_view.h" +#include "shell/browser/ui/drag_util.h" #include "shell/common/color_util.h" #include "shell/common/gin_converters/gfx_converter.h" #include "shell/common/gin_helper/dictionary.h" @@ -80,6 +83,7 @@ BrowserView::BrowserView(gin::Arguments* args, web_contents_.Reset(isolate, web_contents.ToV8()); api_web_contents_ = web_contents.get(); + api_web_contents_->AddObserver(this); Observe(web_contents->web_contents()); view_.reset( @@ -90,6 +94,7 @@ BrowserView::~BrowserView() { if (api_web_contents_) { // destroy() is called // Destroy WebContents asynchronously unless app is shutting down, // because destroy() might be called inside WebContents's event handler. + api_web_contents_->RemoveObserver(this); api_web_contents_->DestroyWebContents(!Browser::Get()->is_shutting_down()); } } @@ -100,6 +105,11 @@ void BrowserView::WebContentsDestroyed() { Unpin(); } +void BrowserView::OnDraggableRegionsUpdated( + const std::vector& regions) { + view_->UpdateDraggableRegions(regions); +} + // static gin::Handle BrowserView::New(gin_helper::ErrorThrower thrower, gin::Arguments* args) { diff --git a/shell/browser/api/electron_api_browser_view.h b/shell/browser/api/electron_api_browser_view.h index 8e1ad0e9b5..9ceba81c01 100644 --- a/shell/browser/api/electron_api_browser_view.h +++ b/shell/browser/api/electron_api_browser_view.h @@ -7,11 +7,14 @@ #include #include +#include #include "content/public/browser/web_contents_observer.h" #include "gin/handle.h" #include "gin/wrappable.h" +#include "shell/browser/extended_web_contents_observer.h" #include "shell/browser/native_browser_view.h" +#include "shell/common/api/api.mojom.h" #include "shell/common/gin_helper/constructible.h" #include "shell/common/gin_helper/error_thrower.h" #include "shell/common/gin_helper/pinnable.h" @@ -35,7 +38,8 @@ class WebContents; class BrowserView : public gin::Wrappable, public gin_helper::Constructible, public gin_helper::Pinnable, - public content::WebContentsObserver { + public content::WebContentsObserver, + public ExtendedWebContentsObserver { public: // gin_helper::Constructible static gin::Handle New(gin_helper::ErrorThrower thrower, @@ -59,6 +63,10 @@ class BrowserView : public gin::Wrappable, // content::WebContentsObserver: void WebContentsDestroyed() override; + // ExtendedWebContentsObserver: + void OnDraggableRegionsUpdated( + const std::vector& regions) override; + private: void SetAutoResize(AutoResizeFlags flags); void SetBounds(const gfx::Rect& bounds); diff --git a/shell/browser/api/electron_api_browser_window.cc b/shell/browser/api/electron_api_browser_window.cc index 2f8d3833c9..38a3223a8b 100644 --- a/shell/browser/api/electron_api_browser_window.cc +++ b/shell/browser/api/electron_api_browser_window.cc @@ -414,19 +414,6 @@ v8::Local BrowserWindow::GetWebContents(v8::Isolate* isolate) { return v8::Local::New(isolate, web_contents_); } -// Convert draggable regions in raw format to SkRegion format. -std::unique_ptr BrowserWindow::DraggableRegionsToSkRegion( - const std::vector& regions) { - auto sk_region = std::make_unique(); - for (const auto& region : regions) { - sk_region->op( - {region->bounds.x(), region->bounds.y(), region->bounds.right(), - region->bounds.bottom()}, - region->draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op); - } - return sk_region; -} - void BrowserWindow::ScheduleUnresponsiveEvent(int ms) { if (!window_unresponsive_closure_.IsCancelled()) return; diff --git a/shell/browser/api/electron_api_browser_window.h b/shell/browser/api/electron_api_browser_window.h index 3df0ff41d1..c7a9c86e62 100644 --- a/shell/browser/api/electron_api_browser_window.h +++ b/shell/browser/api/electron_api_browser_window.h @@ -12,6 +12,7 @@ #include "base/cancelable_callback.h" #include "shell/browser/api/electron_api_base_window.h" #include "shell/browser/api/electron_api_web_contents.h" +#include "shell/browser/ui/drag_util.h" #include "shell/common/gin_helper/error_thrower.h" namespace electron { @@ -102,10 +103,6 @@ class BrowserWindow : public BaseWindow, void UpdateDraggableRegions( const std::vector& regions); - // Convert draggable regions in raw format to SkRegion format. - std::unique_ptr DraggableRegionsToSkRegion( - const std::vector& regions); - // Schedule a notification unresponsive event. void ScheduleUnresponsiveEvent(int ms); diff --git a/shell/browser/api/electron_api_browser_window_mac.mm b/shell/browser/api/electron_api_browser_window_mac.mm index f1c245dad8..81d8e54ede 100644 --- a/shell/browser/api/electron_api_browser_window_mac.mm +++ b/shell/browser/api/electron_api_browser_window_mac.mm @@ -37,26 +37,6 @@ namespace electron { namespace api { -namespace { - -// Return a vector of non-draggable regions that fill a window of size -// |width| by |height|, but leave gaps where the window should be draggable. -std::vector CalculateNonDraggableRegions( - std::unique_ptr draggable, - int width, - int height) { - std::vector result; - SkRegion non_draggable; - non_draggable.op({0, 0, width, height}, SkRegion::kUnion_Op); - non_draggable.op(*draggable, SkRegion::kDifference_Op); - for (SkRegion::Iterator it(non_draggable); !it.done(); it.next()) { - result.push_back(gfx::SkIRectToRect(it.rect())); - } - return result; -} - -} // namespace - void BrowserWindow::OverrideNSWindowContentView(InspectableWebContents* iwc) { // Make NativeWindow use a NSView as content view. static_cast(window())->OverrideNSWindowContentView(); @@ -109,6 +89,12 @@ void BrowserWindow::UpdateDraggableRegions( for (const auto& r : regions) draggable_regions_.push_back(r.Clone()); } + + auto browser_views = window_->browser_views(); + for (NativeBrowserView* view : browser_views) { + view->UpdateDraggableRegions(draggable_regions_); + } + std::vector drag_exclude_rects; if (regions.empty()) { drag_exclude_rects.push_back(gfx::Rect(0, 0, webViewWidth, webViewHeight)); @@ -117,11 +103,6 @@ void BrowserWindow::UpdateDraggableRegions( DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight); } - auto browser_views = window_->browser_views(); - for (NativeBrowserView* view : browser_views) { - view->UpdateDraggableRegions(drag_exclude_rects); - } - // Create and add a ControlRegionView for each region that needs to be // excluded from the dragging. for (const auto& rect : drag_exclude_rects) { diff --git a/shell/browser/api/electron_api_browser_window_views.cc b/shell/browser/api/electron_api_browser_window_views.cc index 8da8a18fa3..1b50f7f0fe 100644 --- a/shell/browser/api/electron_api_browser_window_views.cc +++ b/shell/browser/api/electron_api_browser_window_views.cc @@ -15,7 +15,7 @@ void BrowserWindow::UpdateDraggableRegions( if (window_->has_frame()) return; static_cast(window_.get()) - ->UpdateDraggableRegions(DraggableRegionsToSkRegion(regions)); + ->UpdateDraggableRegions(regions); } } // namespace api diff --git a/shell/browser/api/electron_api_web_contents.h b/shell/browser/api/electron_api_web_contents.h index 1b3baf6811..4447431c43 100644 --- a/shell/browser/api/electron_api_web_contents.h +++ b/shell/browser/api/electron_api_web_contents.h @@ -31,6 +31,7 @@ #include "shell/browser/api/save_page_handler.h" #include "shell/browser/common_web_contents_delegate.h" #include "shell/browser/event_emitter_mixin.h" +#include "shell/browser/extended_web_contents_observer.h" #include "shell/common/gin_helper/cleaned_up_at_exit.h" #include "shell/common/gin_helper/constructible.h" #include "shell/common/gin_helper/error_thrower.h" @@ -120,22 +121,6 @@ class OffScreenRenderWidgetHostView; namespace api { -// Certain events are only in WebContentsDelegate, provide our own Observer to -// dispatch those events. -class ExtendedWebContentsObserver : public base::CheckedObserver { - public: - virtual void OnCloseContents() {} - virtual void OnDraggableRegionsUpdated( - const std::vector& regions) {} - virtual void OnSetContentBounds(const gfx::Rect& rect) {} - virtual void OnActivateContents() {} - virtual void OnPageTitleUpdated(const base::string16& title, - bool explicit_set) {} - - protected: - ~ExtendedWebContentsObserver() override {} -}; - // Wrapper around the content::WebContents. class WebContents : public gin::Wrappable, public gin_helper::EventEmitterMixin, diff --git a/shell/browser/extended_web_contents_observer.h b/shell/browser/extended_web_contents_observer.h new file mode 100644 index 0000000000..78801eef0c --- /dev/null +++ b/shell/browser/extended_web_contents_observer.h @@ -0,0 +1,35 @@ +// Copyright (c) 2020 Microsoft, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef SHELL_BROWSER_EXTENDED_WEB_CONTENTS_OBSERVER_H_ +#define SHELL_BROWSER_EXTENDED_WEB_CONTENTS_OBSERVER_H_ + +#include + +#include "base/observer_list.h" +#include "base/strings/string16.h" +#include "electron/shell/common/api/api.mojom.h" +#include "ui/gfx/geometry/rect.h" + +namespace electron { + +// Certain events are only in WebContentsDelegate, so we provide our own +// Observer to dispatch those events. +class ExtendedWebContentsObserver : public base::CheckedObserver { + public: + virtual void OnCloseContents() {} + virtual void OnDraggableRegionsUpdated( + const std::vector& regions) {} + virtual void OnSetContentBounds(const gfx::Rect& rect) {} + virtual void OnActivateContents() {} + virtual void OnPageTitleUpdated(const base::string16& title, + bool explicit_set) {} + + protected: + ~ExtendedWebContentsObserver() override {} +}; + +} // namespace electron + +#endif // SHELL_BROWSER_EXTENDED_WEB_CONTENTS_OBSERVER_H_ diff --git a/shell/browser/native_browser_view.h b/shell/browser/native_browser_view.h index e9ae6baa8d..aa33d41ac6 100644 --- a/shell/browser/native_browser_view.h +++ b/shell/browser/native_browser_view.h @@ -10,6 +10,7 @@ #include "base/macros.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" +#include "shell/common/api/api.mojom.h" #include "third_party/skia/include/core/SkColor.h" namespace gfx { @@ -48,7 +49,7 @@ class NativeBrowserView : public content::WebContentsObserver { // Called when the window needs to update its draggable region. virtual void UpdateDraggableRegions( - const std::vector& system_drag_exclude_areas) {} + const std::vector& regions) {} protected: explicit NativeBrowserView(InspectableWebContents* inspectable_web_contents); diff --git a/shell/browser/native_browser_view_mac.h b/shell/browser/native_browser_view_mac.h index 7149952caf..d9bd10f5b8 100644 --- a/shell/browser/native_browser_view_mac.h +++ b/shell/browser/native_browser_view_mac.h @@ -25,7 +25,7 @@ class NativeBrowserViewMac : public NativeBrowserView { void SetBackgroundColor(SkColor color) override; void UpdateDraggableRegions( - const std::vector& system_drag_exclude_areas) override; + const std::vector& regions) override; private: DISALLOW_COPY_AND_ASSIGN(NativeBrowserViewMac); diff --git a/shell/browser/native_browser_view_mac.mm b/shell/browser/native_browser_view_mac.mm index ca1afa6b62..bafd038dfd 100644 --- a/shell/browser/native_browser_view_mac.mm +++ b/shell/browser/native_browser_view_mac.mm @@ -6,6 +6,7 @@ #include +#include "shell/browser/ui/drag_util.h" #include "shell/browser/ui/inspectable_web_contents.h" #include "shell/browser/ui/inspectable_web_contents_view.h" #include "skia/ext/skia_utils_mac.h" @@ -35,8 +36,8 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask = - (NSView*)hitTest:(NSPoint)aPoint { // Pass-through events that don't hit one of the exclusion zones - for (NSView* exlusion_zones in [self subviews]) { - if ([exlusion_zones hitTest:aPoint]) + for (NSView* exclusion_zones in [self subviews]) { + if ([exclusion_zones hitTest:aPoint]) return nil; } @@ -230,7 +231,7 @@ void NativeBrowserViewMac::SetBackgroundColor(SkColor color) { } void NativeBrowserViewMac::UpdateDraggableRegions( - const std::vector& drag_exclude_rects) { + const std::vector& regions) { if (!inspectable_web_contents_) return; auto* web_contents = inspectable_web_contents_->GetWebContents(); @@ -240,6 +241,11 @@ void NativeBrowserViewMac::UpdateDraggableRegions( NSView* window_content_view = inspectable_view.superview; const auto window_content_view_height = NSHeight(window_content_view.bounds); + NSInteger webViewWidth = NSWidth([web_view bounds]); + NSInteger webViewHeight = NSHeight([web_view bounds]); + auto drag_exclude_rects = CalculateNonDraggableRegions( + DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight); + // 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 subviews([[web_view subviews] copy]); diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index f3f95c5b9e..ca36457c2e 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -20,6 +20,7 @@ #include "content/public/browser/desktop_media_id.h" #include "shell/browser/api/electron_api_web_contents.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_view.h" #include "shell/browser/ui/views/root_view.h" @@ -1329,8 +1330,8 @@ gfx::Rect NativeWindowViews::WindowBoundsToContentBounds( } void NativeWindowViews::UpdateDraggableRegions( - std::unique_ptr region) { - draggable_region_ = std::move(region); + const std::vector& regions) { + draggable_region_ = DraggableRegionsToSkRegion(regions); } #if defined(OS_WIN) diff --git a/shell/browser/native_window_views.h b/shell/browser/native_window_views.h index b0377ed675..f7bcb1f6ad 100644 --- a/shell/browser/native_window_views.h +++ b/shell/browser/native_window_views.h @@ -11,7 +11,9 @@ #include #include #include +#include +#include "shell/common/api/api.mojom.h" #include "ui/views/widget/widget_observer.h" #if defined(OS_WIN) @@ -138,7 +140,8 @@ class NativeWindowViews : public NativeWindow, gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override; gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override; - void UpdateDraggableRegions(std::unique_ptr region); + void UpdateDraggableRegions( + const std::vector& regions); void IncrementChildModals(); void DecrementChildModals(); diff --git a/shell/browser/ui/drag_util.cc b/shell/browser/ui/drag_util.cc new file mode 100644 index 0000000000..861f182210 --- /dev/null +++ b/shell/browser/ui/drag_util.cc @@ -0,0 +1,42 @@ +// Copyright (c) 2020 Microsoft, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "shell/browser/ui/drag_util.h" + +#include + +#include "ui/gfx/skia_util.h" + +namespace electron { + +// Return a vector of non-draggable regions that fill a window of size +// |width| by |height|, but leave gaps where the window should be draggable. +std::vector CalculateNonDraggableRegions( + std::unique_ptr draggable, + int width, + int height) { + std::vector result; + SkRegion non_draggable; + non_draggable.op({0, 0, width, height}, SkRegion::kUnion_Op); + non_draggable.op(*draggable, SkRegion::kDifference_Op); + for (SkRegion::Iterator it(non_draggable); !it.done(); it.next()) { + result.push_back(gfx::SkIRectToRect(it.rect())); + } + return result; +} + +// Convert draggable regions in raw format to SkRegion format. +std::unique_ptr DraggableRegionsToSkRegion( + const std::vector& regions) { + auto sk_region = std::make_unique(); + for (const auto& region : regions) { + sk_region->op( + {region->bounds.x(), region->bounds.y(), region->bounds.right(), + region->bounds.bottom()}, + region->draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op); + } + return sk_region; +} + +} // namespace electron diff --git a/shell/browser/ui/drag_util.h b/shell/browser/ui/drag_util.h index 784bf879b9..9fe50a4b59 100644 --- a/shell/browser/ui/drag_util.h +++ b/shell/browser/ui/drag_util.h @@ -5,8 +5,12 @@ #ifndef SHELL_BROWSER_UI_DRAG_UTIL_H_ #define SHELL_BROWSER_UI_DRAG_UTIL_H_ +#include #include +#include "shell/common/api/api.mojom.h" +#include "third_party/skia/include/core/SkRegion.h" +#include "ui/gfx/geometry/rect.h" #include "ui/gfx/image/image.h" namespace base { @@ -19,6 +23,15 @@ void DragFileItems(const std::vector& files, const gfx::Image& icon, gfx::NativeView view); +std::vector CalculateNonDraggableRegions( + std::unique_ptr draggable, + int width, + int height); + +// Convert draggable regions in raw format to SkRegion format. +std::unique_ptr DraggableRegionsToSkRegion( + const std::vector& regions); + } // namespace electron #endif // SHELL_BROWSER_UI_DRAG_UTIL_H_