How to scale the UI properly with High DPI screens?

But the scaling for non-font things is not necessarily based on the resulting pixel size of the font. Some things are, some other are based on the ratio in points (so 18 would be 1.5x the default size), and finally some have fixed bounds (for example scrollbars shouldn’t get smaller if you use a 10pt font size)

Overall, this is more work for us, but in theory it allows to scale things to “look nice” at any size, and not have empty spaces becoming too large, icons becoming too small, …

This pretty muchrequires a lot of nonlinear behavior and not just a straightforward scaling. But then maybe it’s so much work that it will never be quite perfect

1 Like

I see. Not using a simple linear scaling is definitely the right direction, but I firmly believe a user-provided scaling factor (or desired UI size if you like) should be the basis of every size-relatrd calculation in the GUI. Calculating such a factor implicitly from “font-size/12” is a shortcut that shouldn’t be taken.

For that matter, specifying screen fonts in pt units doesn’t make sense to begin with. A pt should always refer to physical dimension, just like inches, centimetres, etc, so wherever we see 12 pt, it should be showing up the same physical size on a big TV, a phone’s screen, or printed on paper (which can be done if we know the devices’ DPI resolution). But that’s generally not the property we want from UI text. Instead we probably want to control how many lines of text we want to see on a screen. We want a consistent ratio to screen height, or percentage of the shortest side perhaps (thinking of portrait mode displays). Using pt was acceptable in the age of VGA displays with vaguely standard DPI, but the variety of different display devices of our time does not justify the practice anymore. I think it originated from xerox machines anyway, where it did ofc make sense, but not so much on a PC.

So let the user select his font size in such a relative unit, instead of points. And let this be a separate user preference from the general UI size preference. A good example for why this is desirable is the case with my android phone. It provides me with the same two options: size of UI elements (icons, menu items, buttons, etc) and text size. The two are obviously not independent. Bigger text will result in thicker menu items that can faciliate the text, but we’re given the separate options anyway, and I’m glad we are because I prefer the UI to be just one step smaller than the default, on the other hand, prefer the text to be the smallest possible because it is still perfectly legible on the high-DPI screen, and I can have a lot more info on a single screen. I couldn’t do this if the UI was scaled to the text only. I would either be unable to hit the too small controls, or would be stuck with too big text that would make the screen feel too small for any useful work. It would frustrate me that I cannot choose them independently.

Also both should be a per-display (or per-workspace) preference because we dont use all displays the same way. Sometimes we want a higher resolution display because we want to fill it with more useful stuff (a crowded graphics editor UI, for example), and sometimes we want one because we want the less objects to show up just more detailed (on a TV, for example).

So the way I imagine the options working together is the following:

  1. the user selects his desired UI size (R_UI).
  2. the system calculates a matching font size.
  3. let the user fine tune his text size preference (smaller–>default–>larger).
  4. system scales the font accordingly, and calculates the actual final font size (probably rounded to integer pt size, considering constraints, etc).
  5. draw UI elements that doesn’t contain text (scrollbars, window frames, etc) as indicated directly by R_UI.
  6. draw buttons, tabs, etc with captions just as now, based on text extent, but using R_UI for features independent from text-size, instead of “font-size/12”, also with constraints that don’t let the control shrink from desired size even with smaller fonts. (But let it grow if larger text would neccessiate it.)

Nowhere in the UI says that font sizes are in points. It just say “12”.

image

We could relabel that as “100%” or “0.55336 arbitrary units of size” or made up things like “device independant pixels”. Or we could use an unlabelled slider going from “tiny” to “huge”.

It wouldn’t change anything to what we’re doing with it, but if it makes people happy… :slight_smile:

There is no such calculation, almost all metrics derive directly from the fonts apparent size. Those that do not are controlled directly by the controllook (like spacing constants, scrollbars etc)

As a user I would indeed prefer to have by default a scaling percentage: 100% - 125% - 150% - 200% - 250%, with granular font size settings hidden behind some Advanced Settings button.

Which one of four font sizes does determine the scaling factor at the moment? Are all of them relevant just to different parts of the UI?

There is no scaling factor. The menu font site determines the size of the menus… the bold one of the decorator tabs, plain of normal controls and fixed width of controls with fixed width content.

A scaling factor implies a calculation of
original coordinates * scale factor = new coordinates

that simply doesn’t happen as pulkomandy already explained.

Edit:

No reason we can’t have some sliders to set the font size. But there is no reason to use these wierd percentages. They make no sense.
200% scaling takes up 400% of the screen area of an originally scaled application.

Independent of the way element size is calculated, how about having different default font sizes depending on HDPI factor? That would at least make Haiku more usable for newcomers (and old time users) without having to change any setting. At least for the first run/before installation of the OS. Of course users may change it later.

I can’t help but found these two statements contradictory. :point_up_2::point_down:

Which one is then?

Problem is that this DPi factor is a device depndant property, not a setting, and displays lie about this often. So we take the assumption currently that displays above a certain resolution are probably high dpi (or are viewed from a distance) so we can scale fonts in that case.

PulkoMandy is talking about internal calculations of the controllook. These are an implementation detail, and can be changed by swapping out the controllook.

As far as I am aware there are no size/12 calls left anywhere in haikus souce tree except in haikucontrollook.

And even then those are not used without adjustment, e.g clamping the value. So there is again no scaling factor. That’s simply not how it is calculated.

1 Like

For example the api for scrollbars, before this was implemented in Interface kit, and it is now in HaikuControlLook. The interface kit and apps using scrollbar sizes directly “only” follow this, and the controllook is in control of the actual size.

https://cgit.haiku-os.org/haiku/commit/src/kits/interface/HaikuControlLook.cpp?id=409d65c0d64212efc6882e81140647201c03c59d

1 Like

Would there be a significant performance hit on simply sticking to the largest font size at all times and then downscaling it? I feel like this would make the proportions more predictable and make font quirks a bit less problematic.

That’s fair enough, just as icon sizes do not say pixels, but

  1. Font size 12 derives from a time when it actually meant 12 pt (on a standard 14" VGA, i.e. 640x480 display). (Not in Windows where they decided to use a fake DPI value of 96 instead of 72).
    Later, with the advance of technology, it lost that meaning, so the unit was (rightly) removed: it bacame unitless.
  2. Unitless measures are best to be expressed in percentages, not arbitrary numbers.
  3. It would still not resolve the basic “problem” until the default (100%) is just an arbitrarily chosen font size with fixed height in pixels. For example, the ratio from font size to pixels (with the default font) is about 1.2, so size 12 results in a 15-pixel tall line of text, size 10: in 12 pixel, etc. If we want the UI to look consistent on different displays (thus seamlessly portable to different displays), we would rather calculate the default size from screen resolution (not DPI), so that the default size would always result in, say 50 text lines per screen. The default (100%) would change from 12 pixels on a 800x600 screen to 43 pixels on a 3680x2160 4K screen. The user could then scale that to whichever percentage as per his personal preference.

My proposal, though is another twist in the process. Instead of letting the system calculate the default font size directly from screen resolution, we should acknowledge that all dislays (even with same resolution) aren’t used the same way. I want big buttons and less clutter (less info) on my TV, so that it looks similar to a BeOS desktop on a 400x300 screen (even though it is a 4K display), but more useful space (smaller buttons, window deco, labels, etc) on my work computer with the same display resolution. So let the scaling be made in 2 steps:

  1. UI size. Because truly, I just want to control how busy my desktop is, not the absolute font size. For example, let it accomodate room for 30 single-line edit boxes stacked upon each other as a default. Regardless of screen resolution. But allow the user to customize this. This determines the text size.
  2. Text size further scaled. Because not everybody’s vision is the same and because legibility depends a lot on screen DPI (which we completely ignored in the calculations till now).

That would result in illegible text on almost any resolution. We didn’t invent comlex hinting mechanisms and elaborate outline-scaling font programs that provide the sharpest letters at any given font size to just throw it out the window and do something so primitive.

1 Like

I think we don’t want that.

If you just scale it according to the DPI, and you display it on a small but high resolution display (similar to a smartphone display), you get tiny and barely readable text and buttons that are hard to target. And likewise on large but low resolution displays, the UI would remain the same physical size, but would lose precision, to the point where it becomes completely unreadable if you have, say, a 48" but 1080p display.

You also have to factor in how close you sit to the display, and that depends mainly on the use case: is it a computer display, or is it a media center running on your TV? On the latter you probably want larger text.

So, there is no need to try to relate the font size to any absolute units, be it pixels or physical size. It doesn’t matter. All you need it a way to make things generally larger or generally smaller, and the UI should scale and adjust nicely (and probably nonlinearly: some things don’t scale as much as others) to that.

I really don’t see what we gain by having more settings here. A single size setting, and a good way to handle the scaling, should make things work for all these use cases and not make it a nightmare for developers to test their apps in all possible size combinations (we also have to take that into account when adding more customization). If we make the scaling be just one step, it is a lot easier to reason about for developers, and to test maybe 2 extreme sizes and the default one (this is what I do in my apps). If you have two settings, you need to test at least the 4 “corner” values and the middle, so that’s at least 5 cases to check.

The system has no means to know that, that’s why it needs to be a provided by the user. Hence an option for UI size.

Yes, we agree. It doesn’t matter. Calc it based on desired UI size, then apply a scaling factor as per user preference.

Because text legibility depends on somewhat different factors than the desired UI size. It should be a separate user preference.

Why would we burden the developers with such an impossible task. It is the user’s responsibility to choose the rational settings that provide the best look and behaviour on their own hardware. The developers cannot possibly test every possible device on the market, it is not their job.

Especially considering that the 2-step scaling settings is mostly just a decorative frame put on the current design, it’s not that we have to screw up every algo in use and start it from the scratch. It just makes the current capabilities more useful for the user. The “frame” provides an output font size, that can be directly used as input in the current scaling methods. Most of the scaling would be done the same way, based on text extent, except, other factors, where text size is not applicable, would come directly from user UI-size preference instead of magic numbers or funny calculations. It is the cleaner way to do it anyway. Some constraints (padding, etc) would come from the UI-size, too, besides the text size, but I can’t imagine it would cause so much complexity.

If you really want a control density other than the default, it’s probably best to just write or modify a ControlLook to compute metrics differently. The number of use-cases where people really “need” a different control density (instead of just different text sizes) is very small (if any?), and if it’s just a power-user option, then having it be changeable only in sourcecode or with third-party add-ons makes the most sense.

Here is a quick test I did with the Noto Sans font in Kolourpaint. One picture is the original, the other one is downscaled to 5% of the original size. Does the downscaled text look illegible?

I’m pretty sure that the methods you describe are an evolution of the fact that fonts were originally pixel-based and very small. Performance was probably a consideration as well, but computers are much more powerful these days.

noto sans test2

So basically it is possible to write a different ControlLook, to get the desired result. Perhaps one that takes several user preferences into account, instead of just my personal preferences. But we just don’t want to make it default because we don’t want the user to have so much control?