summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/mac
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-18 13:36:51 +0100
committerSteve Block <steveblock@google.com>2011-05-24 15:38:28 +0100
commit2fc2651226baac27029e38c9d6ef883fa32084db (patch)
treee396d4bf89dcce6ed02071be66212495b1df1dec /Source/WebCore/platform/mac
parentb3725cedeb43722b3b175aaeff70552e562d2c94 (diff)
downloadexternal_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/WebCore/platform/mac')
-rw-r--r--Source/WebCore/platform/mac/DragImageMac.mm210
-rw-r--r--Source/WebCore/platform/mac/EmptyProtocolDefinitions.h5
-rw-r--r--Source/WebCore/platform/mac/FileSystemMac.mm25
-rw-r--r--Source/WebCore/platform/mac/MIMETypeRegistryMac.mm3
-rw-r--r--Source/WebCore/platform/mac/PasteboardMac.mm3
-rw-r--r--Source/WebCore/platform/mac/PopupMenuMac.mm25
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.h79
-rw-r--r--Source/WebCore/platform/mac/ScrollAnimatorMac.mm923
-rw-r--r--Source/WebCore/platform/mac/ScrollViewMac.mm4
-rw-r--r--Source/WebCore/platform/mac/ScrollbarThemeMac.h7
-rw-r--r--Source/WebCore/platform/mac/ScrollbarThemeMac.mm126
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.h43
-rw-r--r--Source/WebCore/platform/mac/WebCoreSystemInterface.mm43
-rw-r--r--Source/WebCore/platform/mac/WheelEventMac.mm3
-rw-r--r--Source/WebCore/platform/mac/WidgetMac.mm4
15 files changed, 1447 insertions, 56 deletions
diff --git a/Source/WebCore/platform/mac/DragImageMac.mm b/Source/WebCore/platform/mac/DragImageMac.mm
index f444b6e..fc58173 100644
--- a/Source/WebCore/platform/mac/DragImageMac.mm
+++ b/Source/WebCore/platform/mac/DragImageMac.mm
@@ -28,9 +28,16 @@
#if ENABLE(DRAG_SUPPORT)
#import "CachedImage.h"
+#import "Font.h"
+#import "FontDescription.h"
+#import "FontSelector.h"
+#import "GraphicsContext.h"
#import "Image.h"
#import "KURL.h"
#import "ResourceResponse.h"
+#import "Settings.h"
+#import "StringTruncator.h"
+#import "TextRun.h"
namespace WebCore {
@@ -98,7 +105,210 @@ RetainPtr<NSImage> createDragImageIconForCachedImage(CachedImage* image)
return [[NSWorkspace sharedWorkspace] iconForFileType:extension];
}
+
+
+const float DragLabelBorderX = 4;
+//Keep border_y in synch with DragController::LinkDragBorderInset
+const float DragLabelBorderY = 2;
+const float DragLabelRadius = 5;
+const float LabelBorderYOffset = 2;
+
+const float MinDragLabelWidthBeforeClip = 120;
+const float MaxDragLabelWidth = 320;
+
+const float DragLinkLabelFontsize = 11;
+const float DragLinkUrlFontSize = 10;
+
+// FIXME - we should move all the functionality of NSString extras to WebCore
+
+static Font& fontFromNSFont(NSFont *font)
+{
+ static NSFont *currentFont;
+ DEFINE_STATIC_LOCAL(Font, currentRenderer, ());
+
+ if ([font isEqual:currentFont])
+ return currentRenderer;
+ if (currentFont)
+ CFRelease(currentFont);
+ currentFont = font;
+ CFRetain(currentFont);
+ FontPlatformData f(font, [font pointSize]);
+ currentRenderer = Font(f, ![[NSGraphicsContext currentContext] isDrawingToScreen]);
+ return currentRenderer;
+}
+
+static bool canUseFastRenderer(const UniChar* buffer, unsigned length)
+{
+ unsigned i;
+ for (i = 0; i < length; i++) {
+ UCharDirection direction = u_charDirection(buffer[i]);
+ if (direction == U_RIGHT_TO_LEFT || direction > U_OTHER_NEUTRAL)
+ return false;
+ }
+ return true;
+}
+
+static float widthWithFont(NSString *string, NSFont *font)
+{
+ unsigned length = [string length];
+ Vector<UniChar, 2048> buffer(length);
+ [string getCharacters:buffer.data()];
+
+ if (canUseFastRenderer(buffer.data(), length)) {
+ Font webCoreFont(FontPlatformData(font, [font pointSize]), ![[NSGraphicsContext currentContext] isDrawingToScreen]);
+ TextRun run(buffer.data(), length);
+ run.disableRoundingHacks();
+ return webCoreFont.floatWidth(run);
+ }
+
+ return [string sizeWithAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil]].width;
+}
+
+static inline CGFloat webkit_CGCeiling(CGFloat value)
+{
+ if (sizeof(value) == sizeof(float))
+ return ceilf(value);
+ return static_cast<CGFloat>(ceil(value));
+}
+
+static void drawAtPoint(NSString *string, NSPoint point, NSFont *font, NSColor *textColor)
+{
+ unsigned length = [string length];
+ Vector<UniChar, 2048> buffer(length);
+
+ [string getCharacters:buffer.data()];
+
+ if (canUseFastRenderer(buffer.data(), length)) {
+ // The following is a half-assed attempt to match AppKit's rounding rules for drawAtPoint.
+ // It's probably incorrect for high DPI.
+ // If you change this, be sure to test all the text drawn this way in Safari, including
+ // the status bar, bookmarks bar, tab bar, and activity window.
+ point.y = webkit_CGCeiling(point.y);
+
+ NSGraphicsContext *nsContext = [NSGraphicsContext currentContext];
+ CGContextRef cgContext = static_cast<CGContextRef>([nsContext graphicsPort]);
+ GraphicsContext graphicsContext(cgContext);
+
+ // Safari doesn't flip the NSGraphicsContext before calling WebKit, yet WebCore requires a flipped graphics context.
+ BOOL flipped = [nsContext isFlipped];
+ if (!flipped)
+ CGContextScaleCTM(cgContext, 1, -1);
+
+ Font webCoreFont(FontPlatformData(font, [font pointSize]), ![nsContext isDrawingToScreen], Antialiased);
+ TextRun run(buffer.data(), length);
+ run.disableRoundingHacks();
+
+ CGFloat red;
+ CGFloat green;
+ CGFloat blue;
+ CGFloat alpha;
+ [[textColor colorUsingColorSpaceName:NSDeviceRGBColorSpace] getRed:&red green:&green blue:&blue alpha:&alpha];
+ graphicsContext.setFillColor(makeRGBA(red * 255, green * 255, blue * 255, alpha * 255), ColorSpaceDeviceRGB);
+
+ webCoreFont.drawText(&graphicsContext, run, FloatPoint(point.x, (flipped ? point.y : (-1 * point.y))));
+
+ if (!flipped)
+ CGContextScaleCTM(cgContext, 1, -1);
+ } else {
+ // The given point is on the baseline.
+ if ([[NSView focusView] isFlipped])
+ point.y -= [font ascender];
+ else
+ point.y += [font descender];
+
+ [string drawAtPoint:point withAttributes:[NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, textColor, NSForegroundColorAttributeName, nil]];
+ }
+}
+
+static void drawDoubledAtPoint(NSString *string, NSPoint textPoint, NSColor *topColor, NSColor *bottomColor, NSFont *font)
+{
+ // turn off font smoothing so translucent text draws correctly (Radar 3118455)
+ drawAtPoint(string, textPoint, font, bottomColor);
+
+ textPoint.y += 1;
+ drawAtPoint(string, textPoint, font, topColor);
+}
+
+DragImageRef createDragImageForLink(KURL& url, const String& title, Frame* frame)
+{
+ if (!frame)
+ return nil;
+ NSString *label = 0;
+ if (!title.isEmpty())
+ label = title;
+ NSURL *cocoaURL = url;
+ NSString *urlString = [cocoaURL absoluteString];
+
+ BOOL drawURLString = YES;
+ BOOL clipURLString = NO;
+ BOOL clipLabelString = NO;
+
+ if (!label) {
+ drawURLString = NO;
+ label = urlString;
+ }
+
+ NSFont *labelFont = [[NSFontManager sharedFontManager] convertFont:[NSFont systemFontOfSize:DragLinkLabelFontsize]
+ toHaveTrait:NSBoldFontMask];
+ NSFont *urlFont = [NSFont systemFontOfSize:DragLinkUrlFontSize];
+ NSSize labelSize;
+ labelSize.width = widthWithFont(label, labelFont);
+ labelSize.height = [labelFont ascender] - [labelFont descender];
+ if (labelSize.width > MaxDragLabelWidth){
+ labelSize.width = MaxDragLabelWidth;
+ clipLabelString = YES;
+ }
+
+ NSSize imageSize;
+ imageSize.width = labelSize.width + DragLabelBorderX * 2;
+ imageSize.height = labelSize.height + DragLabelBorderY * 2;
+ if (drawURLString) {
+ NSSize urlStringSize;
+ urlStringSize.width = widthWithFont(urlString, urlFont);
+ urlStringSize.height = [urlFont ascender] - [urlFont descender];
+ imageSize.height += urlStringSize.height;
+ if (urlStringSize.width > MaxDragLabelWidth) {
+ imageSize.width = std::max(MaxDragLabelWidth + DragLabelBorderY * 2, MinDragLabelWidthBeforeClip);
+ clipURLString = YES;
+ } else
+ imageSize.width = std::max(labelSize.width + DragLabelBorderX * 2, urlStringSize.width + DragLabelBorderX * 2);
+ }
+ NSImage *dragImage = [[[NSImage alloc] initWithSize: imageSize] autorelease];
+ [dragImage lockFocus];
+
+ [[NSColor colorWithDeviceRed: 0.7f green: 0.7f blue: 0.7f alpha: 0.8f] set];
+
+ // Drag a rectangle with rounded corners
+ NSBezierPath *path = [NSBezierPath bezierPath];
+ [path appendBezierPathWithOvalInRect: NSMakeRect(0, 0, DragLabelRadius * 2, DragLabelRadius * 2)];
+ [path appendBezierPathWithOvalInRect: NSMakeRect(0, imageSize.height - DragLabelRadius * 2, DragLabelRadius * 2, DragLabelRadius * 2)];
+ [path appendBezierPathWithOvalInRect: NSMakeRect(imageSize.width - DragLabelRadius * 2, imageSize.height - DragLabelRadius * 2, DragLabelRadius * 2, DragLabelRadius * 2)];
+ [path appendBezierPathWithOvalInRect: NSMakeRect(imageSize.width - DragLabelRadius * 2, 0, DragLabelRadius * 2, DragLabelRadius * 2)];
+
+ [path appendBezierPathWithRect: NSMakeRect(DragLabelRadius, 0, imageSize.width - DragLabelRadius * 2, imageSize.height)];
+ [path appendBezierPathWithRect: NSMakeRect(0, DragLabelRadius, DragLabelRadius + 10, imageSize.height - 2 * DragLabelRadius)];
+ [path appendBezierPathWithRect: NSMakeRect(imageSize.width - DragLabelRadius - 20, DragLabelRadius, DragLabelRadius + 20, imageSize.height - 2 * DragLabelRadius)];
+ [path fill];
+
+ NSColor *topColor = [NSColor colorWithDeviceWhite:0.0f alpha:0.75f];
+ NSColor *bottomColor = [NSColor colorWithDeviceWhite:1.0f alpha:0.5f];
+ if (drawURLString) {
+ if (clipURLString)
+ urlString = StringTruncator::centerTruncate(urlString, imageSize.width - (DragLabelBorderX * 2), fontFromNSFont(urlFont));
+
+ drawDoubledAtPoint(urlString, NSMakePoint(DragLabelBorderX, DragLabelBorderY - [urlFont descender]), topColor, bottomColor, urlFont);
+ }
+
+ if (clipLabelString)
+ label = StringTruncator::rightTruncate(label, imageSize.width - (DragLabelBorderX * 2), fontFromNSFont(labelFont));
+ drawDoubledAtPoint(label, NSMakePoint(DragLabelBorderX, imageSize.height - LabelBorderYOffset - [labelFont pointSize]), topColor, bottomColor, labelFont);
+
+ [dragImage unlockFocus];
+
+ return dragImage;
+}
+
} // namespace WebCore
#endif // ENABLE(DRAG_SUPPORT)
diff --git a/Source/WebCore/platform/mac/EmptyProtocolDefinitions.h b/Source/WebCore/platform/mac/EmptyProtocolDefinitions.h
index b73177b..04bf236 100644
--- a/Source/WebCore/platform/mac/EmptyProtocolDefinitions.h
+++ b/Source/WebCore/platform/mac/EmptyProtocolDefinitions.h
@@ -23,6 +23,9 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef EmptyProtocolDefinitions_h
+#define EmptyProtocolDefinitions_h
+
#if defined(__OBJC__)
#define EMPTY_PROTOCOL(NAME) \
@@ -47,3 +50,5 @@ EMPTY_PROTOCOL(NSURLDownloadDelegate)
#undef EMPTY_PROTOCOL
#endif /* defined(__OBJC__) */
+
+#endif /* EmptyProtocolDefinitions_h */
diff --git a/Source/WebCore/platform/mac/FileSystemMac.mm b/Source/WebCore/platform/mac/FileSystemMac.mm
index 0df3c89..bbeb76a 100644
--- a/Source/WebCore/platform/mac/FileSystemMac.mm
+++ b/Source/WebCore/platform/mac/FileSystemMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,10 +25,12 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#import "config.h"
#import "FileSystem.h"
#import "PlatformString.h"
+#import <wtf/RetainPtr.h>
#import <wtf/text/CString.h>
namespace WebCore {
@@ -62,4 +64,25 @@ CString openTemporaryFile(const char* prefix, PlatformFileHandle& platformFileHa
return CString(temporaryFilePath.data());
}
+bool canExcludeFromBackup()
+{
+#ifdef BUILDING_ON_TIGER
+ return false;
+#else
+ return true;
+#endif
+}
+
+bool excludeFromBackup(const String& path)
+{
+#ifdef BUILDING_ON_TIGER
+ UNUSED_PARAM(path);
+ return false;
+#else
+ // It is critical to pass FALSE for excludeByPath because excluding by path requires root privileges.
+ CSBackupSetItemExcluded(pathAsURL(path).get(), TRUE, FALSE);
+ return true;
+#endif
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/MIMETypeRegistryMac.mm b/Source/WebCore/platform/mac/MIMETypeRegistryMac.mm
index 82348e0..3792b5a 100644
--- a/Source/WebCore/platform/mac/MIMETypeRegistryMac.mm
+++ b/Source/WebCore/platform/mac/MIMETypeRegistryMac.mm
@@ -28,12 +28,15 @@
#include "MIMETypeRegistry.h"
#include "WebCoreSystemInterface.h"
+#include <wtf/Assertions.h>
+#include <wtf/MainThread.h>
namespace WebCore
{
String MIMETypeRegistry::getMIMETypeForExtension(const String &ext)
{
+ ASSERT(isMainThread());
return wkGetMIMETypeForExtension(ext);
}
diff --git a/Source/WebCore/platform/mac/PasteboardMac.mm b/Source/WebCore/platform/mac/PasteboardMac.mm
index 71e4046..65180a0 100644
--- a/Source/WebCore/platform/mac/PasteboardMac.mm
+++ b/Source/WebCore/platform/mac/PasteboardMac.mm
@@ -27,7 +27,6 @@
#import "Pasteboard.h"
#import "CachedResource.h"
-#import "CharacterNames.h"
#import "DOMRangeInternal.h"
#import "Document.h"
#import "DocumentFragment.h"
@@ -49,10 +48,10 @@
#import "Text.h"
#import "WebCoreNSStringExtras.h"
#import "markup.h"
-
#import <wtf/StdLibExtras.h>
#import <wtf/RetainPtr.h>
#import <wtf/UnusedParam.h>
+#import <wtf/unicode/CharacterNames.h>
@interface NSAttributedString (AppKitSecretsIKnowAbout)
- (id)_initWithDOMRange:(DOMRange *)domRange;
diff --git a/Source/WebCore/platform/mac/PopupMenuMac.mm b/Source/WebCore/platform/mac/PopupMenuMac.mm
index 1bf500b..e69bcb2 100644
--- a/Source/WebCore/platform/mac/PopupMenuMac.mm
+++ b/Source/WebCore/platform/mac/PopupMenuMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2008, 2010, 2011 Apple Inc. All rights reserved.
* Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
*
* This library is free software; you can redistribute it and/or
@@ -75,6 +75,11 @@ void PopupMenuMac::populate()
if (!client()->shouldPopOver())
[m_popup.get() addItemWithTitle:@""];
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ TextDirection menuTextDirection = client()->menuStyle().textDirection();
+ [m_popup.get() setUserInterfaceLayoutDirection:menuTextDirection == LTR ? NSUserInterfaceLayoutDirectionLeftToRight : NSUserInterfaceLayoutDirectionRightToLeft];
+#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
ASSERT(client());
int size = client()->listSize();
@@ -92,13 +97,27 @@ void PopupMenuMac::populate()
}
[attributes setObject:font forKey:NSFontAttributeName];
}
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+ RetainPtr<NSMutableParagraphStyle> paragraphStyle(AdoptNS, [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
+ [paragraphStyle.get() setAlignment:menuTextDirection == LTR ? NSLeftTextAlignment : NSRightTextAlignment];
+ NSWritingDirection writingDirection = style.textDirection() == LTR ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft;
+ [paragraphStyle.get() setBaseWritingDirection:writingDirection];
+ if (style.hasTextDirectionOverride()) {
+ RetainPtr<NSNumber> writingDirectionValue(AdoptNS, [[NSNumber alloc] initWithInteger:writingDirection + NSTextWritingDirectionOverride]);
+ RetainPtr<NSArray> writingDirectionArray(AdoptNS, [[NSArray alloc] initWithObjects:writingDirectionValue.get(), nil]);
+ [attributes setObject:writingDirectionArray.get() forKey:NSWritingDirectionAttributeName];
+ }
+ [attributes setObject:paragraphStyle.get() forKey:NSParagraphStyleAttributeName];
+#endif // !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
+
// FIXME: Add support for styling the foreground and background colors.
// FIXME: Find a way to customize text color when an item is highlighted.
- NSAttributedString* string = [[NSAttributedString alloc] initWithString:client()->itemText(i) attributes:attributes];
+ NSAttributedString *string = [[NSAttributedString alloc] initWithString:client()->itemText(i) attributes:attributes];
[attributes release];
[m_popup.get() addItemWithTitle:@""];
- NSMenuItem* menuItem = [m_popup.get() lastItem];
+ NSMenuItem *menuItem = [m_popup.get() lastItem];
[menuItem setAttributedTitle:string];
[menuItem setEnabled:client()->itemIsEnabled(i)];
[menuItem setToolTip:client()->itemToolTip(i)];
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.h b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
index f05db40..3f7612a 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.h
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,17 +28,30 @@
#if ENABLE(SMOOTH_SCROLLING)
+#include "FloatPoint.h"
+#include "FloatSize.h"
+#include "HeaderDetection.h"
#include "ScrollAnimator.h"
+#include "Timer.h"
+#include "WebCoreSystemInterface.h"
#include <wtf/RetainPtr.h>
#ifdef __OBJC__
@class ScrollAnimationHelperDelegate;
+@class ScrollbarPainterDelegate;
+@class ScrollbarPainterControllerDelegate;
+@class ScrollbarPainterDelegate;
#else
class ScrollAnimationHelperDelegate;
+class ScrollbarPainterDelegate;
+class ScrollbarPainterControllerDelegate;
+class ScrollbarPainterDelegate;
#endif
namespace WebCore {
+class Scrollbar;
+
class ScrollAnimatorMac : public ScrollAnimator {
public:
ScrollAnimatorMac(ScrollableArea*);
@@ -47,12 +60,72 @@ public:
virtual bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier);
virtual void scrollToOffsetWithoutAnimation(const FloatPoint&);
- // Called by the ScrollAnimationHelperDelegate.
- void immediateScrollToPoint(const FloatPoint& newPosition);
+#if ENABLE(RUBBER_BANDING)
+ virtual void handleWheelEvent(PlatformWheelEvent&);
+#if ENABLE(GESTURE_EVENTS)
+ virtual void handleGestureEvent(const PlatformGestureEvent&);
+#endif
+#endif
+ void immediateScrollToPoint(const FloatPoint& newPosition);
+ void immediateScrollByDeltaX(float deltaX);
+ void immediateScrollByDeltaY(float deltaY);
+
private:
RetainPtr<id> m_scrollAnimationHelper;
RetainPtr<ScrollAnimationHelperDelegate> m_scrollAnimationHelperDelegate;
+
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ RetainPtr<WKScrollbarPainterControllerRef> m_scrollbarPainterController;
+ RetainPtr<ScrollbarPainterControllerDelegate> m_scrollbarPainterControllerDelegate;
+ RetainPtr<id> m_scrollbarPainterDelegate;
+#endif
+
+ virtual void notityPositionChanged();
+ virtual void contentAreaWillPaint() const;
+ virtual void mouseEnteredContentArea() const;
+ virtual void mouseExitedContentArea() const;
+ virtual void mouseMovedInContentArea() const;
+ virtual void willStartLiveResize();
+ virtual void contentsResized() const;
+ virtual void willEndLiveResize();
+ virtual void contentAreaDidShow() const;
+ virtual void contentAreaDidHide() const;
+
+ virtual void didAddVerticalScrollbar(Scrollbar*);
+ virtual void willRemoveVerticalScrollbar(Scrollbar*);
+ virtual void didAddHorizontalScrollbar(Scrollbar*);
+ virtual void willRemoveHorizontalScrollbar(Scrollbar*);
+
+ float adjustScrollXPositionIfNecessary(float) const;
+ float adjustScrollYPositionIfNecessary(float) const;
+ FloatPoint adjustScrollPositionIfNecessary(const FloatPoint&) const;
+
+#if ENABLE(RUBBER_BANDING)
+ bool allowsVerticalStretching() const;
+ bool allowsHorizontalStretching() const;
+ bool pinnedInDirection(float deltaX, float deltaY);
+ void snapRubberBand();
+ void snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*);
+ void smoothScrollWithEvent(PlatformWheelEvent&);
+ void beginScrollGesture();
+ void endScrollGesture();
+
+ bool m_inScrollGesture;
+ bool m_momentumScrollInProgress;
+ bool m_ignoreMomentumScrolls;
+ CFTimeInterval m_lastMomemtumScrollTimestamp;
+ FloatSize m_overflowScrollDelta;
+ FloatSize m_stretchScrollForce;
+ FloatSize m_momentumVelocity;
+
+ // Rubber band state.
+ CFTimeInterval m_startTime;
+ FloatSize m_startStretch;
+ FloatPoint m_origOrigin;
+ FloatSize m_origVelocity;
+ Timer<ScrollAnimatorMac> m_snapRubberBandTimer;
+#endif
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
index 59b333b..c1154d5 100644
--- a/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
+++ b/Source/WebCore/platform/mac/ScrollAnimatorMac.mm
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -30,10 +30,20 @@
#include "ScrollAnimatorMac.h"
#include "FloatPoint.h"
+#include "IntRect.h"
+#include "PlatformGestureEvent.h"
+#include "PlatformWheelEvent.h"
+#include "ScrollView.h"
#include "ScrollableArea.h"
+#include "ScrollbarTheme.h"
+#include "ScrollbarThemeMac.h"
#include <wtf/PassOwnPtr.h>
+#include <wtf/UnusedParam.h>
-@interface NSObject (NSScrollAnimationHelperDetails)
+using namespace WebCore;
+using namespace std;
+
+@interface NSObject (ScrollAnimationHelperDetails)
- (id)initWithDelegate:(id)delegate;
- (void)_stopRun;
- (BOOL)_isAnimating;
@@ -44,18 +54,7 @@
{
WebCore::ScrollAnimatorMac* _animator;
}
-
- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
-
-- (NSRect)bounds;
-- (void)_immediateScrollToPoint:(NSPoint)newPosition;
-- (NSSize)convertSizeToBase:(NSSize)size;
-- (NSSize)convertSizeFromBase:(NSSize)size;
-
-- (id)superview; // Return nil.
-- (id)documentView; // Return nil.
-- (id)window; // Return nil.
-- (void)_recursiveRecomputeToolTips; // No-op.
@end
static NSSize abs(NSSize size)
@@ -80,14 +79,24 @@ static NSSize abs(NSSize size)
return self;
}
+- (void)scrollAnimatorDestroyed
+{
+ _animator = 0;
+}
+
- (NSRect)bounds
{
+ if (!_animator)
+ return NSZeroRect;
+
WebCore::FloatPoint currentPosition = _animator->currentPosition();
return NSMakeRect(currentPosition.x(), currentPosition.y(), 0, 0);
}
- (void)_immediateScrollToPoint:(NSPoint)newPosition
{
+ if (!_animator)
+ return;
_animator->immediateScrollToPoint(newPosition);
}
@@ -101,6 +110,16 @@ static NSSize abs(NSSize size)
return abs(size);
}
+- (NSSize)convertSizeToBacking:(NSSize)size
+{
+ return abs(size);
+}
+
+- (NSSize)convertSizeFromBacking:(NSSize)size
+{
+ return abs(size);
+}
+
- (id)superview
{
return nil;
@@ -122,6 +141,307 @@ static NSSize abs(NSSize size)
@end
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+
+@interface ScrollbarPainterControllerDelegate : NSObject
+{
+ WebCore::ScrollAnimatorMac* _animator;
+}
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
+@end
+
+@implementation ScrollbarPainterControllerDelegate
+
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _animator = scrollAnimator;
+ return self;
+}
+
+- (void)scrollAnimatorDestroyed
+{
+ _animator = 0;
+}
+
+- (NSRect)contentAreaRectForScrollerImpPair:(id)scrollerImpPair
+{
+ UNUSED_PARAM(scrollerImpPair);
+ if (!_animator)
+ return NSZeroRect;
+
+ WebCore::IntSize contentsSize = _animator->scrollableArea()->contentsSize();
+ return NSMakeRect(0, 0, contentsSize.width(), contentsSize.height());
+}
+
+- (BOOL)inLiveResizeForScrollerImpPair:(id)scrollerImpPair
+{
+ UNUSED_PARAM(scrollerImpPair);
+ if (!_animator)
+ return NO;
+
+ return _animator->scrollableArea()->inLiveResize();
+}
+
+- (NSPoint)mouseLocationInContentAreaForScrollerImpPair:(id)scrollerImpPair
+{
+ UNUSED_PARAM(scrollerImpPair);
+ if (!_animator)
+ return NSZeroPoint;
+
+ return _animator->scrollableArea()->currentMousePosition();
+}
+
+- (NSPoint)scrollerImpPair:(id)scrollerImpPair convertContentPoint:(NSPoint)pointInContentArea toScrollerImp:(id)scrollerImp
+{
+ UNUSED_PARAM(scrollerImpPair);
+ if (!_animator)
+ return NSZeroPoint;
+
+ WebCore::Scrollbar* scrollbar = 0;
+ if (wkScrollbarPainterIsHorizontal((WKScrollbarPainterRef)scrollerImp))
+ scrollbar = _animator->scrollableArea()->horizontalScrollbar();
+ else
+ scrollbar = _animator->scrollableArea()->verticalScrollbar();
+
+ // It is possible to have a null scrollbar here since it is possible for this delegate
+ // method to be called between the moment when a scrollbar has been set to 0 and the
+ // moment when its destructor has been called. We should probably de-couple some
+ // of the clean-up work in ScrollbarThemeMac::unregisterScrollbar() to avoid this
+ // issue.
+ if (!scrollbar)
+ return WebCore::IntPoint();
+
+ return scrollbar->convertFromContainingView(WebCore::IntPoint(pointInContentArea));
+}
+
+- (void)scrollerImpPair:(id)scrollerImpPair setContentAreaNeedsDisplayInRect:(NSRect)rect
+{
+ UNUSED_PARAM(scrollerImpPair);
+ UNUSED_PARAM(rect);
+}
+
+- (void)scrollerImpPair:(id)scrollerImpPair updateScrollerStyleForNewRecommendedScrollerStyle:(NSScrollerStyle)newRecommendedScrollerStyle
+{
+ if (!_animator)
+ return;
+
+ WKScrollbarPainterControllerRef painterController = (WKScrollbarPainterControllerRef)scrollerImpPair;
+ WebCore::ScrollbarThemeMac* macTheme = (WebCore::ScrollbarThemeMac*)WebCore::ScrollbarTheme::nativeTheme();
+
+ WKScrollbarPainterRef oldVerticalPainter = wkVerticalScrollbarPainterForController(painterController);
+ if (oldVerticalPainter) {
+ WebCore::Scrollbar* verticalScrollbar = _animator->scrollableArea()->verticalScrollbar();
+ WKScrollbarPainterRef newVerticalPainter = wkMakeScrollbarReplacementPainter(oldVerticalPainter,
+ newRecommendedScrollerStyle,
+ verticalScrollbar->controlSize(),
+ false);
+ macTheme->setNewPainterForScrollbar(verticalScrollbar, newVerticalPainter);
+ }
+
+ WKScrollbarPainterRef oldHorizontalPainter = wkHorizontalScrollbarPainterForController(painterController);
+ if (oldHorizontalPainter) {
+ WebCore::Scrollbar* horizontalScrollbar = _animator->scrollableArea()->horizontalScrollbar();
+ WKScrollbarPainterRef newHorizontalPainter = wkMakeScrollbarReplacementPainter(oldHorizontalPainter,
+ newRecommendedScrollerStyle,
+ horizontalScrollbar->controlSize(),
+ true);
+ macTheme->setNewPainterForScrollbar(horizontalScrollbar, newHorizontalPainter);
+ }
+
+ wkSetScrollbarPainterControllerStyle(painterController, newRecommendedScrollerStyle);
+}
+
+@end
+
+@interface ScrollbarPartAnimation : NSAnimation
+{
+ RetainPtr<WKScrollbarPainterRef> _scrollerPainter;
+ WebCore::ScrollbarPart _part;
+ WebCore::ScrollAnimatorMac* _animator;
+ CGFloat _initialAlpha;
+ CGFloat _newAlpha;
+}
+- (id)initWithScrollbarPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part scrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration;
+@end
+
+@implementation ScrollbarPartAnimation
+
+- (id)initWithScrollbarPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part scrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
+{
+ self = [super initWithDuration:duration animationCurve:NSAnimationEaseInOut];
+ if (!self)
+ return nil;
+
+ _scrollerPainter = scrollerPainter;
+ _part = part;
+ _animator = scrollAnimator;
+ _initialAlpha = _part == WebCore::ThumbPart ? wkScrollbarPainterKnobAlpha(_scrollerPainter.get()) : wkScrollbarPainterTrackAlpha(_scrollerPainter.get());
+ _newAlpha = newAlpha;
+
+ return self;
+}
+
+- (void)setCurrentProgress:(NSAnimationProgress)progress
+{
+ [super setCurrentProgress:progress];
+
+ if (!_animator)
+ return;
+
+ CGFloat currentAlpha;
+ if (_initialAlpha > _newAlpha)
+ currentAlpha = 1 - progress;
+ else
+ currentAlpha = progress;
+
+ if (_part == WebCore::ThumbPart)
+ wkSetScrollbarPainterKnobAlpha(_scrollerPainter.get(), currentAlpha);
+ else
+ wkSetScrollbarPainterTrackAlpha(_scrollerPainter.get(), currentAlpha);
+
+ // Invalidate the scrollbars so that they paint the animation
+ if (WebCore::Scrollbar* verticalScrollbar = _animator->scrollableArea()->verticalScrollbar())
+ _animator->scrollableArea()->invalidateScrollbarRect(verticalScrollbar, WebCore::IntRect(0, 0, verticalScrollbar->width(), verticalScrollbar->height()));
+ if (WebCore::Scrollbar* horizontalScrollbar = _animator->scrollableArea()->horizontalScrollbar())
+ _animator->scrollableArea()->invalidateScrollbarRect(horizontalScrollbar, WebCore::IntRect(0, 0, horizontalScrollbar->width(), horizontalScrollbar->height()));
+}
+
+- (void)scrollAnimatorDestroyed
+{
+ [self stopAnimation];
+ _animator = 0;
+}
+
+@end
+
+@interface ScrollbarPainterDelegate : NSObject<NSAnimationDelegate>
+{
+ WebCore::ScrollAnimatorMac* _animator;
+
+ RetainPtr<ScrollbarPartAnimation> _verticalKnobAnimation;
+ RetainPtr<ScrollbarPartAnimation> _horizontalKnobAnimation;
+
+ RetainPtr<ScrollbarPartAnimation> _verticalTrackAnimation;
+ RetainPtr<ScrollbarPartAnimation> _horizontalTrackAnimation;
+}
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator;
+@end
+
+@implementation ScrollbarPainterDelegate
+
+- (id)initWithScrollAnimator:(WebCore::ScrollAnimatorMac*)scrollAnimator
+{
+ self = [super init];
+ if (!self)
+ return nil;
+
+ _animator = scrollAnimator;
+ return self;
+}
+
+- (NSRect)convertRectToBacking:(NSRect)aRect
+{
+ return aRect;
+}
+
+- (NSRect)convertRectFromBacking:(NSRect)aRect
+{
+ return aRect;
+}
+
+- (CALayer *)layer
+{
+ if (!_animator)
+ return nil;
+ if (!_animator->scrollableArea()->scrollbarWillRenderIntoCompositingLayer())
+ return nil;
+
+ // FIXME: This should attempt to return an actual layer.
+ static CALayer *dummyLayer = [[CALayer alloc] init];
+ return dummyLayer;
+}
+
+- (void)setUpAnimation:(RetainPtr<ScrollbarPartAnimation>&)scrollbarPartAnimation scrollerPainter:(WKScrollbarPainterRef)scrollerPainter part:(WebCore::ScrollbarPart)part animateAlphaTo:(CGFloat)newAlpha duration:(NSTimeInterval)duration
+{
+ // If we are currently animating, stop
+ if (scrollbarPartAnimation) {
+ [scrollbarPartAnimation.get() stopAnimation];
+ scrollbarPartAnimation = nil;
+ }
+
+ scrollbarPartAnimation.adoptNS([[ScrollbarPartAnimation alloc] initWithScrollbarPainter:scrollerPainter
+ part:part
+ scrollAnimator:_animator
+ animateAlphaTo:newAlpha
+ duration:duration]);
+ [scrollbarPartAnimation.get() setAnimationBlockingMode:NSAnimationNonblocking];
+ [scrollbarPartAnimation.get() startAnimation];
+}
+
+- (void)scrollerImp:(id)scrollerImp animateKnobAlphaTo:(CGFloat)newKnobAlpha duration:(NSTimeInterval)duration
+{
+ if (!_animator)
+ return;
+
+ WKScrollbarPainterRef scrollerPainter = (WKScrollbarPainterRef)scrollerImp;
+ if (newKnobAlpha == wkScrollbarPainterKnobAlpha(scrollerPainter))
+ return;
+
+ if (wkScrollbarPainterIsHorizontal(scrollerPainter))
+ [self setUpAnimation:_horizontalKnobAnimation scrollerPainter:scrollerPainter part:WebCore::ThumbPart animateAlphaTo:newKnobAlpha duration:duration];
+ else
+ [self setUpAnimation:_verticalKnobAnimation scrollerPainter:scrollerPainter part:WebCore::ThumbPart animateAlphaTo:newKnobAlpha duration:duration];
+}
+
+- (void)scrollerImp:(id)scrollerImp animateTrackAlphaTo:(CGFloat)newTrackAlpha duration:(NSTimeInterval)duration
+{
+ if (!_animator)
+ return;
+
+ WKScrollbarPainterRef scrollerPainter = (WKScrollbarPainterRef)scrollerImp;
+ if (newTrackAlpha == wkScrollbarPainterTrackAlpha(scrollerPainter))
+ return;
+
+ if (wkScrollbarPainterIsHorizontal(scrollerPainter))
+ [self setUpAnimation:_horizontalTrackAnimation scrollerPainter:scrollerPainter part:WebCore::BackTrackPart animateAlphaTo:newTrackAlpha duration:duration];
+ else
+ [self setUpAnimation:_verticalTrackAnimation scrollerPainter:scrollerPainter part:WebCore::BackTrackPart animateAlphaTo:newTrackAlpha duration:duration];
+}
+
+- (void)scrollerImp:(id)scrollerImp overlayScrollerStateChangedTo:(NSUInteger)newOverlayScrollerState
+{
+ if (!_animator)
+ return;
+
+ WKScrollbarPainterRef scrollbarPainter = (WKScrollbarPainterRef)scrollerImp;
+ wkScrollbarPainterSetOverlayState(scrollbarPainter, newOverlayScrollerState);
+
+ if (wkScrollbarPainterIsHorizontal(scrollbarPainter)) {
+ WebCore::Scrollbar* horizontalScrollbar = _animator->scrollableArea()->horizontalScrollbar();
+ _animator->scrollableArea()->invalidateScrollbarRect(horizontalScrollbar, WebCore::IntRect(0, 0, horizontalScrollbar->width(), horizontalScrollbar->height()));
+ } else {
+ WebCore::Scrollbar* verticalScrollbar = _animator->scrollableArea()->verticalScrollbar();
+ _animator->scrollableArea()->invalidateScrollbarRect(verticalScrollbar, WebCore::IntRect(0, 0, verticalScrollbar->width(), verticalScrollbar->height()));
+
+ }
+}
+
+- (void)scrollAnimatorDestroyed
+{
+ _animator = 0;
+ [_verticalKnobAnimation.get() scrollAnimatorDestroyed];
+ [_horizontalKnobAnimation.get() scrollAnimatorDestroyed];
+ [_verticalTrackAnimation.get() scrollAnimatorDestroyed];
+ [_horizontalTrackAnimation.get() scrollAnimatorDestroyed];
+}
+
+@end
+#endif // #if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+
namespace WebCore {
PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea)
@@ -131,13 +451,33 @@ PassOwnPtr<ScrollAnimator> ScrollAnimator::create(ScrollableArea* scrollableArea
ScrollAnimatorMac::ScrollAnimatorMac(ScrollableArea* scrollableArea)
: ScrollAnimator(scrollableArea)
+#if ENABLE(RUBBER_BANDING)
+ , m_inScrollGesture(false)
+ , m_momentumScrollInProgress(false)
+ , m_ignoreMomentumScrolls(false)
+ , m_lastMomemtumScrollTimestamp(0)
+ , m_startTime(0)
+ , m_snapRubberBandTimer(this, &ScrollAnimatorMac::snapRubberBandTimerFired)
+#endif
{
m_scrollAnimationHelperDelegate.adoptNS([[ScrollAnimationHelperDelegate alloc] initWithScrollAnimator:this]);
m_scrollAnimationHelper.adoptNS([[NSClassFromString(@"NSScrollAnimationHelper") alloc] initWithDelegate:m_scrollAnimationHelperDelegate.get()]);
+
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ m_scrollbarPainterControllerDelegate.adoptNS([[ScrollbarPainterControllerDelegate alloc] initWithScrollAnimator:this]);
+ m_scrollbarPainterController = wkMakeScrollbarPainterController(m_scrollbarPainterControllerDelegate.get());
+ m_scrollbarPainterDelegate.adoptNS([[ScrollbarPainterDelegate alloc] initWithScrollAnimator:this]);
+#endif
}
ScrollAnimatorMac::~ScrollAnimatorMac()
{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ [m_scrollbarPainterControllerDelegate.get() scrollAnimatorDestroyed];
+ [(id)m_scrollbarPainterController.get() setDelegate:nil];
+ [m_scrollbarPainterDelegate.get() scrollAnimatorDestroyed];
+ [m_scrollAnimationHelperDelegate.get() scrollAnimatorDestroyed];
+#endif
}
bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
@@ -167,16 +507,567 @@ bool ScrollAnimatorMac::scroll(ScrollbarOrientation orientation, ScrollGranulari
void ScrollAnimatorMac::scrollToOffsetWithoutAnimation(const FloatPoint& offset)
{
[m_scrollAnimationHelper.get() _stopRun];
- ScrollAnimator::scrollToOffsetWithoutAnimation(offset);
+ immediateScrollToPoint(offset);
+}
+
+float ScrollAnimatorMac::adjustScrollXPositionIfNecessary(float position) const
+{
+ if (!m_scrollableArea->constrainsScrollingToContentEdge())
+ return position;
+
+ return max<float>(min<float>(position, m_scrollableArea->contentsSize().width() - m_scrollableArea->visibleWidth()), 0);
+}
+
+float ScrollAnimatorMac::adjustScrollYPositionIfNecessary(float position) const
+{
+ if (!m_scrollableArea->constrainsScrollingToContentEdge())
+ return position;
+
+ return max<float>(min<float>(position, m_scrollableArea->contentsSize().height() - m_scrollableArea->visibleHeight()), 0);
+}
+
+FloatPoint ScrollAnimatorMac::adjustScrollPositionIfNecessary(const FloatPoint& position) const
+{
+ if (!m_scrollableArea->constrainsScrollingToContentEdge())
+ return position;
+
+ float newX = max<float>(min<float>(position.x(), m_scrollableArea->contentsSize().width() - m_scrollableArea->visibleWidth()), 0);
+ float newY = max<float>(min<float>(position.y(), m_scrollableArea->contentsSize().height() - m_scrollableArea->visibleHeight()), 0);
+
+ return FloatPoint(newX, newY);
}
void ScrollAnimatorMac::immediateScrollToPoint(const FloatPoint& newPosition)
{
- m_currentPosX = newPosition.x();
- m_currentPosY = newPosition.y();
+ FloatPoint adjustedPosition = adjustScrollPositionIfNecessary(newPosition);
+
+ m_currentPosX = adjustedPosition.x();
+ m_currentPosY = adjustedPosition.y();
notityPositionChanged();
}
+void ScrollAnimatorMac::immediateScrollByDeltaX(float deltaX)
+{
+ m_currentPosX = adjustScrollXPositionIfNecessary(m_currentPosX + deltaX);
+ notityPositionChanged();
+}
+
+void ScrollAnimatorMac::immediateScrollByDeltaY(float deltaY)
+{
+ m_currentPosY = adjustScrollYPositionIfNecessary(m_currentPosY + deltaY);
+ notityPositionChanged();
+}
+
+void ScrollAnimatorMac::notityPositionChanged()
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaScrolled(m_scrollbarPainterController.get());
+#endif
+ ScrollAnimator::notityPositionChanged();
+}
+
+void ScrollAnimatorMac::contentAreaWillPaint() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaWillPaint(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::mouseEnteredContentArea() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkMouseEnteredContentArea(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::mouseExitedContentArea() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkMouseExitedContentArea(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::mouseMovedInContentArea() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkMouseMovedInContentArea(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::willStartLiveResize()
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkWillStartLiveResize(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::contentsResized() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaResized(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::willEndLiveResize()
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkWillEndLiveResize(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::contentAreaDidShow() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaDidShow(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::contentAreaDidHide() const
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ wkContentAreaDidHide(m_scrollbarPainterController.get());
+#endif
+}
+
+void ScrollAnimatorMac::didAddVerticalScrollbar(Scrollbar* scrollbar)
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
+ wkScrollbarPainterSetDelegate(painter, m_scrollbarPainterDelegate.get());
+ wkSetPainterForPainterController(m_scrollbarPainterController.get(), painter, false);
+ if (scrollableArea()->inLiveResize())
+ wkSetScrollbarPainterKnobAlpha(painter, 1);
+#else
+ UNUSED_PARAM(scrollbar);
+#endif
+}
+
+void ScrollAnimatorMac::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
+ wkScrollbarPainterSetDelegate(painter, nil);
+ wkSetPainterForPainterController(m_scrollbarPainterController.get(), nil, false);
+#else
+ UNUSED_PARAM(scrollbar);
+#endif
+}
+
+void ScrollAnimatorMac::didAddHorizontalScrollbar(Scrollbar* scrollbar)
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
+ wkScrollbarPainterSetDelegate(painter, m_scrollbarPainterDelegate.get());
+ wkSetPainterForPainterController(m_scrollbarPainterController.get(), painter, true);
+ if (scrollableArea()->inLiveResize())
+ wkSetScrollbarPainterKnobAlpha(painter, 1);
+#else
+ UNUSED_PARAM(scrollbar);
+#endif
+}
+
+void ScrollAnimatorMac::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
+{
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ WKScrollbarPainterRef painter = static_cast<WebCore::ScrollbarThemeMac*>(WebCore::ScrollbarTheme::nativeTheme())->painterForScrollbar(scrollbar);
+ wkScrollbarPainterSetDelegate(painter, nil);
+ wkSetPainterForPainterController(m_scrollbarPainterController.get(), nil, true);
+#else
+ UNUSED_PARAM(scrollbar);
+#endif
+}
+
+#if ENABLE(RUBBER_BANDING)
+
+static const float scrollVelocityZeroingTimeout = 0.10f;
+static const float rubberbandStiffness = 20;
+static const float rubberbandDirectionLockStretchRatio = 1;
+static const float rubberbandMinimumRequiredDeltaBeforeStretch = 10;
+static const float rubberbandAmplitude = 0.31f;
+static const float rubberbandPeriod = 1.6f;
+
+static float elasticDeltaForTimeDelta(float initialPosition, float initialVelocity, float elapsedTime)
+{
+ float amplitude = rubberbandAmplitude;
+ float period = rubberbandPeriod;
+ float criticalDampeningFactor = expf((-elapsedTime * rubberbandStiffness) / period);
+
+ return (initialPosition + (-initialVelocity * elapsedTime * amplitude)) * criticalDampeningFactor;
+}
+
+static float elasticDeltaForReboundDelta(float delta)
+{
+ float stiffness = std::max(rubberbandStiffness, 1.0f);
+ return delta / stiffness;
+}
+
+static float reboundDeltaForElasticDelta(float delta)
+{
+ return delta * rubberbandStiffness;
+}
+
+static float scrollWheelMultiplier()
+{
+ static float multiplier = -1;
+ if (multiplier < 0) {
+ multiplier = [[NSUserDefaults standardUserDefaults] floatForKey:@"NSScrollWheelMultiplier"];
+ if (multiplier <= 0)
+ multiplier = 1;
+ }
+ return multiplier;
+}
+
+void ScrollAnimatorMac::handleWheelEvent(PlatformWheelEvent& wheelEvent)
+{
+ if (!wheelEvent.hasPreciseScrollingDeltas()) {
+ ScrollAnimator::handleWheelEvent(wheelEvent);
+ return;
+ }
+
+ wheelEvent.accept();
+
+ bool isMometumScrollEvent = (wheelEvent.phase() != PlatformWheelEventPhaseNone);
+ if (m_ignoreMomentumScrolls && (isMometumScrollEvent || m_snapRubberBandTimer.isActive())) {
+ if (wheelEvent.phase() == PlatformWheelEventPhaseEnded)
+ m_ignoreMomentumScrolls = false;
+ return;
+ }
+
+ smoothScrollWithEvent(wheelEvent);
+}
+
+void ScrollAnimatorMac::handleGestureEvent(const PlatformGestureEvent& gestureEvent)
+{
+ if (gestureEvent.type() == PlatformGestureEvent::ScrollBeginType)
+ beginScrollGesture();
+ else
+ endScrollGesture();
+}
+
+bool ScrollAnimatorMac::pinnedInDirection(float deltaX, float deltaY)
+{
+ FloatSize limitDelta;
+ if (fabsf(deltaY) >= fabsf(deltaX)) {
+ if (deltaY < 0) {
+ // We are trying to scroll up. Make sure we are not pinned to the top
+ limitDelta.setHeight(m_scrollableArea->visibleContentRect().y());
+ } else {
+ // We are trying to scroll down. Make sure we are not pinned to the bottom
+ limitDelta.setHeight(m_scrollableArea->contentsSize().height() - m_scrollableArea->visibleContentRect().maxY());
+ }
+ } else if (deltaX != 0) {
+ if (deltaX < 0) {
+ // We are trying to scroll left. Make sure we are not pinned to the left
+ limitDelta.setWidth(m_scrollableArea->visibleContentRect().x());
+ } else {
+ // We are trying to scroll right. Make sure we are not pinned to the right
+ limitDelta.setWidth(m_scrollableArea->contentsSize().width() - m_scrollableArea->visibleContentRect().maxX());
+ }
+ }
+
+ if ((deltaX != 0 || deltaY != 0) && (limitDelta.width() < 1 && limitDelta.height() < 1))
+ return true;
+ return false;
+}
+
+bool ScrollAnimatorMac::allowsVerticalStretching() const
+{
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ if (((vScroller && vScroller->enabled()) || (!hScroller || !hScroller->enabled())))
+ return true;
+
+ return false;
+}
+
+bool ScrollAnimatorMac::allowsHorizontalStretching() const
+{
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ if (((hScroller && hScroller->enabled()) || (!vScroller || !vScroller->enabled())))
+ return true;
+
+ return false;
+}
+
+void ScrollAnimatorMac::smoothScrollWithEvent(PlatformWheelEvent& wheelEvent)
+{
+ float deltaX = m_overflowScrollDelta.width();
+ float deltaY = m_overflowScrollDelta.height();
+
+ // Reset overflow values because we may decide to remove delta at various points and put it into overflow.
+ m_overflowScrollDelta = FloatSize();
+
+ float eventCoallescedDeltaX = -wheelEvent.deltaX();
+ float eventCoallescedDeltaY = -wheelEvent.deltaY();
+
+ deltaX += eventCoallescedDeltaX;
+ deltaY += eventCoallescedDeltaY;
+
+ // Slightly prefer scrolling vertically by applying the = case to deltaY
+ if (fabsf(deltaY) >= fabsf(deltaX))
+ deltaX = 0;
+ else
+ deltaY = 0;
+
+ bool isVerticallyStretched = false;
+ bool isHorizontallyStretched = false;
+ bool shouldStretch = false;
+
+ IntSize stretchAmount = m_scrollableArea->overhangAmount();
+
+ isHorizontallyStretched = stretchAmount.width();
+ isVerticallyStretched = stretchAmount.height();
+
+ PlatformWheelEventPhase phase = wheelEvent.phase();
+
+ // If we are starting momentum scrolling then do some setup.
+ if (!m_momentumScrollInProgress && (phase == PlatformWheelEventPhaseBegan || phase == PlatformWheelEventPhaseChanged))
+ m_momentumScrollInProgress = true;
+
+ CFTimeInterval timeDelta = wheelEvent.timestamp() - m_lastMomemtumScrollTimestamp;
+ if (m_inScrollGesture || m_momentumScrollInProgress) {
+ if (m_lastMomemtumScrollTimestamp && timeDelta > 0 && timeDelta < scrollVelocityZeroingTimeout) {
+ m_momentumVelocity.setWidth(eventCoallescedDeltaX / (float)timeDelta);
+ m_momentumVelocity.setHeight(eventCoallescedDeltaY / (float)timeDelta);
+ m_lastMomemtumScrollTimestamp = wheelEvent.timestamp();
+ } else {
+ m_lastMomemtumScrollTimestamp = wheelEvent.timestamp();
+ m_momentumVelocity = FloatSize();
+ }
+
+ if (isVerticallyStretched) {
+ if (!isHorizontallyStretched && pinnedInDirection(deltaX, 0)) {
+ // Stretching only in the vertical.
+ if (deltaY != 0 && (fabsf(deltaX / deltaY) < rubberbandDirectionLockStretchRatio))
+ deltaX = 0;
+ else if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ deltaX = 0;
+ } else
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ }
+ } else if (isHorizontallyStretched) {
+ // Stretching only in the horizontal.
+ if (pinnedInDirection(0, deltaY)) {
+ if (deltaX != 0 && (fabsf(deltaY / deltaX) < rubberbandDirectionLockStretchRatio))
+ deltaY = 0;
+ else if (fabsf(deltaY) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
+ deltaY = 0;
+ } else
+ m_overflowScrollDelta.setHeight(m_overflowScrollDelta.height() + deltaY);
+ }
+ } else {
+ // Not stretching at all yet.
+ if (pinnedInDirection(deltaX, deltaY)) {
+ if (fabsf(deltaY) >= fabsf(deltaX)) {
+ if (fabsf(deltaX) < rubberbandMinimumRequiredDeltaBeforeStretch) {
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ deltaX = 0;
+ } else
+ m_overflowScrollDelta.setWidth(m_overflowScrollDelta.width() + deltaX);
+ }
+ shouldStretch = true;
+ }
+ }
+ }
+
+ if (deltaX != 0 || deltaY != 0) {
+ if (!(shouldStretch || isVerticallyStretched || isHorizontallyStretched)) {
+ if (deltaY != 0) {
+ deltaY *= scrollWheelMultiplier();
+ immediateScrollByDeltaY(deltaY);
+ }
+ if (deltaX != 0) {
+ deltaX *= scrollWheelMultiplier();
+ immediateScrollByDeltaX(deltaX);
+ }
+ } else {
+ if (!allowsHorizontalStretching()) {
+ deltaX = 0;
+ eventCoallescedDeltaX = 0;
+ } else if ((deltaX != 0) && !isHorizontallyStretched && !pinnedInDirection(deltaX, 0)) {
+ deltaX *= scrollWheelMultiplier();
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollByDeltaX(deltaX);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ deltaX = 0;
+ }
+
+ if (!allowsVerticalStretching()) {
+ deltaY = 0;
+ eventCoallescedDeltaY = 0;
+ } else if ((deltaY != 0) && !isVerticallyStretched && !pinnedInDirection(0, deltaY)) {
+ deltaY *= scrollWheelMultiplier();
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollByDeltaY(deltaY);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ deltaY = 0;
+ }
+
+ IntSize stretchAmount = m_scrollableArea->overhangAmount();
+
+ if (m_momentumScrollInProgress) {
+ if ((pinnedInDirection(eventCoallescedDeltaX, eventCoallescedDeltaY) || (fabsf(eventCoallescedDeltaX) + fabsf(eventCoallescedDeltaY) <= 0)) && m_lastMomemtumScrollTimestamp) {
+ m_ignoreMomentumScrolls = true;
+ m_momentumScrollInProgress = false;
+ snapRubberBand();
+ }
+ }
+
+ m_stretchScrollForce.setWidth(m_stretchScrollForce.width() + deltaX);
+ m_stretchScrollForce.setHeight(m_stretchScrollForce.height() + deltaY);
+
+ FloatSize dampedDelta(ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.width())), ceilf(elasticDeltaForReboundDelta(m_stretchScrollForce.height())));
+ FloatPoint origOrigin = m_scrollableArea->visibleContentRect().location() - stretchAmount;
+ FloatPoint newOrigin = origOrigin + dampedDelta;
+
+ if (origOrigin != newOrigin) {
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollToPoint(newOrigin);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+ }
+ }
+ }
+
+ if (m_momentumScrollInProgress && phase == PlatformWheelEventPhaseEnded) {
+ m_momentumScrollInProgress = false;
+ m_ignoreMomentumScrolls = false;
+ m_lastMomemtumScrollTimestamp = 0;
+ }
+}
+
+void ScrollAnimatorMac::beginScrollGesture()
+{
+ m_inScrollGesture = true;
+ m_momentumScrollInProgress = false;
+ m_ignoreMomentumScrolls = false;
+ m_lastMomemtumScrollTimestamp = 0;
+ m_momentumVelocity = FloatSize();
+
+ IntSize stretchAmount = m_scrollableArea->overhangAmount();
+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(stretchAmount.width()));
+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(stretchAmount.height()));
+
+ m_overflowScrollDelta = FloatSize();
+
+ if (m_snapRubberBandTimer.isActive())
+ m_snapRubberBandTimer.stop();
+}
+
+void ScrollAnimatorMac::endScrollGesture()
+{
+ snapRubberBand();
+}
+
+void ScrollAnimatorMac::snapRubberBand()
+{
+ CFTimeInterval timeDelta = [[NSProcessInfo processInfo] systemUptime] - m_lastMomemtumScrollTimestamp;
+ if (m_lastMomemtumScrollTimestamp && timeDelta >= scrollVelocityZeroingTimeout)
+ m_momentumVelocity = FloatSize();
+
+ m_inScrollGesture = false;
+
+ if (m_snapRubberBandTimer.isActive())
+ return;
+
+ m_startTime = [NSDate timeIntervalSinceReferenceDate];
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+
+ m_snapRubberBandTimer.startRepeating(1.0/60.0);
+}
+
+static inline float roundTowardZero(float num)
+{
+ return num > 0 ? ceilf(num - 0.5f) : floorf(num + 0.5f);
+}
+
+static inline float roundToDevicePixelTowardZero(float num)
+{
+ float roundedNum = roundf(num);
+ if (fabs(num - roundedNum) < 0.125)
+ num = roundedNum;
+
+ return roundTowardZero(num);
+}
+
+void ScrollAnimatorMac::snapRubberBandTimerFired(Timer<ScrollAnimatorMac>*)
+{
+ if (!m_momentumScrollInProgress || m_ignoreMomentumScrolls) {
+ CFTimeInterval timeDelta = [NSDate timeIntervalSinceReferenceDate] - m_startTime;
+
+ if (m_startStretch == FloatSize()) {
+ m_startStretch = m_scrollableArea->overhangAmount();
+ if (m_startStretch == FloatSize()) {
+ m_snapRubberBandTimer.stop();
+ m_stretchScrollForce = FloatSize();
+ m_startTime = 0;
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+
+ return;
+ }
+
+ m_origOrigin = m_scrollableArea->visibleContentRect().location() - m_startStretch;
+ m_origVelocity = m_momentumVelocity;
+
+ // Just like normal scrolling, prefer vertical rubberbanding
+ if (fabsf(m_origVelocity.height()) >= fabsf(m_origVelocity.width()))
+ m_origVelocity.setWidth(0);
+
+ // Don't rubber-band horizontally if it's not possible to scroll horizontally
+ Scrollbar* hScroller = m_scrollableArea->horizontalScrollbar();
+ if (!hScroller || !hScroller->enabled())
+ m_origVelocity.setWidth(0);
+
+ // Don't rubber-band vertically if it's not possible to scroll horizontally
+ Scrollbar* vScroller = m_scrollableArea->verticalScrollbar();
+ if (!vScroller || !vScroller->enabled())
+ m_origVelocity.setHeight(0);
+ }
+
+ FloatPoint delta(roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.width(), -m_origVelocity.width(), (float)timeDelta)),
+ roundToDevicePixelTowardZero(elasticDeltaForTimeDelta(m_startStretch.height(), -m_origVelocity.height(), (float)timeDelta)));
+
+ if (fabs(delta.x()) >= 1 || fabs(delta.y()) >= 1) {
+ FloatPoint newOrigin = m_origOrigin + delta;
+
+ m_scrollableArea->setConstrainsScrollingToContentEdge(false);
+ immediateScrollToPoint(newOrigin);
+ m_scrollableArea->setConstrainsScrollingToContentEdge(true);
+
+ FloatSize newStretch = m_scrollableArea->overhangAmount();
+
+ m_stretchScrollForce.setWidth(reboundDeltaForElasticDelta(newStretch.width()));
+ m_stretchScrollForce.setHeight(reboundDeltaForElasticDelta(newStretch.height()));
+ } else {
+ immediateScrollToPoint(m_origOrigin);
+
+ m_scrollableArea->didCompleteRubberBand(roundedIntSize(m_startStretch));
+
+ m_snapRubberBandTimer.stop();
+ m_stretchScrollForce = FloatSize();
+
+ m_startTime = 0;
+ m_startStretch = FloatSize();
+ m_origOrigin = FloatPoint();
+ m_origVelocity = FloatSize();
+ }
+ } else {
+ m_startTime = [NSDate timeIntervalSinceReferenceDate];
+ m_startStretch = FloatSize();
+ }
+}
+#endif
+
} // namespace WebCore
#endif // ENABLE(SMOOTH_SCROLLING)
diff --git a/Source/WebCore/platform/mac/ScrollViewMac.mm b/Source/WebCore/platform/mac/ScrollViewMac.mm
index 93ec971..ff2e14e 100644
--- a/Source/WebCore/platform/mac/ScrollViewMac.mm
+++ b/Source/WebCore/platform/mac/ScrollViewMac.mm
@@ -203,10 +203,10 @@ bool ScrollView::platformIsOffscreen() const
return ![platformWidget() window] || ![[platformWidget() window] isVisible];
}
-void ScrollView::platformSetScrollOrigin(const IntPoint& origin, bool updatePosition)
+void ScrollView::platformSetScrollOrigin(const IntPoint& origin, bool updatePositionAtAll, bool updatePositionSynchronously)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
- [scrollView() setScrollOrigin:origin updatePosition:updatePosition];
+ [scrollView() setScrollOrigin:origin updatePositionAtAll:updatePositionAtAll immediately:updatePositionSynchronously];
END_BLOCK_OBJC_EXCEPTIONS;
}
diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.h b/Source/WebCore/platform/mac/ScrollbarThemeMac.h
index 8b5412d..844a088 100644
--- a/Source/WebCore/platform/mac/ScrollbarThemeMac.h
+++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.h
@@ -26,7 +26,9 @@
#ifndef ScrollbarThemeMac_h
#define ScrollbarThemeMac_h
+#include "HeaderDetection.h"
#include "ScrollbarThemeComposite.h"
+#include "WebCoreSystemInterface.h"
namespace WebCore {
@@ -50,6 +52,11 @@ public:
virtual void registerScrollbar(Scrollbar*);
virtual void unregisterScrollbar(Scrollbar*);
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+ void setNewPainterForScrollbar(Scrollbar*, WKScrollbarPainterRef);
+ WKScrollbarPainterRef painterForScrollbar(Scrollbar*);
+#endif
+
protected:
virtual bool hasButtons(Scrollbar*);
virtual bool hasThumb(Scrollbar*);
diff --git a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
index 032d9f3..c35dfa0 100644
--- a/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
+++ b/Source/WebCore/platform/mac/ScrollbarThemeMac.mm
@@ -29,17 +29,13 @@
#include "ImageBuffer.h"
#include "LocalCurrentGraphicsContext.h"
#include "PlatformMouseEvent.h"
+#include "ScrollAnimatorMac.h"
#include "ScrollView.h"
-#include "WebCoreSystemInterface.h"
#include <Carbon/Carbon.h>
#include <wtf/HashMap.h>
#include <wtf/StdLibExtras.h>
#include <wtf/UnusedParam.h>
-#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
-#define USE_WK_SCROLLBAR_PAINTER
-#endif
-
// FIXME: There are repainting problems due to Aqua scroll bar buttons' visual overflow.
using namespace std;
@@ -47,7 +43,7 @@ using namespace WebCore;
namespace WebCore {
-#if defined(USE_WK_SCROLLBAR_PAINTER)
+#if USE(WK_SCROLLBAR_PAINTER)
typedef HashMap<Scrollbar*, RetainPtr<WKScrollbarPainterRef> > ScrollbarPainterMap;
#else
typedef HashSet<Scrollbar*> ScrollbarPainterMap;
@@ -83,7 +79,7 @@ static ScrollbarPainterMap* scrollbarMap()
return;
ScrollbarPainterMap::iterator end = scrollbarMap()->end();
for (ScrollbarPainterMap::iterator it = scrollbarMap()->begin(); it != end; ++it) {
-#if defined(USE_WK_SCROLLBAR_PAINTER)
+#if USE(WK_SCROLLBAR_PAINTER)
it->first->styleChanged();
it->first->invalidate();
#else
@@ -117,13 +113,15 @@ ScrollbarTheme* ScrollbarTheme::nativeTheme()
}
// FIXME: Get these numbers from CoreUI.
-static int cScrollbarThickness[] = { 15, 11 };
static int cRealButtonLength[] = { 28, 21 };
-static int cButtonInset[] = { 14, 11 };
static int cButtonHitInset[] = { 3, 2 };
// cRealButtonLength - cButtonInset
static int cButtonLength[] = { 14, 10 };
+#if !USE(WK_SCROLLBAR_PAINTER)
+static int cScrollbarThickness[] = { 15, 11 };
+static int cButtonInset[] = { 14, 11 };
static int cThumbMinLength[] = { 26, 20 };
+#endif
static int cOuterButtonLength[] = { 16, 14 }; // The outer button in a double button pair is a bit bigger.
static int cOuterButtonOverlap = 2;
@@ -131,13 +129,15 @@ static int cOuterButtonOverlap = 2;
static float gInitialButtonDelay = 0.5f;
static float gAutoscrollButtonDelay = 0.05f;
static bool gJumpOnTrackClick = false;
+
+#if USE(WK_SCROLLBAR_PAINTER)
+static ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsNone;
+#else
static ScrollbarButtonsPlacement gButtonPlacement = ScrollbarButtonsDoubleEnd;
+#endif
static void updateArrowPlacement()
{
-#if defined(USE_WK_SCROLLBAR_PAINTER)
- gButtonPlacement = ScrollbarButtonsNone;
-#else
NSString *buttonPlacement = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleScrollBarVariant"];
if ([buttonPlacement isEqualToString:@"Single"])
gButtonPlacement = ScrollbarButtonsSingle;
@@ -145,16 +145,20 @@ static void updateArrowPlacement()
gButtonPlacement = ScrollbarButtonsDoubleStart;
else if ([buttonPlacement isEqualToString:@"DoubleBoth"])
gButtonPlacement = ScrollbarButtonsDoubleBoth;
- else
- gButtonPlacement = ScrollbarButtonsDoubleEnd; // The default is ScrollbarButtonsDoubleEnd.
+ else {
+#if USE(WK_SCROLLBAR_PAINTER)
+ gButtonPlacement = ScrollbarButtonsNone;
+#else
+ gButtonPlacement = ScrollbarButtonsDoubleEnd;
#endif
+ }
}
void ScrollbarThemeMac::registerScrollbar(Scrollbar* scrollbar)
{
-#if defined(USE_WK_SCROLLBAR_PAINTER)
- WKScrollbarPainterRef scrollbarPainter = wkMakeScrollbarPainter(scrollbar->controlSize(),
- scrollbar->orientation() == HorizontalScrollbar);
+#if USE(WK_SCROLLBAR_PAINTER)
+ bool isHorizontal = scrollbar->orientation() == HorizontalScrollbar;
+ WKScrollbarPainterRef scrollbarPainter = wkMakeScrollbarPainter(scrollbar->controlSize(), isHorizontal);
scrollbarMap()->add(scrollbar, scrollbarPainter);
#else
scrollbarMap()->add(scrollbar);
@@ -163,9 +167,22 @@ void ScrollbarThemeMac::registerScrollbar(Scrollbar* scrollbar)
void ScrollbarThemeMac::unregisterScrollbar(Scrollbar* scrollbar)
{
+
scrollbarMap()->remove(scrollbar);
}
+#if defined(USE_WK_SCROLLBAR_PAINTER_AND_CONTROLLER)
+void ScrollbarThemeMac::setNewPainterForScrollbar(Scrollbar* scrollbar, WKScrollbarPainterRef newPainter)
+{
+ scrollbarMap()->set(scrollbar, newPainter);
+}
+
+WKScrollbarPainterRef ScrollbarThemeMac::painterForScrollbar(Scrollbar* scrollbar)
+{
+ return scrollbarMap()->get(scrollbar).get();
+}
+#endif
+
ScrollbarThemeMac::ScrollbarThemeMac()
{
static bool initialized;
@@ -192,13 +209,20 @@ void ScrollbarThemeMac::preferencesChanged()
int ScrollbarThemeMac::scrollbarThickness(ScrollbarControlSize controlSize)
{
+#if USE(WK_SCROLLBAR_PAINTER)
+ return wkScrollbarThickness(controlSize);
+#else
return cScrollbarThickness[controlSize];
+#endif
}
bool ScrollbarThemeMac::usesOverlayScrollbars() const
{
- // FIXME: This should be enabled when <rdar://problem/8492788> is resolved.
+#if USE(WK_SCROLLBAR_PAINTER)
+ return wkScrollbarPainterUsesOverlayScrollers();
+#else
return false;
+#endif
}
double ScrollbarThemeMac::initialAutoscrollTimerDelay()
@@ -218,20 +242,29 @@ ScrollbarButtonsPlacement ScrollbarThemeMac::buttonsPlacement() const
bool ScrollbarThemeMac::hasButtons(Scrollbar* scrollbar)
{
- return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ?
- scrollbar->width() :
- scrollbar->height()) >= 2 * (cRealButtonLength[scrollbar->controlSize()] - cButtonHitInset[scrollbar->controlSize()]);
+ return scrollbar->enabled() && gButtonPlacement != ScrollbarButtonsNone
+ && (scrollbar->orientation() == HorizontalScrollbar
+ ? scrollbar->width()
+ : scrollbar->height()) >= 2 * (cRealButtonLength[scrollbar->controlSize()] - cButtonHitInset[scrollbar->controlSize()]);
}
bool ScrollbarThemeMac::hasThumb(Scrollbar* scrollbar)
{
+ int minLengthForThumb;
+#if USE(WK_SCROLLBAR_PAINTER)
+ minLengthForThumb = wkScrollbarMinimumTotalLengthNeededForThumb(scrollbarMap()->get(scrollbar).get());
+#else
+ minLengthForThumb = 2 * cButtonInset[scrollbar->controlSize()] + cThumbMinLength[scrollbar->controlSize()] + 1;
+#endif
return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ?
scrollbar->width() :
- scrollbar->height()) >= 2 * cButtonInset[scrollbar->controlSize()] + cThumbMinLength[scrollbar->controlSize()] + 1;
+ scrollbar->height()) >= minLengthForThumb;
}
static IntRect buttonRepaintRect(const IntRect& buttonRect, ScrollbarOrientation orientation, ScrollbarControlSize controlSize, bool start)
{
+ ASSERT(gButtonPlacement != ScrollbarButtonsNone);
+
IntRect paintRect(buttonRect);
if (orientation == HorizontalScrollbar) {
paintRect.setWidth(cRealButtonLength[controlSize]);
@@ -359,7 +392,11 @@ IntRect ScrollbarThemeMac::trackRect(Scrollbar* scrollbar, bool painting)
int ScrollbarThemeMac::minimumThumbLength(Scrollbar* scrollbar)
{
+#if USE(WK_SCROLLBAR_PAINTER)
+ return wkScrollbarMinimumThumbLength(scrollbarMap()->get(scrollbar).get());
+#else
return cThumbMinLength[scrollbar->controlSize()];
+#endif
}
bool ScrollbarThemeMac::shouldCenterOnThumb(Scrollbar*, const PlatformMouseEvent& evt)
@@ -391,15 +428,32 @@ static int scrollbarPartToHIPressedState(ScrollbarPart part)
bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, const IntRect& damageRect)
{
-#if defined(USE_WK_SCROLLBAR_PAINTER)
+#if USE(WK_SCROLLBAR_PAINTER)
+ float value = 0.0f;
+ float totalSize = 0.0f;
+
+ if (scrollbar->currentPos() < 0) {
+ // Scrolled past the top.
+ value = 0.0f;
+ totalSize = scrollbar->totalSize() - scrollbar->currentPos();
+ } else if (scrollbar->visibleSize() + scrollbar->currentPos() > scrollbar->totalSize()) {
+ // Scrolled past the bottom.
+ value = 1.0f;
+ totalSize = scrollbar->visibleSize() + scrollbar->currentPos();
+ } else {
+ // Within the bounds of the scrollable area.
+ value = scrollbar->currentPos() / scrollbar->maximum();
+ totalSize = scrollbar->totalSize();
+ }
+
context->save();
context->clip(damageRect);
context->translate(scrollbar->frameRect().x(), scrollbar->frameRect().y());
LocalCurrentGraphicsContext localContext(context);
wkScrollbarPainterPaint(scrollbarMap()->get(scrollbar).get(),
scrollbar->enabled(),
- scrollbar->currentPos() / scrollbar->maximum(),
- static_cast<CGFloat>(scrollbar->visibleSize()) / scrollbar->totalSize(),
+ value,
+ static_cast<CGFloat>(scrollbar->visibleSize()) / totalSize,
scrollbar->frameRect());
context->restore();
return true;
@@ -409,9 +463,27 @@ bool ScrollbarThemeMac::paint(Scrollbar* scrollbar, GraphicsContext* context, co
trackInfo.version = 0;
trackInfo.kind = scrollbar->controlSize() == RegularScrollbar ? kThemeMediumScrollBar : kThemeSmallScrollBar;
trackInfo.bounds = scrollbar->frameRect();
+
+ float maximum = 0.0f;
+ float position = 0.0f;
+ if (scrollbar->currentPos() < 0) {
+ // Scrolled past the top.
+ maximum = (scrollbar->totalSize() - scrollbar->currentPos()) - scrollbar->visibleSize();
+ position = 0;
+ } else if (scrollbar->visibleSize() + scrollbar->currentPos() > scrollbar->totalSize()) {
+ // Scrolled past the bottom.
+ maximum = scrollbar->currentPos();
+ position = maximum;
+ } else {
+ // Within the bounds of the scrollable area.
+ maximum = scrollbar->maximum();
+ position = scrollbar->currentPos();
+ }
+
trackInfo.min = 0;
- trackInfo.max = scrollbar->maximum();
- trackInfo.value = scrollbar->currentPos();
+ trackInfo.max = static_cast<int>(maximum);
+ trackInfo.value = static_cast<int>(position);
+
trackInfo.trackInfo.scrollbar.viewsize = scrollbar->visibleSize();
trackInfo.attributes = 0;
if (scrollbar->orientation() == HorizontalScrollbar)
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.h b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
index 045864a..e6d6cf6 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.h
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.h
@@ -147,6 +147,8 @@ extern void (*wkSignalCFReadStreamEnd)(CFReadStreamRef stream);
extern void (*wkSignalCFReadStreamError)(CFReadStreamRef stream, CFStreamError *error);
extern void (*wkSignalCFReadStreamHasBytes)(CFReadStreamRef stream);
extern unsigned (*wkInitializeMaximumHTTPConnectionCountPerHost)(unsigned preferredConnectionCount);
+extern int (*wkGetHTTPPipeliningPriority)(NSURLRequest *);
+extern void (*wkSetHTTPPipeliningPriority)(NSMutableURLRequest *, int priority);
extern void (*wkSetCONNECTProxyForStream)(CFReadStreamRef, CFStringRef proxyHost, CFNumberRef proxyPort);
extern void (*wkSetCONNECTProxyAuthorizationForStream)(CFReadStreamRef, CFStringRef proxyAuthorizationString);
extern CFHTTPMessageRef (*wkCopyCONNECTProxyResponse)(CFReadStreamRef, CFURLRef responseURL);
@@ -189,9 +191,50 @@ extern CGImageRef (*wkIOSurfaceContextCreateImage)(CGContextRef context);
typedef struct __WKScrollbarPainter *WKScrollbarPainterRef;
extern WKScrollbarPainterRef (*wkMakeScrollbarPainter)(int controlSize, bool isHorizontal);
+extern WKScrollbarPainterRef (*wkMakeScrollbarReplacementPainter)(WKScrollbarPainterRef oldPainter, int newStyle, int controlSize, bool isHorizontal);
+extern void (*wkScrollbarPainterSetDelegate)(WKScrollbarPainterRef, id scrollbarPainterDelegate);
extern void (*wkScrollbarPainterPaint)(WKScrollbarPainterRef, bool enabled, double value, CGFloat proportion, CGRect frameRect);
+extern int (*wkScrollbarThickness)(int controlSize);
+extern int (*wkScrollbarMinimumThumbLength)(WKScrollbarPainterRef);
+extern int (*wkScrollbarMinimumTotalLengthNeededForThumb)(WKScrollbarPainterRef);
+extern CGFloat (*wkScrollbarPainterKnobAlpha)(WKScrollbarPainterRef);
+extern void (*wkSetScrollbarPainterKnobAlpha)(WKScrollbarPainterRef, CGFloat);
+extern CGFloat (*wkScrollbarPainterTrackAlpha)(WKScrollbarPainterRef);
+extern void (*wkSetScrollbarPainterTrackAlpha)(WKScrollbarPainterRef, CGFloat);
+extern bool (*wkScrollbarPainterIsHorizontal)(WKScrollbarPainterRef);
+extern void (*wkScrollbarPainterSetOverlayState)(WKScrollbarPainterRef, int overlayScrollerState);
+
+typedef struct __WKScrollbarPainterController *WKScrollbarPainterControllerRef;
+extern WKScrollbarPainterControllerRef (*wkMakeScrollbarPainterController)(id painterControllerDelegate);
+extern void (*wkSetPainterForPainterController)(WKScrollbarPainterControllerRef, WKScrollbarPainterRef, bool isHorizontal);
+extern WKScrollbarPainterRef (*wkVerticalScrollbarPainterForController)(WKScrollbarPainterControllerRef);
+extern WKScrollbarPainterRef (*wkHorizontalScrollbarPainterForController)(WKScrollbarPainterControllerRef);
+extern void (*wkSetScrollbarPainterControllerStyle)(WKScrollbarPainterControllerRef, int newStyle);
+extern void (*wkContentAreaScrolled)(WKScrollbarPainterControllerRef);
+extern void (*wkContentAreaWillPaint)(WKScrollbarPainterControllerRef);
+extern void (*wkMouseEnteredContentArea)(WKScrollbarPainterControllerRef);
+extern void (*wkMouseExitedContentArea)(WKScrollbarPainterControllerRef);
+extern void (*wkMouseMovedInContentArea)(WKScrollbarPainterControllerRef);
+extern void (*wkWillStartLiveResize)(WKScrollbarPainterControllerRef);
+extern void (*wkContentAreaResized)(WKScrollbarPainterControllerRef);
+extern void (*wkWillEndLiveResize)(WKScrollbarPainterControllerRef);
+extern void (*wkContentAreaDidShow)(WKScrollbarPainterControllerRef);
+extern void (*wkContentAreaDidHide)(WKScrollbarPainterControllerRef);
+
+extern bool (*wkScrollbarPainterUsesOverlayScrollers)(void);
#endif
+extern void (*wkUnregisterUniqueIdForElement)(id element);
+extern void (*wkAccessibilityHandleFocusChanged)(void);
+extern CFTypeID (*wkGetAXTextMarkerTypeID)(void);
+extern CFTypeID (*wkGetAXTextMarkerRangeTypeID)(void);
+extern CFTypeRef (*wkCreateAXTextMarkerRange)(CFTypeRef start, CFTypeRef end);
+extern CFTypeRef (*wkCopyAXTextMarkerRangeStart)(CFTypeRef range);
+extern CFTypeRef (*wkCopyAXTextMarkerRangeEnd)(CFTypeRef range);
+extern CFTypeRef (*wkCreateAXTextMarker)(const void *bytes, size_t len);
+extern BOOL (*wkGetBytesFromAXTextMarker)(CFTypeRef textMarker, void *bytes, size_t length);
+extern AXUIElementRef (*wkCreateAXUIElementRef)(id element);
+
}
#endif
diff --git a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
index 047827f..24bdcb1 100644
--- a/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
+++ b/Source/WebCore/platform/mac/WebCoreSystemInterface.mm
@@ -89,6 +89,8 @@ void (*wkSetNSURLConnectionDefersCallbacks)(NSURLConnection *, BOOL);
void (*wkSetNSURLRequestShouldContentSniff)(NSMutableURLRequest *, BOOL);
id (*wkCreateNSURLConnectionDelegateProxy)(void);
unsigned (*wkInitializeMaximumHTTPConnectionCountPerHost)(unsigned preferredConnectionCount);
+int (*wkGetHTTPPipeliningPriority)(NSURLRequest *);
+void (*wkSetHTTPPipeliningPriority)(NSMutableURLRequest *, int priority);
void (*wkSetCONNECTProxyForStream)(CFReadStreamRef, CFStringRef proxyHost, CFNumberRef proxyPort);
void (*wkSetCONNECTProxyAuthorizationForStream)(CFReadStreamRef, CFStringRef proxyAuthorizationString);
CFHTTPMessageRef (*wkCopyCONNECTProxyResponse)(CFReadStreamRef, CFURLRef responseURL);
@@ -127,5 +129,46 @@ CGContextRef (*wkIOSurfaceContextCreate)(IOSurfaceRef surface, unsigned width, u
CGImageRef (*wkIOSurfaceContextCreateImage)(CGContextRef context);
WKScrollbarPainterRef (*wkMakeScrollbarPainter)(int controlSize, bool isHorizontal);
+WKScrollbarPainterRef (*wkMakeScrollbarReplacementPainter)(WKScrollbarPainterRef oldPainter, int newStyle, int controlSize, bool isHorizontal);
+void (*wkScrollbarPainterSetDelegate)(WKScrollbarPainterRef, id scrollbarPainterDelegate);
void (*wkScrollbarPainterPaint)(WKScrollbarPainterRef, bool enabled, double value, CGFloat proportion, CGRect frameRect);
+int (*wkScrollbarThickness)(int controlSize);
+int (*wkScrollbarMinimumThumbLength)(WKScrollbarPainterRef);
+int (*wkScrollbarMinimumTotalLengthNeededForThumb)(WKScrollbarPainterRef);
+CGFloat (*wkScrollbarPainterKnobAlpha)(WKScrollbarPainterRef);
+void (*wkSetScrollbarPainterKnobAlpha)(WKScrollbarPainterRef, CGFloat);
+CGFloat (*wkScrollbarPainterTrackAlpha)(WKScrollbarPainterRef);
+void (*wkSetScrollbarPainterTrackAlpha)(WKScrollbarPainterRef, CGFloat);
+bool (*wkScrollbarPainterIsHorizontal)(WKScrollbarPainterRef);
+void (*wkScrollbarPainterSetOverlayState)(WKScrollbarPainterRef, int overlayScrollerState);
+
+WKScrollbarPainterControllerRef (*wkMakeScrollbarPainterController)(id painterControllerDelegate);
+void (*wkSetPainterForPainterController)(WKScrollbarPainterControllerRef, WKScrollbarPainterRef, bool isHorizontal);
+WKScrollbarPainterRef (*wkVerticalScrollbarPainterForController)(WKScrollbarPainterControllerRef);
+WKScrollbarPainterRef (*wkHorizontalScrollbarPainterForController)(WKScrollbarPainterControllerRef);
+void (*wkSetScrollbarPainterControllerStyle)(WKScrollbarPainterControllerRef, int newStyle);
+void (*wkContentAreaScrolled)(WKScrollbarPainterControllerRef);
+void (*wkContentAreaWillPaint)(WKScrollbarPainterControllerRef);
+void (*wkMouseEnteredContentArea)(WKScrollbarPainterControllerRef);
+void (*wkMouseExitedContentArea)(WKScrollbarPainterControllerRef);
+void (*wkMouseMovedInContentArea)(WKScrollbarPainterControllerRef);
+void (*wkWillStartLiveResize)(WKScrollbarPainterControllerRef);
+void (*wkContentAreaResized)(WKScrollbarPainterControllerRef);
+void (*wkWillEndLiveResize)(WKScrollbarPainterControllerRef);
+void (*wkContentAreaDidShow)(WKScrollbarPainterControllerRef);
+void (*wkContentAreaDidHide)(WKScrollbarPainterControllerRef);
+
+bool (*wkScrollbarPainterUsesOverlayScrollers)(void);
#endif
+
+void (*wkUnregisterUniqueIdForElement)(id element);
+void (*wkAccessibilityHandleFocusChanged)(void);
+CFTypeID (*wkGetAXTextMarkerTypeID)(void);
+CFTypeID (*wkGetAXTextMarkerRangeTypeID)(void);
+CFTypeRef (*wkCreateAXTextMarkerRange)(CFTypeRef start, CFTypeRef end);
+CFTypeRef (*wkCopyAXTextMarkerRangeStart)(CFTypeRef range);
+CFTypeRef (*wkCopyAXTextMarkerRangeEnd)(CFTypeRef range);
+CFTypeRef (*wkCreateAXTextMarker)(const void *bytes, size_t len);
+BOOL (*wkGetBytesFromAXTextMarker)(CFTypeRef textMarker, void *bytes, size_t length);
+AXUIElementRef (*wkCreateAXUIElementRef)(id element);
+
diff --git a/Source/WebCore/platform/mac/WheelEventMac.mm b/Source/WebCore/platform/mac/WheelEventMac.mm
index d4fc698..74265d1 100644
--- a/Source/WebCore/platform/mac/WheelEventMac.mm
+++ b/Source/WebCore/platform/mac/WheelEventMac.mm
@@ -64,6 +64,7 @@ PlatformWheelEvent::PlatformWheelEvent(NSEvent* event, NSView *windowView)
, m_altKey([event modifierFlags] & NSAlternateKeyMask)
, m_metaKey([event modifierFlags] & NSCommandKeyMask)
, m_phase(phaseForEvent(event))
+ , m_timestamp([event timestamp])
{
BOOL continuous;
@@ -71,11 +72,13 @@ PlatformWheelEvent::PlatformWheelEvent(NSEvent* event, NSView *windowView)
if (continuous) {
m_wheelTicksX = m_deltaX / static_cast<float>(Scrollbar::pixelsPerLineStep());
m_wheelTicksY = m_deltaY / static_cast<float>(Scrollbar::pixelsPerLineStep());
+ m_hasPreciseScrollingDeltas = true;
} else {
m_wheelTicksX = m_deltaX;
m_wheelTicksY = m_deltaY;
m_deltaX *= static_cast<float>(Scrollbar::pixelsPerLineStep());
m_deltaY *= static_cast<float>(Scrollbar::pixelsPerLineStep());
+ m_hasPreciseScrollingDeltas = false;
}
}
diff --git a/Source/WebCore/platform/mac/WidgetMac.mm b/Source/WebCore/platform/mac/WidgetMac.mm
index f3c951a..96bcde2 100644
--- a/Source/WebCore/platform/mac/WidgetMac.mm
+++ b/Source/WebCore/platform/mac/WidgetMac.mm
@@ -252,7 +252,7 @@ void Widget::paint(GraphicsContext* p, const IntRect& r)
IntRect dirtyRect = r;
dirtyRect.move(-transformOrigin.x(), -transformOrigin.y());
if (![view isFlipped])
- dirtyRect.setY([view bounds].size.height - dirtyRect.bottom());
+ dirtyRect.setY([view bounds].size.height - dirtyRect.maxY());
[view displayRectIgnoringOpacity:dirtyRect];
@@ -296,7 +296,7 @@ void Widget::paint(GraphicsContext* p, const IntRect& r)
IntRect dirtyRect = r;
dirtyRect.move(-transformOrigin.x(), -transformOrigin.y());
if (![view isFlipped])
- dirtyRect.setY([view bounds].size.height - dirtyRect.bottom());
+ dirtyRect.setY([view bounds].size.height - dirtyRect.maxY());
BEGIN_BLOCK_OBJC_EXCEPTIONS;
{