| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |