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

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

Powered by Google App Engine
This is Rietveld 408576698