OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" |
| 6 |
5 #include <QuartzCore/QuartzCore.h> | 7 #include <QuartzCore/QuartzCore.h> |
6 | 8 |
7 #include "chrome/browser/renderer_host/render_widget_host_view_mac.h" | 9 #include <cmath> |
8 | 10 |
9 #include "base/debug/trace_event.h" | 11 #include "base/debug/trace_event.h" |
10 #include "base/logging.h" | 12 #include "base/logging.h" |
11 #include "base/mac/mac_util.h" | 13 #include "base/mac/mac_util.h" |
12 #include "base/mac/scoped_cftyperef.h" | 14 #include "base/mac/scoped_cftyperef.h" |
13 #import "base/mac/scoped_nsautorelease_pool.h" | 15 #import "base/mac/scoped_nsautorelease_pool.h" |
14 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
15 #import "base/memory/scoped_nsobject.h" | 17 #import "base/memory/scoped_nsobject.h" |
16 #include "base/string_util.h" | 18 #include "base/string_util.h" |
17 #include "base/sys_info.h" | 19 #include "base/sys_info.h" |
18 #include "base/sys_string_conversions.h" | 20 #include "base/sys_string_conversions.h" |
19 #include "chrome/browser/browser_trial.h" | 21 #include "chrome/browser/browser_trial.h" |
| 22 #include "chrome/browser/mac/closure_blocks_leopard_compat.h" |
20 #import "chrome/browser/renderer_host/accelerated_plugin_view_mac.h" | 23 #import "chrome/browser/renderer_host/accelerated_plugin_view_mac.h" |
21 #import "chrome/browser/renderer_host/text_input_client_mac.h" | 24 #import "chrome/browser/renderer_host/text_input_client_mac.h" |
22 #include "chrome/browser/spellchecker/spellchecker_platform_engine.h" | 25 #include "chrome/browser/spellchecker/spellchecker_platform_engine.h" |
| 26 #include "chrome/browser/ui/browser.h" |
| 27 #include "chrome/browser/ui/browser_list.h" |
23 #import "chrome/browser/ui/cocoa/rwhvm_editcommand_helper.h" | 28 #import "chrome/browser/ui/cocoa/rwhvm_editcommand_helper.h" |
24 #import "chrome/browser/ui/cocoa/view_id_util.h" | 29 #import "chrome/browser/ui/cocoa/view_id_util.h" |
25 #include "chrome/common/render_messages.h" | 30 #include "chrome/common/render_messages.h" |
26 #include "chrome/common/spellcheck_messages.h" | 31 #include "chrome/common/spellcheck_messages.h" |
27 #import "content/browser/accessibility/browser_accessibility_cocoa.h" | 32 #import "content/browser/accessibility/browser_accessibility_cocoa.h" |
28 #include "content/browser/browser_thread.h" | 33 #include "content/browser/browser_thread.h" |
29 #include "content/browser/gpu/gpu_process_host.h" | 34 #include "content/browser/gpu/gpu_process_host.h" |
30 #include "content/browser/gpu/gpu_process_host_ui_shim.h" | 35 #include "content/browser/gpu/gpu_process_host_ui_shim.h" |
31 #include "content/browser/plugin_process_host.h" | 36 #include "content/browser/plugin_process_host.h" |
32 #include "content/browser/renderer_host/backing_store_mac.h" | 37 #include "content/browser/renderer_host/backing_store_mac.h" |
(...skipping 16 matching lines...) Expand all Loading... |
49 #include "ui/gfx/surface/io_surface_support_mac.h" | 54 #include "ui/gfx/surface/io_surface_support_mac.h" |
50 #include "webkit/glue/webaccessibility.h" | 55 #include "webkit/glue/webaccessibility.h" |
51 #include "webkit/plugins/npapi/webplugin.h" | 56 #include "webkit/plugins/npapi/webplugin.h" |
52 | 57 |
53 using WebKit::WebInputEvent; | 58 using WebKit::WebInputEvent; |
54 using WebKit::WebInputEventFactory; | 59 using WebKit::WebInputEventFactory; |
55 using WebKit::WebMouseEvent; | 60 using WebKit::WebMouseEvent; |
56 using WebKit::WebMouseWheelEvent; | 61 using WebKit::WebMouseWheelEvent; |
57 using WebKit::WebGestureEvent; | 62 using WebKit::WebGestureEvent; |
58 | 63 |
| 64 // Declare symbols that are part of the 10.7 SDK. |
| 65 #if !defined(MAC_OS_X_VERSION_10_7) || \ |
| 66 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 |
| 67 enum { |
| 68 NSEventPhaseNone = 0, // event not associated with a phase. |
| 69 NSEventPhaseBegan = 0x1 << 0, |
| 70 NSEventPhaseStationary = 0x1 << 1, |
| 71 NSEventPhaseChanged = 0x1 << 2, |
| 72 NSEventPhaseEnded = 0x1 << 3, |
| 73 NSEventPhaseCancelled = 0x1 << 4, |
| 74 }; |
| 75 typedef NSUInteger NSEventPhase; |
| 76 |
| 77 enum { |
| 78 NSEventSwipeTrackingLockDirection = 0x1 << 0, |
| 79 NSEventSwipeTrackingClampGestureAmount = 0x1 << 1 |
| 80 }; |
| 81 typedef NSUInteger NSEventSwipeTrackingOptions; |
| 82 |
| 83 @interface NSEvent (LionAPI) |
| 84 + (BOOL)isSwipeTrackingFromScrollEventsEnabled; |
| 85 |
| 86 - (NSEventPhase)phase; |
| 87 - (CGFloat)scrollingDeltaX; |
| 88 - (CGFloat)scrollingDeltaY; |
| 89 - (void)trackSwipeEventWithOptions:(NSEventSwipeTrackingOptions)options |
| 90 dampenAmountThresholdMin:(CGFloat)minDampenThreshold |
| 91 max:(CGFloat)maxDampenThreshold |
| 92 usingHandler:(void (^)(CGFloat gestureAmount, |
| 93 NSEventPhase phase, |
| 94 BOOL isComplete, |
| 95 BOOL *stop))trackingHandler; |
| 96 @end |
| 97 #endif // 10.7 |
| 98 |
59 static inline int ToWebKitModifiers(NSUInteger flags) { | 99 static inline int ToWebKitModifiers(NSUInteger flags) { |
60 int modifiers = 0; | 100 int modifiers = 0; |
61 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey; | 101 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey; |
62 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey; | 102 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey; |
63 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey; | 103 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey; |
64 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; | 104 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; |
65 return modifiers; | 105 return modifiers; |
66 } | 106 } |
67 | 107 |
68 // Private methods: | 108 // Private methods: |
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1011 | 1051 |
1012 void RenderWidgetHostViewMac::ForceTextureReload() { | 1052 void RenderWidgetHostViewMac::ForceTextureReload() { |
1013 plugin_container_manager_.ForceTextureReload(); | 1053 plugin_container_manager_.ForceTextureReload(); |
1014 } | 1054 } |
1015 | 1055 |
1016 void RenderWidgetHostViewMac::SetVisuallyDeemphasized(const SkColor* color, | 1056 void RenderWidgetHostViewMac::SetVisuallyDeemphasized(const SkColor* color, |
1017 bool animate) { | 1057 bool animate) { |
1018 // This is not used on mac. | 1058 // This is not used on mac. |
1019 } | 1059 } |
1020 | 1060 |
| 1061 void RenderWidgetHostViewMac::UnhandledWheelEvent( |
| 1062 const WebKit::WebMouseWheelEvent& event) { |
| 1063 [cocoa_view_ setGotUnhandledWheelEvent:YES]; |
| 1064 } |
| 1065 |
| 1066 void RenderWidgetHostViewMac::SetHasHorizontalScrollbar( |
| 1067 bool has_horizontal_scrollbar) { |
| 1068 [cocoa_view_ setHasHorizontalScrollbar:has_horizontal_scrollbar]; |
| 1069 } |
| 1070 |
| 1071 void RenderWidgetHostViewMac::SetScrollOffsetPinning( |
| 1072 bool is_pinned_to_left, bool is_pinned_to_right) { |
| 1073 [cocoa_view_ setPinnedLeft:is_pinned_to_left]; |
| 1074 [cocoa_view_ setPinnedRight:is_pinned_to_right]; |
| 1075 } |
| 1076 |
1021 void RenderWidgetHostViewMac::ShutdownHost() { | 1077 void RenderWidgetHostViewMac::ShutdownHost() { |
1022 shutdown_factory_.RevokeAll(); | 1078 shutdown_factory_.RevokeAll(); |
1023 render_widget_host_->Shutdown(); | 1079 render_widget_host_->Shutdown(); |
1024 // Do not touch any members at this point, |this| has been deleted. | 1080 // Do not touch any members at this point, |this| has been deleted. |
1025 } | 1081 } |
1026 | 1082 |
1027 gfx::Rect RenderWidgetHostViewMac::GetViewCocoaBounds() const { | 1083 gfx::Rect RenderWidgetHostViewMac::GetViewCocoaBounds() const { |
1028 return gfx::Rect(NSRectToCGRect([cocoa_view_ bounds])); | 1084 return gfx::Rect(NSRectToCGRect([cocoa_view_ bounds])); |
1029 } | 1085 } |
1030 | 1086 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1094 DisablePasswordInput(); | 1150 DisablePasswordInput(); |
1095 } | 1151 } |
1096 } | 1152 } |
1097 | 1153 |
1098 // RenderWidgetHostViewCocoa --------------------------------------------------- | 1154 // RenderWidgetHostViewCocoa --------------------------------------------------- |
1099 | 1155 |
1100 @implementation RenderWidgetHostViewCocoa | 1156 @implementation RenderWidgetHostViewCocoa |
1101 | 1157 |
1102 @synthesize selectedRange = selectedRange_; | 1158 @synthesize selectedRange = selectedRange_; |
1103 @synthesize markedRange = markedRange_; | 1159 @synthesize markedRange = markedRange_; |
| 1160 @synthesize gotUnhandledWheelEvent = gotUnhandledWheelEvent_; |
| 1161 @synthesize isPinnedLeft = isPinnedLeft_; |
| 1162 @synthesize isPinnedRight = isPinnedRight_; |
| 1163 @synthesize hasHorizontalScrollbar = hasHorizontalScrollbar_; |
1104 | 1164 |
1105 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { | 1165 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { |
1106 self = [super initWithFrame:NSZeroRect]; | 1166 self = [super initWithFrame:NSZeroRect]; |
1107 if (self) { | 1167 if (self) { |
1108 editCommand_helper_.reset(new RWHVMEditCommandHelper); | 1168 editCommand_helper_.reset(new RWHVMEditCommandHelper); |
1109 editCommand_helper_->AddEditingSelectorsToClass([self class]); | 1169 editCommand_helper_->AddEditingSelectorsToClass([self class]); |
1110 | 1170 |
1111 renderWidgetHostView_.reset(r); | 1171 renderWidgetHostView_.reset(r); |
1112 canBeKeyView_ = YES; | 1172 canBeKeyView_ = YES; |
1113 focusedPluginIdentifier_ = -1; | 1173 focusedPluginIdentifier_ = -1; |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 renderWidgetHostView_->render_widget_host_->ForwardMouseEvent(event); | 1284 renderWidgetHostView_->render_widget_host_->ForwardMouseEvent(event); |
1225 } | 1285 } |
1226 | 1286 |
1227 - (void)beginGestureWithEvent:(NSEvent*)event { | 1287 - (void)beginGestureWithEvent:(NSEvent*)event { |
1228 if (base::mac::IsOSLionOrLater() && | 1288 if (base::mac::IsOSLionOrLater() && |
1229 [event subtype] == kIOHIDEventTypeScroll && | 1289 [event subtype] == kIOHIDEventTypeScroll && |
1230 renderWidgetHostView_->render_widget_host_) { | 1290 renderWidgetHostView_->render_widget_host_) { |
1231 WebGestureEvent webEvent = WebInputEventFactory::gestureEvent(event, self); | 1291 WebGestureEvent webEvent = WebInputEventFactory::gestureEvent(event, self); |
1232 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(webEvent); | 1292 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(webEvent); |
1233 } | 1293 } |
1234 | |
1235 // Forward the gesture event to the next responder so that the browser window | |
1236 // controller has a chance to act on back/forward gestures. | |
1237 [[self nextResponder] beginGestureWithEvent:event]; | |
1238 } | 1294 } |
1239 | 1295 |
1240 - (void)endGestureWithEvent:(NSEvent*)event { | 1296 - (void)endGestureWithEvent:(NSEvent*)event { |
1241 if (base::mac::IsOSLionOrLater() && | 1297 if (base::mac::IsOSLionOrLater() && |
1242 [event subtype] == kIOHIDEventTypeScroll && | 1298 [event subtype] == kIOHIDEventTypeScroll && |
1243 renderWidgetHostView_->render_widget_host_) { | 1299 renderWidgetHostView_->render_widget_host_) { |
1244 WebGestureEvent webEvent = WebInputEventFactory::gestureEvent(event, self); | 1300 WebGestureEvent webEvent = WebInputEventFactory::gestureEvent(event, self); |
1245 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(webEvent); | 1301 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(webEvent); |
1246 } | 1302 } |
1247 | |
1248 // Forward the gesture event to the next responder so that the browser window | |
1249 // controller has a chance to act on back/forward gestures. | |
1250 [[self nextResponder] endGestureWithEvent:event]; | |
1251 } | 1303 } |
1252 | 1304 |
1253 - (BOOL)performKeyEquivalent:(NSEvent*)theEvent { | 1305 - (BOOL)performKeyEquivalent:(NSEvent*)theEvent { |
1254 // |performKeyEquivalent:| is sent to all views of a window, not only down the | 1306 // |performKeyEquivalent:| is sent to all views of a window, not only down the |
1255 // responder chain (cf. "Handling Key Equivalents" in | 1307 // responder chain (cf. "Handling Key Equivalents" in |
1256 // http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Event
Overview/HandlingKeyEvents/HandlingKeyEvents.html | 1308 // http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Event
Overview/HandlingKeyEvents/HandlingKeyEvents.html |
1257 // ). We only want to handle key equivalents if we're first responder. | 1309 // ). We only want to handle key equivalents if we're first responder. |
1258 if ([[self window] firstResponder] != self) | 1310 if ([[self window] firstResponder] != self) |
1259 return NO; | 1311 return NO; |
1260 | 1312 |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1490 event.skip_in_browser = true; | 1542 event.skip_in_browser = true; |
1491 widgetHost->ForwardKeyboardEvent(event); | 1543 widgetHost->ForwardKeyboardEvent(event); |
1492 } | 1544 } |
1493 } | 1545 } |
1494 | 1546 |
1495 // Possibly autohide the cursor. | 1547 // Possibly autohide the cursor. |
1496 if ([RenderWidgetHostViewCocoa shouldAutohideCursorForEvent:theEvent]) | 1548 if ([RenderWidgetHostViewCocoa shouldAutohideCursorForEvent:theEvent]) |
1497 [NSCursor setHiddenUntilMouseMoves:YES]; | 1549 [NSCursor setHiddenUntilMouseMoves:YES]; |
1498 } | 1550 } |
1499 | 1551 |
1500 - (void)scrollWheel:(NSEvent *)theEvent { | 1552 // Checks if |theEvent| should trigger history swiping, and if so, does |
| 1553 // history swiping. Returns YES if the event was consumed or NO if it should |
| 1554 // be passed on to the renderer. |
| 1555 - (BOOL)maybeHandleHistorySwiping:(NSEvent*)theEvent { |
| 1556 BOOL canUseLionApis = [theEvent respondsToSelector:@selector(phase)]; |
| 1557 if (!canUseLionApis) |
| 1558 return NO; |
| 1559 |
| 1560 // Scroll events always go to the web first, and can only trigger history |
| 1561 // swiping if they come back unhandled. |
| 1562 if ([theEvent phase] == NSEventPhaseBegan) { |
| 1563 totalScrollDelta_ = NSZeroSize; |
| 1564 gotUnhandledWheelEvent_ = false; |
| 1565 } |
| 1566 |
| 1567 if (gotUnhandledWheelEvent_ && |
| 1568 [NSEvent isSwipeTrackingFromScrollEventsEnabled] && |
| 1569 [theEvent phase] == NSEventPhaseChanged) { |
| 1570 totalScrollDelta_.width += [theEvent scrollingDeltaX]; |
| 1571 totalScrollDelta_.height += [theEvent scrollingDeltaY]; |
| 1572 |
| 1573 bool isHorizontalGesture = |
| 1574 std::abs(totalScrollDelta_.width) > std::abs(totalScrollDelta_.height); |
| 1575 |
| 1576 bool isRightScroll = [theEvent scrollingDeltaX] < 0; |
| 1577 bool goForward = isRightScroll; |
| 1578 |
| 1579 if (isHorizontalGesture && |
| 1580 // If "forward" is inactive and the user rubber-bands to the right, |
| 1581 // "isPinnedLeft" will be false. When the user then rubber-bands to |
| 1582 // the left in the same gesture, that should trigger history |
| 1583 // immediately if there's no scrollbar, hence the check for |
| 1584 // hasHorizontalScrollbar_. |
| 1585 (!hasHorizontalScrollbar_ || |
| 1586 // One would think we have to check canGoBack / canGoForward here, but |
| 1587 // that's actually done in the renderer |
| 1588 // (ChromeClientImpl::shouldRubberBand()), when it decides if it should |
| 1589 // rubberband or send back an event unhandled. |
| 1590 (isPinnedLeft_ && !isRightScroll) || |
| 1591 (isPinnedRight_ && isRightScroll))) { |
| 1592 // The way this api works: gestureAmount is between -1 and 1 (float). If |
| 1593 // the user does the gesture for more than about 25% (i.e. < -0.25 or > |
| 1594 // 0.25) and then lets go, it is accepted, we get a NSEventPhaseEnded, |
| 1595 // and after that the block is called with amounts animating towards 1 |
| 1596 // (or -1, depending on the direction). If the user lets go below that |
| 1597 // threshold, we get NSEventPhaseCancelled, and the amount animates |
| 1598 // toward 0. |
| 1599 [theEvent trackSwipeEventWithOptions:0 |
| 1600 dampenAmountThresholdMin:-1 |
| 1601 max:1 |
| 1602 usingHandler:^(CGFloat gestureAmount, |
| 1603 NSEventPhase phase, |
| 1604 BOOL isComplete, |
| 1605 BOOL *stop) { |
| 1606 // |gestureAmount| obeys -[NSEvent isDirectionInvertedFromDevice] |
| 1607 // automatically. |
| 1608 // TODO(thakis): UI. |
| 1609 Browser* browser = BrowserList::GetLastActive(); |
| 1610 if (phase == NSEventPhaseEnded && browser) { |
| 1611 if (goForward) |
| 1612 browser->GoForward(CURRENT_TAB); |
| 1613 else |
| 1614 browser->GoBack(CURRENT_TAB); |
| 1615 } |
| 1616 }]; |
| 1617 return YES; |
| 1618 } |
| 1619 } |
| 1620 return NO; |
| 1621 } |
| 1622 |
| 1623 - (void)scrollWheel:(NSEvent*)theEvent { |
1501 [self cancelChildPopups]; | 1624 [self cancelChildPopups]; |
1502 | 1625 |
| 1626 if ([self maybeHandleHistorySwiping:theEvent]) |
| 1627 return; |
| 1628 |
1503 const WebMouseWheelEvent& event = | 1629 const WebMouseWheelEvent& event = |
1504 WebInputEventFactory::mouseWheelEvent(theEvent, self); | 1630 WebInputEventFactory::mouseWheelEvent(theEvent, self); |
1505 if (renderWidgetHostView_->render_widget_host_) | 1631 if (renderWidgetHostView_->render_widget_host_) |
1506 renderWidgetHostView_->render_widget_host_->ForwardWheelEvent(event); | 1632 renderWidgetHostView_->render_widget_host_->ForwardWheelEvent(event); |
1507 } | 1633 } |
1508 | 1634 |
1509 // See the comment in RenderWidgetHostViewMac::Destroy() about cancellation | 1635 // See the comment in RenderWidgetHostViewMac::Destroy() about cancellation |
1510 // events. On the Mac we must kill popups on outside events, thus this lovely | 1636 // events. On the Mac we must kill popups on outside events, thus this lovely |
1511 // case of filicide caused by events on parent views. | 1637 // case of filicide caused by events on parent views. |
1512 - (void)cancelChildPopups { | 1638 - (void)cancelChildPopups { |
(...skipping 1248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2761 if (!string) return NO; | 2887 if (!string) return NO; |
2762 | 2888 |
2763 // If the user is currently using an IME, confirm the IME input, | 2889 // If the user is currently using an IME, confirm the IME input, |
2764 // and then insert the text from the service, the same as TextEdit and Safari. | 2890 // and then insert the text from the service, the same as TextEdit and Safari. |
2765 [self confirmComposition]; | 2891 [self confirmComposition]; |
2766 [self insertText:string]; | 2892 [self insertText:string]; |
2767 return YES; | 2893 return YES; |
2768 } | 2894 } |
2769 | 2895 |
2770 @end | 2896 @end |
OLD | NEW |