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

Side by Side Diff: chrome/browser/renderer_host/render_widget_host_view_mac.mm

Issue 7618036: mac: Only let two-finger-scrolling trigger history if web doesn't swallow gesture (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: TestRenderViewHost Created 9 years, 4 months 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 | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698