Hi everyone,

I’m still pretty new to contributing here, so please bear with me if I am 
misunderstanding something or missing some history behind this.

I have been using the Qt6/Wayland build on a HiDPI laptop, and I kept noticing 
dialogs where text was either getting cut off or wrapping in strange places. 
The one that finally made me look into it was the “Select Your Preferred User 
Interface” dialog. The description on the right gets clipped, and the 
“Toolbars” tab breaks into “Toolba / rs.”

It is a small issue, but it kept bothering me.

I was able to fix that specific dialog by changing the .ui file, and the result 
looked fine. The problem is that this only fixes one dialog. If the text 
changes later, or another dialog has the same issue, it can easily happen 
again. Because of that, I started trying to understand why this is happening 
instead of only fixing the individual UI file.

From what I can tell, the main issue is that VCL’s box and grid layouts only 
ask a widget for one preferred size through GetOptimalSize() or 
get_preferred_size(). The layout then uses that size when deciding how much 
space everything should get.

For a wrapping label, FixedText::GetOptimalSize() calculates the preferred size 
once, based partly on max-width-chars. It goes through CalcMinimumSize, 
CalcMinimumTextSize, and then GetTextRect with WordBreak enabled.

What seems to be missing is a way for the layout to go back afterward and ask 
the widget, “Now that you only have this much width, how much height do you 
actually need?”

Right now, if VclBox::setAllocation gives a wrapping label less width than its 
preferred size, the label does not seem to recalculate its height based on the 
new width. It keeps the wider layout and then gets clipped by the smaller 
allocation.

The main thing that made me think this is the actual cause is that the same 
dialogs look fine when I use SAL_USE_VCLPLUGIN=gtk3. GTK already supports 
height-for-width, so it recalculates the required height after the width is 
known. The issue seems to mainly affect VCL’s own layout path, which is being 
used by qt6, kf6, gen, Windows, and macOS.

What I am thinking about is adding basic height-for-width support to VCL, 
similar to what GTK already does.

Something roughly like this:

virtual tools::Long get_preferred_height_for_width(
    tools::Long nWidth) const;

virtual bool has_height_for_width() const;

The default get_preferred_height_for_width() implementation could just return 
GetOptimalSize().Height(), and has_height_for_width() could return false by 
default.

That way, nothing changes for an existing widget unless it specifically opts 
into the new behavior.

FixedText could be the first widget to implement it. It could reuse the 
GetTextRect wrapping code it already has, but calculate the height using the 
actual width passed in by the container.

Later, other wrapping widgets, such as multiline edits or check box and radio 
button labels, could add support in the same way.

The containers, such as VclBox and VclGrid, already seem to settle the child 
widths before the final allocation. Once the width is known, the container 
could check whether the child has height-for-width support and ask for the 
correct height at the width it actually received.

The same idea could also be used in setOptimalLayoutSize so the dialog reserves 
enough height from the beginning.

I think having a no-op default and making this opt-in per widget would make the 
change safer. A widget that does not support height-for-width would continue 
behaving exactly the way it does now. It could also be added gradually, 
starting with FixedText, instead of changing the behavior of every widget at 
once.

The part I am honestly nervous about is that this would touch layout code used 
by basically every dialog in the suite. If I make a mistake, it could cause 
dialogs to be incorrectly sized in many places.

A few things might make that easier to control.

First, because the behavior would be opt-in, the first patch could be limited 
to the new API, FixedText, and maybe VclBox. During testing, the second layout 
pass could also be placed behind a runtime flag so the current and new behavior 
are easy to compare.

Second, GTK3 gives us a useful reference. Since the same dialogs already lay 
out correctly there, I could compare the VCL output against GTK3 across 
different dialogs, display scales, and text lengths instead of only checking 
one dialog by eye.

Before I start putting a lot of time into this, I wanted to ask a few questions.

-

Is height-for-width support something that would actually be wanted in VCL, or 
was it left out intentionally because of performance or another problem?

-

Does the API above make sense, or should this be handled through the existing 
GetOptimalSize() or get_preferred_size() system instead?

-

Does an opt-in approach with a no-op default seem reasonable for introducing it 
gradually?

-

Has anyone attempted something similar before, or is there an old branch or 
patch that I should look at?

-

Would comparing the results against GTK3 be a reasonable testing method, or is 
there already a dialog layout testing setup that would be better to extend?

If this sounds like a reasonable direction, I would start small. My first goal 
would only be the new API, FixedText, and VclBox, tested against the UI-picker 
dialog and a few other dialogs that currently have wrapping or clipping 
problems.

I am not trying to submit a huge layout rewrite all at once. I mostly want to 
find out whether this is worth working on before I spend a lot of time going 
further into it.

Thanks for reading, and I would appreciate any advice or background people can 
provide.

Jamie Fitzgerald

[email protected]

Reply via email to