Chromium Code Reviews| Index: Source/WebKit/chromium/src/WebViewImpl.cpp |
| diff --git a/Source/WebKit/chromium/src/WebViewImpl.cpp b/Source/WebKit/chromium/src/WebViewImpl.cpp |
| index bf3f449e7450b3a2bb01572f826019f02b124eab..cc8dda056853538a1c3ff0dfe13b4bcb35bfc70c 100644 |
| --- a/Source/WebKit/chromium/src/WebViewImpl.cpp |
| +++ b/Source/WebKit/chromium/src/WebViewImpl.cpp |
| @@ -56,6 +56,7 @@ |
| #include "Extensions3D.h" |
| #include "FocusController.h" |
| #include "FontDescription.h" |
| +#include "Frame.h" |
| #include "FrameLoader.h" |
| #include "FrameSelection.h" |
| #include "FrameTree.h" |
| @@ -114,6 +115,7 @@ |
| #include "WebDevToolsAgentPrivate.h" |
| #include "WebDragData.h" |
| #include "WebFrameImpl.h" |
| +#include "WebFrameClient.h" |
| #include "WebGraphicsContext3D.h" |
| #include "WebImage.h" |
| #include "WebInputElement.h" |
| @@ -334,6 +336,8 @@ WebViewImpl::WebViewImpl(WebViewClient* client) |
| , m_dragClientImpl(this) |
| , m_editorClientImpl(this) |
| , m_inspectorClientImpl(this) |
| + , m_autoSize(false) |
| + , m_inLayoutBeforeScrollbarUpdate(false) |
| , m_observedNewNavigation(false) |
| #ifndef NDEBUG |
| , m_newNavigationLoader(0) |
| @@ -1037,7 +1041,10 @@ void WebViewImpl::resize(const WebSize& newSize) |
| m_size = newSize; |
| if (mainFrameImpl()->frameView()) { |
| - mainFrameImpl()->frameView()->resize(m_size.width, m_size.height); |
| + // Maintain the current frame size when doing autosize but still send |
| + // a resize event for any auto-resizes that happened. |
| + if (!m_autoSize) |
| + mainFrameImpl()->frameView()->resize(m_size.width, m_size.height); |
| mainFrameImpl()->frame()->eventHandler()->sendResizeEvent(); |
| } |
| @@ -1053,6 +1060,97 @@ void WebViewImpl::resize(const WebSize& newSize) |
| } |
| } |
| +void WebViewImpl::layoutBeforeScrollbarUpdate() |
|
darin (slow to review)
2011/11/28 16:50:40
It feels like this should be a function on FrameVi
levin
2011/11/28 18:34:01
I was mildly considering that. I'm not sure it we
levin
2011/11/28 18:39:06
I guess as long as it is ifdef'ed we could add all
|
| +{ |
| + if (!m_autoSize) |
| + return; |
| + |
| + if (!mainFrameImpl()->client()) |
| + return; |
| + |
| + if (m_inLayoutBeforeScrollbarUpdate) |
| + return; |
| + |
| + m_inLayoutBeforeScrollbarUpdate = true; |
| + |
| + double zoomFactor = WebView::zoomLevelToZoomFactor(zoomLevel()); |
| + |
| + WebCore::Frame* frame = mainFrameImpl()->frame(); |
| + WebCore::FrameView* frameView = frame->view(); |
| + WebCore::Document* document = frame->document(); |
| + for (int i = 0; i < 2; i++) { |
| + // Update various sizes including contentsSize. |
| + document->updateLayoutIgnorePendingStylesheets(); |
| + WebSize size = frameView->frameRect().size(); |
| + // During the first iteration, we use the preferred width but after that we use the width |
| + // that was determined during the first iteration (which may be smaller than the preferred width |
| + // in order to fit within the framerect). |
| + int width = (i == 0) ? mainFrameImpl()->contentsPreferredWidth() : frameView->contentsSize().width(); |
| + // Adjust the size because it is reported unzoomed. |
| + int height = static_cast<int>(zoomFactor * mainFrameImpl()->documentElementScrollHeight()); |
| + |
| + WebSize newSize(width, height); |
| + |
| + // Ensure the size is at least the min bounds. |
| + newSize.width = std::max(newSize.width, m_minAutoSize.width); |
| + newSize.height = std::max(newSize.height, m_minAutoSize.height); |
| + |
| + // Increase the dimensions due to any scrollbars that are displayed. |
| + if (newSize.width > m_maxAutoSize.width) { |
| + RefPtr<Scrollbar> horizontalScrollbar = frameView->createScrollbar(WebCore::HorizontalScrollbar); |
| + if (!horizontalScrollbar->isOverlayScrollbar()) |
| + newSize.height += horizontalScrollbar->height(); |
| + } else if (newSize.height > m_maxAutoSize.height) { |
| + RefPtr<Scrollbar> verticalScrollbar = frameView->createScrollbar(WebCore::VerticalScrollbar); |
| + if (!verticalScrollbar->isOverlayScrollbar()) |
| + newSize.width += verticalScrollbar->width(); |
| + } |
| + |
| + // Bound the dimensions by the max bounds. |
| + ScrollbarMode horizonalScrollbarMode = ScrollbarAlwaysOff; |
| + if (newSize.width > m_maxAutoSize.width) { |
| + newSize.width = m_maxAutoSize.width; |
| + horizonalScrollbarMode = ScrollbarAlwaysOn; |
| + } |
| + ScrollbarMode verticalScrollbarMode = ScrollbarAlwaysOff; |
| + if (newSize.height > m_maxAutoSize.height) { |
| + newSize.height = m_maxAutoSize.height; |
| + verticalScrollbarMode = ScrollbarAlwaysOn; |
| + } |
| + |
| + if (newSize == size) |
| + continue; |
| + |
| + // Avoid doing resizing to a smaller size while the frame is loading to avoid changing between too many sizes. |
| + if (!frame->loader()->isComplete() && (newSize.width < size.width || newSize.width < size.width)) |
| + break; |
| + frameView->resize(newSize.width, newSize.height); |
| + // Force the scrollbar state to avoid the scrollbar code adding them and causing them to be needed. For example, |
| + // a vertical scrollbar may cause text to wrap and thus increase the height (which is the only reason the scollbar is needed). |
| + frameView->setVerticalScrollbarLock(false); |
| + frameView->setHorizontalScrollbarLock(false); |
| + frameView->setScrollbarModes(horizonalScrollbarMode, verticalScrollbarMode, true, true); |
| + } |
| + |
| + m_inLayoutBeforeScrollbarUpdate = false; |
| +} |
| + |
| +void WebViewImpl::didUpdateLayout(WebFrameImpl* webframe) |
| +{ |
| + if (!m_client || webframe != mainFrameImpl()) |
| + return; |
| + |
| + if (m_autoSize) { |
| + WebSize frameSize = mainFrameImpl()->frame()->view()->frameRect().size(); |
| + if (frameSize != m_lastAutoSize) { |
| + m_lastAutoSize = frameSize; |
| + m_client->autoSizeChanged(frameSize); |
| + } |
| + } |
| + |
| + m_client->didUpdateLayout(); |
| +} |
| + |
| void WebViewImpl::willEndLiveResize() |
| { |
| if (mainFrameImpl() && mainFrameImpl()->frameView()) |
| @@ -1202,8 +1300,26 @@ void WebViewImpl::doPixelReadbackToCanvas(WebCanvas* canvas, const IntRect& rect |
| } |
| #endif |
| -void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect) |
| +void WebViewImpl::paint(WebCanvas* canvas, const WebRect& unscaledRect) |
| { |
| + WebRect rect = unscaledRect; |
| + |
| + if (m_autoSize && !m_size.isEmpty() && !m_lastAutoSize.isEmpty()) { |
|
darin (slow to review)
2011/11/28 16:50:40
what about the case where the page is rendered thr
levin
2011/11/28 18:34:01
That case is right below. It writes into the same
|
| + // In autosize mode, scale the rendered content size to match what the widget wants. |
| + // This is only to compensate for a very short term intermediate state while the widget |
| + // is being resized (animated) to match the desired size (so mouse click, hover, etc. |
| + // are not adjusted in a similar manner). |
| + float scaleX = static_cast<float>(m_size.width) / m_lastAutoSize.width; |
| + float scaleY = static_cast<float>(m_size.height) / m_lastAutoSize.height; |
| + |
| + canvas->save(); |
| + canvas->scale(scaleX, scaleY); |
| + rect.x = static_cast<int>(rect.x / scaleX); |
| + rect.width = static_cast<int>(rect.width / scaleX); |
| + rect.y = static_cast<int>(rect.y / scaleY); |
| + rect.height = static_cast<int>(rect.height / scaleY); |
| + } |
| + |
| if (isAcceleratedCompositingActive()) { |
| #if USE(ACCELERATED_COMPOSITING) |
| // If a canvas was passed in, we use it to grab a copy of the |
| @@ -1225,6 +1341,9 @@ void WebViewImpl::paint(WebCanvas* canvas, const WebRect& rect) |
| PlatformSupport::histogramCustomCounts("Renderer4.SoftwarePaintDurationMS", (paintEnd - paintStart) * 1000, 0, 120, 30); |
| PlatformSupport::histogramCustomCounts("Renderer4.SoftwarePaintMegapixPerSecond", pixelsPerSec / 1000000, 10, 210, 30); |
| } |
| + |
| + if (m_autoSize) |
| + canvas->restore(); |
| } |
| void WebViewImpl::themeChanged() |
| @@ -2041,6 +2160,21 @@ void WebViewImpl::enableFixedLayoutMode(bool enable) |
| #endif |
| } |
| +void WebViewImpl::enableAutoSizeMode(bool enable, const WebSize& minSize, const WebSize& maxSize) |
| +{ |
| + ASSERT(!enable || !minSize.isEmpty()); |
| + ASSERT(minSize.width <= maxSize.width); |
| + ASSERT(minSize.height <= maxSize.height); |
| + |
| + m_autoSize = enable; |
| + m_minAutoSize = minSize; |
| + m_maxAutoSize = maxSize; |
| + |
| + FrameView* frameView = mainFrameImpl()->frame()->view(); |
| + frameView->setNeedsLayout(); |
| + frameView->scheduleRelayout(); |
| +} |
| + |
| void WebViewImpl::setPageScaleFactorLimits(float minPageScale, float maxPageScale) |
| { |
| m_minimumPageScaleFactor = min(max(minPageScale, minPageScaleFactor), maxPageScaleFactor) * deviceScaleFactor(); |