diff options
Diffstat (limited to 'WebCore/platform/mac/WidgetMac.mm')
-rw-r--r-- | WebCore/platform/mac/WidgetMac.mm | 294 |
1 files changed, 163 insertions, 131 deletions
diff --git a/WebCore/platform/mac/WidgetMac.mm b/WebCore/platform/mac/WidgetMac.mm index 533f721..3fe8e0d 100644 --- a/WebCore/platform/mac/WidgetMac.mm +++ b/WebCore/platform/mac/WidgetMac.mm @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2006 Apple Computer, Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 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 @@ -30,29 +30,31 @@ #import "Cursor.h" #import "Document.h" #import "Font.h" +#import "FoundationExtras.h" #import "Frame.h" #import "GraphicsContext.h" #import "Page.h" #import "PlatformMouseEvent.h" -#import "WebCoreFrameBridge.h" +#import "ScrollView.h" #import "WebCoreFrameView.h" #import "WebCoreView.h" -#import "WidgetClient.h" #import <wtf/RetainPtr.h> -@interface NSWindow (WindowPrivate) -- (BOOL) _needsToResetDragMargins; -- (void) _setNeedsToResetDragMargins:(BOOL)s; +@interface NSWindow (WebWindowDetails) +- (BOOL)_needsToResetDragMargins; +- (void)_setNeedsToResetDragMargins:(BOOL)needs; +@end + +@interface NSView (WebSetSelectedMethods) +- (void)setIsSelected:(BOOL)isSelected; +- (void)webPlugInSetIsSelected:(BOOL)isSelected; @end namespace WebCore { class WidgetPrivate { public: - RetainPtr<NSView> view; - WidgetClient* client; - bool visible; bool mustStayInWindow; bool removeFromSuperviewSoon; }; @@ -73,58 +75,18 @@ static void safeRemoveFromSuperview(NSView *view) [window _setNeedsToResetDragMargins:resetDragMargins]; } -Widget::Widget() : data(new WidgetPrivate) +Widget::Widget(NSView* view) + : m_data(new WidgetPrivate) { - data->view = nil; - data->client = 0; - data->visible = true; - data->mustStayInWindow = false; - data->removeFromSuperviewSoon = false; + init(view); + m_data->mustStayInWindow = false; + m_data->removeFromSuperviewSoon = false; } -Widget::Widget(NSView* view) : data(new WidgetPrivate) +Widget::~Widget() { - data->view = view; - data->client = 0; - data->visible = true; - data->mustStayInWindow = false; - data->removeFromSuperviewSoon = false; -} - -Widget::~Widget() -{ - delete data; -} - -void Widget::setEnabled(bool enabled) -{ - id view = data->view.get(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view respondsToSelector:@selector(setEnabled:)]) { - [view setEnabled:enabled]; - } - END_BLOCK_OBJC_EXCEPTIONS; -} - -bool Widget::isEnabled() const -{ - id view = data->view.get(); - - BEGIN_BLOCK_OBJC_EXCEPTIONS; - if ([view respondsToSelector:@selector(isEnabled)]) { - return [view isEnabled]; - } - END_BLOCK_OBJC_EXCEPTIONS; - - return true; -} - -IntRect Widget::frameGeometry() const -{ - BEGIN_BLOCK_OBJC_EXCEPTIONS; - return enclosingIntRect([getOuterView() frame]); - END_BLOCK_OBJC_EXCEPTIONS; - return IntRect(); + releasePlatformWidget(); + delete m_data; } // FIXME: Should move this to Chrome; bad layering that this knows about Frame. @@ -136,7 +98,7 @@ void Widget::setFocus() BEGIN_BLOCK_OBJC_EXCEPTIONS; - NSView *view = [getView() _webcore_effectiveFirstResponder]; + NSView *view = [platformWidget() _webcore_effectiveFirstResponder]; if (Page* page = frame->page()) page->chrome()->focusNSView(view); @@ -152,10 +114,10 @@ void Widget::setFocus() void Widget::show() { - if (!data || data->visible) + if (isSelfVisible()) return; - data->visible = true; + setSelfVisible(true); BEGIN_BLOCK_OBJC_EXCEPTIONS; [getOuterView() setHidden:NO]; @@ -164,46 +126,49 @@ void Widget::show() void Widget::hide() { - if (!data || !data->visible) + if (!isSelfVisible()) return; - data->visible = false; + setSelfVisible(false); BEGIN_BLOCK_OBJC_EXCEPTIONS; [getOuterView() setHidden:YES]; END_BLOCK_OBJC_EXCEPTIONS; } -void Widget::setFrameGeometry(const IntRect &rect) +IntRect Widget::frameRect() const { + if (!platformWidget()) + return m_frame; + BEGIN_BLOCK_OBJC_EXCEPTIONS; - NSView *v = getOuterView(); - NSRect f = rect; - if (!NSEqualRects(f, [v frame])) { - [v setFrame:f]; - [v setNeedsDisplay: NO]; - } + return enclosingIntRect([getOuterView() frame]); END_BLOCK_OBJC_EXCEPTIONS; + + return m_frame; } -NSView* Widget::getView() const +void Widget::setFrameRect(const IntRect& rect) { - return data->view.get(); -} + m_frame = rect; -void Widget::setView(NSView* view) -{ BEGIN_BLOCK_OBJC_EXCEPTIONS; - data->view = view; + NSView *v = getOuterView(); + NSRect f = rect; + if (!NSEqualRects(f, [v frame])) { + [v setFrame:f]; + [v setNeedsDisplay: NO]; + } END_BLOCK_OBJC_EXCEPTIONS; } NSView* Widget::getOuterView() const { - // If this widget's view is a WebCoreFrameView the we resize its containing view, a WebFrameView. + NSView* view = platformWidget(); - NSView* view = data->view.get(); - if ([view conformsToProtocol:@protocol(WebCoreFrameView)]) { + // If this widget's view is a WebCoreFrameScrollView then we + // resize its containing view, a WebFrameView. + if ([view conformsToProtocol:@protocol(WebCoreFrameScrollView)]) { view = [view superview]; ASSERT(view); } @@ -216,58 +181,71 @@ void Widget::paint(GraphicsContext* p, const IntRect& r) if (p->paintingDisabled()) return; NSView *view = getOuterView(); - BEGIN_BLOCK_OBJC_EXCEPTIONS; - [view displayRectIgnoringOpacity:[view convertRect:r fromView:[view superview]]]; - END_BLOCK_OBJC_EXCEPTIONS; -} + NSGraphicsContext *currentContext = [NSGraphicsContext currentContext]; + if (currentContext == [[view window] graphicsContext] || ![currentContext isDrawingToScreen]) { + // This is the common case of drawing into a window or printing. + BEGIN_BLOCK_OBJC_EXCEPTIONS; + [view displayRectIgnoringOpacity:[view convertRect:r fromView:[view superview]]]; + END_BLOCK_OBJC_EXCEPTIONS; + } else { + // This is the case of drawing into a bitmap context other than a window backing store. It gets hit beneath + // -cacheDisplayInRect:toBitmapImageRep:. + + // Transparent subframes are in fact implemented with scroll views that return YES from -drawsBackground (whenever the WebView + // itself is in drawsBackground mode). In the normal drawing code path, the scroll views are never asked to draw the background, + // so this is not an issue, but in this code path they are, so the following code temporarily turns background drwaing off. + NSView *innerView = platformWidget(); + NSScrollView *scrollView = 0; + if ([innerView conformsToProtocol:@protocol(WebCoreFrameScrollView)]) { + ASSERT([innerView isKindOfClass:[NSScrollView class]]); + NSScrollView *scrollView = static_cast<NSScrollView *>(innerView); + // -copiesOnScroll will return NO whenever the content view is not fully opaque. + if ([scrollView drawsBackground] && ![[scrollView contentView] copiesOnScroll]) + [scrollView setDrawsBackground:NO]; + else + scrollView = 0; + } + + CGContextRef cgContext = p->platformContext(); + ASSERT(cgContext == [currentContext graphicsPort]); + CGContextSaveGState(cgContext); + + NSRect viewFrame = [view frame]; + NSRect viewBounds = [view bounds]; + // Set up the translation and (flipped) orientation of the graphics context. In normal drawing, AppKit does it as it descends down + // the view hierarchy. + CGContextTranslateCTM(cgContext, viewFrame.origin.x - viewBounds.origin.x, viewFrame.origin.y + viewFrame.size.height + viewBounds.origin.y); + CGContextScaleCTM(cgContext, 1, -1); -void Widget::invalidate() -{ - BEGIN_BLOCK_OBJC_EXCEPTIONS; - [getView() setNeedsDisplay: YES]; - END_BLOCK_OBJC_EXCEPTIONS; -} + BEGIN_BLOCK_OBJC_EXCEPTIONS; + NSGraphicsContext *nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES]; + [view displayRectIgnoringOpacity:[view convertRect:r fromView:[view superview]] inContext:nsContext]; + END_BLOCK_OBJC_EXCEPTIONS; -void Widget::invalidateRect(const IntRect& r) -{ - BEGIN_BLOCK_OBJC_EXCEPTIONS; - [getView() setNeedsDisplayInRect: r]; - END_BLOCK_OBJC_EXCEPTIONS; -} + CGContextRestoreGState(cgContext); -// FIXME: Should move this to Chrome; bad layering that this knows about Frame. -void Widget::setIsSelected(bool isSelected) -{ - if (Frame* frame = Frame::frameForWidget(this)) - [frame->bridge() setIsSelected:isSelected forView:getView()]; + if (scrollView) + [scrollView setDrawsBackground:YES]; + } } -void Widget::addToSuperview(NSView *view) +void Widget::setIsSelected(bool isSelected) { + NSView *view = platformWidget(); BEGIN_BLOCK_OBJC_EXCEPTIONS; - - ASSERT(view); - NSView *subview = getOuterView(); - ASSERT(![view isDescendantOf:subview]); - - // Suppress the resetting of drag margins since we know we can't affect them. - NSWindow* window = [view window]; - BOOL resetDragMargins = [window _needsToResetDragMargins]; - [window _setNeedsToResetDragMargins:NO]; - if ([subview superview] != view) - [view addSubview:subview]; - data->removeFromSuperviewSoon = false; - [window _setNeedsToResetDragMargins:resetDragMargins]; - + if ([view respondsToSelector:@selector(webPlugInSetIsSelected:)]) + [view webPlugInSetIsSelected:isSelected]; + else if ([view respondsToSelector:@selector(setIsSelected:)]) + [view setIsSelected:isSelected]; END_BLOCK_OBJC_EXCEPTIONS; } void Widget::removeFromSuperview() { - if (data->mustStayInWindow) - data->removeFromSuperviewSoon = true; + if (m_data->mustStayInWindow) + m_data->removeFromSuperviewSoon = true; else { - data->removeFromSuperviewSoon = false; + m_data->removeFromSuperviewSoon = false; BEGIN_BLOCK_OBJC_EXCEPTIONS; safeRemoveFromSuperview(getOuterView()); END_BLOCK_OBJC_EXCEPTIONS; @@ -278,8 +256,8 @@ void Widget::beforeMouseDown(NSView *view, Widget* widget) { if (widget) { ASSERT(view == widget->getOuterView()); - ASSERT(!widget->data->mustStayInWindow); - widget->data->mustStayInWindow = true; + ASSERT(!widget->m_data->mustStayInWindow); + widget->m_data->mustStayInWindow = true; } } @@ -290,32 +268,86 @@ void Widget::afterMouseDown(NSView *view, Widget* widget) safeRemoveFromSuperview(view); END_BLOCK_OBJC_EXCEPTIONS; } else { - ASSERT(widget->data->mustStayInWindow); - widget->data->mustStayInWindow = false; - if (widget->data->removeFromSuperviewSoon) + ASSERT(widget->m_data->mustStayInWindow); + widget->m_data->mustStayInWindow = false; + if (widget->m_data->removeFromSuperviewSoon) widget->removeFromSuperview(); } } -void Widget::setClient(WidgetClient* c) +IntPoint Widget::convertFromContainingWindow(const IntPoint& point) const +{ + if (!platformWidget() && parent()) { + IntPoint result = parent()->convertFromContainingWindow(point); + result.move(parent()->scrollX() - x(), parent()->scrollY() - y()); + return result; + } + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return IntPoint([platformWidget() convertPoint:point fromView:nil]); + END_BLOCK_OBJC_EXCEPTIONS; + + return point; +} + +IntRect Widget::convertFromContainingWindow(const IntRect& rect) const { - data->client = c; + if (!platformWidget() && parent()) { + IntRect result = parent()->convertFromContainingWindow(rect); + result.move(parent()->scrollX() - x(), parent()->scrollY() - y()); + return result; + } + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return enclosingIntRect([platformWidget() convertRect:rect fromView:nil]); + END_BLOCK_OBJC_EXCEPTIONS; + + return rect; } -WidgetClient* Widget::client() const +IntRect Widget::convertToContainingWindow(const IntRect& r) const +{ + if (!platformWidget()) { + if (!parent()) + return r; + IntRect result = r; + result.move(parent()->scrollX() - x(), parent()->scrollY() - y()); + return parent()->convertToContainingWindow(result); + } + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return IntRect([platformWidget() convertRect:r toView:nil]); + END_BLOCK_OBJC_EXCEPTIONS; + + return r; +} + +IntPoint Widget::convertToContainingWindow(const IntPoint& p) const { - return data->client; + if (!platformWidget()) { + if (!parent()) + return p; + IntPoint result = p; + result.move(parent()->scrollX() - x(), parent()->scrollY() - y()); + return parent()->convertToContainingWindow(result); + } + + BEGIN_BLOCK_OBJC_EXCEPTIONS; + return IntPoint([platformWidget() convertPoint:p toView:nil]); + END_BLOCK_OBJC_EXCEPTIONS; + + return p; } -void Widget::removeFromParent() +void Widget::releasePlatformWidget() { + HardRelease(m_widget); } -IntPoint Widget::convertToScreenCoordinate(NSView *view, const IntPoint& point) +void Widget::retainPlatformWidget() { - NSPoint conversionPoint = { point.x(), point.y() }; - conversionPoint = [view convertPoint:conversionPoint toView:nil]; - return globalPoint(conversionPoint, [view window]); + HardRetain(m_widget); } } + |