blob: 7cf0d3c871cb8db8ea72aeb1e9a20ac40ea859f8 [file] [log] [blame]
/*
* Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (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 "ScrollView.h"
#if PLATFORM(IOS_FAMILY)
#import "FloatRect.h"
#import "IntRect.h"
#import "Logging.h"
#import "NotImplemented.h"
#import "WAKAppKitStubs.h"
#import "WAKClipView.h"
#import "WAKScrollView.h"
#import "WAKViewInternal.h"
#import "WAKWindow.h"
#import "WKViewPrivate.h"
#import "WebCoreFrameView.h"
#import <wtf/BlockObjCExceptions.h>
using namespace std;
namespace WebCore {
inline NSScrollView<WebCoreFrameScrollView> *ScrollView::scrollView() const
{
ASSERT(!platformWidget() || [platformWidget() isKindOfClass:[NSScrollView class]]);
ASSERT(!platformWidget() || [platformWidget() conformsToProtocol:@protocol(WebCoreFrameScrollView)]);
return static_cast<NSScrollView<WebCoreFrameScrollView> *>(platformWidget());
}
NSView *ScrollView::documentView() const
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
return [scrollView() documentView];
END_BLOCK_OBJC_EXCEPTIONS;
return nil;
}
void ScrollView::platformAddChild(Widget* child)
{
ASSERT(child != this);
child->addToSuperview(documentView());
}
void ScrollView::platformRemoveChild(Widget* child)
{
child->removeFromSuperview();
}
void ScrollView::platformSetScrollbarModes()
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[scrollView() setScrollingModes:m_horizontalScrollbarMode vertical:m_verticalScrollbarMode andLock:NO];
END_BLOCK_OBJC_EXCEPTIONS;
}
void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[scrollView() scrollingModes:&horizontal vertical:&vertical];
END_BLOCK_OBJC_EXCEPTIONS;
}
void ScrollView::platformSetCanBlitOnScroll(bool canBlitOnScroll)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[[scrollView() contentView] setCopiesOnScroll:canBlitOnScroll];
END_BLOCK_OBJC_EXCEPTIONS;
}
bool ScrollView::platformCanBlitOnScroll() const
{
return [[scrollView() contentView] copiesOnScroll];
}
IntRect ScrollView::unobscuredContentRect(VisibleContentRectIncludesScrollbars) const
{
if (WAKScrollView *view = static_cast<WAKScrollView *>(platformWidget())) {
CGRect r = CGRectZero;
BEGIN_BLOCK_OBJC_EXCEPTIONS;
r = [view unobscuredContentRect];
END_BLOCK_OBJC_EXCEPTIONS;
return enclosingIntRect(r);
}
if (!m_unobscuredContentSize.isEmpty())
return IntRect(m_scrollPosition, roundedIntSize(m_unobscuredContentSize));
return unobscuredContentRectInternal();
}
void ScrollView::setUnobscuredContentSize(const FloatSize& size)
{
ASSERT(!platformWidget());
if (size == m_unobscuredContentSize)
return;
m_unobscuredContentSize = size;
unobscuredContentSizeChanged();
}
FloatRect ScrollView::exposedContentRect() const
{
if (NSScrollView *view = static_cast<NSScrollView *>(platformWidget())) {
CGRect r = CGRectZero;
BEGIN_BLOCK_OBJC_EXCEPTIONS;
if ([view isKindOfClass:[NSScrollView class]])
r = [view exposedContentRect];
else {
r.origin = [view visibleRect].origin;
r.size = [view bounds].size;
}
END_BLOCK_OBJC_EXCEPTIONS;
return r;
}
const ScrollView* parent = this->parent();
if (!parent)
return m_exposedContentRect;
IntRect parentViewExtentContentRect = enclosingIntRect(parent->exposedContentRect());
IntRect selfExtentContentRect = rootViewToContents(parentViewExtentContentRect);
selfExtentContentRect.intersect(boundsRect());
return selfExtentContentRect;
}
void ScrollView::setExposedContentRect(const FloatRect& rect)
{
ASSERT(!platformWidget());
m_exposedContentRect = rect;
}
void ScrollView::setActualScrollPosition(const IntPoint& position)
{
NSScrollView *view = static_cast<NSScrollView *>(platformWidget());
BEGIN_BLOCK_OBJC_EXCEPTIONS;
if ([view isKindOfClass:[NSScrollView class]])
[view setActualScrollPosition:position];
END_BLOCK_OBJC_EXCEPTIONS;
}
float ScrollView::platformTopContentInset() const
{
return 0;
}
void ScrollView::platformSetTopContentInset(float)
{
}
IntRect ScrollView::platformVisibleContentRect(bool includeScrollbars) const
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
if (includeScrollbars) {
if (NSView* documentView = this->documentView())
return enclosingIntRect([documentView visibleRect]);
}
return enclosingIntRect([scrollView() documentVisibleRect]);
END_BLOCK_OBJC_EXCEPTIONS;
return IntRect();
}
IntSize ScrollView::platformVisibleContentSize(bool includeScrollbars) const
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
if (includeScrollbars) {
if (NSView* documentView = this->documentView())
return IntSize([documentView visibleRect].size);
}
return expandedIntSize(FloatSize([scrollView() documentVisibleRect].size));
END_BLOCK_OBJC_EXCEPTIONS;
return IntSize();
}
IntRect ScrollView::platformVisibleContentRectIncludingObscuredArea(bool includeScrollbars) const
{
return platformVisibleContentRect(includeScrollbars);
}
IntSize ScrollView::platformVisibleContentSizeIncludingObscuredArea(bool includeScrollbars) const
{
return platformVisibleContentSize(includeScrollbars);
}
LegacyTileCache* ScrollView::legacyTileCache()
{
// Make tile cache pointer available via the main frame only. Tile cache interaction should be managed by
// the main frame and this avoids having to add parent checks to all call sites.
if (parent())
return 0;
BEGIN_BLOCK_OBJC_EXCEPTIONS;
WAKScrollView *view = static_cast<WAKScrollView *>(platformWidget());
return [[view window] tileCache];
END_BLOCK_OBJC_EXCEPTIONS;
}
void ScrollView::platformSetContentsSize()
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
int w = m_contentsSize.width();
int h = m_contentsSize.height();
#if !PLATFORM(IOS_FAMILY)
LOG(Frames, "%p %@ at w %d h %d\n", documentView(), [(id)[documentView() class] className], w, h);
#else
LOG(Frames, "%p %@ at w %d h %d\n", documentView(), NSStringFromClass([documentView() class]), w, h);
#endif
NSSize tempSize = { static_cast<CGFloat>(max(0, w)), static_cast<CGFloat>(max(0, h)) }; // workaround for 4213314
[documentView() setBoundsSize:tempSize];
END_BLOCK_OBJC_EXCEPTIONS;
}
void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[scrollView() setScrollBarsSuppressed:m_scrollbarsSuppressed
repaintOnUnsuppress:repaintOnUnsuppress];
END_BLOCK_OBJC_EXCEPTIONS;
}
void ScrollView::platformSetScrollPosition(const IntPoint& scrollPoint)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
NSPoint floatPoint = scrollPoint;
NSPoint tempPoint = { max(-[scrollView() scrollOrigin].x, floatPoint.x), max(-[scrollView() scrollOrigin].y, floatPoint.y) }; // Don't use NSMakePoint to work around 4213314.
[documentView() scrollPoint:tempPoint];
END_BLOCK_OBJC_EXCEPTIONS;
}
bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity)
{
// FIXME: It would be nice to implement this so that all of the code in WebFrameView could go away.
notImplemented();
return false;
}
void ScrollView::platformRepaintContentRectangle(const IntRect& rect)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
NSView *view = documentView();
[view setNeedsDisplayInRect:rect];
END_BLOCK_OBJC_EXCEPTIONS;
}
// "Containing Window" means the NSWindow's coord system, which is origin lower left
IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
if (NSView* documentView = this->documentView()) {
NSRect tempRect = rect;
tempRect = [documentView convertRect:tempRect toView:nil];
tempRect.origin = [[documentView window] convertBaseToScreen:tempRect.origin];
return enclosingIntRect(tempRect);
}
END_BLOCK_OBJC_EXCEPTIONS;
return IntRect();
}
IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
if (NSView* documentView = this->documentView()) {
NSPoint windowCoord = [[documentView window] convertScreenToBase: point];
return IntPoint([documentView convertPoint:windowCoord fromView:nil]);
}
END_BLOCK_OBJC_EXCEPTIONS;
return IntPoint();
}
bool ScrollView::platformIsOffscreen() const
{
// FIXME: DDK: ScrollViewMac.mm also checks: ![[platformWidget() window] isVisible]
// but -[WAKWindow isVisible] doesn't exist.
return ![platformWidget() window];
}
void ScrollView::platformSetScrollbarOverlayStyle(ScrollbarOverlayStyle)
{
}
void ScrollView::platformSetScrollOrigin(const IntPoint& origin, bool updatePositionAll, bool updatePositionSynchronously)
{
BEGIN_BLOCK_OBJC_EXCEPTIONS;
[scrollView() setScrollOrigin:static_cast<CGPoint>(origin) updatePositionAtAll:updatePositionAll immediately:updatePositionSynchronously];
END_BLOCK_OBJC_EXCEPTIONS;
}
}
#endif // PLATFORM(IOS_FAMILY)