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 6f5dec0f96864ede56c8a7cf940de5ebf964aa92..2ef4548ff7bbbf904b18d574a90d448a28c395ca 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. |
@@ -94,6 +84,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); |
@@ -191,6 +183,11 @@ NSEvent* RepostEventIfHandledByWindow(NSEvent* ns_event) { |
// - any repost loop. |
if (repost_state == NONE) { |
+ if (g_ignore_next_mouse_down_for_draggable_regions) { |
+ 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; |
@@ -265,6 +262,16 @@ scoped_refptr<base::SingleThreadTaskRunner> GetCompositorTaskRunner() { |
} // namespace |
+extern "C" { |
+ |
+typedef int32_t CGSConnection; |
+CGSConnection _CGSDefaultConnection(); |
+CGError CGSSetWindowBackgroundBlurRadius(CGSConnection connection, |
+ NSInteger windowNumber, |
+ int radius); |
+ |
+} |
+ |
namespace views { |
// static |
@@ -569,6 +576,53 @@ 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. |
+ NSPoint mouse_in_screen = gfx::ScreenPointToNSPoint( |
+ gfx::Screen::GetScreen()->GetCursorScreenPoint()); |
+ NSRect frame = [window_ frame]; |
+ frame.origin.x = mouse_in_screen.x - drag_offset.x(); |
+ frame.origin.y = mouse_in_screen.y - NSHeight(frame) + drag_offset.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)); |
+ |
+ // Animating may provide a less janky UX, but something custom would be |
+ // required so that it follows updates to the mouse position. |
+ [window_ setFrame: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; |
+ |
+ 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(); |
tapted
2016/03/11 09:38:28
is the .get() needed?
themblsha
2016/04/05 17:20:42
Yes. error: no viable conversion from returned val
|
+} |
+ |
void BridgedNativeWidget::SetNativeWindowProperty(const char* name, |
void* value) { |
NSString* key = [NSString stringWithUTF8String:name]; |
@@ -590,6 +644,7 @@ void BridgedNativeWidget::SetCursor(NSCursor* cursor) { |
} |
void BridgedNativeWidget::OnWindowWillClose() { |
+ DCHECK(!drag_run_loop_); |
if (parent_) { |
parent_->RemoveChildWindow(this); |
parent_ = nullptr; |
@@ -692,6 +747,10 @@ void BridgedNativeWidget::OnSizeChanged() { |
[bridged_view_ updateWindowMask]; |
} |
+void BridgedNativeWidget::OnPositionChanged() { |
+ native_widget_mac_->GetWidget()->OnNativeWidgetMove(); |
+} |
+ |
void BridgedNativeWidget::OnVisibilityChanged() { |
OnVisibilityChangedTo([window_ isVisible]); |
} |
@@ -1244,4 +1303,9 @@ void BridgedNativeWidget::SetDraggable(bool draggable) { |
[window_ setMovableByWindowBackground:YES]; |
} |
+// static |
+void BridgedNativeWidget::IgnoreNextMouseDownForDraggableRegions() { |
+ g_ignore_next_mouse_down_for_draggable_regions = true; |
+} |
+ |
} // namespace views |