bool LayoutPart::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { if (!widget() || !widget()->isFrameView() || !result.hitTestRequest().allowsChildFrameContent()) return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, action); FrameView* childFrameView = toFrameView(widget()); LayoutView* childRoot = childFrameView->layoutView(); if (visibleToHitTestRequest(result.hitTestRequest()) && childRoot) { LayoutPoint adjustedLocation = accumulatedOffset + location(); LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - LayoutSize(childFrameView->scrollOffset()); HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset); HitTestRequest newHitTestRequest(result.hitTestRequest().type() | HitTestRequest::ChildFrameHitTest); HitTestResult childFrameResult(newHitTestRequest, newHitTestLocation); bool isInsideChildFrame = childRoot->hitTest(newHitTestRequest, newHitTestLocation, childFrameResult); if (result.hitTestRequest().listBased()) result.append(childFrameResult); else if (isInsideChildFrame) result = childFrameResult; if (isInsideChildFrame) return true; } return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, action); }
void PrintContext::computePageRects(const FloatRect& printRect, float headerHeight, float footerHeight, float userScaleFactor, float& outPageHeight) { m_pageRects.clear(); outPageHeight = 0; if (!m_frame->document() || !m_frame->view() || !m_frame->document()->layoutView()) return; if (userScaleFactor <= 0) { WTF_LOG_ERROR("userScaleFactor has bad value %.2f", userScaleFactor); return; } LayoutView* view = m_frame->document()->layoutView(); const IntRect& documentRect = view->documentRect(); FloatSize pageSize = m_frame->resizePageRectsKeepingRatio(FloatSize(printRect.width(), printRect.height()), FloatSize(documentRect.width(), documentRect.height())); float pageWidth = pageSize.width(); float pageHeight = pageSize.height(); outPageHeight = pageHeight; // this is the height of the page adjusted by margins pageHeight -= headerHeight + footerHeight; if (pageHeight <= 0) { WTF_LOG_ERROR("pageHeight has bad value %.2f", pageHeight); return; } computePageRectsWithPageSizeInternal(FloatSize(pageWidth / userScaleFactor, pageHeight / userScaleFactor)); }
ClipRect PaintLayerClipper::backgroundClipRect( const ClipRectsContext& context) const { if (m_geometryMapper) { ClipRect backgroundClipRect = clipRectWithGeometryMapper(context, false); #ifdef CHECK_CLIP_RECTS ClipRect testBackgroundClipRect = PaintLayerClipper(m_layer, false).backgroundClipRect(context); CHECK_RECTS_EQ(testBackgroundClipRect, backgroundClipRect); #endif return backgroundClipRect; } DCHECK(m_layer.parent()); LayoutView* layoutView = m_layer.layoutObject()->view(); DCHECK(layoutView); RefPtr<ClipRects> parentClipRects = ClipRects::create(); if (&m_layer == context.rootLayer) parentClipRects->reset(LayoutRect(LayoutRect::infiniteIntRect())); else m_layer.parent()->clipper().getOrCalculateClipRects(context, *parentClipRects); ClipRect result = backgroundClipRectForPosition( *parentClipRects, m_layer.layoutObject()->styleRef().position()); // Note: infinite clipRects should not be scrolled here, otherwise they will // accidentally no longer be considered infinite. if (parentClipRects->fixed() && context.rootLayer->layoutObject() == layoutView && result != LayoutRect(LayoutRect::infiniteIntRect())) result.move(LayoutSize(layoutView->frameView()->scrollOffset())); return result; }
static void applyClipRects(const ClipRectsContext& context, const LayoutObject& layoutObject, LayoutPoint offset, ClipRects& clipRects) { ASSERT(layoutObject.hasOverflowClip() || layoutObject.hasClip() || layoutObject.style()->containsPaint()); LayoutView* view = layoutObject.view(); ASSERT(view); if (clipRects.fixed() && context.rootLayer->layoutObject() == view) offset -= toIntSize(view->frameView()->scrollPosition()); if (layoutObject.hasOverflowClip() || layoutObject.style()->containsPaint()) { ClipRect newOverflowClip = toLayoutBox(layoutObject).overflowClipRect(offset, context.scrollbarRelevancy); newOverflowClip.setHasRadius(layoutObject.style()->hasBorderRadius()); clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect())); if (layoutObject.isPositioned()) clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect())); if (layoutObject.isLayoutView()) clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.fixedClipRect())); if (layoutObject.style()->containsPaint()) { clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect())); clipRects.setFixedClipRect(intersection(newOverflowClip, clipRects.fixedClipRect())); } } if (layoutObject.hasClip()) { LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset); clipRects.setPosClipRect(intersection(newClip, clipRects.posClipRect()).setIsClippedByClipCss()); clipRects.setOverflowClipRect(intersection(newClip, clipRects.overflowClipRect()).setIsClippedByClipCss()); clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect()).setIsClippedByClipCss()); } }
PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vector<LayoutObject*>& pendingDelayedPaintInvalidations, PaintInvalidationState* ownerPaintInvalidationState) : m_clipped(false) , m_cachedOffsetsEnabled(true) , m_forcedSubtreeInvalidationWithinContainer(false) , m_forcedSubtreeInvalidationRectUpdateWithinContainer(false) , m_viewClippingAndScrollOffsetDisabled(false) , m_paintInvalidationContainer(layoutView.containerForPaintInvalidation()) , m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations) , m_enclosingSelfPaintingLayer(*layoutView.layer()) { bool establishesPaintInvalidationContainer = layoutView == m_paintInvalidationContainer; if (!establishesPaintInvalidationContainer) { if ((ownerPaintInvalidationState && !ownerPaintInvalidationState->m_cachedOffsetsEnabled) || !layoutView.supportsPaintInvalidationStateCachedOffsets()) { m_cachedOffsetsEnabled = false; return; } if (ownerPaintInvalidationState && ownerPaintInvalidationState->m_forcedSubtreeInvalidationWithinContainer) m_forcedSubtreeInvalidationWithinContainer = true; FloatPoint point = layoutView.localToAncestorPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries); m_paintOffset = LayoutSize(point.x(), point.y()); } m_clipRect = layoutView.viewRect(); m_clipRect.move(m_paintOffset); m_clipped = true; }
static void frameContentAsPlainText(size_t maxChars, LocalFrame* frame, StringBuilder& output) { Document* document = frame->document(); if (!document) return; if (!frame->view()) return; // Select the document body. if (document->body()) { const EphemeralRange range = EphemeralRange::rangeOfContents(*document->body()); // The text iterator will walk nodes giving us text. This is similar to // the plainText() function in core/editing/TextIterator.h, but we implement the maximum // size and also copy the results directly into a wstring, avoiding the // string conversion. for (TextIterator it(range.startPosition(), range.endPosition()); !it.atEnd(); it.advance()) { it.text().appendTextToStringBuilder(output, 0, maxChars - output.length()); if (output.length() >= maxChars) return; // Filled up the buffer. } } // The separator between frames when the frames are converted to plain text. const LChar frameSeparator[] = { '\n', '\n' }; const size_t frameSeparatorLength = WTF_ARRAY_LENGTH(frameSeparator); // Recursively walk the children. const FrameTree& frameTree = frame->tree(); for (Frame* curChild = frameTree.firstChild(); curChild; curChild = curChild->tree().nextSibling()) { if (!curChild->isLocalFrame()) continue; LocalFrame* curLocalChild = toLocalFrame(curChild); // Ignore the text of non-visible frames. LayoutView* contentLayoutObject = curLocalChild->contentLayoutObject(); LayoutPart* ownerLayoutObject = curLocalChild->ownerLayoutObject(); if (!contentLayoutObject || !contentLayoutObject->size().width() || !contentLayoutObject->size().height() || (contentLayoutObject->location().x() + contentLayoutObject->size().width() <= 0) || (contentLayoutObject->location().y() + contentLayoutObject->size().height() <= 0) || (ownerLayoutObject && ownerLayoutObject->style() && ownerLayoutObject->style()->visibility() != VISIBLE)) { continue; } // Make sure the frame separator won't fill up the buffer, and give up if // it will. The danger is if the separator will make the buffer longer than // maxChars. This will cause the computation above: // maxChars - output->size() // to be a negative number which will crash when the subframe is added. if (output.length() >= maxChars - frameSeparatorLength) return; output.append(frameSeparator, frameSeparatorLength); frameContentAsPlainText(maxChars, curLocalChild, output); if (output.length() >= maxChars) return; // Filled up the buffer. } }
void TextAutosizer::updatePageInfo() { if (m_updatePageInfoDeferred || !m_document->page() || !m_document->settings()) return; PageInfo previousPageInfo(m_pageInfo); m_pageInfo.m_settingEnabled = m_document->settings()->textAutosizingEnabled(); if (!m_pageInfo.m_settingEnabled || m_document->printing()) { m_pageInfo.m_pageNeedsAutosizing = false; } else { LayoutView* layoutView = m_document->layoutView(); bool horizontalWritingMode = isHorizontalWritingMode(layoutView->style()->writingMode()); // FIXME: With out-of-process iframes, the top frame can be remote and // doesn't have sizing information. Just return if this is the case. Frame* frame = m_document->frame()->tree().top(); if (frame->isRemoteFrame()) return; LocalFrame* mainFrame = toLocalFrame(frame); IntSize frameSize = m_document->settings()->textAutosizingWindowSizeOverride(); if (frameSize.isEmpty()) frameSize = windowSize(); m_pageInfo.m_frameWidth = horizontalWritingMode ? frameSize.width() : frameSize.height(); IntSize layoutSize = mainFrame->view()->layoutSize(); m_pageInfo.m_layoutWidth = horizontalWritingMode ? layoutSize.width() : layoutSize.height(); // Compute the base font scale multiplier based on device and accessibility settings. m_pageInfo.m_baseMultiplier = m_document->settings()->accessibilityFontScaleFactor(); // If the page has a meta viewport or @viewport, don't apply the device scale adjustment. const ViewportDescription& viewportDescription = mainFrame->document()->viewportDescription(); if (!viewportDescription.isSpecifiedByAuthor()) { float deviceScaleAdjustment = m_document->settings()->deviceScaleAdjustment(); m_pageInfo.m_baseMultiplier *= deviceScaleAdjustment; } m_pageInfo.m_pageNeedsAutosizing = !!m_pageInfo.m_frameWidth && (m_pageInfo.m_baseMultiplier * (static_cast<float>(m_pageInfo.m_layoutWidth) / m_pageInfo.m_frameWidth) > 1.0f); } if (m_pageInfo.m_pageNeedsAutosizing) { // If page info has changed, multipliers may have changed. Force a layout to recompute them. if (m_pageInfo.m_frameWidth != previousPageInfo.m_frameWidth || m_pageInfo.m_layoutWidth != previousPageInfo.m_layoutWidth || m_pageInfo.m_baseMultiplier != previousPageInfo.m_baseMultiplier || m_pageInfo.m_settingEnabled != previousPageInfo.m_settingEnabled) setAllTextNeedsLayout(); } else if (previousPageInfo.m_hasAutosized) { // If we are no longer autosizing the page, we won't do anything during the next layout. // Set all the multipliers back to 1 now. resetMultipliers(); m_pageInfo.m_hasAutosized = false; } }
bool LayoutPart::nodeAtPoint(HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action) { if (!widget() || !widget()->isFrameView() || !result.hitTestRequest().allowsChildFrameContent()) return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, action); // A hit test can never hit an off-screen element; only off-screen iframes are throttled; // therefore, hit tests can skip descending into throttled iframes. if (toFrameView(widget())->shouldThrottleRendering()) return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, action); ASSERT(document().lifecycle().state() >= DocumentLifecycle::CompositingClean); if (action == HitTestForeground) { FrameView* childFrameView = toFrameView(widget()); LayoutView* childRoot = childFrameView->layoutView(); if (visibleToHitTestRequest(result.hitTestRequest()) && childRoot) { LayoutPoint adjustedLocation = accumulatedOffset + location(); LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - LayoutSize(childFrameView->scrollOffset()); HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset); HitTestRequest newHitTestRequest(result.hitTestRequest().type() | HitTestRequest::ChildFrameHitTest); HitTestResult childFrameResult(newHitTestRequest, newHitTestLocation); // The frame's layout and style must be up-to-date if we reach here. bool isInsideChildFrame = childRoot->hitTestNoLifecycleUpdate(childFrameResult); if (result.hitTestRequest().listBased()) { result.append(childFrameResult); } else if (isInsideChildFrame) { // Force the result not to be cacheable because the parent // frame should not cache this result; as it won't be notified of // changes in the child. childFrameResult.setCacheable(false); result = childFrameResult; } // Don't trust |isInsideChildFrame|. For rect-based hit-test, returns // true only when the hit test rect is totally within the iframe, // i.e. nodeAtPointOverWidget() also returns true. // Use a temporary HitTestResult because we don't want to collect the // iframe element itself if the hit-test rect is totally within the iframe. if (isInsideChildFrame) { if (!locationInContainer.isRectBasedTest()) return true; HitTestResult pointOverWidgetResult = result; bool pointOverWidget = nodeAtPointOverWidget(pointOverWidgetResult, locationInContainer, accumulatedOffset, action); if (pointOverWidget) return true; result = pointOverWidgetResult; return false; } } } return nodeAtPointOverWidget(result, locationInContainer, accumulatedOffset, action); }
LayoutState::LayoutState(LayoutView& view) : m_isPaginated(view.pageLogicalHeight()), m_containingBlockLogicalWidthChanged(false), m_paginationStateChanged(false), m_flowThread(nullptr), m_next(nullptr), m_layoutObject(view) { ASSERT(!view.layoutState()); view.pushLayoutState(*this); }
void PrintContext::computePageRectsWithPageSizeInternal(const FloatSize& pageSizeInPixels) { if (!m_frame->document() || !m_frame->view() || !m_frame->document()->layoutView()) return; LayoutView* view = m_frame->document()->layoutView(); IntRect docRect = view->documentRect(); int pageWidth = pageSizeInPixels.width(); int pageHeight = pageSizeInPixels.height(); bool isHorizontal = view->style()->isHorizontalWritingMode(); int docLogicalHeight = isHorizontal ? docRect.height() : docRect.width(); int pageLogicalHeight = isHorizontal ? pageHeight : pageWidth; int pageLogicalWidth = isHorizontal ? pageWidth : pageHeight; int inlineDirectionStart; int inlineDirectionEnd; int blockDirectionStart; int blockDirectionEnd; if (isHorizontal) { if (view->style()->isFlippedBlocksWritingMode()) { blockDirectionStart = docRect.maxY(); blockDirectionEnd = docRect.y(); } else { blockDirectionStart = docRect.y(); blockDirectionEnd = docRect.maxY(); } inlineDirectionStart = view->style()->isLeftToRightDirection() ? docRect.x() : docRect.maxX(); inlineDirectionEnd = view->style()->isLeftToRightDirection() ? docRect.maxX() : docRect.x(); } else { if (view->style()->isFlippedBlocksWritingMode()) { blockDirectionStart = docRect.maxX(); blockDirectionEnd = docRect.x(); } else { blockDirectionStart = docRect.x(); blockDirectionEnd = docRect.maxX(); } inlineDirectionStart = view->style()->isLeftToRightDirection() ? docRect.y() : docRect.maxY(); inlineDirectionEnd = view->style()->isLeftToRightDirection() ? docRect.maxY() : docRect.y(); } unsigned pageCount = ceilf((float)docLogicalHeight / pageLogicalHeight); for (unsigned i = 0; i < pageCount; ++i) { int pageLogicalTop = blockDirectionEnd > blockDirectionStart ? blockDirectionStart + i * pageLogicalHeight : blockDirectionStart - (i + 1) * pageLogicalHeight; int pageLogicalLeft = inlineDirectionEnd > inlineDirectionStart ? inlineDirectionStart : inlineDirectionStart - pageLogicalWidth; IntRect pageRect(pageLogicalLeft, pageLogicalTop, pageLogicalWidth, pageLogicalHeight); if (!isHorizontal) pageRect = pageRect.transposedRect(); m_pageRects.append(pageRect); } }
void PendingSelection::commitAlgorithm(LayoutView& layoutView) { if (!hasPendingSelection()) return; ASSERT(!layoutView.needsLayout()); m_hasPendingSelection = false; const VisibleSelectionTemplate<Strategy> originalSelection = m_frameSelection->visibleSelection<Strategy>(); // Skip if pending VisibilePositions became invalid before we reach here. if (!isSelectionInDocument(originalSelection, layoutView.document())) return; // Construct a new VisibleSolution, since visibleSelection() is not necessarily // valid, and the following steps assume a valid selection. // See <https://bugs.webkit.org/show_bug.cgi?id=69563> and // <rdar://problem/10232866>. const VisibleSelectionTemplate<Strategy> selection = calcVisibleSelectionAlgorithm<Strategy>(originalSelection); if (!selection.isRange()) { layoutView.clearSelection(); return; } // Use the rightmost candidate for the start of the selection, and the // leftmost candidate for the end of the selection. Example: foo <a>bar</a>. // Imagine that a line wrap occurs after 'foo', and that 'bar' is selected. // If we pass [foo, 3] as the start of the selection, the selection painting // code will think that content on the line containing 'foo' is selected // and will fill the gap before 'bar'. PositionTemplate<Strategy> startPos = selection.start(); PositionTemplate<Strategy> candidate = mostForwardCaretPosition(startPos); if (isVisuallyEquivalentCandidate(candidate)) startPos = candidate; PositionTemplate<Strategy> endPos = selection.end(); candidate = mostBackwardCaretPosition(endPos); if (isVisuallyEquivalentCandidate(candidate)) endPos = candidate; // We can get into a state where the selection endpoints map to the same // |VisiblePosition| when a selection is deleted because we don't yet notify // the |FrameSelection| of text removal. if (startPos.isNull() || endPos.isNull() || selection.visibleStart().deepEquivalent() == selection.visibleEnd().deepEquivalent()) return; LayoutObject* startLayoutObject = startPos.anchorNode()->layoutObject(); LayoutObject* endLayoutObject = endPos.anchorNode()->layoutObject(); if (!startLayoutObject || !endLayoutObject) return; ASSERT(layoutView == startLayoutObject->view() && layoutView == endLayoutObject->view()); layoutView.setSelection(startLayoutObject, startPos.computeEditingOffset(), endLayoutObject, endPos.computeEditingOffset()); }
TEST_F(PaintPropertyTreeBuilderTest, FrameScrollingTraditional) { setBodyInnerHTML("<style> body { height: 10000px; } </style>"); document().domWindow()->scrollTo(0, 100); FrameView* frameView = document().view(); frameView->updateAllLifecyclePhases(); EXPECT_EQ(TransformationMatrix(), frameView->preTranslation()->matrix()); EXPECT_EQ(nullptr, frameView->preTranslation()->parent()); EXPECT_EQ(TransformationMatrix().translate(0, -100), frameView->scrollTranslation()->matrix()); EXPECT_EQ(frameView->preTranslation(), frameView->scrollTranslation()->parent()); LayoutView* layoutView = document().layoutView(); ObjectPaintProperties* layoutViewProperties = layoutView->objectPaintProperties(); EXPECT_EQ(nullptr, layoutViewProperties); }
static void applyClipRects(const ClipRectsContext& context, const LayoutBoxModelObject& layoutObject, LayoutPoint offset, ClipRects& clipRects) { DCHECK(layoutObject.hasClipRelatedProperty() || (layoutObject.isSVGRoot() && toLayoutSVGRoot(&layoutObject)->shouldApplyViewportClip())); LayoutView* view = layoutObject.view(); DCHECK(view); if (clipRects.fixed() && context.rootLayer->layoutObject() == view) offset -= LayoutSize(view->frameView()->scrollOffset()); if (layoutObject.hasOverflowClip() || (layoutObject.isSVGRoot() && toLayoutSVGRoot(&layoutObject)->shouldApplyViewportClip()) || (layoutObject.styleRef().containsPaint() && layoutObject.isBox())) { ClipRect newOverflowClip = toLayoutBox(layoutObject) .overflowClipRect(offset, context.overlayScrollbarClipBehavior); newOverflowClip.setHasRadius(layoutObject.styleRef().hasBorderRadius()); clipRects.setOverflowClipRect( intersection(newOverflowClip, clipRects.overflowClipRect())); if (layoutObject.isPositioned()) clipRects.setPosClipRect( intersection(newOverflowClip, clipRects.posClipRect())); if (layoutObject.isLayoutView()) clipRects.setFixedClipRect( intersection(newOverflowClip, clipRects.fixedClipRect())); if (layoutObject.styleRef().containsPaint()) { clipRects.setPosClipRect( intersection(newOverflowClip, clipRects.posClipRect())); clipRects.setFixedClipRect( intersection(newOverflowClip, clipRects.fixedClipRect())); } } if (layoutObject.hasClip()) { LayoutRect newClip = toLayoutBox(layoutObject).clipRect(offset); clipRects.setPosClipRect( intersection(newClip, clipRects.posClipRect()).setIsClippedByClipCss()); clipRects.setOverflowClipRect( intersection(newClip, clipRects.overflowClipRect()) .setIsClippedByClipCss()); clipRects.setFixedClipRect(intersection(newClip, clipRects.fixedClipRect()) .setIsClippedByClipCss()); } }
TEST_F(ScrollingCoordinatorTest, iframeScrolling) { registerMockedHttpURLLoad("iframe-scrolling.html"); registerMockedHttpURLLoad("iframe-scrolling-inner.html"); navigateTo(m_baseURL + "iframe-scrolling.html"); forceFullCompositingUpdate(); // Verify the properties of the accelerated scrolling element starting from the LayoutObject // all the way to the WebLayer. Element* scrollableFrame = frame()->document()->getElementById("scrollable"); ASSERT_TRUE(scrollableFrame); LayoutObject* layoutObject = scrollableFrame->layoutObject(); ASSERT_TRUE(layoutObject); ASSERT_TRUE(layoutObject->isLayoutPart()); LayoutPart* layoutPart = toLayoutPart(layoutObject); ASSERT_TRUE(layoutPart); ASSERT_TRUE(layoutPart->widget()); ASSERT_TRUE(layoutPart->widget()->isFrameView()); FrameView* innerFrameView = toFrameView(layoutPart->widget()); LayoutView* innerLayoutView = innerFrameView->layoutView(); ASSERT_TRUE(innerLayoutView); PaintLayerCompositor* innerCompositor = innerLayoutView->compositor(); ASSERT_TRUE(innerCompositor->inCompositingMode()); ASSERT_TRUE(innerCompositor->scrollLayer()); GraphicsLayer* scrollLayer = innerCompositor->scrollLayer(); ASSERT_EQ(innerFrameView, scrollLayer->scrollableArea()); WebLayer* webScrollLayer = scrollLayer->platformLayer(); ASSERT_TRUE(webScrollLayer->scrollable()); #if OS(ANDROID) // Now verify we've attached impl-side scrollbars onto the scrollbar layers ASSERT_TRUE(innerCompositor->layerForHorizontalScrollbar()); ASSERT_TRUE(innerCompositor->layerForHorizontalScrollbar()->hasContentsLayer()); ASSERT_TRUE(innerCompositor->layerForVerticalScrollbar()); ASSERT_TRUE(innerCompositor->layerForVerticalScrollbar()->hasContentsLayer()); #endif }
TEST_F(ScrollingCoordinatorTest, rtlIframe) { registerMockedHttpURLLoad("rtl-iframe.html"); registerMockedHttpURLLoad("rtl-iframe-inner.html"); navigateTo(m_baseURL + "rtl-iframe.html"); forceFullCompositingUpdate(); // Verify the properties of the accelerated scrolling element starting from the LayoutObject // all the way to the WebLayer. Element* scrollableFrame = frame()->document()->getElementById("scrollable"); ASSERT_TRUE(scrollableFrame); LayoutObject* layoutObject = scrollableFrame->layoutObject(); ASSERT_TRUE(layoutObject); ASSERT_TRUE(layoutObject->isLayoutPart()); LayoutPart* layoutPart = toLayoutPart(layoutObject); ASSERT_TRUE(layoutPart); ASSERT_TRUE(layoutPart->widget()); ASSERT_TRUE(layoutPart->widget()->isFrameView()); FrameView* innerFrameView = toFrameView(layoutPart->widget()); LayoutView* innerLayoutView = innerFrameView->layoutView(); ASSERT_TRUE(innerLayoutView); PaintLayerCompositor* innerCompositor = innerLayoutView->compositor(); ASSERT_TRUE(innerCompositor->inCompositingMode()); ASSERT_TRUE(innerCompositor->scrollLayer()); GraphicsLayer* scrollLayer = innerCompositor->scrollLayer(); ASSERT_EQ(innerFrameView, scrollLayer->scrollableArea()); WebLayer* webScrollLayer = scrollLayer->platformLayer(); ASSERT_TRUE(webScrollLayer->scrollable()); int expectedScrollPosition = 958 + (innerFrameView->verticalScrollbar()->isOverlayScrollbar() ? 0 : 15); ASSERT_EQ(expectedScrollPosition, webScrollLayer->scrollPositionDouble().x); }
PaintInvalidationState::PaintInvalidationState(const LayoutView& layoutView, Vector<LayoutObject*>& pendingDelayedPaintInvalidations, PaintInvalidationState* ownerPaintInvalidationState) : m_clipped(false) , m_cachedOffsetsEnabled(true) , m_ancestorHadPaintInvalidationForLocationChange(false) , m_paintInvalidationContainer(*layoutView.containerForPaintInvalidation()) , m_pendingDelayedPaintInvalidations(pendingDelayedPaintInvalidations) { bool establishesPaintInvalidationContainer = layoutView == m_paintInvalidationContainer; if (!establishesPaintInvalidationContainer) { if ((ownerPaintInvalidationState && !ownerPaintInvalidationState->m_cachedOffsetsEnabled) || !layoutView.supportsPaintInvalidationStateCachedOffsets()) { m_cachedOffsetsEnabled = false; return; } if (ownerPaintInvalidationState && ownerPaintInvalidationState->m_ancestorHadPaintInvalidationForLocationChange) m_ancestorHadPaintInvalidationForLocationChange = true; FloatPoint point = layoutView.localToContainerPoint(FloatPoint(), &m_paintInvalidationContainer, TraverseDocumentBoundaries); m_paintOffset = LayoutSize(point.x(), point.y()); } m_clipRect = layoutView.viewRect(); m_clipRect.move(m_paintOffset); m_clipped = true; }
PaintLayerCompositor::PaintLayerCompositor(LayoutView& layoutView) : m_layoutView(layoutView) , m_compositingReasonFinder(layoutView) , m_pendingUpdateType(CompositingUpdateNone) , m_hasAcceleratedCompositing(true) , m_compositing(false) , m_rootShouldAlwaysCompositeDirty(true) , m_needsUpdateFixedBackground(false) , m_isTrackingPaintInvalidations(layoutView.frameView()->isTrackingPaintInvalidations()) , m_inOverlayFullscreenVideo(false) , m_needsUpdateDescendantDependentFlags(false) , m_rootLayerAttachment(RootLayerUnattached) { updateAcceleratedCompositingSettings(); }
void ScrollableAreaPainter::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls) { // Don't do anything if we have no overflow. if (!m_scrollableArea.box().hasOverflowClip()) return; IntPoint adjustedPaintOffset = paintOffset; if (paintingOverlayControls) adjustedPaintOffset = m_scrollableArea.cachedOverlayScrollbarOffset(); IntRect localDamageRect = damageRect; localDamageRect.moveBy(-adjustedPaintOffset); // Overlay scrollbars paint in a second pass through the layer tree so that they will paint // on top of everything else. If this is the normal painting pass, paintingOverlayControls // will be false, and we should just tell the root layer that there are overlay scrollbars // that need to be painted. That will cause the second pass through the layer tree to run, // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the // second pass doesn't need to re-enter the LayoutTree to get it right. if (m_scrollableArea.hasOverlayScrollbars() && !paintingOverlayControls) { m_scrollableArea.setCachedOverlayScrollbarOffset(paintOffset); // It's not necessary to do the second pass if the scrollbars paint into layers. if ((m_scrollableArea.horizontalScrollbar() && m_scrollableArea.layerForHorizontalScrollbar()) || (m_scrollableArea.verticalScrollbar() && m_scrollableArea.layerForVerticalScrollbar())) return; if (!overflowControlsIntersectRect(localDamageRect)) return; LayoutView* layoutView = m_scrollableArea.box().view(); DeprecatedPaintLayer* paintingRoot = m_scrollableArea.layer()->enclosingLayerWithCompositedDeprecatedPaintLayerMapping(IncludeSelf); if (!paintingRoot) paintingRoot = layoutView->layer(); paintingRoot->setContainsDirtyOverlayScrollbars(true); return; } // This check is required to avoid painting custom CSS scrollbars twice. if (paintingOverlayControls && !m_scrollableArea.hasOverlayScrollbars()) return; { if (m_scrollableArea.horizontalScrollbar() && !m_scrollableArea.layerForHorizontalScrollbar()) { TransformRecorder translateRecorder(*context, *m_scrollableArea.horizontalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); m_scrollableArea.horizontalScrollbar()->paint(context, localDamageRect); } if (m_scrollableArea.verticalScrollbar() && !m_scrollableArea.layerForVerticalScrollbar()) { TransformRecorder translateRecorder(*context, *m_scrollableArea.verticalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); m_scrollableArea.verticalScrollbar()->paint(context, localDamageRect); } } if (m_scrollableArea.layerForScrollCorner()) return; // We fill our scroll corner with white if we have a scrollbar that doesn't run all the way up to the // edge of the box. paintScrollCorner(context, adjustedPaintOffset, damageRect); // Paint our resizer last, since it sits on top of the scroll corner. paintResizer(context, adjustedPaintOffset, damageRect); }
PaintLayerCompositor* InspectorLayerTreeAgent::paintLayerCompositor() { LayoutView* layoutView = m_inspectedFrames->root()->contentLayoutObject(); PaintLayerCompositor* compositor = layoutView ? layoutView->compositor() : nullptr; return compositor; }
void ScrollableAreaPainter::paintOverflowControls( GraphicsContext& context, const IntPoint& paintOffset, const CullRect& cullRect, bool paintingOverlayControls) { // Don't do anything if we have no overflow. if (!getScrollableArea().box().hasOverflowClip()) return; IntPoint adjustedPaintOffset = paintOffset; if (paintingOverlayControls) adjustedPaintOffset = getScrollableArea().cachedOverlayScrollbarOffset(); CullRect adjustedCullRect(cullRect, -adjustedPaintOffset); // Overlay scrollbars paint in a second pass through the layer tree so that // they will paint on top of everything else. If this is the normal painting // pass, paintingOverlayControls will be false, and we should just tell the // root layer that there are overlay scrollbars that need to be painted. That // will cause the second pass through the layer tree to run, and we'll paint // the scrollbars then. In the meantime, cache tx and ty so that the second // pass doesn't need to re-enter the LayoutTree to get it right. if (getScrollableArea().hasOverlayScrollbars() && !paintingOverlayControls) { getScrollableArea().setCachedOverlayScrollbarOffset(paintOffset); // It's not necessary to do the second pass if the scrollbars paint into // layers. if ((getScrollableArea().horizontalScrollbar() && getScrollableArea().layerForHorizontalScrollbar()) || (getScrollableArea().verticalScrollbar() && getScrollableArea().layerForVerticalScrollbar())) return; if (!overflowControlsIntersectRect(adjustedCullRect)) return; LayoutView* layoutView = getScrollableArea().box().view(); PaintLayer* paintingRoot = getScrollableArea().layer()->enclosingLayerWithCompositedLayerMapping( IncludeSelf); if (!paintingRoot) paintingRoot = layoutView->layer(); paintingRoot->setContainsDirtyOverlayScrollbars(true); return; } // This check is required to avoid painting custom CSS scrollbars twice. if (paintingOverlayControls && !getScrollableArea().hasOverlayScrollbars()) return; { Optional<ScopedPaintChunkProperties> scopedTransformProperty; if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { const auto* objectProperties = getScrollableArea().box().paintProperties(); if (objectProperties && objectProperties->scrollbarPaintOffset()) { PaintChunkProperties properties( context.getPaintController().currentPaintChunkProperties()); properties.transform = objectProperties->scrollbarPaintOffset(); scopedTransformProperty.emplace( context.getPaintController(), getScrollableArea().box(), DisplayItem::kScrollOverflowControls, properties); } } if (getScrollableArea().horizontalScrollbar() && !getScrollableArea().layerForHorizontalScrollbar()) { TransformRecorder translateRecorder( context, *getScrollableArea().horizontalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); getScrollableArea().horizontalScrollbar()->paint(context, adjustedCullRect); } if (getScrollableArea().verticalScrollbar() && !getScrollableArea().layerForVerticalScrollbar()) { TransformRecorder translateRecorder( context, *getScrollableArea().verticalScrollbar(), AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y())); getScrollableArea().verticalScrollbar()->paint(context, adjustedCullRect); } } if (getScrollableArea().layerForScrollCorner()) return; // We fill our scroll corner with white if we have a scrollbar that doesn't // run all the way up to the edge of the box. paintScrollCorner(context, adjustedPaintOffset, cullRect); // Paint our resizer last, since it sits on top of the scroll corner. paintResizer(context, adjustedPaintOffset, cullRect); }
void PaintPropertyTreeBuilder::buildTreeNodes( FrameView& frameView, PaintPropertyTreeBuilderContext& context) { if (RuntimeEnabledFeatures::rootLayerScrollingEnabled()) { LayoutView* layoutView = frameView.layoutView(); if (!layoutView) return; TransformationMatrix frameTranslate; frameTranslate.translate(frameView.x() + layoutView->location().x() + context.current.paintOffset.x(), frameView.y() + layoutView->location().y() + context.current.paintOffset.y()); context.current.transform = layoutView->getMutableForPainting() .ensurePaintProperties() .updatePaintOffsetTranslation(context.current.transform, frameTranslate, FloatPoint3D()); context.current.paintOffset = LayoutPoint(); context.current.renderingContextID = 0; context.current.shouldFlattenInheritedTransform = true; context.absolutePosition = context.current; context.containerForAbsolutePosition = nullptr; // This will get set in updateOutOfFlowContext(). context.fixedPosition = context.current; return; } TransformationMatrix frameTranslate; frameTranslate.translate(frameView.x() + context.current.paintOffset.x(), frameView.y() + context.current.paintOffset.y()); context.current.transform = updateFrameViewPreTranslation( frameView, context.current.transform, frameTranslate, FloatPoint3D()); FloatRoundedRect contentClip( IntRect(IntPoint(), frameView.visibleContentSize())); context.current.clip = updateFrameViewContentClip( frameView, context.current.clip, frameView.preTranslation(), contentClip); // Record the fixed properties before any scrolling occurs. const auto* fixedTransformNode = context.current.transform; auto* fixedScrollNode = context.current.scroll; ScrollOffset scrollOffset = frameView.scrollOffset(); if (frameView.isScrollable() || !scrollOffset.isZero()) { TransformationMatrix frameScroll; frameScroll.translate(-scrollOffset.width(), -scrollOffset.height()); context.current.transform = updateFrameViewScrollTranslation( frameView, frameView.preTranslation(), frameScroll, FloatPoint3D()); IntSize scrollClip = frameView.visibleContentSize(); IntSize scrollBounds = frameView.contentsSize(); bool userScrollableHorizontal = frameView.userInputScrollable(HorizontalScrollbar); bool userScrollableVertical = frameView.userInputScrollable(VerticalScrollbar); context.current.scroll = updateFrameViewScroll( frameView, context.current.scroll, frameView.scrollTranslation(), scrollClip, scrollBounds, userScrollableHorizontal, userScrollableVertical); } else { // Ensure pre-existing properties are cleared when there is no scrolling. frameView.setScrollTranslation(nullptr); frameView.setScroll(nullptr); } // Initialize the context for current, absolute and fixed position cases. // They are the same, except that scroll translation does not apply to // fixed position descendants. context.current.paintOffset = LayoutPoint(); context.current.renderingContextID = 0; context.current.shouldFlattenInheritedTransform = true; context.absolutePosition = context.current; context.containerForAbsolutePosition = nullptr; context.fixedPosition = context.current; context.fixedPosition.transform = fixedTransformNode; context.fixedPosition.scroll = fixedScrollNode; std::unique_ptr<PropertyTreeState> contentsState( new PropertyTreeState(context.current.transform, context.current.clip, context.currentEffect, context.current.scroll)); frameView.setTotalPropertyTreeStateForContents(std::move(contentsState)); }
PaintLayerCompositor* InspectorLayerTreeAgent::deprecatedPaintLayerCompositor() { LayoutView* layoutView = m_pageAgent->inspectedFrame()->contentLayoutObject(); PaintLayerCompositor* compositor = layoutView ? layoutView->compositor() : nullptr; return compositor; }
void FramePainter::paintContents(GraphicsContext& context, const GlobalPaintFlags globalPaintFlags, const IntRect& rect) { Document* document = frameView().frame().document(); #ifndef NDEBUG bool fillWithRed; if (document->printing()) fillWithRed = false; // Printing, don't fill with red (can't remember why). else if (frameView().frame().owner()) fillWithRed = false; // Subframe, don't fill with red. else if (frameView().isTransparent()) fillWithRed = false; // Transparent, don't fill with red. else if (globalPaintFlags & GlobalPaintSelectionOnly) fillWithRed = false; // Selections are transparent, don't fill with red. else fillWithRed = true; if (fillWithRed && !LayoutObjectDrawingRecorder::useCachedDrawingIfPossible(context, *frameView().layoutView(), DisplayItem::DebugRedFill, LayoutPoint())) { IntRect contentRect(IntPoint(), frameView().contentsSize()); LayoutObjectDrawingRecorder drawingRecorder(context, *frameView().layoutView(), DisplayItem::DebugRedFill, contentRect, LayoutPoint()); } #endif LayoutView* layoutView = frameView().layoutView(); if (!layoutView) { WTF_LOG_ERROR("called FramePainter::paint with nil layoutObject"); return; } if (!frameView().shouldThrottleRendering()) { RELEASE_ASSERT(!frameView().needsLayout()); ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean); } TRACE_EVENT1("devtools.timeline", "Paint", "data", InspectorPaintEvent::data(layoutView, LayoutRect(rect), 0)); bool isTopLevelPainter = !s_inPaintContents; s_inPaintContents = true; FontCachePurgePreventer fontCachePurgePreventer; // TODO(jchaffraix): GlobalPaintFlags should be const during a paint // phase. Thus we should set this flag upfront (crbug.com/510280). GlobalPaintFlags localPaintFlags = globalPaintFlags; if (document->printing()) localPaintFlags |= GlobalPaintFlattenCompositingLayers | GlobalPaintPrinting; PaintLayer* rootLayer = layoutView->layer(); #if ENABLE(ASSERT) if (!frameView().shouldThrottleRendering()) layoutView->assertSubtreeIsLaidOut(); LayoutObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->layoutObject()); #endif PaintLayerPainter layerPainter(*rootLayer); float deviceScaleFactor = blink::deviceScaleFactor(rootLayer->layoutObject()->frame()); context.setDeviceScaleFactor(deviceScaleFactor); layerPainter.paint(context, LayoutRect(rect), localPaintFlags); if (rootLayer->containsDirtyOverlayScrollbars()) layerPainter.paintOverlayScrollbars(context, LayoutRect(rect), localPaintFlags); // Regions may have changed as a result of the visibility/z-index of element changing. if (document->annotatedRegionsDirty()) frameView().updateDocumentAnnotatedRegions(); if (isTopLevelPainter) { // Everything that happens after paintContents completions is considered // to be part of the next frame. memoryCache()->updateFramePaintTimestamp(); s_inPaintContents = false; } InspectorInstrumentation::didPaint(layoutView, 0, context, LayoutRect(rect)); }
void FramePainter::paintContents(GraphicsContext* context, const IntRect& rect) { Document* document = m_frameView.frame().document(); #ifndef NDEBUG bool fillWithRed; if (document->printing()) fillWithRed = false; // Printing, don't fill with red (can't remember why). else if (m_frameView.frame().owner()) fillWithRed = false; // Subframe, don't fill with red. else if (m_frameView.isTransparent()) fillWithRed = false; // Transparent, don't fill with red. else if (m_frameView.paintBehavior() & PaintBehaviorSelectionOnly) fillWithRed = false; // Selections are transparent, don't fill with red. else if (m_frameView.nodeToDraw()) fillWithRed = false; // Element images are transparent, don't fill with red. else fillWithRed = true; if (fillWithRed) { IntRect contentRect(IntPoint(), m_frameView.contentsSize()); DrawingRecorder drawingRecorder(*context, *m_frameView.layoutView(), DisplayItem::DebugRedFill, contentRect); if (!drawingRecorder.canUseCachedDrawing()) context->fillRect(contentRect, Color(0xFF, 0, 0)); } #endif LayoutView* layoutView = m_frameView.layoutView(); if (!layoutView) { WTF_LOG_ERROR("called FramePainter::paint with nil renderer"); return; } RELEASE_ASSERT(!m_frameView.needsLayout()); ASSERT(document->lifecycle().state() >= DocumentLifecycle::CompositingClean); TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Paint", "data", InspectorPaintEvent::data(layoutView, LayoutRect(rect), 0)); bool isTopLevelPainter = !s_inPaintContents; s_inPaintContents = true; FontCachePurgePreventer fontCachePurgePreventer; PaintBehavior oldPaintBehavior = m_frameView.paintBehavior(); if (FrameView* parentView = m_frameView.parentFrameView()) { if (parentView->paintBehavior() & PaintBehaviorFlattenCompositingLayers) m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers); } if (m_frameView.paintBehavior() == PaintBehaviorNormal) document->markers().invalidateRenderedRectsForMarkersInRect(LayoutRect(rect)); if (document->printing()) m_frameView.setPaintBehavior(m_frameView.paintBehavior() | PaintBehaviorFlattenCompositingLayers); ASSERT(!m_frameView.isPainting()); m_frameView.setIsPainting(true); // m_frameView.nodeToDraw() is used to draw only one element (and its descendants) LayoutObject* renderer = m_frameView.nodeToDraw() ? m_frameView.nodeToDraw()->layoutObject() : 0; DeprecatedPaintLayer* rootLayer = layoutView->layer(); #if ENABLE(ASSERT) layoutView->assertSubtreeIsLaidOut(); LayoutObject::SetLayoutNeededForbiddenScope forbidSetNeedsLayout(*rootLayer->layoutObject()); #endif DeprecatedPaintLayerPainter layerPainter(*rootLayer); float deviceScaleFactor = blink::deviceScaleFactor(rootLayer->layoutObject()->frame()); context->setDeviceScaleFactor(deviceScaleFactor); layerPainter.paint(context, LayoutRect(rect), m_frameView.paintBehavior(), renderer); if (rootLayer->containsDirtyOverlayScrollbars()) layerPainter.paintOverlayScrollbars(context, LayoutRect(rect), m_frameView.paintBehavior(), renderer); m_frameView.setIsPainting(false); m_frameView.setPaintBehavior(oldPaintBehavior); m_frameView.setLastPaintTime(currentTime()); // Regions may have changed as a result of the visibility/z-index of element changing. if (document->annotatedRegionsDirty()) m_frameView.updateAnnotatedRegions(); if (isTopLevelPainter) { // Everything that happens after paintContents completions is considered // to be part of the next frame. memoryCache()->updateFramePaintTimestamp(); s_inPaintContents = false; } InspectorInstrumentation::didPaint(layoutView, 0, context, LayoutRect(rect)); }
//BrowserWindow::BrowserWindow( BRect cFrame, std::vector<HistoryEntry*>* pcHistory, bool bLoadPos ) : BrowserWindow::BrowserWindow( BRect cFrame, bool /*bLoadPos*/ ) :BWindow( cFrame, "ABrowse", B_TITLED_WINDOW, 0 ) ,m_pcHTMLPart( NULL ) ,m_pcStatusBar( NULL ) ,m_pcURLView( NULL ) { atomic_add( &s_nWndCount, 1 ); // BAutolock al( GlobalMutex::GetMutex() ); // GlobalMutex::Lock(); RootView *pcRoot = new RootView( Bounds() ); AddChild( pcRoot ); // AddChild( pcRoot ); // AddTimer( this, 1, 100000, false ); // GlobalMutex::Unlock(); //-------------------------------------------------------------------------- #if 0 LayoutView* pcFrame = new LayoutView( cWndBounds, "frame_view" ); VLayoutNode* pcRoot = new VLayoutNode( "root" ); FrameView* pcNavBarFrame = new FrameView( Rect(0,0,0,0), "nav_bar_frame", "" ); HLayoutNode* pcNavBar = new HLayoutNode( "nav_bar" ); m_pcURLView = new TextView( Rect(0,0,0,0), "url_view", ""/*g_pzDefaultURL*/ ); m_pcURLView->SetEventMask( os::TextView::EI_ENTER_PRESSED | os::TextView::EI_ESC_PRESSED ); m_pcURLView->SetMultiLine( false ); m_pcURLView->SetMessage( new Message( ID_URL_CHANGED ) ); m_pcToolBar = new ToolBar( Rect(0,0,0,0), "tool_bar" ); m_pcStatusBar = new StatusBar( Rect(), "status_bar" ); m_pcToolBar->AddButton( "hi16-action-back.png", os::Message( ID_PREV_URL ) ); m_pcToolBar->AddButton( "hi16-action-forward.png", os::Message( ID_NEXT_URL ) ); m_pcToolBar->AddButton( "hi16-action-gohome.png", os::Message( ID_GOHOME ) ); m_pcToolBar->AddButton( "hi16-action-reload.png", os::Message( ID_RELOAD ) ); m_pcToolBar->AddButton( "hi16-action-find.png", os::Message( ID_FIND ) ); m_pcToolBar->AddButton( "hi16-action-editcopy.png", os::Message( ID_COPY ) ); pcNavBar->AddChild( m_pcToolBar )->SetBorders( Rect( 4, 2, 10, 2 ) ); pcNavBar->AddChild( m_pcURLView ); pcNavBarFrame->SetRoot( pcNavBar ); pcRoot->AddChild( pcNavBarFrame ); QWidget* pcTopView = new TopView; pcTopView->show(); pcTopView->SetResizeMask( CF_FOLLOW_ALL ); pcTopView->SetFrame( cWndBounds.Bounds() ); pcRoot->AddChild( pcTopView ); pcRoot->AddChild( m_pcStatusBar ); pcFrame->SetRoot( pcRoot ); m_pcHTMLPart = new KHTMLPart( pcTopView, "khtmlpart" ); // ### frame name m_pcHTMLPart->browserExtension()->SetCallback( this ); AddChild( pcFrame ); KHTMLView* pcView = m_pcHTMLPart->view(); pcView->SetResizeMask( CF_FOLLOW_ALL ); pcView->SetFrame( pcTopView->GetBounds() ); pcView->MakeFocus(); pcView->SetMsgTarget( Messenger( this ) ); pcView->show(); m_pcURLView->SetTarget( this ); m_pcToolBar->SetTarget( Messenger( this ) ); m_pcToolBar->EnableButton( BI_BACK, false ); m_pcToolBar->EnableButton( BI_FORWARD, false ); m_pcToolBar->EnableButton( BI_COPY, false ); char* pzHome = getenv( "HOME" ); if ( bLoadPos && NULL != pzHome ) { FILE* hFile; char zPath[ 256 ]; strcpy( zPath, pzHome ); strcat( zPath, "/config/abrowse.cfg" ); hFile = fopen( zPath, "rb" ); if ( NULL != hFile ) { Rect cNewFrame; fread( &cNewFrame, sizeof( cNewFrame ), 1, hFile ); fclose( hFile ); SetFrame( cNewFrame ); } } if ( pcHistory != NULL ) { for ( uint i = 0 ; i < pcHistory->size() ; ++i ) { HistoryEntry* pcEntry = new HistoryEntry; // *pcEntry = *(*pcHistory)[i]; pcEntry->m_cURL = (*pcHistory)[i]->m_cURL; pcEntry->m_cState = (*pcHistory)[i]->m_cState; m_cHistory.push_back( pcEntry ); } m_nCurHistoryPos = m_cHistory.size() - 1; m_pcToolBar->EnableButton( BI_BACK, true ); } // AddTimer( this, 1, 100000, false ); GlobalMutex::PopLooper(); // GlobalMutex::Unlock(); #endif }