GtkFrame seems to ignore height in get_preferred_width_for_height
get_preferred_width_for_height
for GtkFrame
seems to return incorrect width when child widget implements width-for-height
size request mode.
https://gitlab.gnome.org/GNOME/gtk/-/blob/3.24.48/gtk/gtkframe.c?ref_type=tags#L998-1008
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
}
else
{
if (for_size > 0)
gtk_widget_get_preferred_height_for_width (child, for_size, &child_min, &child_nat);
else
gtk_widget_get_preferred_height (child, &child_min, &child_nat);
}
For horizontal orientation for_size
is ignored while it is used when orientation is vertical. Is that design choice or bug that nobody has noticed? Should I open merge request with code updated to?:
if (orientation == GTK_ORIENTATION_HORIZONTAL)
{
if (for_size > 0)
gtk_widget_get_preferred_width_for_height (child, for_size, &child_min, &child_nat);
else
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
}
...
Following code can be used for testing:
#include <gtk/gtk.h>
#define FRAME_TYPE_SIZE (frame_size_get_type ())
G_DECLARE_FINAL_TYPE (FrameSize, frame_size, FRAME, SIZE, GtkDrawingArea)
struct _FrameSize
{
GtkDrawingArea parent;
};
G_DEFINE_TYPE (FrameSize, frame_size, GTK_TYPE_DRAWING_AREA)
static GtkSizeRequestMode
frame_size_get_request_mode (GtkWidget *widget)
{
return GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT;
}
static void
frame_size_get_preferred_width (GtkWidget *widget,
int *minimum_width,
int *natural_width)
{
*minimum_width = 16;
*natural_width = 16;
g_print ("frame_size_get_preferred_width: min - %d, nat - %d\n",
*minimum_width, *natural_width);
}
static void
frame_size_get_preferred_width_for_height (GtkWidget *widget,
int height,
int *minimum_width,
int *natural_width)
{
*minimum_width = height * 2;
*natural_width = height * 2;
g_print ("frame_size_get_preferred_width_for_height (%d): min - %d, nat - %d\n",
height, *minimum_width, *natural_width);
}
static void
frame_size_get_preferred_height (GtkWidget *widget,
int *minimum_height,
int *natural_height)
{
*minimum_height = 8;
*natural_height = 8;
g_print ("frame_size_get_preferred_height: min - %d, nat - %d\n",
*minimum_height, *natural_height);
}
static void
frame_size_get_preferred_height_for_width (GtkWidget *widget,
int width,
int *minimum_height,
int *natural_height)
{
*minimum_height = width / 2;
*natural_height = width / 2;
g_print ("frame_size_get_preferred_height_for_width (%d): min - %d, nat - %d\n",
width, *minimum_height, *natural_height);
}
static void
frame_size_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GTK_WIDGET_CLASS (frame_size_parent_class)->size_allocate (widget, allocation);
g_print ("frame_size_size_allocate: width - %d, height - %d\n\n",
allocation->width, allocation->height);
}
static gboolean
frame_size_draw (GtkWidget *widget,
cairo_t *cr)
{
cairo_set_source_rgb (cr, 1, 0, 1);
cairo_paint (cr);
return TRUE;
}
static void
frame_size_class_init (FrameSizeClass *self_class)
{
GtkWidgetClass *widget_class;
widget_class = GTK_WIDGET_CLASS (self_class);
widget_class->get_request_mode = frame_size_get_request_mode;
widget_class->get_preferred_width = frame_size_get_preferred_width;
widget_class->get_preferred_width_for_height = frame_size_get_preferred_width_for_height;
widget_class->get_preferred_height = frame_size_get_preferred_height;
widget_class->get_preferred_height_for_width = frame_size_get_preferred_height_for_width;
widget_class->size_allocate = frame_size_size_allocate;
widget_class->draw = frame_size_draw;
}
static void
frame_size_init (FrameSize *self)
{
}
static void
destroy_cb (GtkWidget *widget,
void *user_data)
{
gtk_main_quit ();
}
int
main (int argc,
char **argv)
{
GtkWidget *window;
GtkWidget *hbox;
GtkWidget *frame;
GtkWidget *test;
gtk_init (NULL, NULL);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (window), 600, 120);
g_signal_connect (window, "destroy", G_CALLBACK (destroy_cb), NULL);
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
gtk_container_add (GTK_CONTAINER (window), hbox);
g_object_set (hbox, "margin", 30, NULL);
gtk_widget_show (hbox);
frame = gtk_frame_new (NULL);
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
test = g_object_new (FRAME_TYPE_SIZE, NULL);
gtk_container_add (GTK_CONTAINER (frame), test);
gtk_widget_show (test);
frame = gtk_aspect_frame_new (NULL, 0.5, 0.5, 1.0, TRUE);
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
test = g_object_new (FRAME_TYPE_SIZE, NULL);
gtk_container_add (GTK_CONTAINER (frame), test);
gtk_widget_show (test);
frame = gtk_event_box_new ();
gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, FALSE, 0);
gtk_widget_show (frame);
test = g_object_new (FRAME_TYPE_SIZE, NULL);
gtk_container_add (GTK_CONTAINER (frame), test);
gtk_widget_show (test);
gtk_window_present (GTK_WINDOW (window));
gtk_main ();
return EXIT_SUCCESS;
}