Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: ui/views/cocoa/bridged_native_widget.mm

Issue 2448173002: Fix processing of mouse events on MacViews.
Patch Set: Fix review issues. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/views/cocoa/bridged_native_widget.h ('k') | ui/views/test/event_generator_delegate_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import "ui/views/cocoa/bridged_native_widget.h" 5 #import "ui/views/cocoa/bridged_native_widget.h"
6 6
7 #import <objc/runtime.h> 7 #import <objc/runtime.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <stdint.h> 9 #include <stdint.h>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #import "base/mac/foundation_util.h" 12 #import "base/mac/foundation_util.h"
13 #include "base/mac/mac_util.h" 13 #include "base/mac/mac_util.h"
14 #import "base/mac/sdk_forward_declarations.h" 14 #import "base/mac/sdk_forward_declarations.h"
15 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
16 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h" 16 #include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
17 #include "ui/base/cocoa/cocoa_base_utils.h"
17 #import "ui/base/cocoa/constrained_window/constrained_window_animation.h" 18 #import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
18 #include "ui/base/hit_test.h" 19 #include "ui/base/hit_test.h"
19 #include "ui/base/ime/input_method.h" 20 #include "ui/base/ime/input_method.h"
20 #include "ui/base/ime/input_method_factory.h" 21 #include "ui/base/ime/input_method_factory.h"
21 #include "ui/display/display.h" 22 #include "ui/display/display.h"
22 #include "ui/display/screen.h" 23 #include "ui/display/screen.h"
24 #include "ui/events/event_utils.h"
23 #include "ui/gfx/geometry/dip_util.h" 25 #include "ui/gfx/geometry/dip_util.h"
24 #import "ui/gfx/mac/coordinate_conversion.h" 26 #import "ui/gfx/mac/coordinate_conversion.h"
25 #import "ui/gfx/mac/nswindow_frame_controls.h" 27 #import "ui/gfx/mac/nswindow_frame_controls.h"
26 #import "ui/native_theme/native_theme_mac.h" 28 #import "ui/native_theme/native_theme_mac.h"
27 #import "ui/views/cocoa/bridged_content_view.h" 29 #import "ui/views/cocoa/bridged_content_view.h"
28 #import "ui/views/cocoa/drag_drop_client_mac.h"
29 #import "ui/views/cocoa/cocoa_mouse_capture.h" 30 #import "ui/views/cocoa/cocoa_mouse_capture.h"
30 #import "ui/views/cocoa/cocoa_window_move_loop.h" 31 #import "ui/views/cocoa/cocoa_window_move_loop.h"
32 #import "ui/views/cocoa/drag_drop_client_mac.h"
31 #include "ui/views/cocoa/tooltip_manager_mac.h" 33 #include "ui/views/cocoa/tooltip_manager_mac.h"
32 #import "ui/views/cocoa/views_nswindow_delegate.h" 34 #import "ui/views/cocoa/views_nswindow_delegate.h"
33 #import "ui/views/cocoa/widget_owner_nswindow_adapter.h" 35 #import "ui/views/cocoa/widget_owner_nswindow_adapter.h"
34 #include "ui/views/view.h" 36 #include "ui/views/view.h"
35 #include "ui/views/views_delegate.h" 37 #include "ui/views/views_delegate.h"
36 #include "ui/views/widget/native_widget_mac.h" 38 #include "ui/views/widget/native_widget_mac.h"
37 #include "ui/views/widget/widget.h" 39 #include "ui/views/widget/widget.h"
38 #include "ui/views/widget/widget_aura_utils.h" 40 #include "ui/views/widget/widget_aura_utils.h"
39 #include "ui/views/widget/widget_delegate.h" 41 #include "ui/views/widget/widget_delegate.h"
40 42
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 // |child_windows| array ignoring the windows added by AppKit. 318 // |child_windows| array ignoring the windows added by AppKit.
317 NSUInteger CountBridgedWindows(NSArray* child_windows) { 319 NSUInteger CountBridgedWindows(NSArray* child_windows) {
318 NSUInteger count = 0; 320 NSUInteger count = 0;
319 for (NSWindow* child in child_windows) 321 for (NSWindow* child in child_windows)
320 if ([[child delegate] isKindOfClass:[ViewsNSWindowDelegate class]]) 322 if ([[child delegate] isKindOfClass:[ViewsNSWindowDelegate class]])
321 ++count; 323 ++count;
322 324
323 return count; 325 return count;
324 } 326 }
325 327
328 // Convert an |event|'s mouse point to |target_view|'s content rect, with the
329 // origin at the top left of the content area.
330 // If -[|event| window] is nil, original point will be treated as screen
331 // coordinates.
332 gfx::Point GetEventLocationInView(NSEvent* event, NSView* target_view) {
333 NSWindow* source = [event window];
334 NSWindow* target = [target_view window];
335 DCHECK(target);
336 NSPoint point_in_window = [event locationInWindow];
337 if (![target isEqual:source]) {
338 NSPoint point_in_screen =
339 source ? ui::ConvertPointFromWindowToScreen(source, point_in_window)
340 : point_in_window;
341 point_in_window =
342 ui::ConvertPointFromScreenToWindow(target, point_in_screen);
343 }
344 NSPoint point_in_view =
345 [target_view convertPoint:point_in_window fromView:nil];
346 return gfx::Point(point_in_view.x,
347 NSHeight([target_view frame]) - point_in_view.y);
348 }
349
326 } // namespace 350 } // namespace
327 351
328 namespace views { 352 namespace views {
329 353
330 // static 354 // static
331 gfx::Size BridgedNativeWidget::GetWindowSizeForClientSize( 355 gfx::Size BridgedNativeWidget::GetWindowSizeForClientSize(
332 NSWindow* window, 356 NSWindow* window,
333 const gfx::Size& content_size) { 357 const gfx::Size& content_size) {
334 NSRect content_rect = 358 NSRect content_rect =
335 NSMakeRect(0, 0, content_size.width(), content_size.height()); 359 NSMakeRect(0, 0, content_size.width(), content_size.height());
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after
1054 if (!focus_manager_->OnKeyEvent(*key)) 1078 if (!focus_manager_->OnKeyEvent(*key))
1055 key->StopPropagation(); 1079 key->StopPropagation();
1056 } 1080 }
1057 return ui::EventDispatchDetails(); 1081 return ui::EventDispatchDetails();
1058 } 1082 }
1059 1083
1060 //////////////////////////////////////////////////////////////////////////////// 1084 ////////////////////////////////////////////////////////////////////////////////
1061 // BridgedNativeWidget, CocoaMouseCaptureDelegate: 1085 // BridgedNativeWidget, CocoaMouseCaptureDelegate:
1062 1086
1063 void BridgedNativeWidget::PostCapturedEvent(NSEvent* event) { 1087 void BridgedNativeWidget::PostCapturedEvent(NSEvent* event) {
1064 [bridged_view_ processCapturedMouseEvent:event]; 1088 OnMouseEvent(event);
1065 } 1089 }
1066 1090
1067 void BridgedNativeWidget::OnMouseCaptureLost() { 1091 void BridgedNativeWidget::OnMouseCaptureLost() {
1068 native_widget_mac_->GetWidget()->OnMouseCaptureLost(); 1092 native_widget_mac_->GetWidget()->OnMouseCaptureLost();
1093 SendStoredMouseExitedEventToWidget();
1069 } 1094 }
1070 1095
1071 NSWindow* BridgedNativeWidget::GetWindow() const { 1096 NSWindow* BridgedNativeWidget::GetWindow() const {
1072 return window_; 1097 return window_;
1073 } 1098 }
1074 1099
1100 void BridgedNativeWidget::OnMouseEvent(NSEvent* native_event) {
1101 pendingExitEvent_.reset();
1102
1103 const gfx::Point location =
1104 GetEventLocationInView(native_event, bridged_view_);
1105 views::Widget* widget = native_widget_mac_->GetWidget();
1106
1107 bool event_inside_widget = false;
1108 if (widget->HasHitTestMask()) {
1109 gfx::Path hit_test_mask;
1110 widget->GetHitTestMask(&hit_test_mask);
1111 event_inside_widget = hit_test_mask.contains(location.x(), location.y());
1112 } else {
1113 event_inside_widget =
1114 gfx::Rect(widget->GetWindowBoundsInScreen().size()).Contains(location);
1115 }
1116 const bool should_send_entered_event =
1117 !mouse_inside_ && (event_inside_widget || HasCapture());
1118 if (should_send_entered_event) {
1119 ui::MouseEvent entered_event(ui::ET_MOUSE_ENTERED, location, location,
1120 ui::EventTimeFromNative(native_event),
1121 ui::EF_NONE, ui::EF_NONE);
1122 widget->OnMouseEvent(&entered_event);
1123 mouse_inside_ = true;
1124 }
1125
1126 if (!mouse_inside_) {
1127 return [bridged_view_ passMouseEventToSuperview:native_event];
1128 }
1129
1130 if ([native_event type] == NSScrollWheel) {
1131 ui::ScrollEvent event(native_event);
1132 event.set_location(location);
1133 widget->OnScrollEvent(&event);
1134 } else if ([native_event type] != NSMouseEntered &&
1135 [native_event type] != NSMouseExited) {
1136 ui::MouseEvent event(native_event);
1137 event.set_location(location);
1138 widget->OnMouseEvent(&event);
1139 }
1140 // We could get an NSMouseExited with its location within the bounds of the
1141 // view.
1142 const bool should_send_exited_event =
1143 !HasCapture() &&
1144 (!event_inside_widget || [native_event type] == NSMouseExited);
1145 // If we don't need to send the ET_MOUSE_EXITED event immediately, postpone it
1146 // until later.
1147 const bool should_create_exited_event =
1148 should_send_exited_event || !event_inside_widget;
1149
1150 if (should_create_exited_event) {
1151 // The tracking area will send an exit event even during a drag, which isn't
1152 // how the event flow for drags should work. This stores the exit event, and
1153 // sends it when the drag completes instead.
1154 pendingExitEvent_.reset(new ui::MouseEvent(
1155 ui::ET_MOUSE_EXITED, location, location,
1156 ui::EventTimeFromNative(native_event), ui::EF_NONE, ui::EF_NONE));
1157 }
1158
1159 if (should_send_exited_event) {
1160 SendStoredMouseExitedEventToWidget();
1161 } else {
1162 [bridged_view_ updateTooltipIfRequiredAt:location];
1163 }
1164 }
1165
1166 void BridgedNativeWidget::SendStoredMouseExitedEventToWidget() {
1167 if (pendingExitEvent_) {
1168 mouse_inside_ = false;
1169 auto exited_event = std::move(pendingExitEvent_);
1170 native_widget_mac_->GetWidget()->OnMouseEvent(exited_event.get());
1171 [bridged_view_ hideTooltipIfRequired];
1172 }
1173 }
1174
1075 //////////////////////////////////////////////////////////////////////////////// 1175 ////////////////////////////////////////////////////////////////////////////////
1076 // BridgedNativeWidget, FocusChangeListener: 1176 // BridgedNativeWidget, FocusChangeListener:
1077 1177
1078 void BridgedNativeWidget::OnWillChangeFocus(View* focused_before, 1178 void BridgedNativeWidget::OnWillChangeFocus(View* focused_before,
1079 View* focused_now) { 1179 View* focused_now) {
1080 } 1180 }
1081 1181
1082 void BridgedNativeWidget::OnDidChangeFocus(View* focused_before, 1182 void BridgedNativeWidget::OnDidChangeFocus(View* focused_before,
1083 View* focused_now) { 1183 View* focused_now) {
1084 ui::InputMethod* input_method = 1184 ui::InputMethod* input_method =
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 [bridged_view_ setMouseDownCanMoveWindow:draggable]; 1502 [bridged_view_ setMouseDownCanMoveWindow:draggable];
1403 // AppKit will not update its cache of mouseDownCanMoveWindow unless something 1503 // AppKit will not update its cache of mouseDownCanMoveWindow unless something
1404 // changes. Previously we tried adding an NSView and removing it, but for some 1504 // changes. Previously we tried adding an NSView and removing it, but for some
1405 // reason it required reposting the mouse-down event, and didn't always work. 1505 // reason it required reposting the mouse-down event, and didn't always work.
1406 // Calling the below seems to be an effective solution. 1506 // Calling the below seems to be an effective solution.
1407 [window_ setMovableByWindowBackground:NO]; 1507 [window_ setMovableByWindowBackground:NO];
1408 [window_ setMovableByWindowBackground:YES]; 1508 [window_ setMovableByWindowBackground:YES];
1409 } 1509 }
1410 1510
1411 } // namespace views 1511 } // namespace views
OLDNEW
« no previous file with comments | « ui/views/cocoa/bridged_native_widget.h ('k') | ui/views/test/event_generator_delegate_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698