| 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 8e47513350dc150013b5a19023ea9e969f42d8e1..5e1c24a31ce817e9516ae8f5118a2807b97e948f 100644
|
| --- a/ui/views/cocoa/bridged_native_widget.mm
|
| +++ b/ui/views/cocoa/bridged_native_widget.mm
|
| @@ -14,20 +14,22 @@
|
| #import "base/mac/sdk_forward_declarations.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
|
| +#include "ui/base/cocoa/cocoa_base_utils.h"
|
| #import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
|
| #include "ui/base/hit_test.h"
|
| #include "ui/base/ime/input_method.h"
|
| #include "ui/base/ime/input_method_factory.h"
|
| #include "ui/display/display.h"
|
| #include "ui/display/screen.h"
|
| +#include "ui/events/event_utils.h"
|
| #include "ui/gfx/geometry/dip_util.h"
|
| #import "ui/gfx/mac/coordinate_conversion.h"
|
| #import "ui/gfx/mac/nswindow_frame_controls.h"
|
| #import "ui/native_theme/native_theme_mac.h"
|
| #import "ui/views/cocoa/bridged_content_view.h"
|
| -#import "ui/views/cocoa/drag_drop_client_mac.h"
|
| #import "ui/views/cocoa/cocoa_mouse_capture.h"
|
| #import "ui/views/cocoa/cocoa_window_move_loop.h"
|
| +#import "ui/views/cocoa/drag_drop_client_mac.h"
|
| #include "ui/views/cocoa/tooltip_manager_mac.h"
|
| #import "ui/views/cocoa/views_nswindow_delegate.h"
|
| #import "ui/views/cocoa/widget_owner_nswindow_adapter.h"
|
| @@ -323,6 +325,28 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
|
| return count;
|
| }
|
|
|
| +// Convert an |event|'s mouse point to |target_view|'s content rect, with the
|
| +// origin at the top left of the content area.
|
| +// If -[|event| window] is nil, original point will be treated as screen
|
| +// coordinates.
|
| +gfx::Point GetEventLocationInView(NSEvent* event, NSView* target_view) {
|
| + NSWindow* source = [event window];
|
| + NSWindow* target = [target_view window];
|
| + DCHECK(target);
|
| + NSPoint point_in_window = [event locationInWindow];
|
| + if (![target isEqual:source]) {
|
| + NSPoint point_in_screen =
|
| + source ? ui::ConvertPointFromWindowToScreen(source, point_in_window)
|
| + : point_in_window;
|
| + point_in_window =
|
| + ui::ConvertPointFromScreenToWindow(target, point_in_screen);
|
| + }
|
| + NSPoint point_in_view =
|
| + [target_view convertPoint:point_in_window fromView:nil];
|
| + return gfx::Point(point_in_view.x,
|
| + NSHeight([target_view frame]) - point_in_view.y);
|
| +}
|
| +
|
| } // namespace
|
|
|
| namespace views {
|
| @@ -1061,17 +1085,93 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
|
| // BridgedNativeWidget, CocoaMouseCaptureDelegate:
|
|
|
| void BridgedNativeWidget::PostCapturedEvent(NSEvent* event) {
|
| - [bridged_view_ processCapturedMouseEvent:event];
|
| + OnMouseEvent(event);
|
| }
|
|
|
| void BridgedNativeWidget::OnMouseCaptureLost() {
|
| native_widget_mac_->GetWidget()->OnMouseCaptureLost();
|
| + SendStoredMouseExitedEventToWidget();
|
| }
|
|
|
| NSWindow* BridgedNativeWidget::GetWindow() const {
|
| return window_;
|
| }
|
|
|
| +void BridgedNativeWidget::OnMouseEvent(NSEvent* native_event) {
|
| + pendingExitEvent_.reset();
|
| +
|
| + const gfx::Point location =
|
| + GetEventLocationInView(native_event, bridged_view_);
|
| + views::Widget* widget = native_widget_mac_->GetWidget();
|
| +
|
| + bool event_inside_widget = false;
|
| + if (widget->HasHitTestMask()) {
|
| + gfx::Path hit_test_mask;
|
| + widget->GetHitTestMask(&hit_test_mask);
|
| + event_inside_widget = hit_test_mask.contains(location.x(), location.y());
|
| + } else {
|
| + event_inside_widget =
|
| + gfx::Rect(widget->GetWindowBoundsInScreen().size()).Contains(location);
|
| + }
|
| + const bool should_send_entered_event =
|
| + !mouse_inside_ && (event_inside_widget || HasCapture());
|
| + if (should_send_entered_event) {
|
| + ui::MouseEvent entered_event(ui::ET_MOUSE_ENTERED, location, location,
|
| + ui::EventTimeFromNative(native_event),
|
| + ui::EF_NONE, ui::EF_NONE);
|
| + widget->OnMouseEvent(&entered_event);
|
| + mouse_inside_ = true;
|
| + }
|
| +
|
| + if (!mouse_inside_) {
|
| + return [bridged_view_ passMouseEventToSuperview:native_event];
|
| + }
|
| +
|
| + if ([native_event type] == NSScrollWheel) {
|
| + ui::ScrollEvent event(native_event);
|
| + event.set_location(location);
|
| + widget->OnScrollEvent(&event);
|
| + } else if ([native_event type] != NSMouseEntered &&
|
| + [native_event type] != NSMouseExited) {
|
| + ui::MouseEvent event(native_event);
|
| + event.set_location(location);
|
| + widget->OnMouseEvent(&event);
|
| + }
|
| + // We could get an NSMouseExited with its location within the bounds of the
|
| + // view.
|
| + const bool should_send_exited_event =
|
| + !HasCapture() &&
|
| + (!event_inside_widget || [native_event type] == NSMouseExited);
|
| + // If we don't need to send the ET_MOUSE_EXITED event immediately, postpone it
|
| + // until later.
|
| + const bool should_create_exited_event =
|
| + should_send_exited_event || !event_inside_widget;
|
| +
|
| + if (should_create_exited_event) {
|
| + // The tracking area will send an exit event even during a drag, which isn't
|
| + // how the event flow for drags should work. This stores the exit event, and
|
| + // sends it when the drag completes instead.
|
| + pendingExitEvent_.reset(new ui::MouseEvent(
|
| + ui::ET_MOUSE_EXITED, location, location,
|
| + ui::EventTimeFromNative(native_event), ui::EF_NONE, ui::EF_NONE));
|
| + }
|
| +
|
| + if (should_send_exited_event) {
|
| + SendStoredMouseExitedEventToWidget();
|
| + } else {
|
| + [bridged_view_ updateTooltipIfRequiredAt:location];
|
| + }
|
| +}
|
| +
|
| +void BridgedNativeWidget::SendStoredMouseExitedEventToWidget() {
|
| + if (pendingExitEvent_) {
|
| + mouse_inside_ = false;
|
| + auto exited_event = std::move(pendingExitEvent_);
|
| + native_widget_mac_->GetWidget()->OnMouseEvent(exited_event.get());
|
| + [bridged_view_ hideTooltipIfRequired];
|
| + }
|
| +}
|
| +
|
| ////////////////////////////////////////////////////////////////////////////////
|
| // BridgedNativeWidget, FocusChangeListener:
|
|
|
|
|