mac: Move draggable region code to BrowserWindow
On macOS current draggable region implementation highly relies on WebContents, the code is only meaningful for BrowserWindow.
This commit is contained in:
		
					parent
					
						
							
								bc34ca9e25
							
						
					
				
			
			
				commit
				
					
						503b0ba1b1
					
				
			
		
					 10 changed files with 127 additions and 132 deletions
				
			
		|  | @ -409,6 +409,10 @@ void BrowserWindow::OnWindowRestore() { | |||
| } | ||||
| 
 | ||||
| void BrowserWindow::OnWindowResize() { | ||||
| #if defined(OS_MACOSX) | ||||
|   if (!draggable_regions_.empty()) | ||||
|     UpdateDraggableRegions(nullptr, draggable_regions_); | ||||
| #endif | ||||
|   Emit("resize"); | ||||
| } | ||||
| 
 | ||||
|  | @ -1169,6 +1173,21 @@ void BrowserWindow::RemoveFromParentChildWindows() { | |||
|   parent->child_windows_.Remove(ID()); | ||||
| } | ||||
| 
 | ||||
| // Convert draggable regions in raw format to SkRegion format.
 | ||||
| std::unique_ptr<SkRegion> BrowserWindow::DraggableRegionsToSkRegion( | ||||
|     const std::vector<DraggableRegion>& regions) { | ||||
|   std::unique_ptr<SkRegion> sk_region(new SkRegion); | ||||
|   for (const DraggableRegion& 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; | ||||
|  |  | |||
|  | @ -261,6 +261,10 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>, | |||
|       content::RenderFrameHost* rfh, | ||||
|       const std::vector<DraggableRegion>& regions); | ||||
| 
 | ||||
|   // Convert draggable regions in raw format to SkRegion format.
 | ||||
|   std::unique_ptr<SkRegion> DraggableRegionsToSkRegion( | ||||
|       const std::vector<DraggableRegion>& regions); | ||||
| 
 | ||||
|   // Schedule a notification unresponsive event.
 | ||||
|   void ScheduleUnresponsiveEvent(int ms); | ||||
| 
 | ||||
|  | @ -272,6 +276,10 @@ class BrowserWindow : public mate::TrackableObject<BrowserWindow>, | |||
|   MessageCallbackMap messages_callback_map_; | ||||
| #endif | ||||
| 
 | ||||
| #if defined(OS_MACOSX) | ||||
|   std::vector<DraggableRegion> draggable_regions_; | ||||
| #endif | ||||
| 
 | ||||
|   // Closure that would be called when window is unresponsive when closing,
 | ||||
|   // it should be cancelled when we can prove that the window is responsive.
 | ||||
|   base::CancelableClosure window_unresponsive_closure_; | ||||
|  |  | |||
|  | @ -6,24 +6,115 @@ | |||
| 
 | ||||
| #import <Cocoa/Cocoa.h> | ||||
| 
 | ||||
| #include "atom/browser/native_browser_view_mac.h" | ||||
| #include "atom/browser/native_window_mac.h" | ||||
| #include "atom/common/draggable_region.h" | ||||
| #include "base/mac/scoped_nsobject.h" | ||||
| 
 | ||||
| @interface NSView (WebContentsView) | ||||
| - (void)setMouseDownCanMoveWindow:(BOOL)can_move; | ||||
| @end | ||||
| 
 | ||||
| @interface ControlRegionView : NSView | ||||
| @end | ||||
| 
 | ||||
| @implementation ControlRegionView | ||||
| 
 | ||||
| - (BOOL)mouseDownCanMoveWindow { | ||||
|   return NO; | ||||
| } | ||||
| 
 | ||||
| - (NSView*)hitTest:(NSPoint)aPoint { | ||||
|   return nil; | ||||
| } | ||||
| 
 | ||||
| @end | ||||
| 
 | ||||
| namespace atom { | ||||
| 
 | ||||
| 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<gfx::Rect> CalculateNonDraggableRegions( | ||||
|     std::unique_ptr<SkRegion> draggable, int width, int height) { | ||||
|   std::vector<gfx::Rect> result; | ||||
|   std::unique_ptr<SkRegion> non_draggable(new SkRegion); | ||||
|   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::UpdateDraggableRegions( | ||||
|     content::RenderFrameHost* rfh, | ||||
|     const std::vector<DraggableRegion>& regions) { | ||||
|   if (window_->has_frame()) | ||||
|     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(); | ||||
|   NSInteger webViewWidth = NSWidth([webView bounds]); | ||||
|   NSInteger webViewHeight = NSHeight([webView bounds]); | ||||
| 
 | ||||
|   if ([webView respondsToSelector:@selector(setMouseDownCanMoveWindow:)]) { | ||||
|     [webView setMouseDownCanMoveWindow:YES]; | ||||
|   } | ||||
|   window_->UpdateDraggableRegions(regions); | ||||
| 
 | ||||
|   // 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 is implemented by having the whole web view draggable | ||||
|   // (mouseDownCanMoveWindow) and overlaying regions that are not draggable. | ||||
|   draggable_regions_ = regions; | ||||
|   std::vector<gfx::Rect> system_drag_exclude_areas; | ||||
|   if (regions.empty()) { | ||||
|     system_drag_exclude_areas.push_back( | ||||
|         gfx::Rect(0, 0, webViewWidth, webViewHeight)); | ||||
|   } else { | ||||
|     CalculateNonDraggableRegions( | ||||
|         DraggableRegionsToSkRegion(regions), webViewWidth, webViewHeight); | ||||
|   } | ||||
| 
 | ||||
|   NativeWindowMac* window = static_cast<NativeWindowMac*>(window_.get()); | ||||
|   if (window->browser_view()) | ||||
|     window->browser_view()->UpdateDraggableRegions(system_drag_exclude_areas); | ||||
| 
 | ||||
|   // 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) { | ||||
|     base::scoped_nsobject<NSView> controlRegion( | ||||
|         [[ControlRegionView alloc] initWithFrame:NSZeroRect]); | ||||
|     [controlRegion setFrame:NSMakeRect(iter->x(), | ||||
|                                        webViewHeight - iter->bottom(), | ||||
|                                        iter->width(), | ||||
|                                        iter->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 api | ||||
|  |  | |||
|  | @ -11,7 +11,9 @@ namespace api { | |||
| void BrowserWindow::UpdateDraggableRegions( | ||||
|     content::RenderFrameHost* rfh, | ||||
|     const std::vector<DraggableRegion>& regions) { | ||||
|   window_->UpdateDraggableRegions(regions); | ||||
|   if (window_->has_frame()) | ||||
|     return; | ||||
|   window_->UpdateDraggableRegions(DraggableRegionsToSkRegion(regions)); | ||||
| } | ||||
| 
 | ||||
| }  // namespace api
 | ||||
|  |  | |||
|  | @ -13,7 +13,6 @@ | |||
| #include "atom/browser/browser.h" | ||||
| #include "atom/browser/window_list.h" | ||||
| #include "atom/common/color_util.h" | ||||
| #include "atom/common/draggable_region.h" | ||||
| #include "atom/common/native_mate_converters/file_path_converter.h" | ||||
| #include "atom/common/options_switches.h" | ||||
| #include "base/files/file_util.h" | ||||
|  | @ -33,7 +32,6 @@ | |||
| #include "content/public/common/content_switches.h" | ||||
| #include "ipc/ipc_message_macros.h" | ||||
| #include "native_mate/dictionary.h" | ||||
| #include "third_party/skia/include/core/SkRegion.h" | ||||
| #include "ui/gfx/codec/png_codec.h" | ||||
| #include "ui/gfx/geometry/point.h" | ||||
| #include "ui/gfx/geometry/rect.h" | ||||
|  | @ -569,18 +567,4 @@ void NativeWindow::NotifyWindowMessage( | |||
| } | ||||
| #endif | ||||
| 
 | ||||
| std::unique_ptr<SkRegion> NativeWindow::DraggableRegionsToSkRegion( | ||||
|     const std::vector<DraggableRegion>& regions) { | ||||
|   std::unique_ptr<SkRegion> sk_region(new SkRegion); | ||||
|   for (const DraggableRegion& 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 atom
 | ||||
|  |  | |||
|  | @ -221,10 +221,6 @@ class NativeWindow : public base::SupportsUserData, | |||
|   virtual gfx::Rect WindowBoundsToContentBounds( | ||||
|       const gfx::Rect& bounds) const = 0; | ||||
| 
 | ||||
|   // Called when the window needs to update its draggable region.
 | ||||
|   virtual void UpdateDraggableRegions( | ||||
|       const std::vector<DraggableRegion>& regions) = 0; | ||||
| 
 | ||||
|   base::WeakPtr<NativeWindow> GetWeakPtr() { | ||||
|     return weak_factory_.GetWeakPtr(); | ||||
|   } | ||||
|  | @ -304,11 +300,6 @@ class NativeWindow : public base::SupportsUserData, | |||
|                const mate::Dictionary& options, | ||||
|                NativeWindow* parent); | ||||
| 
 | ||||
|   // Convert draggable regions in raw format to SkRegion format. Caller is
 | ||||
|   // responsible for deleting the returned SkRegion instance.
 | ||||
|   std::unique_ptr<SkRegion> DraggableRegionsToSkRegion( | ||||
|       const std::vector<DraggableRegion>& regions); | ||||
| 
 | ||||
|  private: | ||||
|   // Whether window has standard frame.
 | ||||
|   bool has_frame_; | ||||
|  |  | |||
|  | @ -119,8 +119,6 @@ class NativeWindowMac : public NativeWindow { | |||
| 
 | ||||
|   gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const; | ||||
|   gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const; | ||||
|   void UpdateDraggableRegions( | ||||
|       const std::vector<DraggableRegion>& regions) override; | ||||
| 
 | ||||
|   // Set the attribute of NSWindow while work around a bug of zoom button.
 | ||||
|   void SetStyleMask(bool on, NSUInteger flag); | ||||
|  | @ -137,15 +135,7 @@ class NativeWindowMac : public NativeWindow { | |||
|   bool zoom_to_page_width() const { return zoom_to_page_width_; } | ||||
|   bool fullscreen_window_title() const { return fullscreen_window_title_; } | ||||
|   bool simple_fullscreen() const { return always_simple_fullscreen_; } | ||||
|   const std::vector<DraggableRegion>& draggable_regions() const { | ||||
|     return draggable_regions_; | ||||
|   } | ||||
| 
 | ||||
|  protected: | ||||
|   // 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<gfx::Rect> CalculateNonDraggableRegions( | ||||
|       const std::vector<DraggableRegion>& regions, int width, int height); | ||||
|   NativeBrowserView* browser_view() const { return browser_view_; } | ||||
| 
 | ||||
|  private: | ||||
|   void InternalSetParentWindow(NativeWindow* parent, bool attach); | ||||
|  | @ -165,8 +155,6 @@ class NativeWindowMac : public NativeWindow { | |||
| 
 | ||||
|   NativeBrowserView* browser_view_; | ||||
| 
 | ||||
|   std::vector<DraggableRegion> draggable_regions_; | ||||
| 
 | ||||
|   bool is_kiosk_; | ||||
| 
 | ||||
|   bool was_fullscreen_; | ||||
|  |  | |||
|  | @ -12,7 +12,6 @@ | |||
| #include "atom/browser/native_browser_view_mac.h" | ||||
| #include "atom/browser/ui/cocoa/atom_touch_bar.h" | ||||
| #include "atom/browser/window_list.h" | ||||
| #include "atom/common/draggable_region.h" | ||||
| #include "atom/common/options_switches.h" | ||||
| #include "base/mac/mac_util.h" | ||||
| #include "base/mac/scoped_cftyperef.h" | ||||
|  | @ -23,7 +22,6 @@ | |||
| #include "content/public/browser/browser_accessibility_state.h" | ||||
| #include "native_mate/dictionary.h" | ||||
| #include "skia/ext/skia_utils_mac.h" | ||||
| #include "third_party/skia/include/core/SkRegion.h" | ||||
| #include "ui/gfx/skia_util.h" | ||||
| 
 | ||||
| namespace { | ||||
|  | @ -270,7 +268,6 @@ bool ScopedDisableResize::disable_resize_ = false; | |||
| } | ||||
| 
 | ||||
| - (void)windowDidResize:(NSNotification*)notification { | ||||
|   shell_->UpdateDraggableRegions(shell_->draggable_regions()); | ||||
|   shell_->NotifyWindowResize(); | ||||
| } | ||||
| 
 | ||||
|  | @ -721,21 +718,6 @@ enum { | |||
| 
 | ||||
| @end | ||||
| 
 | ||||
| @interface ControlRegionView : NSView | ||||
| @end | ||||
| 
 | ||||
| @implementation ControlRegionView | ||||
| 
 | ||||
| - (BOOL)mouseDownCanMoveWindow { | ||||
|   return NO; | ||||
| } | ||||
| 
 | ||||
| - (NSView*)hitTest:(NSPoint)aPoint { | ||||
|   return nil; | ||||
| } | ||||
| 
 | ||||
| @end | ||||
| 
 | ||||
| @interface AtomProgressBar : NSProgressIndicator | ||||
| @end | ||||
| 
 | ||||
|  | @ -1759,73 +1741,6 @@ gfx::Rect NativeWindowMac::WindowBoundsToContentBounds( | |||
|   } | ||||
| } | ||||
| 
 | ||||
| void NativeWindowMac::UpdateDraggableRegions( | ||||
|     const std::vector<DraggableRegion>& regions) { | ||||
|   // 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(); | ||||
|   NSInteger webViewWidth = NSWidth([webView bounds]); | ||||
|   NSInteger webViewHeight = NSHeight([webView bounds]); | ||||
| 
 | ||||
|   // 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 is implemented by having the whole web view draggable | ||||
|   // (mouseDownCanMoveWindow) and overlaying regions that are not draggable. | ||||
|   draggable_regions_ = regions; | ||||
|   std::vector<gfx::Rect> system_drag_exclude_areas = | ||||
|       CalculateNonDraggableRegions(regions, webViewWidth, webViewHeight); | ||||
| 
 | ||||
|   if (browser_view_) | ||||
|     browser_view_->UpdateDraggableRegions(system_drag_exclude_areas); | ||||
| 
 | ||||
|   // 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) { | ||||
|     base::scoped_nsobject<NSView> controlRegion( | ||||
|         [[ControlRegionView alloc] initWithFrame:NSZeroRect]); | ||||
|     [controlRegion setFrame:NSMakeRect(iter->x(), | ||||
|                                        webViewHeight - iter->bottom(), | ||||
|                                        iter->width(), | ||||
|                                        iter->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. | ||||
|   [window_ setMovableByWindowBackground:NO]; | ||||
|   [window_ setMovableByWindowBackground:YES]; | ||||
| } | ||||
| 
 | ||||
| std::vector<gfx::Rect> NativeWindowMac::CalculateNonDraggableRegions( | ||||
|     const std::vector<DraggableRegion>& regions, int width, int height) { | ||||
|   std::vector<gfx::Rect> result; | ||||
|   if (regions.empty()) { | ||||
|     result.push_back(gfx::Rect(0, 0, width, height)); | ||||
|   } else { | ||||
|     std::unique_ptr<SkRegion> draggable(DraggableRegionsToSkRegion(regions)); | ||||
|     std::unique_ptr<SkRegion> non_draggable(new SkRegion); | ||||
|     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; | ||||
| } | ||||
| 
 | ||||
| void NativeWindowMac::InternalSetParentWindow(NativeWindow* parent, bool attach) { | ||||
|   if (is_modal()) | ||||
|     return; | ||||
|  |  | |||
|  | @ -1121,11 +1121,8 @@ gfx::Rect NativeWindowViews::WindowBoundsToContentBounds( | |||
| } | ||||
| 
 | ||||
| void NativeWindowViews::UpdateDraggableRegions( | ||||
|     const std::vector<DraggableRegion>& regions) { | ||||
|   // Draggable region is not supported for non-frameless window.
 | ||||
|   if (has_frame()) | ||||
|     return; | ||||
|   draggable_region_ = DraggableRegionsToSkRegion(regions); | ||||
|     std::unique_ptr<SkRegion> region) { | ||||
|   draggable_region_ = std::move(region); | ||||
| } | ||||
| 
 | ||||
| #if defined(OS_WIN) | ||||
|  |  | |||
|  | @ -128,8 +128,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( | ||||
|       const std::vector<DraggableRegion>& regions) override; | ||||
| 
 | ||||
|   void UpdateDraggableRegions(std::unique_ptr<SkRegion> region); | ||||
| 
 | ||||
| #if defined(OS_WIN) | ||||
|   void SetIcon(HICON small_icon, HICON app_icon); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Cheng Zhao
				Cheng Zhao