From df66223f4c21b4aeb7c9a31088d3c7831e76589b Mon Sep 17 00:00:00 2001 From: Felix Rieseberg Date: Tue, 8 Aug 2017 17:00:00 -0700 Subject: [PATCH 1/4] =?UTF-8?q?:wrench:=20Draggable=20(using=20the=20windo?= =?UTF-8?q?w=E2=80=99s=20regions)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- atom/browser/native_browser_view.h | 6 +++ atom/browser/native_browser_view_mac.h | 3 ++ atom/browser/native_browser_view_mac.mm | 52 +++++++++++++++++++++++++ atom/browser/native_window_mac.h | 2 +- atom/browser/native_window_mac.mm | 6 +++ 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/atom/browser/native_browser_view.h b/atom/browser/native_browser_view.h index 236f615c2b..47741aaf5c 100644 --- a/atom/browser/native_browser_view.h +++ b/atom/browser/native_browser_view.h @@ -7,6 +7,8 @@ #include "base/macros.h" #include "third_party/skia/include/core/SkColor.h" +#include "atom/common/draggable_region.h" +#include namespace brightray { class InspectableWebContentsView; @@ -38,6 +40,10 @@ class NativeBrowserView { virtual void SetBounds(const gfx::Rect& bounds) = 0; virtual void SetBackgroundColor(SkColor color) = 0; + // Called when the window needs to update its draggable region. + virtual void UpdateDraggableRegions( + const std::vector& regions) = 0; + protected: explicit NativeBrowserView( brightray::InspectableWebContentsView* web_contents_view); diff --git a/atom/browser/native_browser_view_mac.h b/atom/browser/native_browser_view_mac.h index 4e7aa429ce..9b87728571 100644 --- a/atom/browser/native_browser_view_mac.h +++ b/atom/browser/native_browser_view_mac.h @@ -7,6 +7,8 @@ #import +#include "atom/common/draggable_region.h" +#include "base/mac/scoped_nsobject.h" #include "atom/browser/native_browser_view.h" namespace atom { @@ -20,6 +22,7 @@ class NativeBrowserViewMac : public NativeBrowserView { void SetAutoResizeFlags(uint8_t flags) override; void SetBounds(const gfx::Rect& bounds) override; void SetBackgroundColor(SkColor color) override; + void UpdateDraggableRegions(const std::vector& regions) override; private: DISALLOW_COPY_AND_ASSIGN(NativeBrowserViewMac); diff --git a/atom/browser/native_browser_view_mac.mm b/atom/browser/native_browser_view_mac.mm index 2ce2adc1f4..096b87dbb4 100644 --- a/atom/browser/native_browser_view_mac.mm +++ b/atom/browser/native_browser_view_mac.mm @@ -8,10 +8,37 @@ #include "skia/ext/skia_utils_mac.h" #include "ui/gfx/geometry/rect.h" +using base::scoped_nsobject; + // Match view::Views behavior where the view sticks to the top-left origin. const NSAutoresizingMaskOptions kDefaultAutoResizingMask = NSViewMaxXMargin | NSViewMinYMargin; +@interface DragRegionView : NSView +@end + +@implementation DragRegionView + +- (BOOL)mouseDownCanMoveWindow +{ + return NO; +} + +- (void)mouseDown:(NSEvent *)event +{ + [self.window performWindowDragWithEvent:event]; +} + +// Debugging tips: +// Uncomment the following four lines to color DragRegionViews bright red +- (void)drawRect:(NSRect)aRect +{ + [[NSColor redColor] set]; + NSRectFill([self bounds]); +} + +@end + namespace atom { NativeBrowserViewMac::NativeBrowserViewMac( @@ -51,6 +78,31 @@ void NativeBrowserViewMac::SetBackgroundColor(SkColor color) { view.layer.backgroundColor = skia::CGColorCreateFromSkColor(color); } +void NativeBrowserViewMac::UpdateDraggableRegions( + const std::vector& regions) { + NSView* webView = GetInspectableWebContentsView()->GetNativeView(); + NSInteger webViewHeight = NSHeight([webView bounds]); + + // Remove all DraggableRegionViews 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 subviews([[webView subviews] copy]); + for (NSView* subview in subviews.get()) + if ([subview isKindOfClass:[DragRegionView class]]) + [subview removeFromSuperview]; + + for (const DraggableRegion& region : regions) { + base::scoped_nsobject dragRegion( + [[DragRegionView alloc] initWithFrame:NSZeroRect]); + [dragRegion setFrame:NSMakeRect(region.bounds.x(), + webViewHeight - region.bounds.bottom(), + region.bounds.width(), + region.bounds.height())]; + [webView addSubview:dragRegion]; + } +} + // static NativeBrowserView* NativeBrowserView::Create( brightray::InspectableWebContentsView* web_contents_view) { diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 3dfb88d539..45636eb702 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -154,7 +154,7 @@ class NativeWindowMac : public NativeWindow, void UninstallView(); // Install the drag view, which will cover the whole window and decides - // whehter we can drag. + // whether we can drag. void UpdateDraggableRegionViews(const std::vector& regions); void RegisterInputEventObserver(content::RenderViewHost* host); diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 2719c67295..679624fa98 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -1753,6 +1753,12 @@ void NativeWindowMac::UpdateDraggableRegionViews( [webView setMouseDownCanMoveWindow:YES]; } + // Call down to a BrowserView, if it exists, and inform it about the + // draggable areas + if (browser_view_) { + browser_view_->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 From fdd0d67fd3ccb54e2cc95101ad4d1d5f1ce1f432 Mon Sep 17 00:00:00 2001 From: Felix Rieseberg Date: Wed, 9 Aug 2017 11:57:57 -0700 Subject: [PATCH 2/4] :wrench: Support older versions of macOS --- atom/browser/native_browser_view_mac.mm | 35 ++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/atom/browser/native_browser_view_mac.mm b/atom/browser/native_browser_view_mac.mm index 096b87dbb4..5e8db8cf55 100644 --- a/atom/browser/native_browser_view_mac.mm +++ b/atom/browser/native_browser_view_mac.mm @@ -15,6 +15,9 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask = NSViewMaxXMargin | NSViewMinYMargin; @interface DragRegionView : NSView + +@property (assign) NSPoint initialLocation; + @end @implementation DragRegionView @@ -26,7 +29,37 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask = - (void)mouseDown:(NSEvent *)event { - [self.window performWindowDragWithEvent:event]; + if ([self.window respondsToSelector:@selector(performWindowDragWithEvent:)]) { + [self.window performWindowDragWithEvent:event]; + return; + } + + self.initialLocation = [event locationInWindow]; +} + +- (void)mouseDragged:(NSEvent *)theEvent +{ + if ([self.window respondsToSelector:@selector(performWindowDragWithEvent:)]) { + return; + } + + NSPoint currentLocation; + NSPoint newOrigin; + + NSRect screenFrame = [[NSScreen mainScreen] frame]; + NSRect windowFrame = [self.window frame]; + + currentLocation = [NSEvent mouseLocation]; + newOrigin.x = currentLocation.x - self.initialLocation.x; + newOrigin.y = currentLocation.y - self.initialLocation.y; + + // Don't let window get dragged up under the menu bar + if( (newOrigin.y+windowFrame.size.height) > (screenFrame.origin.y+screenFrame.size.height) ){ + newOrigin.y=screenFrame.origin.y + (screenFrame.size.height-windowFrame.size.height); + } + + // Move the window to the new location + [self.window setFrameOrigin:newOrigin]; } // Debugging tips: From ebe058e7cb8231e0e94ae6ab4fb5e25a6cc2e35f Mon Sep 17 00:00:00 2001 From: Felix Rieseberg Date: Wed, 9 Aug 2017 14:49:11 -0700 Subject: [PATCH 3/4] :wrench: Make work with complex shapes --- atom/browser/native_browser_view.h | 2 +- atom/browser/native_browser_view_mac.h | 2 +- atom/browser/native_browser_view_mac.mm | 72 ++++++++++++++++++++----- atom/browser/native_window_mac.mm | 12 ++--- 4 files changed, 67 insertions(+), 21 deletions(-) diff --git a/atom/browser/native_browser_view.h b/atom/browser/native_browser_view.h index 47741aaf5c..11c4dd228d 100644 --- a/atom/browser/native_browser_view.h +++ b/atom/browser/native_browser_view.h @@ -42,7 +42,7 @@ class NativeBrowserView { // Called when the window needs to update its draggable region. virtual void UpdateDraggableRegions( - const std::vector& regions) = 0; + std::vector system_drag_exclude_areas) = 0; protected: explicit NativeBrowserView( diff --git a/atom/browser/native_browser_view_mac.h b/atom/browser/native_browser_view_mac.h index 9b87728571..600a3df8da 100644 --- a/atom/browser/native_browser_view_mac.h +++ b/atom/browser/native_browser_view_mac.h @@ -22,7 +22,7 @@ class NativeBrowserViewMac : public NativeBrowserView { void SetAutoResizeFlags(uint8_t flags) override; void SetBounds(const gfx::Rect& bounds) override; void SetBackgroundColor(SkColor color) override; - void UpdateDraggableRegions(const std::vector& regions) override; + void UpdateDraggableRegions(std::vector system_drag_exclude_areas) override; private: DISALLOW_COPY_AND_ASSIGN(NativeBrowserViewMac); diff --git a/atom/browser/native_browser_view_mac.mm b/atom/browser/native_browser_view_mac.mm index 5e8db8cf55..589278dbce 100644 --- a/atom/browser/native_browser_view_mac.mm +++ b/atom/browser/native_browser_view_mac.mm @@ -27,6 +27,17 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask = return NO; } +- (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]) + return nil; + } + + return self; +} + - (void)mouseDown:(NSEvent *)event { if ([self.window respondsToSelector:@selector(performWindowDragWithEvent:)]) { @@ -63,13 +74,32 @@ const NSAutoresizingMaskOptions kDefaultAutoResizingMask = } // Debugging tips: -// Uncomment the following four lines to color DragRegionViews bright red -- (void)drawRect:(NSRect)aRect -{ - [[NSColor redColor] set]; - NSRectFill([self bounds]); +// Uncomment the following four lines to color DragRegionView bright red +// - (void)drawRect:(NSRect)aRect +// { +// [[NSColor redColor] set]; +// NSRectFill([self bounds]); +// } + +@end + +@interface ExcludeDragRegionView : NSView +@end + +@implementation ExcludeDragRegionView + +- (BOOL)mouseDownCanMoveWindow { + return NO; } +// Debugging tips: +// Uncomment the following four lines to color ExcludeDragRegionView bright red +// - (void)drawRect:(NSRect)aRect +// { +// [[NSColor greenColor] set]; +// NSRectFill([self bounds]); +// } + @end namespace atom { @@ -112,9 +142,10 @@ void NativeBrowserViewMac::SetBackgroundColor(SkColor color) { } void NativeBrowserViewMac::UpdateDraggableRegions( - const std::vector& regions) { + std::vector system_drag_exclude_areas) { NSView* webView = GetInspectableWebContentsView()->GetNativeView(); NSInteger webViewHeight = NSHeight([webView bounds]); + NSInteger webViewWidth = NSWidth([webView bounds]); // Remove all DraggableRegionViews that are added last time. // Note that [webView subviews] returns the view's mutable internal array and @@ -125,15 +156,30 @@ void NativeBrowserViewMac::UpdateDraggableRegions( if ([subview isKindOfClass:[DragRegionView class]]) [subview removeFromSuperview]; - for (const DraggableRegion& region : regions) { - base::scoped_nsobject dragRegion( + // Create one giant NSView that is draggable. + base::scoped_nsobject dragRegion( [[DragRegionView alloc] initWithFrame:NSZeroRect]); - [dragRegion setFrame:NSMakeRect(region.bounds.x(), - webViewHeight - region.bounds.bottom(), - region.bounds.width(), - region.bounds.height())]; - [webView addSubview:dragRegion]; + [dragRegion setFrame:NSMakeRect(0, + 0, + webViewWidth, + webViewHeight)]; + + // Then, on top of that, add "exclusion zones" + for (std::vector::const_iterator iter = + system_drag_exclude_areas.begin(); + iter != system_drag_exclude_areas.end(); + ++iter) { + base::scoped_nsobject controlRegion( + [[ExcludeDragRegionView alloc] initWithFrame:NSZeroRect]); + [controlRegion setFrame:NSMakeRect(iter->x(), + webViewHeight - iter->bottom(), + iter->width(), + iter->height())]; + [dragRegion addSubview:controlRegion]; } + + // Add the DragRegion to the WebView + [webView addSubview:dragRegion]; } // static diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 679624fa98..fcaf04aa76 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -1753,12 +1753,6 @@ void NativeWindowMac::UpdateDraggableRegionViews( [webView setMouseDownCanMoveWindow:YES]; } - // Call down to a BrowserView, if it exists, and inform it about the - // draggable areas - if (browser_view_) { - browser_view_->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 @@ -1773,6 +1767,12 @@ void NativeWindowMac::UpdateDraggableRegionViews( std::vector system_drag_exclude_areas = CalculateNonDraggableRegions(regions, webViewWidth, webViewHeight); + // Call down to a BrowserView, if it exists, and inform it about the + // draggable areas + 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::const_iterator iter = From ae5c8e63d99ab19cb71c74bbd704ea4f0dd93e61 Mon Sep 17 00:00:00 2001 From: Felix Rieseberg Date: Thu, 10 Aug 2017 07:09:03 +0900 Subject: [PATCH 4/4] :wrench: Properly derive --- atom/browser/native_browser_view.cc | 4 ++++ atom/browser/native_browser_view.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/atom/browser/native_browser_view.cc b/atom/browser/native_browser_view.cc index 949e5e9ec9..ec49609751 100644 --- a/atom/browser/native_browser_view.cc +++ b/atom/browser/native_browser_view.cc @@ -15,4 +15,8 @@ NativeBrowserView::NativeBrowserView( NativeBrowserView::~NativeBrowserView() {} +void NativeBrowserView::UpdateDraggableRegions( + std::vector system_drag_exclude_areas) { +} + } // namespace atom diff --git a/atom/browser/native_browser_view.h b/atom/browser/native_browser_view.h index 11c4dd228d..69bd933151 100644 --- a/atom/browser/native_browser_view.h +++ b/atom/browser/native_browser_view.h @@ -42,7 +42,7 @@ class NativeBrowserView { // Called when the window needs to update its draggable region. virtual void UpdateDraggableRegions( - std::vector system_drag_exclude_areas) = 0; + std::vector system_drag_exclude_areas); protected: explicit NativeBrowserView(