ab70f9ce4353 — Jorge Arellano Cid 8 years ago
Fix Layout::resizeIdle()

This was three year old bug, that went undiscovered (hg#2863).
The patch is simpler than it looks, it's just a while cycle enclosing
the body, indentation makes it look large.

How to reproduce:

 1. Load [5] at normal size, wait for most images to load, search for "re-re"
    with Find Text, press page down (you'll see an image), go Bck/Fwd, check
    the image is there. If not, you can place the cursor where the image was,
    if you get a hand cursor, Dillo thinks it is there. Wait for the tooltip
    and drag it a bit downwards to the right, Dillo will repaint from the image
    data.

[5] http://tinyurl.com/huvf6pn
1 files changed, 75 insertions(+), 80 deletions(-)

M dw/layout.cc
M dw/layout.cc +75 -80
@@ 864,94 864,89 @@ void Layout::resizeIdle ()
 
    enterResizeIdle ();
 
-   //static int calls = 0;
-   //printf ("Layout::resizeIdle calls = %d\n", ++calls);
+   static int calls = 0;
+
+   while (resizeIdleId != -1) {
+      printf ("Layout::resizeIdle calls = %d\n", ++calls);
+
+      for (typed::Iterator <Widget> it = queueResizeList->iterator();
+           it.hasNext (); ) {
+         Widget *widget = it.getNext ();
 
-   assert (resizeIdleId != -1);
+         if (widget->resizeQueued ()) {
+            widget->setFlags (Widget::NEEDS_RESIZE);
+            widget->unsetFlags (Widget::RESIZE_QUEUED);
+         }
+
+         if (widget->allocateQueued ()) {
+            widget->setFlags (Widget::NEEDS_ALLOCATE);
+            widget->unsetFlags (Widget::ALLOCATE_QUEUED);
+         }
 
-   for (typed::Iterator <Widget> it = queueResizeList->iterator();
-        it.hasNext (); ) {
-      Widget *widget = it.getNext ();
+         if (widget->extremesQueued ()) {
+            widget->setFlags (Widget::EXTREMES_CHANGED);
+            widget->unsetFlags (Widget::EXTREMES_QUEUED);
+         }
+      }
+      queueResizeList->clear ();
+
+      // Reset here, since below, queueResize() may be called again.
+      resizeIdleId = -1;
 
-      //printf ("   the %stop-level %s %p was queued (extremes changed: %s)\n",
-      //        widget->parent ? "non-" : "", widget->getClassName(), widget,
-      //        widget->extremesQueued () ? "yes" : "no");
+      // If this method is triggered by a viewport change, we can save
+      // time when the toplevel widget is not affected (as for a toplevel
+      // image resource).
+      if (topLevel && (topLevel->needsResize () || topLevel->needsAllocate ())) {
+         Requisition requisition;
+         Allocation allocation;
+
+         topLevel->sizeRequest (&requisition);
+         DBG_OBJ_MSGF ("resize", 1, "toplevel size: %d * (%d + %d)",
+                       requisition.width, requisition.ascent,
+                       requisition.descent);
 
-      if (widget->resizeQueued ()) {
-         widget->setFlags (Widget::NEEDS_RESIZE);
-         widget->unsetFlags (Widget::RESIZE_QUEUED);
-      }
+         // This method is triggered by Widget::queueResize, which will,
+         // in any case, set NEEDS_ALLOCATE (indirectly, as ALLOCATE_QUEUED).
+         // This assertion helps to find inconsistencies. (Cases where
+         // this method is triggered by a viewport change, but the
+         // toplevel widget is not affected, are filtered out some lines
+         // above: "if (topLevel && topLevel->needsResize ())".)
+         assert (topLevel->needsAllocate ());
+
+         allocation.x = allocation.y = 0;
+         allocation.width = requisition.width;
+         allocation.ascent = requisition.ascent;
+         allocation.descent = requisition.descent;
+         topLevel->sizeAllocate (&allocation);
 
-      if (widget->allocateQueued ()) {
-         widget->setFlags (Widget::NEEDS_ALLOCATE);
-         widget->unsetFlags (Widget::ALLOCATE_QUEUED);
-      }
+         canvasWidth = requisition.width;
+         canvasAscent = requisition.ascent;
+         canvasDescent = requisition.descent;
+         emitter.emitCanvasSizeChanged (canvasWidth, 
+                                        canvasAscent, canvasDescent);
+         // Tell the view about the new world size.
+         view->setCanvasSize (canvasWidth, canvasAscent, canvasDescent);
+
+         if (usesViewport) {
+            int currHThickness = currHScrollbarThickness();
+            int currVThickness = currVScrollbarThickness();
 
-      if (widget->extremesQueued ()) {
-         widget->setFlags (Widget::EXTREMES_CHANGED);
-         widget->unsetFlags (Widget::EXTREMES_QUEUED);
+            if (!canvasHeightGreater &&
+                canvasAscent + canvasDescent > viewportHeight - currHThickness) {
+               canvasHeightGreater = true;
+               DBG_OBJ_SET_SYM ("canvasHeightGreater",
+                                canvasHeightGreater ? "true" : "false");
+               containerSizeChanged ();
+            }
+
+            // Set viewport sizes.
+            view->setViewportSize (viewportWidth, viewportHeight,
+                                   currHThickness, currVThickness);
+         }
+
+         // views are redrawn via Widget::resizeDrawImpl ()
       }
    }
-   queueResizeList->clear ();
-
-   // Reset already here, since in this function, queueResize() may be
-   // called again.
-   resizeIdleId = -1;
-
-   // If this method is triggered by a viewport change, we can save
-   // time when the toplevel widget is not affected (as for a toplevel
-   // image resource).
-   if (topLevel && (topLevel->needsResize () || topLevel->needsAllocate ())) {
-      Requisition requisition;
-      Allocation allocation;
-
-      topLevel->sizeRequest (&requisition);
-      DBG_OBJ_MSGF ("resize", 1, "toplevel size: %d * (%d + %d)",
-                    requisition.width, requisition.ascent, requisition.descent);
-
-      // This method is triggered by Widget::queueResize, which will,
-      // in any case, set NEEDS_ALLOCATE (indirectly, as ALLOCATE_QUEUED).
-      // This assertion helps to find inconsistences. (Cases where
-      // this method is triggered by a viewport change, but the
-      // toplevel widget is not affected, are filtered out some lines
-      // above: "if (topLevel && topLevel->needsResize ())".)
-      assert (topLevel->needsAllocate ());
-
-      allocation.x = allocation.y = 0;
-      allocation.width = requisition.width;
-      allocation.ascent = requisition.ascent;
-      allocation.descent = requisition.descent;
-      topLevel->sizeAllocate (&allocation);
-
-      canvasWidth = requisition.width;
-      canvasAscent = requisition.ascent;
-      canvasDescent = requisition.descent;
-
-      emitter.emitCanvasSizeChanged (canvasWidth, canvasAscent, canvasDescent);
-
-      // Tell the view about the new world size.
-      view->setCanvasSize (canvasWidth, canvasAscent, canvasDescent);
-
-      if (usesViewport) {
-         int currHThickness = currHScrollbarThickness();
-         int currVThickness = currVScrollbarThickness();
-
-         if (!canvasHeightGreater &&
-             canvasAscent + canvasDescent > viewportHeight - currHThickness) {
-            canvasHeightGreater = true;
-            DBG_OBJ_SET_SYM ("canvasHeightGreater",
-                             canvasHeightGreater ? "true" : "false");
-            containerSizeChanged ();
-         }
-
-         // Set viewport sizes.
-         view->setViewportSize (viewportWidth, viewportHeight,
-                                currHThickness, currVThickness);
-      }
-
-      // views are redrawn via Widget::resizeDrawImpl ()
-   }
-
    updateAnchor ();
 
    DBG_OBJ_MSGF ("resize", 1,