Hi,

I want to flatten frames within a frameset so that no individual scrollbars
of frames would appear. This is the behavior of most mobile browsers
including iPhone and Android.

I found the patch from the Android WebKit source code with FLATTEN_FRAMESET.
I applied the patch to the latest version of WebKit and adjusted it the
latest changes, but it does not seem to work.

WebCore/rendering/RenderFrame.cpp

+#if USE(FLATTEN_FRAMESET)
+void RenderFrame::layout()
+{
+    if (widget() && widget()->isFrameView()) {
+        FrameView* view = static_cast<FrameView*>(widget());
+        RenderView* root = NULL;
+        if (view->frame() && view->frame()->document() &&
+            view->frame()->document()->renderer() &&
view->frame()->document()->renderer()->isRenderView())
+            root =
static_cast<RenderView*>(view->frame()->document()->renderer());
+        if (root) {
+            // Resize the widget so that the RenderView will layout
according to those dimensions.
+            view->resize(m_width, m_height);
+            view->layout();
+            // We can only grow in width and height because if
positionFrames gives us a width and we become smaller,
+            // then the fixup process of forcing the frame to fill extra
space will fail.
+            if (m_width > root->docWidth()) {
+                view->resize(root->docWidth(), 0);
+                view->layout();
+            }
+            // Honor the height set by RenderFrameSet::positionFrames
unless our document height is larger.
+            setHeight(max(root->docHeight(), height()));
+            setWidth(max(root->docWidth(), width()));
+        }
+    }
+    setNeedsLayout(false);
+}
+#endif
+


I tested it with http://java.sun.com/j2se/1.5.0/docs/api/ which has three
frames within a frameset.

GtkLauncher hangs when it loads the Java API page. However, after I remove
the following two lines from the patch, it seems to work and frames are
correctly flattened.

        if (root) {
            // Resize the widget so that the RenderView will layout
according to those dimensions.
-            view->resize(m_width, m_height);
-            view->layout();
            // We can only grow in width and height because if
positionFrames gives us a width and we become smaller,
            // then the fixup process of forcing the frame to fill extra
space will fail.


What's the problem here? I attached the whole patch.

Thanks,
K Seo
Index: WebCore/config.h
===================================================================
--- WebCore/config.h	(revision 45369)
+++ WebCore/config.h	(working copy)
@@ -176,3 +176,8 @@ typedef float CGFloat;
 #if PLATFORM(WIN) && PLATFORM(CG)
 #define WTF_USE_SAFARI_THEME 1
 #endif
+
+#if PLATFORM(GTK)
+#define WTF_USE_FLATTEN_FRAMESET 1
+#endif
+
Index: WebCore/html/HTMLFrameSetElement.cpp
===================================================================
--- WebCore/html/HTMLFrameSetElement.cpp	(revision 45369)
+++ WebCore/html/HTMLFrameSetElement.cpp	(working copy)
@@ -203,6 +203,9 @@ void HTMLFrameSetElement::recalcStyle(St
 {
     if (needsStyleRecalc() && renderer()) {
         renderer()->setNeedsLayout(true);
+#if USE(FLATTEN_FRAMESET)
+        static_cast<RenderFrameSet*>(renderer())->setGridNeedsLayout();
+#endif
         setNeedsStyleRecalc(NoStyleChange);
     }
     HTMLElement::recalcStyle(ch);
Index: WebCore/page/FrameView.cpp
===================================================================
--- WebCore/page/FrameView.cpp	(revision 45369)
+++ WebCore/page/FrameView.cpp	(working copy)
@@ -953,6 +953,11 @@ void FrameView::scheduleRelayout()
         printf("Scheduling layout for %d\n", delay);
 #endif
 
+#if USE(FLATTEN_FRAMESET)
+    if (m_frame->ownerRenderer())
+        m_frame->ownerRenderer()->setNeedsLayoutAndPrefWidthsRecalc();
+#endif
+
     m_layoutTimer.startOneShot(delay * 0.001);
 }
 
Index: WebCore/rendering/RenderFrame.cpp
===================================================================
--- WebCore/rendering/RenderFrame.cpp	(revision 45369)
+++ WebCore/rendering/RenderFrame.cpp	(working copy)
@@ -27,6 +27,12 @@
 #include "FrameView.h"
 #include "HTMLFrameElement.h"
 
+#if USE(FLATTEN_FRAMESET)
+#include "Frame.h"
+#include "Document.h"
+#include "RenderView.h"
+#endif
+
 namespace WebCore {
 
 RenderFrame::RenderFrame(HTMLFrameElement* frame)
@@ -58,4 +64,32 @@ void RenderFrame::viewCleared()
         view->setMarginHeight(marginh);
 }
 
+#if USE(FLATTEN_FRAMESET)
+void RenderFrame::layout()
+{
+    if (widget() && widget()->isFrameView()) {
+        FrameView* view = static_cast<FrameView*>(widget());
+        RenderView* root = NULL;
+        if (view->frame() && view->frame()->document() &&
+            view->frame()->document()->renderer() && view->frame()->document()->renderer()->isRenderView())
+            root = static_cast<RenderView*>(view->frame()->document()->renderer());
+        if (root) {
+            // Resize the widget so that the RenderView will layout according to those dimensions.
+            view->resize(m_width, m_height);
+            view->layout();
+            // We can only grow in width and height because if positionFrames gives us a width and we become smaller,
+            // then the fixup process of forcing the frame to fill extra space will fail.
+            if (m_width > root->docWidth()) {
+                view->resize(root->docWidth(), 0);
+                view->layout();
+            }
+            // Honor the height set by RenderFrameSet::positionFrames unless our document height is larger.
+            setHeight(max(root->docHeight(), height()));
+            setWidth(max(root->docWidth(), width()));
+        }
+    }
+    setNeedsLayout(false);
+}
+#endif
+
 } // namespace WebCore
Index: WebCore/rendering/RenderFrame.h
===================================================================
--- WebCore/rendering/RenderFrame.h	(revision 45369)
+++ WebCore/rendering/RenderFrame.h	(working copy)
@@ -36,6 +36,10 @@ public:
 
     FrameEdgeInfo edgeInfo() const;
 
+#if USE(FLATTEN_FRAMESET)
+    virtual void layout();
+#endif
+
 private:
     virtual const char* renderName() const { return "RenderFrame"; }
     virtual bool isFrame() const { return true; }
Index: WebCore/rendering/RenderFrameSet.cpp
===================================================================
--- WebCore/rendering/RenderFrameSet.cpp	(revision 45369)
+++ WebCore/rendering/RenderFrameSet.cpp	(working copy)
@@ -45,6 +45,9 @@ RenderFrameSet::RenderFrameSet(HTMLFrame
     : RenderBox(frameSet)
     , m_isResizing(false)
     , m_isChildResizing(false)
+#if USE(FLATTEN_FRAMESET)
+    , m_gridCalculated(false)
+#endif
 {
     setInline(false);
 }
@@ -459,6 +462,10 @@ void RenderFrameSet::layout()
     if (!parent()->isFrameSet() && !document()->printing()) {
         setWidth(view()->viewWidth());
         setHeight(view()->viewHeight());
+#if USE(FLATTEN_FRAMESET)
+        // Force a grid recalc.
+        m_gridCalculated = false;
+#endif
     }
 
     size_t cols = frameSet()->totalCols();
@@ -467,11 +474,27 @@ void RenderFrameSet::layout()
     if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) {
         m_rows.resize(rows);
         m_cols.resize(cols);
+#if USE(FLATTEN_FRAMESET)
+        m_gridCalculated = false;
+#endif
     }
 
+#if USE(FLATTEN_FRAMESET)
+    if (!m_gridCalculated) {
+        m_gridCalculated = true;
+        // Make all the child framesets recalculates their grid.
+        RenderObject* child = firstChild();
+        for (; child; child = child->nextSibling()) {
+            if (child->isFrameSet())
+                static_cast<RenderFrameSet*>(child)->setGridNeedsLayout();
+        }
+#endif
     int borderThickness = frameSet()->border();
     layOutAxis(m_rows, frameSet()->rowLengths(), height() - (rows - 1) * borderThickness);
     layOutAxis(m_cols, frameSet()->colLengths(), width() - (cols - 1) * borderThickness);
+#if USE(FLATTEN_FRAMESET)
+    }
+#endif
 
     positionFrames();
 
@@ -500,6 +523,86 @@ void RenderFrameSet::positionFrames()
 
     int yPos = 0;
     int borderThickness = frameSet()->border();
+#if USE(FLATTEN_FRAMESET)
+    // Keep track of the maximum width of a row which will become the maximum width of the frameset.
+    int maxWidth = 0;
+    const Length* rowLengths = frameSet()->rowLengths();
+    const Length* colLengths = frameSet()->colLengths();
+
+    for (int r = 0; r < rows && child; r++) {
+        int xPos = 0;
+        int height = m_rows.m_sizes[r];
+        int rowHeight = -1;
+        if (rowLengths) {
+            Length l = rowLengths[r];
+            if (l.isFixed())
+                rowHeight = l.value();
+        }
+        for (int c = 0; c < cols && child; c++) {
+            child->setX(xPos);
+            child->setY(yPos);
+            child->setWidth(m_cols.m_sizes[c]);
+            child->setHeight(height);
+            int colWidth = -1;
+            if (colLengths) {
+                Length l = colLengths[c];
+                if (l.isFixed())
+                    colWidth = l.value();
+            }
+            if (colWidth && rowHeight) {
+                child->setNeedsLayout(true);
+                child->layout();
+            } else {
+                child->layoutIfNeeded();
+            }
+
+            ASSERT(child->width() >= m_cols.m_sizes[c]);
+            m_cols.m_sizes[c] = child->width();
+
+            height = max(child->height(), height);
+            xPos += child->width() + borderThickness;
+            child = static_cast<RenderBox*>(child->nextSibling());
+        }
+        ASSERT(height >= m_rows.m_sizes[r]);
+        m_rows.m_sizes[r] = height;
+        maxWidth = max(xPos, maxWidth);
+        yPos += height + borderThickness;
+    }
+
+    // Compute a new width and height according to the positioning of each expanded child frame.
+    // Note: we subtract borderThickness because we only count borders between frames.
+    int newWidth = maxWidth - borderThickness;
+    int newHeight = yPos - borderThickness;
+
+    // Distribute the extra width and height evenly across the grid.
+    int dWidth = (width() - newWidth) / cols;
+    int dHeight = (height() - newHeight) / rows;
+    if (dWidth > 0) {
+        int availableWidth = width() - (cols - 1) * borderThickness;
+        for (int c = 0; c < cols; c++)
+            availableWidth -= m_cols.m_sizes[c] += dWidth;
+        // If the extra width did not distribute evenly, add the remainder to
+        // the last column.
+        if (availableWidth)
+            m_cols.m_sizes[cols - 1] += availableWidth;
+    }
+    if (dHeight > 0) {
+        int availableHeight = height() - (rows - 1) * borderThickness;
+        for (int r = 0; r < rows; r++)
+            availableHeight -= m_rows.m_sizes[r] += dHeight;
+        // If the extra height did not distribute evenly, add the remainder to
+        // the last row.
+        if (availableHeight)
+            m_rows.m_sizes[rows - 1] += availableHeight;
+    }
+    // Ensure the rows and columns are filled by falling through to the normal
+    // layout
+    setHeight(max(height(), newHeight));
+    setWidth(max(width(), newWidth));
+    child = static_cast<RenderBox*>(firstChild());
+    yPos = 0;
+#endif // USE(FLATTEN_FRAMESET)
+
     for (int r = 0; r < rows; r++) {
         int xPos = 0;
         int height = m_rows.m_sizes[r];
Index: WebCore/rendering/RenderFrameSet.h
===================================================================
--- WebCore/rendering/RenderFrameSet.h	(revision 45369)
+++ WebCore/rendering/RenderFrameSet.h	(working copy)
@@ -81,6 +81,10 @@ public:
     bool canResizeRow(const IntPoint&) const;
     bool canResizeColumn(const IntPoint&) const;
 
+#if USE(FLATTEN_FRAMESET)
+    void setGridNeedsLayout() { m_gridCalculated = false; }
+#endif
+
 private:
     static const int noSplit = -1;
 
@@ -121,6 +125,9 @@ private:
 
     bool m_isResizing;
     bool m_isChildResizing;
+#if USE(FLATTEN_FRAMESET)
+    bool m_gridCalculated;
+#endif
 };
 
 } // namespace WebCore
Index: WebCore/rendering/RenderView.h
===================================================================
--- WebCore/rendering/RenderView.h	(revision 45369)
+++ WebCore/rendering/RenderView.h	(working copy)
@@ -170,6 +170,9 @@ protected:
 private:
     bool shouldRepaint(const IntRect& r) const;
         
+#if USE(FLATTEN_FRAMESET)
+public:
+#endif
     int docHeight() const;
     int docWidth() const;
 
_______________________________________________
webkit-dev mailing list
webkit-dev@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-dev

Reply via email to