Index: chrome/browser/renderer_host/render_widget_host_view_mac.mm |
=================================================================== |
--- chrome/browser/renderer_host/render_widget_host_view_mac.mm (revision 95810) |
+++ chrome/browser/renderer_host/render_widget_host_view_mac.mm (working copy) |
@@ -52,6 +52,7 @@ |
using WebKit::WebInputEventFactory; |
using WebKit::WebMouseEvent; |
using WebKit::WebMouseWheelEvent; |
+using WebKit::WebGestureEvent; |
static inline int ToWebKitModifiers(NSUInteger flags) { |
int modifiers = 0; |
@@ -75,7 +76,7 @@ |
@end |
// This API was published since 10.6. Provide the declaration so it can be |
-// // called below when building with the 10.5 SDK. |
+// called below when building with the 10.5 SDK. |
#if MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5 |
@class NSTextInputContext; |
@interface NSResponder (AppKitDetails) |
@@ -83,6 +84,14 @@ |
@end |
#endif |
+// Undocumented Lion method to get the pattern for the over scroll area. |
+@interface NSColor (LionSekretAPI) |
++ (NSImage*)_linenPatternImage; |
+@end |
+ |
+// NSEvent subtype for scroll gestures events. |
+static const short kIOHIDEventTypeScroll = 6; |
+ |
namespace { |
// Maximum number of characters we allow in a tooltip. |
@@ -1209,6 +1218,38 @@ |
renderWidgetHostView_->render_widget_host_->ForwardMouseEvent(event); |
} |
+- (void)shortCircuitedEndGestureWithEvent:(NSEvent*)theEvent { |
+ if ([theEvent subtype] == kIOHIDEventTypeScroll) { |
+ WebGestureEvent event = WebInputEventFactory::gestureEvent(theEvent, self); |
+ |
+ if (renderWidgetHostView_->render_widget_host_) |
+ renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(event); |
+ |
+ if (endGestureMonitor_) { |
+ [NSEvent removeMonitor:endGestureMonitor_]; |
+ endGestureMonitor_ = nil; |
+ } |
+ } |
+} |
+ |
+- (void)beginGestureWithEvent:(NSEvent*)theEvent { |
Nico
2011/08/08 17:30:53
s/theEvent/event/
This override means the same ov
Alexei Svitkine (slow)
2011/08/08 20:06:29
I've fixed this by also forwarding it to the next
|
+ if ([theEvent subtype] == kIOHIDEventTypeScroll) { |
+ WebGestureEvent event = WebInputEventFactory::gestureEvent(theEvent, self); |
+ |
+ if (renderWidgetHostView_->render_widget_host_) |
+ renderWidgetHostView_->render_widget_host_->ForwardGestureEvent(event); |
+ |
+ if (!endGestureMonitor_) { |
+ endGestureMonitor_ = |
+ [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskEndGesture |
+ handler: ^(NSEvent *blockEvent) { |
+ [self shortCircuitedEndGestureWithEvent:blockEvent]; |
+ return blockEvent; |
+ }]; |
Nico
2011/08/08 17:30:53
do you want to retain the monitor?
Alexei Svitkine (slow)
2011/08/08 18:31:31
Apple's examples don't do it:
http://developer.ap
Nico
2011/08/08 18:49:15
Did you check if that example is built with garbag
|
+ } |
+ } |
+} |
+ |
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent { |
// |performKeyEquivalent:| is sent to all views of a window, not only down the |
// responder chain (cf. "Handling Key Equivalents" in |
@@ -1564,6 +1605,94 @@ |
} |
} |
+- (void)fillRect:(NSRect)rect withPattern:(NSImage*)patternImage { |
+ if (NSIsEmptyRect(rect)) |
+ return; |
+ |
+ NSColor* patternColor = [NSColor colorWithPatternImage:patternImage]; |
+ [patternColor set]; |
+ NSRectFill(rect); |
+} |
+ |
+- (void)drawShadow:(NSShadow*)shadow |
+ withRect:(NSRect)rect |
+ clip:(NSRect)clipRect { |
+ [NSGraphicsContext saveGraphicsState]; |
Nico
2011/08/08 17:30:53
We have a ScopedSaveNSGraphicsState somewhere in b
Alexei Svitkine (slow)
2011/08/08 18:31:31
Done.
|
+ NSBezierPath *drawingPath = [NSBezierPath bezierPathWithRect:rect]; |
Nico
2011/08/08 17:30:53
space after *, not before
Alexei Svitkine (slow)
2011/08/08 18:31:31
Done.
|
+ [shadow set]; |
+ [[NSColor blackColor] set]; |
+ [[NSBezierPath bezierPathWithRect:clipRect] addClip]; |
+ [drawingPath fill]; |
+ [NSGraphicsContext restoreGraphicsState]; |
+} |
+ |
+- (NSRect)computeVisibleContentRect { |
+ const RenderWidgetHost *rwh = renderWidgetHostView_->render_widget_host_; |
+ gfx::Point offset = rwh->last_scroll_offset(); |
+ gfx::Size size = rwh->contents_size(); |
+ NSRect contentRect = |
+ NSMakeRect(-offset.x(), -offset.y(), size.width(), size.height()); |
+ NSRect frameRect = [self frame]; |
+ frameRect.origin = NSMakePoint(0, 0); |
+ return NSIntersectionRect(frameRect, contentRect); |
+} |
+ |
+- (void)fillOverScrollAreas:(NSRect)dirtyRect { |
+ if (![NSColor respondsToSelector:@selector(_linenPatternImage)]) |
+ return; |
+ |
+ NSRect visibleContentRect = [self computeVisibleContentRect]; |
+ NSSize frameSize = [self frame].size; |
+ bool hasHorizontalOverflow = (NSWidth(visibleContentRect) < frameSize.width); |
+ bool hasVerticalOverflow = (NSHeight(visibleContentRect) < frameSize.height); |
+ |
+ if (!hasHorizontalOverflow && !hasVerticalOverflow) |
+ return; |
+ |
+ NSRect xRect = NSMakeRect(0, |
+ 0, |
+ frameSize.width - NSWidth(visibleContentRect), |
+ frameSize.height); |
+ NSRect yRect = NSMakeRect(0, |
+ 0, |
+ frameSize.width, |
+ frameSize.height - NSHeight(visibleContentRect)); |
+ NSImage* background = [NSColor _linenPatternImage]; |
+ scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]); |
+ [shadow.get() setShadowColor:[NSColor blackColor]]; |
+ [shadow setShadowBlurRadius:5]; |
+ |
+ if (hasHorizontalOverflow) { |
+ NSRect shadowRect; |
+ if (visibleContentRect.origin.x > 0) { |
+ shadowRect = xRect; |
+ shadowRect.origin.x += NSWidth(shadowRect); |
+ } else { |
+ xRect.origin.x = NSWidth(visibleContentRect); |
+ shadowRect = xRect; |
+ shadowRect.origin.x -= 1; |
+ } |
+ shadowRect.size.width = 1; |
+ NSRect intersectRect = NSIntersectionRect(dirtyRect, xRect); |
+ [self fillRect:intersectRect withPattern:background]; |
+ [self drawShadow:shadow.get() withRect:shadowRect clip:intersectRect]; |
+ } |
+ |
+ if (hasVerticalOverflow) { |
+ NSRect shadowRect = visibleContentRect; |
+ if (visibleContentRect.origin.y > 0) { |
+ yRect.origin.y = NSHeight(visibleContentRect); |
+ shadowRect.origin.y = yRect.origin.y - 1; |
+ } else { |
+ shadowRect.origin.y = yRect.origin.y + NSHeight(yRect); |
+ } |
+ shadowRect.size.height = 1; |
+ NSRect intersectRect = NSIntersectionRect(dirtyRect, yRect); |
+ [self fillRect:intersectRect withPattern:background]; |
+ [self drawShadow:shadow.get() withRect:shadowRect clip:intersectRect]; |
+ } |
+} |
+ |
- (void)drawRect:(NSRect)dirtyRect { |
if (!renderWidgetHostView_->render_widget_host_) { |
// TODO(shess): Consider using something more noticable? |
@@ -1639,6 +1768,9 @@ |
// Fill the remaining portion of the damagedRect with white |
[self fillBottomRightRemainderOfRect:bitmapRect dirtyRect:damagedRect]; |
+ // Fill the over-scroll areas, if any, with the appropriate pattern. |
+ [self fillOverScrollAreas:dirtyRect]; |
+ |
if (!renderWidgetHostView_->whiteout_start_time_.is_null()) { |
base::TimeDelta whiteout_duration = base::TimeTicks::Now() - |
renderWidgetHostView_->whiteout_start_time_; |
@@ -1886,7 +2018,7 @@ |
// Performs a right click copying WebKit's |
// accessibilityPerformShowMenuAction. |
NSPoint location = [self accessibilityPointInScreen:accessibility]; |
-NSSize size = [[accessibility size] sizeValue]; |
+ NSSize size = [[accessibility size] sizeValue]; |
location = [[self window] convertScreenToBase:location]; |
location.x += size.width/2; |
location.y += size.height/2; |