[haiku-development] Re: Set*UIColor Version 3 Patch

  • From: looncraz <looncraz@xxxxxxxxxxx>
  • To: haiku-development@xxxxxxxxxxxxx
  • Date: Sat, 7 Nov 2015 09:28:42 -0600

On 11/7/2015 04:01, Axel Dörfler wrote:

Hi looncraz,

Yes, but there is literally no other place it can be done more
appropriately, and it enables the top view to update with layout view
colors (which, usually, will be system colors, but may be custom
colors [previously not possible]).

I'd doubt that :-)
Haiku added the layout API, and we're free to solve things cleanly here.
If an application that uses the layout API does not work correctly, it
surely can be fixed, too.


Only when using the builder on a window itself can the layout API do the trick, otherwise there's no external way to access a window's top view.

It could be done BView::SetLayout, but then we're testing for every view in the hierarchy when we know the exact point which it needs to be set is when the window itself has SetLayout called. Unless, of course, the top view were to default to system colors OR layouts created a parent view OR the window's top view was made accessible to layouts in some way.

It's all about having the top view adopt the colors used by the layout view so we don't have a white window background and not blindly using system colors, limiting adoption of the layout API to just those who want to use system colors.


I'd only automatically resize applications that are using the layout
API. Everything else should only act manually - I don't see how a
blacklist is needed there.


That is the fall-back plan, but plenty of existing apps already have a horrible behavior with large fonts, and a few can handle changing font sizes with ease without layouts. The blacklist could be as simple as a list that forces listed applications to use a set font size (appsig:fontsize\n), the app_server would maintain the list and when an app is created it would send the fonts with that overridden size when called upon doing so.

My current state in fontaware is experimenting with this almost entirely on the client side, since it's easier to change :p

I think a BWindow flag B_FONT_AWARE would be appropriate. When set, the default behavior would be to set the font on all attached views. If using a layout, InvalidateLayout(), otherwise ResizeToPreferred() on each view. Then, each BView/window will respond to B_FONTS_UPDATED, see if the font size changed (to be included in the message), and move children around as needed (except when a layout is present).

A more in depth method which won't require as much work on the part of applications, which would probably also work best, but definitely more work, would be to have BViews keep a snapshot of original placement and sizes at a starting font size. They need a their original frame, original spacing from other objects (perimeter), a cached resizing mode, and starting font size all stored. When a font size is changed, the hierarchy is rebuilt from the bottom-most view down. Since most/all system interface objects use ResizeToPreferred() properly, we can rely upon that to to create the new sizes, starting from the end node and working back, propagating resizes, and maintaining spacing, as we go. One thing I'd have to do is create two scaling factors for the spacing, width would be based on the relative change in a string's width, and height would be based on the font height ratio (who would have guessed? ;-) ).

| Window ______________|
|[TopView ]|
|[ [ Inner View ]|
|[ [BTextControl [textview] ]|
| [BButton] [BButton] |

Here, the bottom-most view is the textview for BTextControl, so it'd scale first, followed by BTextControl (which would need to maintain its relative divider size), then the buttons, which would scale, and move relative to the rest, and the InnerView, which would to the same. The top view would then resize to fit its contents, the window would adopt that new size, and then all resizing modes are restored and, finally, resized hooks are manually called.

This should work with apps that don't have good font handling as well, so we'd need a list of applications that will start at a set font size, then will have their fonts sizes updated. The same list as above would then become a compatibility adaptation list, mostly for the closed source apps people can't fix, or ones too unwieldy to fix (unless I get around to it ;-)).

So the list would need quite a few optional entries

AppSig
#AppVersion = <-"2.0.1"
@MaxFontSizes = plain:14, bold:16, fixed:14, menu:18
@ForcedColor = *:default
@StartFontSizes = *:12

This would have the application, with a version less than, or equal to, 2.0.1, start with all font sizes of 12, only use default colors (ignore user customized colors), then it would rescale to the given font sizes after the fact, IF the system font sizes are that size or larger. Obviously, one option is simply @ForcedFontSizes, which will result in the application ALWAYS using the set font sizes (ignoring any user choices entirely).

It would be better to be able to do this for each window independently, but that's really not needed.

The idea would be to also allow applications to access these capabilities, and to be able to set their own colors and fonts as they see fit. Right now, I added the following to BApplication

bool FontUpdatesEnabled() const
void SetFontUpdatesEnabled();

bool ColorUpdatesEnabled() const
void SetColorUpdatesEnabled();

SetAppColors(const BColorMap* colors) ;
SetAppFont(font_which which, const BFont* font);
// a NULL font will use system fonts

Obviously, this requires quit a bit of reworking in the app_server as well as the client side, but I'm not shy about stirring the pot for the desired results ;-)

The advantages to this, I think, are pretty obvious. There are many applications which do not like my 18pt font sizes, and a few that simply don't like customized colors (though the open source ones will be getting a visit from me ;-) ). If I could force them to use 14pt or so, they become usable once again.

To properly resize apps using the layout API, however, the spacing constants must be evaluated at layout computation time, not when the values are set, as it is now.

That explains a little bit of what I've seen, I'll see about addressing that (since layout enabled views should require no fancy effort).

I'm really impressed how well it worked (even with legacy apps) when I simply iterated through, set font sizes, then called ResizeToPreferred() with no other work. Naturally, views would then step onto each other, but it let me see exactly what should be needed to be done to support all applications.

As always, I love to be shown the error of my ways, don't be shy!

--The loon

Other related posts: