Chromium Code Reviews| Index: ui/views/cocoa/bridged_native_widget.mm |
| diff --git a/ui/views/cocoa/bridged_native_widget.mm b/ui/views/cocoa/bridged_native_widget.mm |
| index 09f7880cc8d3e501e047e89ce2f1eb0b49864527..d631dab28a5e449b3f0ddb4a722a75cbe84b711c 100644 |
| --- a/ui/views/cocoa/bridged_native_widget.mm |
| +++ b/ui/views/cocoa/bridged_native_widget.mm |
| @@ -35,16 +35,6 @@ |
| #include "ui/views/widget/widget_aura_utils.h" |
| #include "ui/views/widget/widget_delegate.h" |
| -extern "C" { |
| - |
| -typedef int32_t CGSConnection; |
| -CGSConnection _CGSDefaultConnection(); |
| -CGError CGSSetWindowBackgroundBlurRadius(CGSConnection connection, |
| - NSInteger windowNumber, |
| - int radius); |
| - |
| -} |
| - |
| // The NSView that hosts the composited CALayer drawing the UI. It fills the |
| // window but is not hittable so that accessibility hit tests always go to the |
| // BridgedContentView. |
| @@ -106,6 +96,8 @@ const int kResizeAreaCornerSize = 12; |
| int kWindowPropertiesKey; |
| +bool g_ignore_next_mouse_down_for_draggable_regions = false; |
| + |
| float GetDeviceScaleFactorFromView(NSView* view) { |
| gfx::Display display = |
| gfx::Screen::GetScreen()->GetDisplayNearestWindow(view); |
| @@ -203,6 +195,11 @@ NSEvent* RepostEventIfHandledByWindow(NSEvent* ns_event) { |
| // - any repost loop. |
| if (repost_state == NONE) { |
| + if (g_ignore_next_mouse_down_for_draggable_regions) { |
|
tapted
2016/04/13 08:28:12
Is it possible to scrap g_ignore_next_mouse_down_f
themblsha
2016/04/18 09:30:01
Yep, kCocoaWindowMoveLoopSimulatedEventUserData wo
|
| + g_ignore_next_mouse_down_for_draggable_regions = false; |
| + return ns_event; |
| + } |
| + |
| if (WindowWantsMouseDownReposted(ns_event)) { |
| repost_state = EXPECTING_REPOST; |
| reposted_event_number = event_number; |
| @@ -311,6 +308,16 @@ NSComparisonResult SubviewSorter(NSViewComparatorValue lhs, |
| } // namespace |
| +extern "C" { |
|
tapted
2016/04/13 08:28:12
keep this where it was?
themblsha
2016/04/18 09:30:01
Done.
|
| + |
| +typedef int32_t CGSConnection; |
| +CGSConnection _CGSDefaultConnection(); |
| +CGError CGSSetWindowBackgroundBlurRadius(CGSConnection connection, |
| + NSInteger windowNumber, |
| + int radius); |
| + |
| +} |
| + |
| namespace views { |
| // static |
| @@ -615,6 +622,81 @@ bool BridgedNativeWidget::HasCapture() { |
| return mouse_capture_ && mouse_capture_->IsActive(); |
| } |
| +Widget::MoveLoopResult BridgedNativeWidget::RunMoveLoop( |
| + const gfx::Vector2d& drag_offset) { |
| + DCHECK(!HasCapture()); |
| + DCHECK(!window_move_loop_); |
| + |
| + // First, position the window in the right place. The point |drag_offset| |
| + // away from the top-left corner needs to be positioned under the mouse. |
| + // TODO(tapted): Figure out why the toolkit-views drag controller doesn't get |
| + // this right when it first initializes the Widget. |
| + gfx::Point mouse_in_screen = gfx::Screen::GetScreen()->GetCursorScreenPoint(); |
| + |
| + // We won't be able to simulate MouseDown events on top of menu bar, so |
| + // constrain the initial dragging. |
| + const gfx::Display display = |
| + gfx::Screen::GetScreen()->GetDisplayNearestPoint(mouse_in_screen); |
| + mouse_in_screen = |
| + gfx::ConstrainToEnclosingRect(display.work_area(), mouse_in_screen); |
|
tapted
2016/04/13 08:28:12
This isn't right. Only the menu bar affects this c
themblsha
2016/04/18 09:30:01
Tests still pass after these changes, so it's good
|
| + |
| + gfx::Rect frame = gfx::ScreenRectFromNSRect([window_ frame]); |
| + frame.set_x(mouse_in_screen.x() - drag_offset.x()); |
| + frame.set_y(mouse_in_screen.y() - drag_offset.y()); |
| + |
| + // We won't be able to simulate MouseDown events on top of menu bar, so |
| + // constrain the initial dragging. Don't use AdjustToFit(display.work_area()) |
| + // as it's totally fine to move beyond the other borders. |
| + // DetachToBrowserTabDragControllerTest.MacDetachesWindowOnTopOfMacMenuBar |
| + // will fail without this code. |
| + if (frame.y() < display.work_area().y()) { |
| + frame.set_y(display.work_area().y()); |
| + } |
| + |
| + // After setting the frame to correct the initial offset, the drag controller |
| + // may immediately want to quit when it's notified of the new bounds. So the |
| + // MoveLoop must be set up before the call to setFrame. |
| + window_move_loop_.reset(new CocoaWindowMoveLoop(this, mouse_in_screen)); |
| + |
| + // Animating may provide a less janky UX, but something custom would be |
|
tapted
2016/04/13 08:28:12
This comment can go - I've changed my mind since I
themblsha
2016/04/18 09:30:01
Done.
|
| + // required so that it follows updates to the mouse position. |
| + const NSRect ns_frame = gfx::ScreenRectToNSRect(frame); |
| + [window_ setFrame:ns_frame display:YES animate:NO]; |
| + |
| + // Setting the frame will call OnWidgetBoundsChanged(), which could result in |
| + // a call to EndMoveLoop(). |
| + if (!window_move_loop_) |
| + return Widget::MOVE_LOOP_SUCCESSFUL; |
| + |
| + // Make sure WindowServer has caught up with moving the window, this is |
| + // required in order to send the MouseDown click to the intended position. |
| + // I was able to always replicate old window coordinates from |
|
tapted
2016/04/13 08:28:12
Shouldn't use "I " in comments (typically not "we"
themblsha
2016/04/18 09:30:01
Thanks :)
|
| + // CGSGetWindowBounds() on El Capitan. |
| + // DetachToBrowserTabDragControllerTest.MacDetachesAndReattachesSecondTab will |
| + // fail without the following NSRunLoop pass. |
| + [[NSRunLoop currentRunLoop] |
| + runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0]]; |
| + DCHECK(NSEqualRects(ns_frame, gfx::ScreenRectToNSRect( |
| + native_widget_mac()->WindowServerFrame()))); |
| + |
| + return window_move_loop_->Run(); |
| + |
| + // |this| may be destroyed during the RunLoop, causing it to exit early. |
| + // Even if that doesn't happen, CocoaWindowMoveLoop will clean itself up by |
| + // calling EndMoveLoop(). So window_move_loop_ will always be null before the |
| + // function returns. But don't DCHECK since |this| might not be valid. |
| +} |
| + |
| +void BridgedNativeWidget::EndMoveLoop() { |
| + DCHECK(window_move_loop_); |
| + window_move_loop_->End(); |
| + window_move_loop_.reset(); |
| +} |
| + |
| +bool BridgedNativeWidget::IsRunMoveLoopActive() const { |
| + return window_move_loop_.get(); |
| +} |
| + |
| void BridgedNativeWidget::SetNativeWindowProperty(const char* name, |
| void* value) { |
| NSString* key = [NSString stringWithUTF8String:name]; |
| @@ -636,6 +718,7 @@ void BridgedNativeWidget::SetCursor(NSCursor* cursor) { |
| } |
| void BridgedNativeWidget::OnWindowWillClose() { |
| + DCHECK(!drag_run_loop_); |
| if (parent_) { |
| parent_->RemoveChildWindow(this); |
| parent_ = nullptr; |
| @@ -738,6 +821,10 @@ void BridgedNativeWidget::OnSizeChanged() { |
| [bridged_view_ updateWindowMask]; |
| } |
| +void BridgedNativeWidget::OnPositionChanged() { |
| + native_widget_mac_->GetWidget()->OnNativeWidgetMove(); |
| +} |
| + |
| void BridgedNativeWidget::OnVisibilityChanged() { |
| OnVisibilityChangedTo([window_ isVisible]); |
| } |
| @@ -1314,4 +1401,9 @@ void BridgedNativeWidget::SetDraggable(bool draggable) { |
| [window_ setMovableByWindowBackground:YES]; |
| } |
| +// static |
| +void BridgedNativeWidget::IgnoreNextMouseDownForDraggableRegions() { |
| + g_ignore_next_mouse_down_for_draggable_regions = true; |
| +} |
| + |
| } // namespace views |