| 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 ce3731d026165eb42ef39e0b00bafe6953e2fcf9..5dded116ff5474a67c59f354da9a31290e809bf1 100644
|
| --- a/ui/views/cocoa/bridged_native_widget.mm
|
| +++ b/ui/views/cocoa/bridged_native_widget.mm
|
| @@ -169,16 +169,20 @@ bool IsPointInResizeArea(NSPoint point, NSWindow* window) {
|
| return false;
|
| }
|
|
|
| +// Routes the |ns_event| to the corresponding BridgedNativeWidget and queries
|
| +// whether the event should be reposted.
|
| BOOL WindowWantsMouseDownReposted(NSEvent* ns_event) {
|
| - id delegate = [[ns_event window] delegate];
|
| - return
|
| - [delegate
|
| - respondsToSelector:@selector(shouldRepostPendingLeftMouseDown:)] &&
|
| - [delegate shouldRepostPendingLeftMouseDown:[ns_event locationInWindow]];
|
| + DCHECK(views::BridgedNativeWidget::ShouldUseDragEventMonitor());
|
| +
|
| + views::BridgedNativeWidget* bridge =
|
| + views::NativeWidgetMac::GetBridgeForNativeWindow([ns_event window]);
|
| + return bridge && bridge->ShouldRepostPendingLeftMouseDown(ns_event);
|
| }
|
|
|
| // Check if a mouse-down event should drag the window. If so, repost the event.
|
| NSEvent* RepostEventIfHandledByWindow(NSEvent* ns_event) {
|
| + DCHECK(views::BridgedNativeWidget::ShouldUseDragEventMonitor());
|
| +
|
| enum RepostState {
|
| // Nothing reposted: hit-test new mouse-downs to see if they need to be
|
| // ignored and reposted after changing draggability.
|
| @@ -253,9 +257,12 @@ BOOL WindowWantsMouseDownReposted(NSEvent* ns_event) {
|
| // To bridge the two models, we monitor mouse-downs with
|
| // +[NSEvent addLocalMonitorForEventsMatchingMask:handler:]. This receives
|
| // events after window dragging is handled, so for mouse-downs that land on a
|
| -// draggable point, we cancel the event and repost it at the CGSessionEventTap
|
| -// level so that window dragging will be handled again.
|
| +// draggable point, we cancel the event, make the window draggable and repost it
|
| +// at the CGSessionEventTap level so that window dragging will be handled again.
|
| +// On Mac OS > 10.10, we don't use an event monitor. Instead, we use [NSWindow
|
| +// performWindowDragWithEvent:]. See [NativeWidgetMacNSWindow sendEvent:].
|
| void SetupDragEventMonitor() {
|
| + DCHECK(views::BridgedNativeWidget::ShouldUseDragEventMonitor());
|
| static id monitor = nil;
|
| if (monitor)
|
| return;
|
| @@ -338,6 +345,14 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
|
| return gfx::Size(NSWidth(frame_rect), NSHeight(frame_rect));
|
| }
|
|
|
| +// static
|
| +// TODO(karandeepb): Remove usage of drag event monitor once we stop supporting
|
| +// Mac OS 10.10.
|
| +bool BridgedNativeWidget::ShouldUseDragEventMonitor() {
|
| + return ![NSWindow
|
| + instancesRespondToSelector:@selector(performWindowDragWithEvent:)];
|
| +}
|
| +
|
| BridgedNativeWidget::BridgedNativeWidget(NativeWidgetMac* parent)
|
| : native_widget_mac_(parent),
|
| focus_manager_(nullptr),
|
| @@ -347,7 +362,9 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
|
| in_fullscreen_transition_(false),
|
| window_visible_(false),
|
| wants_to_be_visible_(false) {
|
| - SetupDragEventMonitor();
|
| + if (BridgedNativeWidget::ShouldUseDragEventMonitor())
|
| + SetupDragEventMonitor();
|
| +
|
| DCHECK(parent);
|
| window_delegate_.reset(
|
| [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]);
|
| @@ -561,11 +578,14 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
|
| // appear with a "flash" if they are made visible before the frame from the
|
| // compositor arrives. To get around this, set the alpha value of the window
|
| // to 0, till we receive the correct frame from the compositor. Also, ignore
|
| - // mouse clicks till then.
|
| + // mouse clicks till then. Also check for an active task runner on the
|
| + // WindowResizeHelperMac instance to ensure visibility is only suppressed when
|
| + // there is an active GPU process.
|
| // TODO(karandeepb): Investigate whether similar technique is needed for other
|
| // dialog types.
|
| if (layer() && [window_ isOpaque] && !window_visible_ &&
|
| - !native_widget_mac_->GetWidget()->IsModal()) {
|
| + !native_widget_mac_->GetWidget()->IsModal() &&
|
| + ui::WindowResizeHelperMac::Get()->task_runner()) {
|
| initial_visibility_suppressed_ = true;
|
| [window_ setAlphaValue:0.0];
|
| [window_ setIgnoresMouseEvents:YES];
|
| @@ -876,26 +896,20 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
|
| }
|
| }
|
|
|
| -bool BridgedNativeWidget::ShouldRepostPendingLeftMouseDown(
|
| - NSPoint location_in_window) {
|
| - if (!bridged_view_)
|
| +bool BridgedNativeWidget::ShouldDragWindow(NSEvent* event) {
|
| + if (!bridged_view_ || [event type] != NSLeftMouseDown)
|
| return false;
|
|
|
| - if ([bridged_view_ mouseDownCanMoveWindow]) {
|
| - // This is a re-post, the movement has already started, so we can make the
|
| - // window non-draggable again.
|
| - SetDraggable(false);
|
| - return false;
|
| - }
|
| -
|
| + NSPoint location_in_window = [event locationInWindow];
|
| if (IsPointInResizeArea(location_in_window, window_))
|
| return false;
|
|
|
| gfx::Point point(location_in_window.x,
|
| NSHeight([window_ frame]) - location_in_window.y);
|
| - bool should_move_window =
|
| - native_widget_mac()->GetWidget()->GetNonClientComponent(point) ==
|
| - HTCAPTION;
|
| +
|
| + if (native_widget_mac()->GetWidget()->GetNonClientComponent(point) !=
|
| + HTCAPTION)
|
| + return false;
|
|
|
| // Check that the point is not obscured by non-content NSViews.
|
| for (NSView* subview : [[bridged_view_ superview] subviews]) {
|
| @@ -903,13 +917,28 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
|
| continue;
|
|
|
| if (![subview mouseDownCanMoveWindow] &&
|
| - NSPointInRect(location_in_window, [subview frame])) {
|
| - should_move_window = false;
|
| - break;
|
| - }
|
| + NSPointInRect(location_in_window, [subview frame]))
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +bool BridgedNativeWidget::ShouldRepostPendingLeftMouseDown(NSEvent* event) {
|
| + DCHECK(BridgedNativeWidget::ShouldUseDragEventMonitor());
|
| + DCHECK_EQ(NSLeftMouseDown, [event type]);
|
| +
|
| + if (!bridged_view_)
|
| + return false;
|
| +
|
| + if ([bridged_view_ mouseDownCanMoveWindow]) {
|
| + // This is a re-post, the movement has already started, so we can make the
|
| + // window non-draggable again.
|
| + SetDraggable(false);
|
| + return false;
|
| }
|
|
|
| - if (!should_move_window)
|
| + if (!ShouldDragWindow(event))
|
| return false;
|
|
|
| // Make the window draggable, then return true to repost the event.
|
| @@ -1375,6 +1404,8 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
|
| }
|
|
|
| void BridgedNativeWidget::SetDraggable(bool draggable) {
|
| + DCHECK(BridgedNativeWidget::ShouldUseDragEventMonitor());
|
| +
|
| [bridged_view_ setMouseDownCanMoveWindow:draggable];
|
| // AppKit will not update its cache of mouseDownCanMoveWindow unless something
|
| // changes. Previously we tried adding an NSView and removing it, but for some
|
|
|