summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/mac/WidgetMac.mm
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-06 11:45:16 +0100
committerSteve Block <steveblock@google.com>2011-05-12 13:44:10 +0100
commitcad810f21b803229eb11403f9209855525a25d57 (patch)
tree29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/platform/mac/WidgetMac.mm
parent121b0cf4517156d0ac5111caf9830c51b69bae8f (diff)
downloadexternal_webkit-cad810f21b803229eb11403f9209855525a25d57.zip
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz
external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/platform/mac/WidgetMac.mm')
-rw-r--r--Source/WebCore/platform/mac/WidgetMac.mm369
1 files changed, 369 insertions, 0 deletions
diff --git a/Source/WebCore/platform/mac/WidgetMac.mm b/Source/WebCore/platform/mac/WidgetMac.mm
new file mode 100644
index 0000000..e8bb81d
--- /dev/null
+++ b/Source/WebCore/platform/mac/WidgetMac.mm
@@ -0,0 +1,369 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2008, 2010 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 COMPUTER, 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 COMPUTER, 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 "Widget.h"
+
+#ifdef BUILDING_ON_TIGER
+#import "AutodrainedPool.h"
+#endif
+
+#import "BlockExceptions.h"
+#import "Chrome.h"
+#import "Cursor.h"
+#import "Document.h"
+#import "Font.h"
+#import "Frame.h"
+#import "GraphicsContext.h"
+#import "NotImplemented.h"
+#import "Page.h"
+#import "PlatformMouseEvent.h"
+#import "ScrollView.h"
+#import "WebCoreFrameView.h"
+#import "WebCoreView.h"
+#import <wtf/RetainPtr.h>
+
+@interface NSWindow (WebWindowDetails)
+- (BOOL)_needsToResetDragMargins;
+- (void)_setNeedsToResetDragMargins:(BOOL)needs;
+@end
+
+@interface NSView (WebSetSelectedMethods)
+- (void)setIsSelected:(BOOL)isSelected;
+- (void)webPlugInSetIsSelected:(BOOL)isSelected;
+@end
+
+@interface NSView (Widget)
+- (void)visibleRectDidChange;
+@end
+
+namespace WebCore {
+
+class WidgetPrivate {
+public:
+ WidgetPrivate()
+ : previousVisibleRect(NSZeroRect)
+ {
+ }
+
+ bool mustStayInWindow;
+ bool removeFromSuperviewSoon;
+ NSRect previousVisibleRect;
+};
+
+static void safeRemoveFromSuperview(NSView *view)
+{
+ // If the the view is the first responder, then set the window's first responder to nil so
+ // we don't leave the window pointing to a view that's no longer in it.
+ NSWindow *window = [view window];
+ NSResponder *firstResponder = [window firstResponder];
+ if ([firstResponder isKindOfClass:[NSView class]] && [(NSView *)firstResponder isDescendantOf:view])
+ [window makeFirstResponder:nil];
+
+ // Suppress the resetting of drag margins since we know we can't affect them.
+ BOOL resetDragMargins = [window _needsToResetDragMargins];
+ [window _setNeedsToResetDragMargins:NO];
+ [view removeFromSuperview];
+ [window _setNeedsToResetDragMargins:resetDragMargins];
+}
+
+Widget::Widget(NSView *view)
+ : m_data(new WidgetPrivate)
+{
+ init(view);
+ m_data->mustStayInWindow = false;
+ m_data->removeFromSuperviewSoon = false;
+}
+
+Widget::~Widget()
+{
+ delete m_data;
+}
+
+// FIXME: Should move this to Chrome; bad layering that this knows about Frame.
+void Widget::setFocus(bool focused)
+{
+ if (!focused)
+ return;
+
+ Frame* frame = Frame::frameForWidget(this);
+ if (!frame)
+ return;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+
+ NSView *view = [platformWidget() _webcore_effectiveFirstResponder];
+ if (Page* page = frame->page())
+ page->chrome()->focusNSView(view);
+
+ END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+void Widget::setCursor(const Cursor& cursor)
+{
+ ScrollView* view = root();
+ if (!view)
+ return;
+ view->hostWindow()->setCursor(cursor);
+}
+
+void Widget::show()
+{
+ if (isSelfVisible())
+ return;
+
+ setSelfVisible(true);
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ [getOuterView() setHidden:NO];
+ END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+void Widget::hide()
+{
+ if (!isSelfVisible())
+ return;
+
+ setSelfVisible(false);
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ [getOuterView() setHidden:YES];
+ END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+IntRect Widget::frameRect() const
+{
+ if (!platformWidget())
+ return m_frame;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return enclosingIntRect([getOuterView() frame]);
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return m_frame;
+}
+
+void Widget::setFrameRect(const IntRect& rect)
+{
+ m_frame = rect;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ NSView *v = getOuterView();
+ if (!v)
+ return;
+
+ NSRect visibleRect = [v visibleRect];
+ NSRect f = rect;
+ if (!NSEqualRects(f, [v frame])) {
+ [v setFrame:f];
+ [v setNeedsDisplay:NO];
+ } else if (!NSEqualRects(visibleRect, m_data->previousVisibleRect) && [v respondsToSelector:@selector(visibleRectDidChange)])
+ [v visibleRectDidChange];
+
+ m_data->previousVisibleRect = visibleRect;
+ END_BLOCK_OBJC_EXCEPTIONS;
+}
+
+NSView* Widget::getOuterView() const
+{
+ NSView* view = platformWidget();
+
+ // 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);
+ }
+
+ return view;
+}
+
+void Widget::paint(GraphicsContext* p, const IntRect& r)
+{
+ if (p->paintingDisabled())
+ return;
+ NSView *view = getOuterView();
+ 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:, and when painting into compositing layers.
+
+ // 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);
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ {
+#ifdef BUILDING_ON_TIGER
+ AutodrainedPool pool;
+#endif
+ NSGraphicsContext *nsContext = [NSGraphicsContext graphicsContextWithGraphicsPort:cgContext flipped:YES];
+ [view displayRectIgnoringOpacity:[view convertRect:r fromView:[view superview]] inContext:nsContext];
+ }
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ CGContextRestoreGState(cgContext);
+
+ if (scrollView)
+ [scrollView setDrawsBackground:YES];
+ }
+}
+
+void Widget::setIsSelected(bool isSelected)
+{
+ NSView *view = platformWidget();
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ 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 (m_data->mustStayInWindow)
+ m_data->removeFromSuperviewSoon = true;
+ else {
+ m_data->removeFromSuperviewSoon = false;
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ safeRemoveFromSuperview(getOuterView());
+ END_BLOCK_OBJC_EXCEPTIONS;
+ }
+}
+
+void Widget::beforeMouseDown(NSView *unusedView, Widget* widget)
+{
+ if (widget) {
+ ASSERT_UNUSED(unusedView, unusedView == widget->getOuterView());
+ ASSERT(!widget->m_data->mustStayInWindow);
+ widget->m_data->mustStayInWindow = true;
+ }
+}
+
+void Widget::afterMouseDown(NSView *view, Widget* widget)
+{
+ if (!widget) {
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ safeRemoveFromSuperview(view);
+ END_BLOCK_OBJC_EXCEPTIONS;
+ } else {
+ ASSERT(widget->m_data->mustStayInWindow);
+ widget->m_data->mustStayInWindow = false;
+ if (widget->m_data->removeFromSuperviewSoon)
+ widget->removeFromSuperview();
+ }
+}
+
+// These are here to deal with flipped coords on Mac.
+IntRect Widget::convertFromRootToContainingWindow(const Widget* rootWidget, const IntRect& rect)
+{
+ if (!rootWidget->platformWidget())
+ return rect;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return enclosingIntRect([rootWidget->platformWidget() convertRect:rect toView:nil]);
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return rect;
+}
+
+IntRect Widget::convertFromContainingWindowToRoot(const Widget* rootWidget, const IntRect& rect)
+{
+ if (!rootWidget->platformWidget())
+ return rect;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return enclosingIntRect([rootWidget->platformWidget() convertRect:rect fromView:nil]);
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return rect;
+}
+
+IntPoint Widget::convertFromRootToContainingWindow(const Widget* rootWidget, const IntPoint& point)
+{
+ if (!rootWidget->platformWidget())
+ return point;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return IntPoint([rootWidget->platformWidget() convertPoint:point toView:nil]);
+ END_BLOCK_OBJC_EXCEPTIONS;
+ return point;
+}
+
+IntPoint Widget::convertFromContainingWindowToRoot(const Widget* rootWidget, const IntPoint& point)
+{
+ if (!rootWidget->platformWidget())
+ return point;
+
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
+ return IntPoint([rootWidget->platformWidget() convertPoint:point fromView:nil]);
+ END_BLOCK_OBJC_EXCEPTIONS;
+
+ return point;
+}
+
+NSView *Widget::platformWidget() const
+{
+ return m_widget.get();
+}
+
+void Widget::setPlatformWidget(NSView *widget)
+{
+ if (widget == m_widget)
+ return;
+
+ m_widget = widget;
+ m_data->previousVisibleRect = NSZeroRect;
+}
+
+} // namespace WebCore