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

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: comments 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 // Forward-declare symbols that are part of the 10.7 SDK.
Mark Mentovai 2011/08/15 16:55:36 These are just declarations. Not too much about th
Nico 2011/08/15 17:05:30 Removed "Forward-".
65 #if !defined(MAC_OS_X_VERSION_10_7) || \
66 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
67
68 enum {
69 NSEventPhaseNone = 0, // event not associated with a phase.
70 NSEventPhaseBegan = 0x1 << 0,
71 NSEventPhaseStationary = 0x1 << 1,
72 NSEventPhaseChanged = 0x1 << 2,
73 NSEventPhaseEnded = 0x1 << 3,
74 NSEventPhaseCancelled = 0x1 << 4,
75 };
76 typedef NSUInteger NSEventPhase;
77
78 enum {
79 NSEventSwipeTrackingLockDirection = 0x1 << 0,
80 NSEventSwipeTrackingClampGestureAmount = 0x1 << 1
81 };
82 typedef NSUInteger NSEventSwipeTrackingOptions;
83
84
85 @interface NSEvent (LionAPI)
86 + (BOOL)isSwipeTrackingFromScrollEventsEnabled;
87
88 - (NSEventPhase)phase;
89 - (CGFloat)scrollingDeltaX;
90 - (CGFloat)scrollingDeltaY;
91 - (void)trackSwipeEventWithOptions:(NSEventSwipeTrackingOptions)options
92 dampenAmountThresholdMin:(CGFloat)minDampenThreshold
93 max:(CGFloat)maxDampenThreshold
94 usingHandler:(void (^)(CGFloat gestureAmount,
95 NSEventPhase phase,
96 BOOL isComplete,
97 BOOL *stop))trackingHandler;
98 @end
99
100 #endif // 10.7
101
59 static inline int ToWebKitModifiers(NSUInteger flags) { 102 static inline int ToWebKitModifiers(NSUInteger flags) {
60 int modifiers = 0; 103 int modifiers = 0;
61 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey; 104 if (flags & NSControlKeyMask) modifiers |= WebInputEvent::ControlKey;
62 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey; 105 if (flags & NSShiftKeyMask) modifiers |= WebInputEvent::ShiftKey;
63 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey; 106 if (flags & NSAlternateKeyMask) modifiers |= WebInputEvent::AltKey;
64 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey; 107 if (flags & NSCommandKeyMask) modifiers |= WebInputEvent::MetaKey;
65 return modifiers; 108 return modifiers;
66 } 109 }
67 110
68 // Private methods: 111 // Private methods:
(...skipping 942 matching lines...) Expand 10 before | Expand all | Expand 10 after
1011 1054
1012 void RenderWidgetHostViewMac::ForceTextureReload() { 1055 void RenderWidgetHostViewMac::ForceTextureReload() {
1013 plugin_container_manager_.ForceTextureReload(); 1056 plugin_container_manager_.ForceTextureReload();
1014 } 1057 }
1015 1058
1016 void RenderWidgetHostViewMac::SetVisuallyDeemphasized(const SkColor* color, 1059 void RenderWidgetHostViewMac::SetVisuallyDeemphasized(const SkColor* color,
1017 bool animate) { 1060 bool animate) {
1018 // This is not used on mac. 1061 // This is not used on mac.
1019 } 1062 }
1020 1063
1064 void RenderWidgetHostViewMac::UnhandledWheelEvent(
1065 const WebKit::WebMouseWheelEvent& event) {
1066 [cocoa_view_ setGotUnhandledWheelEvent:YES];
1067 }
1068
1069 void RenderWidgetHostViewMac::SetHasHorizontalScrollbar(
1070 bool has_horizontal_scrollbar) {
1071 [cocoa_view_ setHasHorizontalScrollbar:has_horizontal_scrollbar];
1072 }
1073
1074 void RenderWidgetHostViewMac::SetScrollOffsetPinning(
1075 bool is_pinned_to_left, bool is_pinned_to_right) {
1076 [cocoa_view_ setPinnedLeft:is_pinned_to_left];
1077 [cocoa_view_ setPinnedRight:is_pinned_to_right];
1078 }
1079
1021 void RenderWidgetHostViewMac::ShutdownHost() { 1080 void RenderWidgetHostViewMac::ShutdownHost() {
1022 shutdown_factory_.RevokeAll(); 1081 shutdown_factory_.RevokeAll();
1023 render_widget_host_->Shutdown(); 1082 render_widget_host_->Shutdown();
1024 // Do not touch any members at this point, |this| has been deleted. 1083 // Do not touch any members at this point, |this| has been deleted.
1025 } 1084 }
1026 1085
1027 gfx::Rect RenderWidgetHostViewMac::GetViewCocoaBounds() const { 1086 gfx::Rect RenderWidgetHostViewMac::GetViewCocoaBounds() const {
1028 return gfx::Rect(NSRectToCGRect([cocoa_view_ bounds])); 1087 return gfx::Rect(NSRectToCGRect([cocoa_view_ bounds]));
1029 } 1088 }
1030 1089
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1094 DisablePasswordInput(); 1153 DisablePasswordInput();
1095 } 1154 }
1096 } 1155 }
1097 1156
1098 // RenderWidgetHostViewCocoa --------------------------------------------------- 1157 // RenderWidgetHostViewCocoa ---------------------------------------------------
1099 1158
1100 @implementation RenderWidgetHostViewCocoa 1159 @implementation RenderWidgetHostViewCocoa
1101 1160
1102 @synthesize selectedRange = selectedRange_; 1161 @synthesize selectedRange = selectedRange_;
1103 @synthesize markedRange = markedRange_; 1162 @synthesize markedRange = markedRange_;
1163 @synthesize gotUnhandledWheelEvent = gotUnhandledWheelEvent_;
1164 @synthesize isPinnedLeft = isPinnedLeft_;
1165 @synthesize isPinnedRight = isPinnedRight_;
1166 @synthesize hasHorizontalScrollbar = hasHorizontalScrollbar_;
1104 1167
1105 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r { 1168 - (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r {
1106 self = [super initWithFrame:NSZeroRect]; 1169 self = [super initWithFrame:NSZeroRect];
1107 if (self) { 1170 if (self) {
1108 editCommand_helper_.reset(new RWHVMEditCommandHelper); 1171 editCommand_helper_.reset(new RWHVMEditCommandHelper);
1109 editCommand_helper_->AddEditingSelectorsToClass([self class]); 1172 editCommand_helper_->AddEditingSelectorsToClass([self class]);
1110 1173
1111 renderWidgetHostView_.reset(r); 1174 renderWidgetHostView_.reset(r);
1112 canBeKeyView_ = YES; 1175 canBeKeyView_ = YES;
1113 focusedPluginIdentifier_ = -1; 1176 focusedPluginIdentifier_ = -1;
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1224 renderWidgetHostView_->render_widget_host_->ForwardMouseEvent(event); 1287 renderWidgetHostView_->render_widget_host_->ForwardMouseEvent(event);
1225 } 1288 }
1226 1289
1227 - (void)beginGestureWithEvent:(NSEvent*)event { 1290 - (void)beginGestureWithEvent:(NSEvent*)event {
1228 if (base::mac::IsOSLionOrLater() && 1291 if (base::mac::IsOSLionOrLater() &&
1229 [event subtype] == kIOHIDEventTypeScroll && 1292 [event subtype] == kIOHIDEventTypeScroll &&
1230 renderWidgetHostView_->render_widget_host_) { 1293 renderWidgetHostView_->render_widget_host_) {
1231 WebGestureEvent webEvent = WebInputEventFactory::gestureEvent(event, self); 1294 WebGestureEvent webEvent = WebInputEventFactory::gestureEvent(event, self);
1232 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(webEvent); 1295 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(webEvent);
1233 } 1296 }
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];
Mark Mentovai 2011/08/15 16:55:36 Nice subtraction. Thanks to Alexei for catching it
1238 } 1297 }
1239 1298
1240 - (void)endGestureWithEvent:(NSEvent*)event { 1299 - (void)endGestureWithEvent:(NSEvent*)event {
1241 if (base::mac::IsOSLionOrLater() && 1300 if (base::mac::IsOSLionOrLater() &&
1242 [event subtype] == kIOHIDEventTypeScroll && 1301 [event subtype] == kIOHIDEventTypeScroll &&
1243 renderWidgetHostView_->render_widget_host_) { 1302 renderWidgetHostView_->render_widget_host_) {
1244 WebGestureEvent webEvent = WebInputEventFactory::gestureEvent(event, self); 1303 WebGestureEvent webEvent = WebInputEventFactory::gestureEvent(event, self);
1245 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(webEvent); 1304 renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(webEvent);
1246 } 1305 }
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 } 1306 }
1252 1307
1253 - (BOOL)performKeyEquivalent:(NSEvent*)theEvent { 1308 - (BOOL)performKeyEquivalent:(NSEvent*)theEvent {
1254 // |performKeyEquivalent:| is sent to all views of a window, not only down the 1309 // |performKeyEquivalent:| is sent to all views of a window, not only down the
1255 // responder chain (cf. "Handling Key Equivalents" in 1310 // responder chain (cf. "Handling Key Equivalents" in
1256 // http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Event Overview/HandlingKeyEvents/HandlingKeyEvents.html 1311 // 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. 1312 // ). We only want to handle key equivalents if we're first responder.
1258 if ([[self window] firstResponder] != self) 1313 if ([[self window] firstResponder] != self)
1259 return NO; 1314 return NO;
1260 1315
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
1490 event.skip_in_browser = true; 1545 event.skip_in_browser = true;
1491 widgetHost->ForwardKeyboardEvent(event); 1546 widgetHost->ForwardKeyboardEvent(event);
1492 } 1547 }
1493 } 1548 }
1494 1549
1495 // Possibly autohide the cursor. 1550 // Possibly autohide the cursor.
1496 if ([RenderWidgetHostViewCocoa shouldAutohideCursorForEvent:theEvent]) 1551 if ([RenderWidgetHostViewCocoa shouldAutohideCursorForEvent:theEvent])
1497 [NSCursor setHiddenUntilMouseMoves:YES]; 1552 [NSCursor setHiddenUntilMouseMoves:YES];
1498 } 1553 }
1499 1554
1500 - (void)scrollWheel:(NSEvent *)theEvent { 1555 - (BOOL)maybeHandleHistorySwiping:(NSEvent*)theEvent {
Mark Mentovai 2011/08/15 16:55:36 Since you don’t declare this in an @interface, you
Nico 2011/08/15 17:05:30 Done.
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);
Mark Mentovai 2011/08/15 16:55:36 Are the |abs| calls helpful here at all? Can’t we
Nico 2011/08/15 17:05:30 Yes, width and height can be both positive or nega
Mark Mentovai 2011/08/15 17:58:24 Nico wrote:
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
« no previous file with comments | « chrome/browser/renderer_host/render_widget_host_view_mac.h ('k') | chrome/browser/ui/cocoa/browser_window_controller.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698