mac: Simplify frameless window dragging code
This commit is contained in:
parent
4ca0458b37
commit
85685feff4
2 changed files with 45 additions and 75 deletions
|
@ -83,8 +83,6 @@ class NativeWindowMac : public NativeWindow {
|
||||||
// Clip web view to rounded corner.
|
// Clip web view to rounded corner.
|
||||||
void ClipWebView();
|
void ClipWebView();
|
||||||
|
|
||||||
SkRegion* draggable_region() const { return draggable_region_.get(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateDraggableRegions(
|
void UpdateDraggableRegions(
|
||||||
const std::vector<DraggableRegion>& regions) override;
|
const std::vector<DraggableRegion>& regions) override;
|
||||||
|
@ -97,9 +95,10 @@ class NativeWindowMac : public NativeWindow {
|
||||||
private:
|
private:
|
||||||
void InstallView();
|
void InstallView();
|
||||||
void UninstallView();
|
void UninstallView();
|
||||||
void InstallDraggableRegionViews();
|
|
||||||
void UpdateDraggableRegionsForCustomDrag(
|
// Install the drag view, which will cover the whole window and decides
|
||||||
const std::vector<DraggableRegion>& regions);
|
// whehter we can drag.
|
||||||
|
void InstallDraggableRegionView();
|
||||||
|
|
||||||
base::scoped_nsobject<NSWindow> window_;
|
base::scoped_nsobject<NSWindow> window_;
|
||||||
|
|
||||||
|
@ -113,10 +112,6 @@ class NativeWindowMac : public NativeWindow {
|
||||||
// The presentation options before entering kiosk mode.
|
// The presentation options before entering kiosk mode.
|
||||||
NSApplicationPresentationOptions kiosk_options_;
|
NSApplicationPresentationOptions kiosk_options_;
|
||||||
|
|
||||||
// For system drag, the whole window is draggable and the non-draggable areas
|
|
||||||
// have to been explicitly excluded.
|
|
||||||
std::vector<gfx::Rect> system_drag_exclude_areas_;
|
|
||||||
|
|
||||||
// For custom drag, the whole window is non-draggable and the draggable region
|
// For custom drag, the whole window is non-draggable and the draggable region
|
||||||
// has to been explicitly provided.
|
// has to been explicitly provided.
|
||||||
scoped_ptr<SkRegion> draggable_region_; // used in custom drag.
|
scoped_ptr<SkRegion> draggable_region_; // used in custom drag.
|
||||||
|
|
|
@ -101,7 +101,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
|
||||||
shell_->NotifyWindowBlur();
|
shell_->NotifyWindowBlur();
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)windowDidResize:(NSNotification*)otification {
|
- (void)windowDidResize:(NSNotification*)notification {
|
||||||
if (!shell_->has_frame())
|
if (!shell_->has_frame())
|
||||||
shell_->ClipWebView();
|
shell_->ClipWebView();
|
||||||
}
|
}
|
||||||
|
@ -280,6 +280,29 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
|
||||||
|
|
||||||
namespace atom {
|
namespace atom {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Convert draggable regions in raw format to SkRegion format. Caller is
|
||||||
|
// responsible for deleting the returned SkRegion instance.
|
||||||
|
SkRegion* DraggableRegionsToSkRegion(
|
||||||
|
const std::vector<DraggableRegion>& regions) {
|
||||||
|
SkRegion* sk_region = new SkRegion;
|
||||||
|
for (std::vector<DraggableRegion>::const_iterator iter = regions.begin();
|
||||||
|
iter != regions.end();
|
||||||
|
++iter) {
|
||||||
|
const DraggableRegion& region = *iter;
|
||||||
|
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
|
||||||
|
|
||||||
NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
|
NativeWindowMac::NativeWindowMac(content::WebContents* web_contents,
|
||||||
const mate::Dictionary& options)
|
const mate::Dictionary& options)
|
||||||
: NativeWindow(web_contents, options),
|
: NativeWindow(web_contents, options),
|
||||||
|
@ -680,7 +703,6 @@ void NativeWindowMac::HandleMouseEvent(NSEvent* event) {
|
||||||
NSRect mouseRect = [window_ convertRectToScreen:NSMakeRect(eventLoc.x, eventLoc.y, 0, 0)];
|
NSRect mouseRect = [window_ convertRectToScreen:NSMakeRect(eventLoc.x, eventLoc.y, 0, 0)];
|
||||||
NSPoint current_mouse_location = mouseRect.origin;
|
NSPoint current_mouse_location = mouseRect.origin;
|
||||||
|
|
||||||
|
|
||||||
if ([event type] == NSLeftMouseDown) {
|
if ([event type] == NSLeftMouseDown) {
|
||||||
NSPoint frame_origin = [window_ frame].origin;
|
NSPoint frame_origin = [window_ frame].origin;
|
||||||
last_mouse_offset_ = NSMakePoint(
|
last_mouse_offset_ = NSMakePoint(
|
||||||
|
@ -699,8 +721,7 @@ void NativeWindowMac::UpdateDraggableRegions(
|
||||||
if (has_frame_)
|
if (has_frame_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
UpdateDraggableRegionsForCustomDrag(regions);
|
draggable_region_.reset(DraggableRegionsToSkRegion(regions));
|
||||||
InstallDraggableRegionViews();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowMac::HandleKeyboardEvent(
|
void NativeWindowMac::HandleKeyboardEvent(
|
||||||
|
@ -757,11 +778,16 @@ void NativeWindowMac::InstallView() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ClipWebView();
|
ClipWebView();
|
||||||
|
InstallDraggableRegionView();
|
||||||
|
|
||||||
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
||||||
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
|
[[window_ standardWindowButton:NSWindowMiniaturizeButton] setHidden:YES];
|
||||||
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
|
[[window_ standardWindowButton:NSWindowCloseButton] setHidden:YES];
|
||||||
[[window_ standardWindowButton:NSWindowFullScreenButton] setHidden:YES];
|
|
||||||
|
// Some third-party OS X utilities check the zoom button's enabled state to
|
||||||
|
// determine whether to show custom UI on hover, so we disable it here to
|
||||||
|
// prevent them from doing so in a frameless app window.
|
||||||
|
[[window_ standardWindowButton:NSWindowZoomButton] setEnabled:NO];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,70 +797,19 @@ void NativeWindowMac::UninstallView() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowMac::ClipWebView() {
|
void NativeWindowMac::ClipWebView() {
|
||||||
NSView* view = GetWebContents()->GetNativeView();
|
|
||||||
view.layer.masksToBounds = YES;
|
|
||||||
view.layer.cornerRadius = kAtomWindowCornerRadius;
|
|
||||||
}
|
|
||||||
|
|
||||||
void NativeWindowMac::InstallDraggableRegionViews() {
|
|
||||||
DCHECK(!has_frame_);
|
|
||||||
|
|
||||||
// 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 = GetWebContents()->GetNativeView();
|
NSView* webView = GetWebContents()->GetNativeView();
|
||||||
NSInteger webViewHeight = NSHeight([webView bounds]);
|
webView.layer.masksToBounds = YES;
|
||||||
|
webView.layer.cornerRadius = kAtomWindowCornerRadius;
|
||||||
// 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];
|
|
||||||
|
|
||||||
// Create and add 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] initWithShellWindow:this]);
|
|
||||||
[controlRegion setFrame:NSMakeRect(iter->x(),
|
|
||||||
webViewHeight - iter->bottom(),
|
|
||||||
iter->width(),
|
|
||||||
iter->height())];
|
|
||||||
[webView addSubview:controlRegion];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NativeWindowMac::UpdateDraggableRegionsForCustomDrag(
|
void NativeWindowMac::InstallDraggableRegionView() {
|
||||||
const std::vector<DraggableRegion>& regions) {
|
NSView* webView = GetWebContents()->GetNativeView();
|
||||||
// We still need one ControlRegionView to cover the whole window such that
|
base::scoped_nsobject<NSView> controlRegion(
|
||||||
// mouse events could be captured.
|
[[ControlRegionView alloc] initWithShellWindow:this]);
|
||||||
NSView* web_view = GetWebContents()->GetNativeView();
|
[controlRegion setFrame:NSMakeRect(0, 0,
|
||||||
gfx::Rect window_bounds(
|
NSWidth([webView bounds]),
|
||||||
0, 0, NSWidth([web_view bounds]), NSHeight([web_view bounds]));
|
NSHeight([webView bounds]))];
|
||||||
system_drag_exclude_areas_.clear();
|
[webView addSubview:controlRegion];
|
||||||
system_drag_exclude_areas_.push_back(window_bounds);
|
|
||||||
|
|
||||||
// Aggregate the draggable areas and non-draggable areas such that hit test
|
|
||||||
// could be performed easily.
|
|
||||||
SkRegion* draggable_region = new SkRegion;
|
|
||||||
for (std::vector<DraggableRegion>::const_iterator iter = regions.begin();
|
|
||||||
iter != regions.end();
|
|
||||||
++iter) {
|
|
||||||
const DraggableRegion& region = *iter;
|
|
||||||
draggable_region->op(
|
|
||||||
region.bounds.x(),
|
|
||||||
region.bounds.y(),
|
|
||||||
region.bounds.right(),
|
|
||||||
region.bounds.bottom(),
|
|
||||||
region.draggable ? SkRegion::kUnion_Op : SkRegion::kDifference_Op);
|
|
||||||
}
|
|
||||||
draggable_region_.reset(draggable_region);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue