diff options
Diffstat (limited to 'WebCore/platform/mac/ScrollViewMac.mm')
-rw-r--r-- | WebCore/platform/mac/ScrollViewMac.mm | 454 |
1 files changed, 84 insertions, 370 deletions
diff --git a/WebCore/platform/mac/ScrollViewMac.mm b/WebCore/platform/mac/ScrollViewMac.mm index 1caa433..6d477e2 100644 --- a/WebCore/platform/mac/ScrollViewMac.mm +++ b/WebCore/platform/mac/ScrollViewMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved. + * 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 @@ -26,333 +26,146 @@ #import "config.h" #import "ScrollView.h" +#import "BlockExceptions.h" #import "FloatRect.h" #import "IntRect.h" -#import "BlockExceptions.h" #import "Logging.h" +#import "NotImplemented.h" #import "WebCoreFrameView.h" -/* - This class implementation does NOT actually emulate the Qt ScrollView. - It does provide an implementation that khtml will use to interact with - WebKit's WebFrameView documentView and our NSScrollView subclass. +using namespace std; - ScrollView's view is a NSScrollView (or subclass of NSScrollView) - in most cases. That scrollview is a subview of an - WebCoreFrameView. The WebCoreFrameView's documentView will also be - the scroll view's documentView. - - The WebCoreFrameView's size is the frame size. The WebCoreFrameView's documentView - corresponds to the frame content size. The scrollview itself is autosized to the - WebCoreFrameView's size (see Widget::resize). -*/ +@interface NSWindow (WebWindowDetails) +- (BOOL)_needsToResetDragMargins; +- (void)_setNeedsToResetDragMargins:(BOOL)needs; +@end namespace WebCore { -int ScrollView::visibleWidth() const -{ - NSScrollView *view = (NSScrollView *)getView(); - - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view isKindOfClass:[NSScrollView class]]) - return (int)[view documentVisibleRect].size.width; - else - return (int)[view bounds].size.width; - END_BLOCK_OBJC_EXCEPTIONS; - - return 0; -} - -int ScrollView::visibleHeight() const -{ - NSScrollView *view = (NSScrollView *)getView(); - - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view isKindOfClass:[NSScrollView class]]) - return (int)[view documentVisibleRect].size.height; - else - return (int)[view bounds].size.height; - END_BLOCK_OBJC_EXCEPTIONS; - - return 0; -} - -FloatRect ScrollView::visibleContentRect() const +inline NSScrollView<WebCoreFrameScrollView> *ScrollView::scrollView() const { - NSScrollView *view = (NSScrollView *)getView(); - - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view isKindOfClass:[NSScrollView class]]) - return [view documentVisibleRect]; - else - return [view visibleRect]; - END_BLOCK_OBJC_EXCEPTIONS; - - return FloatRect(); + ASSERT(!platformWidget() || [platformWidget() isKindOfClass:[NSScrollView class]]); + ASSERT(!platformWidget() || [platformWidget() conformsToProtocol:@protocol(WebCoreFrameScrollView)]); + return static_cast<NSScrollView<WebCoreFrameScrollView> *>(platformWidget()); } -FloatRect ScrollView::visibleContentRectConsideringExternalScrollers() const +NSView *ScrollView::documentView() const { BEGIN_BLOCK_OBJC_EXCEPTIONS; - if (NSView *docView = getDocumentView()) - return [docView visibleRect]; + return [scrollView() documentView]; END_BLOCK_OBJC_EXCEPTIONS; - - return FloatRect(); + return nil; } - -int ScrollView::contentsWidth() const +void ScrollView::platformAddChild(Widget* child) { - NSView *docView, *view = getView(); - docView = getDocumentView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if (docView) - return (int)[docView bounds].size.width; - else - return (int)[view bounds].size.width; + NSView *parentView = documentView(); + NSView *childView = child->getOuterView(); + ASSERT(![parentView isDescendantOf:childView]); + + // Suppress the resetting of drag margins since we know we can't affect them. + NSWindow *window = [parentView window]; + BOOL resetDragMargins = [window _needsToResetDragMargins]; + [window _setNeedsToResetDragMargins:NO]; + if ([childView superview] != parentView) + [parentView addSubview:childView]; + [window _setNeedsToResetDragMargins:resetDragMargins]; END_BLOCK_OBJC_EXCEPTIONS; - - return 0; } -int ScrollView::contentsHeight() const +void ScrollView::platformRemoveChild(Widget* child) { - NSView *docView, *view = getView(); - docView = getDocumentView(); - - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if (docView) - return (int)[docView bounds].size.height; - else - return (int)[view bounds].size.height; - END_BLOCK_OBJC_EXCEPTIONS; - - return 0; + child->removeFromSuperview(); } -int ScrollView::contentsX() const +void ScrollView::platformSetScrollbarModes() { - NSView *view = getView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view isKindOfClass:[NSScrollView class]]) - return (int)[(NSScrollView *)view documentVisibleRect].origin.x; - else - return (int)[view visibleRect].origin.x; + [scrollView() setScrollingModes:m_horizontalScrollbarMode vertical:m_verticalScrollbarMode andLock:NO]; END_BLOCK_OBJC_EXCEPTIONS; - - return 0; } -int ScrollView::contentsY() const +void ScrollView::platformScrollbarModes(ScrollbarMode& horizontal, ScrollbarMode& vertical) const { - NSView *view = getView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view isKindOfClass:[NSScrollView class]]) - return (int)[(NSScrollView *)view documentVisibleRect].origin.y; - else - return (int)[view visibleRect].origin.y; + [scrollView() scrollingModes:&horizontal vertical:&vertical]; END_BLOCK_OBJC_EXCEPTIONS; - - return 0; } - -IntSize ScrollView::scrollOffset() const -{ - NSView *view = getView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view isKindOfClass:[NSScrollView class]]) - return IntPoint([[(NSScrollView *)view contentView] visibleRect].origin) - IntPoint(); - END_BLOCK_OBJC_EXCEPTIONS; - return IntSize(); -} - -void ScrollView::scrollBy(int dx, int dy) -{ - setContentsPos(contentsX() + dx, contentsY() + dy); -} - -void ScrollView::scrollRectIntoViewRecursively(const IntRect& r) -{ - NSRect rect = r; - - BEGIN_BLOCK_OBJC_EXCEPTIONS; - NSView *docView; - NSView *view = getView(); - docView = getDocumentView(); - if (docView) - view = docView; - - NSView *originalView = view; - while (view) { - if ([view isKindOfClass:[NSClipView class]]) { - NSClipView *clipView = (NSClipView *)view; - NSView *documentView = [clipView documentView]; - [documentView scrollRectToVisible:[documentView convertRect:rect fromView:originalView]]; - } - - view = [view superview]; - } - - END_BLOCK_OBJC_EXCEPTIONS; -} - -void ScrollView::setContentsPos(int x, int y) +void ScrollView::platformSetCanBlitOnScroll() { - x = (x < 0) ? 0 : x; - y = (y < 0) ? 0 : y; - NSPoint p = NSMakePoint(x,y); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - NSView *docView; - NSView *view = getView(); - docView = getDocumentView(); - if (docView) - view = docView; - [view scrollPoint:p]; + [[scrollView() contentView] setCopiesOnScroll:canBlitOnScroll()]; END_BLOCK_OBJC_EXCEPTIONS; } -void ScrollView::setVScrollbarMode(ScrollbarMode vMode) +IntRect ScrollView::platformVisibleContentRect(bool includeScrollbars) const { - NSView* view = getView(); - - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) { - NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view; - [frameView setVerticalScrollingMode: (WebCoreScrollbarMode)vMode]; + BEGIN_BLOCK_OBJC_EXCEPTIONS; + if (includeScrollbars) { + if (NSView* documentView = this->documentView()) + return enclosingIntRect([documentView visibleRect]); } - END_BLOCK_OBJC_EXCEPTIONS; + return enclosingIntRect([scrollView() documentVisibleRect]); + END_BLOCK_OBJC_EXCEPTIONS; + return IntRect(); } -void ScrollView::setHScrollbarMode(ScrollbarMode hMode) +IntSize ScrollView::platformContentsSize() const { - NSView* view = getView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) { - NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view; - [frameView setHorizontalScrollingMode: (WebCoreScrollbarMode)hMode]; - } + if (NSView* documentView = this->documentView()) + return enclosingIntRect([documentView bounds]).size(); END_BLOCK_OBJC_EXCEPTIONS; + return IntSize(); } -void ScrollView::setScrollbarsMode(ScrollbarMode mode) +void ScrollView::platformSetContentsSize() { - NSView* view = getView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) { - NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view; - [frameView setScrollingMode: (WebCoreScrollbarMode)mode]; - } + int w = m_contentsSize.width(); + int h = m_contentsSize.height(); + LOG(Frames, "%p %@ at w %d h %d\n", documentView(), [(id)[documentView() class] className], w, h); + NSSize tempSize = { max(0, w), max(0, h) }; // workaround for 4213314 + [documentView() setFrameSize:tempSize]; END_BLOCK_OBJC_EXCEPTIONS; } -ScrollbarMode ScrollView::vScrollbarMode() const +void ScrollView::platformSetScrollbarsSuppressed(bool repaintOnUnsuppress) { - NSView* view = getView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) { - NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view; - return (ScrollbarMode)[frameView verticalScrollingMode]; - } + [scrollView() setScrollBarsSuppressed:m_scrollbarsSuppressed + repaintOnUnsuppress:repaintOnUnsuppress]; END_BLOCK_OBJC_EXCEPTIONS; - - return ScrollbarAuto; } -ScrollbarMode ScrollView::hScrollbarMode() const +void ScrollView::platformSetScrollPosition(const IntPoint& scrollPoint) { - NSView* view = getView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) { - NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view; - return (ScrollbarMode)[frameView horizontalScrollingMode]; - } + NSPoint tempPoint = { max(0, scrollPoint.x()), max(0, scrollPoint.y()) }; // Don't use NSMakePoint to work around 4213314. + [documentView() scrollPoint:tempPoint]; END_BLOCK_OBJC_EXCEPTIONS; - - return ScrollbarAuto; } -void ScrollView::suppressScrollbars(bool suppressed, bool repaintOnUnsuppress) +bool ScrollView::platformScroll(ScrollDirection, ScrollGranularity) { - NSView* view = getView(); - - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) { - NSView<WebCoreFrameView>* frameView = (NSView<WebCoreFrameView>*)view; - [frameView setScrollBarsSuppressed: suppressed - repaintOnUnsuppress: repaintOnUnsuppress]; - } - END_BLOCK_OBJC_EXCEPTIONS; + // FIXME: It would be nice to implement this so that all of the code in WebFrameView could go away. + notImplemented(); + return true; } -void ScrollView::addChild(Widget* child) -{ - ASSERT(child != this); - - NSView *thisView = getView(); - NSView *thisDocView = getDocumentView(); - if (thisDocView) - thisView = thisDocView; - -#ifndef NDEBUG - NSView *subview = child->getOuterView(); - - LOG(Frames, "Adding %p %@ with size w %d h %d\n", subview, - [(id)[subview class] className], (int)[subview frame].size.width, (int)[subview frame].size.height); -#endif - child->addToSuperview(thisView); -} - -void ScrollView::removeChild(Widget* child) -{ - child->removeFromSuperview(); -} - -void ScrollView::resizeContents(int w, int h) -{ - BEGIN_BLOCK_OBJC_EXCEPTIONS; - int _w = w; - int _h = h; - - LOG(Frames, "%p %@ at w %d h %d\n", getView(), [(id)[getView() class] className], w, h); - NSView *view = getView(); - if ([view isKindOfClass:[NSScrollView class]]){ - view = getDocumentView(); - - LOG(Frames, "%p %@ at w %d h %d\n", view, [(id)[view class] className], w, h); - if (_w < 0) - _w = 0; - if (_h < 0) - _h = 0; - - NSSize tempSize = { _w, _h }; // workaround for 4213314 - [view setFrameSize:tempSize]; - } else { - resize (_w, _h); - } - END_BLOCK_OBJC_EXCEPTIONS; -} - -void ScrollView::updateContents(const IntRect &rect, bool now) +void ScrollView::platformRepaintContentRectangle(const IntRect& rect, bool now) { BEGIN_BLOCK_OBJC_EXCEPTIONS; - NSView *view = getView(); - - if ([view isKindOfClass:[NSScrollView class]]) - view = getDocumentView(); - + NSView *view = documentView(); NSRect visibleRect = visibleContentRect(); + // FIXME: I don't think this intersection is necessary any more now that + // selection doesn't call this method directly (but has to go through FrameView's + // repaintContentRectangle, which does the intersection test also). Leaving it in + // for now until I'm sure. // Checking for rect visibility is an important optimization for the case of // Select All of a large document. AppKit does not do this check, and so ends // up building a large complicated NSRegion if we don't perform the check. @@ -368,134 +181,35 @@ void ScrollView::updateContents(const IntRect &rect, bool now) END_BLOCK_OBJC_EXCEPTIONS; } -void ScrollView::update() -{ - BEGIN_BLOCK_OBJC_EXCEPTIONS; - - NSView *view = getView(); - [[view window] displayIfNeeded]; - [[view window] flushWindowIfNeeded]; - - END_BLOCK_OBJC_EXCEPTIONS; -} - // "Containing Window" means the NSWindow's coord system, which is origin lower left -IntPoint ScrollView::contentsToWindow(const IntPoint& contentsPoint) const -{ - BEGIN_BLOCK_OBJC_EXCEPTIONS; - - NSView *docView; - NSView *view = getView(); - - docView = getDocumentView(); - if (docView) - view = docView; - - NSPoint tempPoint = { contentsPoint.x(), contentsPoint.y() }; // workaround for 4213314 - NSPoint np = [view convertPoint:tempPoint toView: nil]; - return IntPoint(np); - - END_BLOCK_OBJC_EXCEPTIONS; - - return IntPoint(); -} - -IntPoint ScrollView::windowToContents(const IntPoint& point) const +IntRect ScrollView::platformContentsToScreen(const IntRect& rect) const { BEGIN_BLOCK_OBJC_EXCEPTIONS; - - NSView *docView; - NSView *view = getView(); - - docView = getDocumentView(); - if (docView) - view = docView; - - NSPoint tempPoint = { point.x(), point.y() }; // workaround for 4213314 - NSPoint np = [view convertPoint:tempPoint fromView: nil]; - - return IntPoint(np); - - END_BLOCK_OBJC_EXCEPTIONS; - - return IntPoint(); -} - -IntRect ScrollView::contentsToWindow(const IntRect& contentsRect) const -{ - BEGIN_BLOCK_OBJC_EXCEPTIONS; - - NSView* docView; - NSView* view = getView(); - - docView = getDocumentView(); - if (docView) - view = docView; - - NSRect nr = [view convertRect:contentsRect toView: nil]; - return IntRect(nr); - - END_BLOCK_OBJC_EXCEPTIONS; - - return IntRect(); -} - -IntRect ScrollView::windowToContents(const IntRect& rect) const -{ - BEGIN_BLOCK_OBJC_EXCEPTIONS; - - NSView* docView; - NSView* view = getView(); - - docView = getDocumentView(); - if (docView) - view = docView; - - NSRect nr = [view convertRect:rect fromView: nil]; - - return IntRect(nr); - + 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(); } -void ScrollView::setStaticBackground(bool b) -{ - NSScrollView *view = (NSScrollView *)getView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view isKindOfClass:[NSScrollView class]]) - [[view contentView] setCopiesOnScroll: !b]; - END_BLOCK_OBJC_EXCEPTIONS; -} - -NSView *ScrollView::getDocumentView() const +IntPoint ScrollView::platformScreenToContents(const IntPoint& point) const { - id view = getView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view respondsToSelector:@selector(documentView)]) - return [view documentView]; + if (NSView* documentView = this->documentView()) { + NSPoint windowCoord = [[documentView window] convertScreenToBase: point]; + return IntPoint([documentView convertPoint:windowCoord fromView:nil]); + } END_BLOCK_OBJC_EXCEPTIONS; - - return nil; -} - -PlatformScrollbar* ScrollView::scrollbarUnderMouse(const PlatformMouseEvent& mouseEvent) -{ - // On Mac, the ScrollView is really the "document", so events will never flow into it to get to the scrollers. - return 0; -} - -bool ScrollView::inWindow() const -{ - return [getView() window]; + return IntPoint(); } -void ScrollView::wheelEvent(PlatformWheelEvent&) +bool ScrollView::platformIsOffscreen() const { - // Do nothing. NSScrollView handles doing the scroll for us. + return ![platformWidget() window] || ![[platformWidget() window] isVisible]; } } |