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.
|
||||
void ClipWebView();
|
||||
|
||||
SkRegion* draggable_region() const { return draggable_region_.get(); }
|
||||
|
||||
protected:
|
||||
void UpdateDraggableRegions(
|
||||
const std::vector<DraggableRegion>& regions) override;
|
||||
|
@ -97,9 +95,10 @@ class NativeWindowMac : public NativeWindow {
|
|||
private:
|
||||
void InstallView();
|
||||
void UninstallView();
|
||||
void InstallDraggableRegionViews();
|
||||
void UpdateDraggableRegionsForCustomDrag(
|
||||
const std::vector<DraggableRegion>& regions);
|
||||
|
||||
// Install the drag view, which will cover the whole window and decides
|
||||
// whehter we can drag.
|
||||
void InstallDraggableRegionView();
|
||||
|
||||
base::scoped_nsobject<NSWindow> window_;
|
||||
|
||||
|
@ -113,10 +112,6 @@ class NativeWindowMac : public NativeWindow {
|
|||
// The presentation options before entering kiosk mode.
|
||||
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
|
||||
// has to been explicitly provided.
|
||||
scoped_ptr<SkRegion> draggable_region_; // used in custom drag.
|
||||
|
|
|
@ -101,7 +101,7 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
|
|||
shell_->NotifyWindowBlur();
|
||||
}
|
||||
|
||||
- (void)windowDidResize:(NSNotification*)otification {
|
||||
- (void)windowDidResize:(NSNotification*)notification {
|
||||
if (!shell_->has_frame())
|
||||
shell_->ClipWebView();
|
||||
}
|
||||
|
@ -280,6 +280,29 @@ static const CGFloat kAtomWindowCornerRadius = 4.0;
|
|||
|
||||
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,
|
||||
const mate::Dictionary& 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)];
|
||||
NSPoint current_mouse_location = mouseRect.origin;
|
||||
|
||||
|
||||
if ([event type] == NSLeftMouseDown) {
|
||||
NSPoint frame_origin = [window_ frame].origin;
|
||||
last_mouse_offset_ = NSMakePoint(
|
||||
|
@ -699,8 +721,7 @@ void NativeWindowMac::UpdateDraggableRegions(
|
|||
if (has_frame_)
|
||||
return;
|
||||
|
||||
UpdateDraggableRegionsForCustomDrag(regions);
|
||||
InstallDraggableRegionViews();
|
||||
draggable_region_.reset(DraggableRegionsToSkRegion(regions));
|
||||
}
|
||||
|
||||
void NativeWindowMac::HandleKeyboardEvent(
|
||||
|
@ -757,11 +778,16 @@ void NativeWindowMac::InstallView() {
|
|||
}
|
||||
|
||||
ClipWebView();
|
||||
InstallDraggableRegionView();
|
||||
|
||||
[[window_ standardWindowButton:NSWindowZoomButton] setHidden:YES];
|
||||
[[window_ standardWindowButton:NSWindowMiniaturizeButton] 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() {
|
||||
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();
|
||||
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];
|
||||
|
||||
// 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];
|
||||
}
|
||||
webView.layer.masksToBounds = YES;
|
||||
webView.layer.cornerRadius = kAtomWindowCornerRadius;
|
||||
}
|
||||
|
||||
void NativeWindowMac::UpdateDraggableRegionsForCustomDrag(
|
||||
const std::vector<DraggableRegion>& regions) {
|
||||
// We still need one ControlRegionView to cover the whole window such that
|
||||
// mouse events could be captured.
|
||||
NSView* web_view = GetWebContents()->GetNativeView();
|
||||
gfx::Rect window_bounds(
|
||||
0, 0, NSWidth([web_view bounds]), NSHeight([web_view bounds]));
|
||||
system_drag_exclude_areas_.clear();
|
||||
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);
|
||||
void NativeWindowMac::InstallDraggableRegionView() {
|
||||
NSView* webView = GetWebContents()->GetNativeView();
|
||||
base::scoped_nsobject<NSView> controlRegion(
|
||||
[[ControlRegionView alloc] initWithShellWindow:this]);
|
||||
[controlRegion setFrame:NSMakeRect(0, 0,
|
||||
NSWidth([webView bounds]),
|
||||
NSHeight([webView bounds]))];
|
||||
[webView addSubview:controlRegion];
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue