]> Pileus Git - ~andy/gtk/commitdiff
Added logic to GtkScrolledWindow when allocating height-for-width children.
authorTristan Van Berkom <tristan.van.berkom@gmail.com>
Tue, 12 Oct 2010 08:16:32 +0000 (17:16 +0900)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Tue, 12 Oct 2010 08:16:32 +0000 (17:16 +0900)
This patch makes the scrolled window reconsider allocating the child
the full width or height (depending on the child's request mode) without
a scrollbar. For instance when the child is height-for-width; the child
will first be tested if the content's height for full allocated width
(without a vscrollbar) will allow the contents height for that width
to fit the allocated height.

Patch is a simplified version of code inspected in st-scroll-view.c.
Note that this patch assumes children will begin to scroll only after
reaching their minimum size; adding a property to the future
GtkScrollableIface to decide whether to scroll-to-minimum or scroll-to-natural
will effect this code (it should then reconsider whether the child
will scroll below the natural size instead of the minimum).

Patch addresses bug 629778.

gtk/gtkscrolledwindow.c

index a6058b14eff499071491dbb7e83887061459627b..1a13b4aa5381f5e6ebaeb98e4495624e8f95c5b6 100644 (file)
@@ -1453,10 +1453,132 @@ gtk_scrolled_window_size_allocate (GtkWidget     *widget,
   child = gtk_bin_get_child (bin);
   if (child && gtk_widget_get_visible (child))
     {
-      gboolean previous_vvis;
+      gint child_min_width;
+      gint child_min_height;
       gboolean previous_hvis;
+      gboolean previous_vvis;
       guint count = 0;
 
+      /* In the case that both scrollbars are visible in the previous round,
+       * we dont do our guess-work before hand because it's possible some
+       * infinite recursion was detected (leave it up to the child scrollable
+       * widget in this case to drive the scrollbar visibility completely 
+       * with the adjustment values).
+       */
+      if (!priv->vscrollbar_visible || !priv->hscrollbar_visible)
+       {
+
+         /* Determine scrollbar visibility first via hfw apis */
+         if (gtk_widget_get_request_mode (child) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
+           {
+             gtk_widget_get_preferred_width (child, &child_min_width, NULL);
+             
+             if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+               {
+                 /* First try without a vertical scrollbar if the content will fit the height
+                  * given the extra width of the scrollbar */
+                 gtk_widget_get_preferred_height_for_width (child, allocation->width, 
+                                                            &child_min_height, NULL);
+                 
+                 if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+                   {
+                     /* Does the content height fit the allocation height ? */
+                     priv->vscrollbar_visible = child_min_height > allocation->height;
+                     
+                     /* Does the content width fit the allocation with minus a possible scrollbar ? */
+                     priv->hscrollbar_visible = 
+                       child_min_width > allocation->width - 
+                       (priv->vscrollbar_visible ? sb_width + sb_spacing : 0);
+                     
+                     /* Now that we've guessed the hscrollbar, does the content height fit
+                      * the possible new allocation height ? */
+                     priv->vscrollbar_visible = 
+                       child_min_height > allocation->height - 
+                       (priv->hscrollbar_visible ? sb_height + sb_spacing : 0);
+                     
+                     /* Now that we've guessed the vscrollbar, does the content width fit
+                      * the possible new allocation width ? */
+                     priv->hscrollbar_visible = 
+                       child_min_width > allocation->width - 
+                       (priv->vscrollbar_visible ? sb_width + sb_spacing : 0);
+                   }
+                 else /* priv->hscrollbar_policy != GTK_POLICY_AUTOMATIC */
+                   {
+                     priv->hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
+                     priv->vscrollbar_visible = child_min_height > allocation->height - 
+                       (priv->hscrollbar_visible ? sb_height + sb_spacing : 0);
+                   }
+               }
+             else /* priv->vscrollbar_policy != GTK_POLICY_AUTOMATIC */
+               {
+                 priv->vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;
+                 
+                 if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+                   priv->hscrollbar_visible = 
+                     child_min_width > allocation->width - 
+                     (priv->vscrollbar_visible ? 0 : sb_width + sb_spacing);
+                 else
+                   priv->hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
+               }
+           } 
+         else /* GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT */
+           {
+             gtk_widget_get_preferred_height (child, &child_min_height, NULL);
+             
+             if (priv->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+               {
+                 /* First try without a horizontal scrollbar if the content will fit the width
+                  * given the extra height of the scrollbar */
+                 gtk_widget_get_preferred_width_for_height (child, allocation->height, 
+                                                            &child_min_width, NULL);
+                 
+                 if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+                   {
+                     /* Does the content width fit the allocation width ? */
+                     priv->hscrollbar_visible = child_min_width > allocation->width;
+                     
+                     /* Does the content height fit the allocation with minus a possible scrollbar ? */
+                     priv->vscrollbar_visible = 
+                       child_min_height > allocation->height - 
+                       (priv->hscrollbar_visible ? sb_height + sb_spacing : 0);
+                     
+                     /* Now that we've guessed the vscrollbar, does the content width fit
+                      * the possible new allocation width ? */
+                     priv->hscrollbar_visible = 
+                       child_min_width > allocation->width - 
+                       (priv->vscrollbar_visible ? sb_width + sb_spacing : 0);
+                     
+                     /* Now that we've guessed the hscrollbar, does the content height fit
+                      * the possible new allocation height ? */
+                     priv->vscrollbar_visible = 
+                       child_min_height > allocation->height - 
+                       (priv->hscrollbar_visible ? sb_height + sb_spacing : 0);
+                   }
+                 else /* priv->vscrollbar_policy != GTK_POLICY_AUTOMATIC */
+                   {
+                     priv->vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;
+                     priv->hscrollbar_visible = child_min_width > allocation->width - 
+                       (priv->vscrollbar_visible ? sb_width + sb_spacing : 0);
+                   }
+               }
+             else /* priv->hscrollbar_policy != GTK_POLICY_AUTOMATIC */
+               {
+                 priv->hscrollbar_visible = priv->hscrollbar_policy != GTK_POLICY_NEVER;
+                 
+                 if (priv->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+                   priv->vscrollbar_visible = 
+                     child_min_height > allocation->height - 
+                     (priv->hscrollbar_visible ? 0 : sb_height + sb_spacing);
+                 else
+                   priv->vscrollbar_visible = priv->vscrollbar_policy != GTK_POLICY_NEVER;
+               }
+           }
+       }
+
+      /* Now after guessing scrollbar visibility; fall back on the allocation loop which 
+       * observes the adjustments to detect scrollbar visibility and also avoids 
+       * infinite recursion
+       */
       do
        {
          gtk_scrolled_window_relative_allocation (widget, &relative_allocation);