static void gtk_revealer_get_child_allocation (GtkRevealer *revealer, GtkAllocation *allocation, GtkAllocation *child_allocation) { GtkWidget *child; GtkRevealerTransitionType transition; g_return_if_fail (revealer != NULL); g_return_if_fail (allocation != NULL); child_allocation->x = 0; child_allocation->y = 0; child_allocation->width = allocation->width; child_allocation->height = allocation->height; child = gtk_bin_get_child (GTK_BIN (revealer)); if (child != NULL && gtk_widget_get_visible (child)) { transition = effective_transition (revealer); if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT || transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT) gtk_widget_get_preferred_width_for_height (child, child_allocation->height, NULL, &child_allocation->width); else gtk_widget_get_preferred_height_for_width (child, child_allocation->width, NULL, &child_allocation->height); } }
static void gtk_application_window_real_get_preferred_width_for_height (GtkWidget *widget, gint height, gint *minimum_width, gint *natural_width) { GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget); gint menubar_height; if (window->priv->menubar != NULL) gtk_widget_get_preferred_height (window->priv->menubar, &menubar_height, NULL); else menubar_height = 0; GTK_WIDGET_CLASS (gtk_application_window_parent_class) ->get_preferred_width_for_height (widget, height - menubar_height, minimum_width, natural_width); if (window->priv->menubar != NULL) { gint menubar_min_width, menubar_nat_width; gtk_widget_get_preferred_width_for_height (window->priv->menubar, menubar_height, &menubar_min_width, &menubar_nat_width); *minimum_width = MAX (*minimum_width, menubar_min_width); *natural_width = MAX (*natural_width, menubar_nat_width); } }
static void gtk_application_window_real_get_preferred_width_for_height (GtkWidget *widget, gint height, gint *minimum_width, gint *natural_width) { GtkApplicationWindow *window = GTK_APPLICATION_WINDOW (widget); gint menubar_height; if (window->priv->menubar != NULL) gtk_widget_get_preferred_height (window->priv->menubar, &menubar_height, NULL); else menubar_height = 0; GTK_WIDGET_CLASS (gtk_application_window_parent_class) ->get_preferred_width_for_height (widget, height - menubar_height, minimum_width, natural_width); if (window->priv->menubar != NULL) { gint menubar_min_width, menubar_nat_width; gint border_width; GtkBorder border = { 0 }; gtk_widget_get_preferred_width_for_height (window->priv->menubar, menubar_height, &menubar_min_width, &menubar_nat_width); border_width = gtk_container_get_border_width (GTK_CONTAINER (widget)); _gtk_window_get_shadow_width (GTK_WINDOW (widget), &border); menubar_min_width += 2 * border_width + border.left + border.right; menubar_nat_width += 2 * border_width + border.left + border.right; *minimum_width = MAX (*minimum_width, menubar_min_width); *natural_width = MAX (*natural_width, menubar_nat_width); } }
static gint columns_gtk3_get_minfh_width(ColumnsChild *child) { gint ret; gtk_widget_get_preferred_width_for_height( child->widget, child->h, &ret, NULL); return ret; }
wxSize wxControl::DoGetBestSize() const { // Do not return any arbitrary default value... wxASSERT_MSG( m_widget, wxT("DoGetBestSize called before creation") ); wxSize best; if (m_wxwindow) { // this is not a native control, size_request is likely to be (0,0) best = wxControlBase::DoGetBestSize(); } else { GtkRequisition req; #ifdef __WXGTK3__ if (gtk_widget_get_request_mode(m_widget) != GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) { gtk_widget_get_preferred_height(m_widget, NULL, &req.height); gtk_widget_get_preferred_width_for_height(m_widget, req.height, NULL, &req.width); } else { gtk_widget_get_preferred_width(m_widget, NULL, &req.width); gtk_widget_get_preferred_height_for_width(m_widget, req.width, NULL, &req.height); } #else GTK_WIDGET_GET_CLASS(m_widget)->size_request(m_widget, &req); #endif best.Set(req.width, req.height); } CacheBestSize(best); return best; }
/** * gtk_widget_get_preferred_size: * @widget: a #GtkWidget instance * @minimum_size: (out) (allow-none): location for storing the minimum size, or %NULL * @natural_size: (out) (allow-none): location for storing the natural size, or %NULL * * Retrieves the minimum and natural size of a widget, taking * into account the widget's preference for height-for-width management. * * This is used to retrieve a suitable size by container widgets which do * not impose any restrictions on the child placement. It can be used * to deduce toplevel window and menu sizes as well as child widgets in * free-form containers such as GtkLayout. * * <note><para>Handle with care. Note that the natural height of a height-for-width * widget will generally be a smaller size than the minimum height, since the required * height for the natural width is generally smaller than the required height for * the minimum width.</para></note> * * Since: 3.0 */ void gtk_widget_get_preferred_size (GtkWidget *widget, GtkRequisition *minimum_size, GtkRequisition *natural_size) { gint min_width, nat_width; gint min_height, nat_height; g_return_if_fail (GTK_IS_WIDGET (widget)); if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH) { gtk_widget_get_preferred_width (widget, &min_width, &nat_width); if (minimum_size) { minimum_size->width = min_width; gtk_widget_get_preferred_height_for_width (widget, min_width, &minimum_size->height, NULL); } if (natural_size) { natural_size->width = nat_width; gtk_widget_get_preferred_height_for_width (widget, nat_width, NULL, &natural_size->height); } } else /* GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT or CONSTANT_SIZE */ { gtk_widget_get_preferred_height (widget, &min_height, &nat_height); if (minimum_size) { minimum_size->height = min_height; gtk_widget_get_preferred_width_for_height (widget, min_height, &minimum_size->width, NULL); } if (natural_size) { natural_size->height = nat_height; gtk_widget_get_preferred_width_for_height (widget, nat_height, NULL, &natural_size->width); } } }
static void gd_notification_get_preferred_width_for_height (GtkWidget *widget, gint height, gint *minimum_width, gint *natural_width) { GdNotification *notification = GD_NOTIFICATION (widget); GdNotificationPrivate *priv = notification->priv; GtkBin *bin = GTK_BIN (widget); gint child_min, child_nat, child_height; GtkWidget *child; GtkBorder padding; gint minimum, natural; get_padding_and_border (notification, &padding); minimum = 0; natural = 0; child_height = height - SHADOW_OFFSET_Y - padding.top - padding.bottom; child = gtk_bin_get_child (bin); if (child && gtk_widget_get_visible (child)) { gtk_widget_get_preferred_width_for_height (child, child_height, &child_min, &child_nat); minimum += child_min; natural += child_nat; } if (priv->show_close_button) { gtk_widget_get_preferred_width_for_height (priv->close_button, child_height, &child_min, &child_nat); minimum += child_min; natural += child_nat; } minimum += padding.left + padding.right + 2 * SHADOW_OFFSET_X; natural += padding.left + padding.right + 2 * SHADOW_OFFSET_X; if (minimum_width) *minimum_width = minimum; if (natural_width) *natural_width = natural; }
static void gtk_notification_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkNotification *notification = GTK_NOTIFICATION (widget); GtkNotificationPrivate *priv = notification->priv; GtkBin *bin = GTK_BIN (widget); GtkAllocation child_allocation; GtkBorder padding; GtkWidget *child; int button_width; gtk_widget_set_allocation (widget, allocation); /* If somehow the notification changes while not hidden and we're not animating, immediately follow the resize */ if (priv->animate_y > 0 && !priv->animate_timeout) priv->animate_y = allocation->height; get_padding_and_border (notification, &padding); if (gtk_widget_get_realized (widget)) { gdk_window_move_resize (gtk_widget_get_window (widget), allocation->x, allocation->y, allocation->width, allocation->height); gdk_window_move_resize (priv->bin_window, 0, -allocation->height + priv->animate_y, allocation->width, allocation->height); } child_allocation.x = SHADOW_OFFSET_X + padding.left; child_allocation.y = padding.top; child_allocation.height = MAX (1, allocation->height - SHADOW_OFFSET_Y - padding.top - padding.bottom); gtk_widget_get_preferred_width_for_height (priv->close_button, child_allocation.height, NULL, &button_width); child_allocation.width = MAX (1, allocation->width - 2 * SHADOW_OFFSET_X - padding.left - padding.right - button_width); child = gtk_bin_get_child (bin); if (child && gtk_widget_get_visible (child)) gtk_widget_size_allocate (child, &child_allocation); child_allocation.x += child_allocation.width; child_allocation.width = button_width; gtk_widget_size_allocate (priv->close_button, &child_allocation); }
/* Like get_group_sizes(), but gets height for width or width for height */ static GtkRequestedSize * get_group_sizes_for_sizes(PSquare *self, GtkOrientation direction, GtkRequestedSize *perpendicular_sizes, unsigned n_groups) { PSquarePrivate *priv = P_SQUARE_PRIVATE(self); /* Allocate an array for the size of each column/row */ GtkRequestedSize *sizes = g_new0(GtkRequestedSize, n_groups); /* Get each child's size; set the width of each group * to the maximum size of each child in that group */ unsigned count = 0; GList *iter; for(iter = priv->children; iter; iter = g_list_next(iter)) { if(!gtk_widget_get_visible(iter->data)) continue; int child_minimal, child_natural; unsigned group_num; if(direction == GTK_ORIENTATION_HORIZONTAL) { gtk_widget_get_preferred_width_for_height(iter->data, perpendicular_sizes[count / n_groups].minimum_size, &child_minimal, &child_natural); group_num = count % n_groups; } else { gtk_widget_get_preferred_height_for_width(iter->data, perpendicular_sizes[count % n_groups].minimum_size, &child_minimal, &child_natural); group_num = count / n_groups; } sizes[group_num].minimum_size = MAX(child_minimal, sizes[group_num].minimum_size); sizes[group_num].natural_size = MAX(child_natural, sizes[group_num].natural_size); count++; } return sizes; }
static void gd_stack_get_preferred_width_for_height (GtkWidget* widget, gint height, gint *minimum_width, gint *natural_width) { GdStack *stack = GD_STACK (widget); GdStackPrivate *priv = stack->priv; GdStackChildInfo *child_info; GtkWidget *child; gint child_min, child_nat; GList *l; *minimum_width = 0; *natural_width = 0; for (l = priv->children; l != NULL; l = l->next) { child_info = l->data; child = child_info->widget; if (!priv->homogeneous && (priv->visible_child != child_info && priv->last_visible_child != child_info)) continue; if (gtk_widget_get_visible (child)) { gtk_widget_get_preferred_width_for_height (child, height, &child_min, &child_nat); *minimum_width = MAX (*minimum_width, child_min); *natural_width = MAX (*natural_width, child_nat); } } if (priv->last_visible_surface != NULL) { *minimum_width = MAX (*minimum_width, priv->last_visible_surface_allocation.width); *natural_width = MAX (*natural_width, priv->last_visible_surface_allocation.width); } }
static void gtk_revealer_get_child_allocation (GtkRevealer *revealer, GtkAllocation *allocation, GtkAllocation *child_allocation) { GtkWidget *child; GtkRevealerTransitionType transition; GtkBorder padding; gint vertical_padding, horizontal_padding; g_return_if_fail (revealer != NULL); g_return_if_fail (allocation != NULL); /* See explanation on gtk_revealer_real_size_allocate */ gtk_revealer_get_padding (revealer, &padding); vertical_padding = padding.top + padding.bottom; horizontal_padding = padding.left + padding.right; child_allocation->x = 0; child_allocation->y = 0; child_allocation->width = 0; child_allocation->height = 0; child = gtk_bin_get_child (GTK_BIN (revealer)); if (child != NULL && gtk_widget_get_visible (child)) { transition = effective_transition (revealer); if (transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_LEFT || transition == GTK_REVEALER_TRANSITION_TYPE_SLIDE_RIGHT) gtk_widget_get_preferred_width_for_height (child, MAX (0, allocation->height - vertical_padding), NULL, &child_allocation->width); else gtk_widget_get_preferred_height_for_width (child, MAX (0, allocation->width - horizontal_padding), NULL, &child_allocation->height); } child_allocation->width = MAX (child_allocation->width, allocation->width - horizontal_padding); child_allocation->height = MAX (child_allocation->height, allocation->height - vertical_padding); }
static void greeter_menu_bar_size_allocate(GtkWidget* widget, GtkAllocation* allocation) { GList* item; GList* shell_children; GList* expand_nums = NULL; guint visible_count = 0, expand_count = 0; g_return_if_fail(allocation != NULL); g_return_if_fail(GREETER_IS_MENU_BAR(widget)); gtk_widget_set_allocation(widget, allocation); GtkPackDirection pack_direction = gtk_menu_bar_get_pack_direction(GTK_MENU_BAR(widget)); g_return_if_fail(pack_direction == GTK_PACK_DIRECTION_LTR || pack_direction == GTK_PACK_DIRECTION_RTL); shell_children = gtk_container_get_children(GTK_CONTAINER(widget)); for(item = shell_children; item; item = g_list_next(item)) if(gtk_widget_get_visible(item->data)) { if(gtk_widget_compute_expand(item->data, GTK_ORIENTATION_HORIZONTAL)) { expand_nums = g_list_prepend(expand_nums, GINT_TO_POINTER(visible_count)); expand_count++; } visible_count++; } if(gtk_widget_get_realized(widget)) gdk_window_move_resize(gtk_widget_get_window(widget), allocation->x, allocation->y, allocation->width, allocation->height); if(visible_count > 0) { GtkAllocation remaining_space; GtkStyleContext* context = gtk_widget_get_style_context(widget); GtkStateFlags flags = gtk_widget_get_state_flags(widget); GtkRequestedSize* requested_sizes = g_newa(GtkRequestedSize, visible_count); guint border_width = gtk_container_get_border_width(GTK_CONTAINER(widget)); GtkShadowType shadow_type = GTK_SHADOW_OUT; GtkBorder border; gint toggle_size; gtk_style_context_get_padding(context, flags, &border); gtk_widget_style_get(widget, "shadow-type", &shadow_type, NULL); remaining_space.x = (border_width + border.left); remaining_space.y = (border_width + border.top); remaining_space.width = allocation->width - 2 * border_width - border.left - border.right; remaining_space.height = allocation->height - 2 * border_width - border.top - border.bottom; if (shadow_type != GTK_SHADOW_NONE) { gtk_style_context_get_border(context, flags, &border); remaining_space.x += border.left; remaining_space.y += border.top; remaining_space.width -= border.left + border.right; remaining_space.height -= border.top + border.bottom; } GtkRequestedSize* request = requested_sizes; int size = remaining_space.width; gboolean ltr = (gtk_widget_get_direction(widget) == GTK_TEXT_DIR_LTR) == (pack_direction == GTK_PACK_DIRECTION_LTR); for(item = shell_children; item; item = g_list_next(item)) { if (!gtk_widget_get_visible(item->data)) continue; request->data = item->data; gtk_widget_get_preferred_width_for_height(item->data, remaining_space.height, &request->minimum_size, &request->natural_size); gtk_menu_item_toggle_size_request(GTK_MENU_ITEM(item->data), &toggle_size); request->minimum_size += toggle_size; request->natural_size += toggle_size; gtk_menu_item_toggle_size_allocate(GTK_MENU_ITEM(item->data), toggle_size); size -= request->minimum_size; request++; } size = gtk_distribute_natural_allocation(size, visible_count, requested_sizes); /* Distribution extra space for widgets with expand=True */ if(size > 0 && expand_nums) { expand_nums = g_list_sort_with_data(expand_nums, (GCompareDataFunc)sort_minimal_size, requested_sizes); GList* first_item = expand_nums; gint needed_size = -1; gint max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size; gint total_needed_size = 0; /* Free space that all widgets need to have the same (max_size) width * [___max_width___][widget ][widget____ ] * total_needed_size := [] + [ ] + [ ] * total_needed_size = [ ] */ for(item = g_list_next(expand_nums); item; item = g_list_next(item)) total_needed_size += max_size - requested_sizes[GPOINTER_TO_INT(item->data)].natural_size; while(first_item) { if(size >= total_needed_size) { /* total_needed_size is enough for all remaining widgets */ needed_size = max_size + (size - total_needed_size)/expand_count; break; } /* Removing current maximal widget from list */ total_needed_size -= max_size - requested_sizes[GPOINTER_TO_INT(item->data)].natural_size; first_item = g_list_next(first_item); if(first_item) max_size = requested_sizes[GPOINTER_TO_INT(first_item->data)].natural_size; } for(item = first_item; item; item = g_list_next(item)) { request = &requested_sizes[GPOINTER_TO_INT(item->data)]; gint dsize = needed_size - request->natural_size; if(size < dsize) dsize = size; size -= dsize; request->natural_size += dsize; } } gint i; for(i = 0; i < visible_count; i++) { GtkAllocation child_allocation = remaining_space; request = &requested_sizes[i]; child_allocation.width = request->natural_size; remaining_space.width -= request->natural_size; if (ltr) remaining_space.x += request->natural_size; else child_allocation.x += remaining_space.width; gtk_widget_size_allocate(request->data, &child_allocation); } g_list_free(expand_nums); } g_list_free(shell_children); }