Supporting light/dark mode on macOS and Linux (at least)

83 views
Skip to first unread message

Michael Sweet

unread,
Mar 21, 2021, 11:20:50 PM3/21/21
to fltk.coredev
I'm working on updating my FLTK-based RasterView application and one of the "features" I want to add is support for light/dark mode on macOS and Linux (at least). I've seen some examples of how to do this but was wondering if there would be general interest in adding support for it in 1.4?

Michael Bäuerle

unread,
Mar 22, 2021, 6:16:59 AM3/22/21
to fltkc...@googlegroups.com, Michael Sweet
Michael Sweet wrote:
>
> Content-Type: text/plain; charset=UTF-8
>
> I?m working on updating my FLTK-based RasterView application and one of the
> "features" I want to add is support for light/dark mode on macOS and Linux
> (at least). I?ve seen some examples of how to do this but was wondering if
> there would be general interest in adding support for it in 1.4?

JFTR:
I was surprised that this seems to work already at least on X11.
A user of flnews newsreader sends me this screenshot:
https://micha.freeshell.org/flnews/screenshots/flnews-0.18_gentoo_kde-plasma_breezedark.png

The only problem I have explicitly fixed for that was the Fl_Tree
widget, it needs:
|
| ->item_labelfgcolor(FL_FOREGROUND_COLOR)

Otherwise the items have no contrast against the dark background
(looks like a bug).

Greg Ercolano

unread,
Mar 22, 2021, 6:32:12 AM3/22/21
to fltkc...@googlegroups.com


On 3/22/21 3:16 AM, Michael Bäuerle wrote:
The only problem I have explicitly fixed for that was the Fl_Tree
widget, it needs:
| 
| ->item_labelfgcolor(FL_FOREGROUND_COLOR)

Otherwise the items have no contrast against the dark background
(looks like a bug).
    If you submit an issue against Fl_Tree, I'll look into it.

Michael Bäuerle

unread,
Mar 22, 2021, 8:22:50 AM3/22/21
to fltkc...@googlegroups.com
Issue number is #204.

BTW:
On my screenshot you can see an ugly workaround for missing columns
with " | " separators. For flnews real columns in the tree are often
requested by users. I have seen a nice tree widget with columns
on your page <http://seriss.com/people/erco/fltk/#TreeWithColumns>.
Is there a chance that this widget will become part of FLTK 1.4?

Albrecht Schlosser

unread,
Mar 22, 2021, 8:50:06 AM3/22/21
to fltkc...@googlegroups.com
How did the examples do it, and/or how would you want to implement this,
i.e. what kind of FLTK support would we need to add?

Why would it be platform dependent (title: "on macOS and Linux (at least)")?

ISTR that Greg posted some screenshots and even code for colored (not
only "dark") themes. IIRC he changed the gray ramp and maybe some more
internal colors. I'm not sure if he needed also widget changes (maybe
setting colors explicitly "per theme").

I know that users have asked for "dark mode" or similar from time to
time, hence I believe this could be an improvement.

Michael Sweet

unread,
Mar 22, 2021, 9:01:23 AM3/22/21
to fltkc...@googlegroups.com
Albrecht,

> On Mar 22, 2021, at 8:50 AM, Albrecht Schlosser <Albrech...@online.de> wrote:
>
> On 3/22/21 4:20 AM Michael Sweet wrote:
>> I'm working on updating my FLTK-based RasterView application and one
>> of the "features" I want to add is support for light/dark mode on
>> macOS and Linux (at least). I've seen some examples of how to do this
>> but was wondering if there would be general interest in adding
>> support for it in 1.4?
>
> How did the examples do it, and/or how would you want to implement this, i.e. what kind of FLTK support would we need to add?

The examples I found on Github basically overrode the foreground/background colors to force the application to be "dark mode" all of the time.

> Why would it be platform dependent (title: "on macOS and Linux (at least)")?

My focus is on following the current system UI mode (light or dark) and not so much on having an explicit method to make an application "dark" or "light" since (as you note below) we already have a way to handle the basic background/gray ramp that supported "historical" X11 color preferences.

I honestly don't use Windows enough to know whether dark mode is a thing there, but I *do* know that current Ubuntu and macOS explicitly expose light/dark mode preferences, and that macOS (at least) can switch dynamically.

> ISTR that Greg posted some screenshots and even code for colored (not only "dark") themes. IIRC he changed the gray ramp and maybe some more internal colors. I'm not sure if he needed also widget changes (maybe setting colors explicitly "per theme").
>
> I know that users have asked for "dark mode" or similar from time to time, hence I believe this could be an improvement.

________________________
Michael Sweet



signature.asc

Michael Sweet

unread,
Mar 22, 2021, 9:31:46 AM3/22/21
to Michael Sweet, fltkc...@googlegroups.com
So this code:

      Fl::background(50, 50, 50);
      Fl::background2(23, 23, 23);
      Fl::foreground(223, 223, 223);
      Fl::set_color(FL_SELECTION_COLOR, 0, 87, 207);

effectively transforms RasterView's standard UI on macOS:


to a dark UI:

Clearly we already have the support for changing colors, and I *think* there is general support for the idea of adding this to FLTK 1.4?

I'm just wondering if we want to make this opt-in or opt-out?  IOW, Fl::get_system_colors() is currently run once when you show the main window, but on macOS[1] (at least) we would need to call it again when the system appearance changes.  But some applications won't want to follow the system colors...


________________________
Michael Sweet



signature.asc

imm

unread,
Mar 22, 2021, 9:31:51 AM3/22/21
to coredev fltk
On Mon, 22 Mar 2021, 13:01 Michael Sweet wrote:

I honestly don't use Windows enough to know whether dark mode is a thing there, but I *do* know that current Ubuntu and macOS explicitly expose light/dark mode preferences, and that macOS (at least) can switch dynamically.

At least for Win10 it is. There's a system setting for it now and it changes "a lot" of the system tools. Some apps also seem to respond to this setting. (Not all!)

But I'm not sure what it actually *does*, since it doesn't appear to be changing the default colours that apps pick up if they "use system colours" so fltk apps seem to use the same colorways regardless of that system setting.
Indeed lots of apps appear to be oblivious to that setting...
--
Ian
From my Fairphone FP3

Albrecht Schlosser

unread,
Mar 22, 2021, 11:06:27 AM3/22/21
to fltkc...@googlegroups.com
Mike,

thanks for your elaboration.

On 3/22/21 2:01 PM Michael Sweet wrote:
>> On Mar 22, 2021, at 8:50 AM, Albrecht Schlosser <...> wrote:
>>
> The examples I found on Github basically overrode the foreground/background colors to force the application to be "dark mode" all of the time.
>
>> Why would it be platform dependent (title: "on macOS and Linux (at least)")?
>
> My focus is on following the current system UI mode (light or dark) ...

So what we get would be

(a) a status info taken from the system which the program can query to
know what the current mode is

and maybe

(b) an FLTK event that would be triggered when the mode switches (i.e.
when the system mode transitions from dark to light mode and vice versa).

Is that about right?

> ... and not so much on having an explicit method to make an application "dark" or "light" since (as you note below) we already have a way to handle the basic background/gray ramp that supported "historical" X11 color preferences.

Would it make sense to provide a "standard" FLTK method to do this
background/gray ramp switch to support programmers in actually doing the
switch in their applications? Someting the user could use directly
(default) or override by their own handle or callback method. Just
thinking...

> I honestly don't use Windows enough to know whether dark mode is a thing there, but I *do* know that current Ubuntu and macOS explicitly expose light/dark mode preferences, and that macOS (at least) can switch dynamically.

Neither do I (know Windows enough) but Ian wrote it's a system setting
so we could probably support Windows as well.

Greg Ercolano

unread,
Mar 22, 2021, 11:16:11 AM3/22/21
to fltkc...@googlegroups.com


On 3/22/21 5:22 AM, Michael Bäuerle wrote:
Greg Ercolano wrote:
On 3/22/21 3:16 AM, Michael Bäuerle wrote:
The only problem I have explicitly fixed for that was the Fl_Tree
widget, it needs:
|
| ->item_labelfgcolor(FL_FOREGROUND_COLOR)

Otherwise the items have no contrast against the dark background
(looks like a bug).
    If you submit an issue against Fl_Tree, I'll look into it.
Issue number is #204.

    Fixed in d6d1d8a


BTW:
On my screenshot you can see an ugly workaround for missing columns
with " | " separators. For flnews real columns in the tree are often
requested by users. I have seen a nice tree widget with columns
on your page <http://seriss.com/people/erco/fltk/#TreeWithColumns>. 
Is there a chance that this widget will become part of FLTK 1.4?
    I have code offline with a few classes showing how to do this,
    along with sorting columns, sort indicators, interactively resizable columns,
    the whole nine yards. Thing is, it's not something I think is fully organized
    for adding to FLTK in the way it exists, as I'm not sure it's implemented in
    a flexible enough way (API wise, etc).. it's implemented in a way that worked
    "for my application".

    It's a bit of work I can tell you, but it's built around Fl_Tree and friends.
    I couldn't fit it all into Fl_Tree, I wanted to keep that base widget relatively simple.

    It'll take some time to rip it out of my offline application and make it into an
    example, and when done, I'll add it to my cheat page at least, if not as a 'large'
    example to FLTK.. depends on if I think it's clean enough to be a good example.




Michael Sweet

unread,
Mar 22, 2021, 11:18:31 AM3/22/21
to fltkc...@googlegroups.com
Albrecht,

> On Mar 22, 2021, at 11:06 AM, Albrecht Schlosser <Albrech...@online.de> wrote:
>
> Mike,
>
> thanks for your elaboration.
>
> On 3/22/21 2:01 PM Michael Sweet wrote:
>>> On Mar 22, 2021, at 8:50 AM, Albrecht Schlosser <...> wrote:
>>>
>> The examples I found on Github basically overrode the foreground/background colors to force the application to be "dark mode" all of the time.
>>> Why would it be platform dependent (title: "on macOS and Linux (at least)")?
>> My focus is on following the current system UI mode (light or dark) ...
>
> So what we get would be
>
> (a) a status info taken from the system which the program can query to know what the current mode is
>
> and maybe
>
> (b) an FLTK event that would be triggered when the mode switches (i.e. when the system mode transitions from dark to light mode and vice versa).
>
> Is that about right?

Yes.

>> ... and not so much on having an explicit method to make an application "dark" or "light" since (as you note below) we already have a way to handle the basic background/gray ramp that supported "historical" X11 color preferences.
>
> Would it make sense to provide a "standard" FLTK method to do this background/gray ramp switch to support programmers in actually doing the switch in their applications? Someting the user could use directly (default) or override by their own handle or callback method. Just thinking...

I'm thinking that "Fl::get_system_colors()" is probably the right (existing) API for this, we just need to wire it up to the light/dark mode APIs on each platform. Then the code that handles the OS notification (appearance change) can send the new "appearance" event.

The other API we should add is something to prevent appearance changes for apps that need that...

>> I honestly don't use Windows enough to know whether dark mode is a thing there, but I *do* know that current Ubuntu and macOS explicitly expose light/dark mode preferences, and that macOS (at least) can switch dynamically.
>
> Neither do I (know Windows enough) but Ian wrote it's a system setting so we could probably support Windows as well.

Sounds like it...

________________________
Michael Sweet



signature.asc

Michael Bäuerle

unread,
Mar 22, 2021, 12:34:32 PM3/22/21
to fltkc...@googlegroups.com
Greg Ercolano wrote:
> On 3/22/21 5:22 AM, Michael Bäuerle wrote:
> > Greg Ercolano wrote:
> > > On 3/22/21 3:16 AM, Michael Bäuerle wrote:
> > > >
> > > > The only problem I have explicitly fixed for that was the Fl_Tree
> > > > widget, it needs:
> > > > |
> > > > | ->item_labelfgcolor(FL_FOREGROUND_COLOR)
> > > >
> > > > Otherwise the items have no contrast against the dark background
> > > > (looks like a bug).
> > >
> > >     If you submit an issue against Fl_Tree, I’ll look into it.
> >
> > Issue number is #204.
>
>     Fixed in |d6d1d8a <https://github.com/fltk/fltk/commit/d6d1d8afe45a2f315f7fd91f2bcc2d9514d7244d>

Thank you.

> > BTW:
> > On my screenshot you can see an ugly workaround for missing columns
> > with " | " separators. For flnews real columns in the tree are often
> > requested by users. I have seen a nice tree widget with columns
> > on your page <http://seriss.com/people/erco/fltk/#TreeWithColumns>.
> > Is there a chance that this widget will become part of FLTK 1.4?
>
>     I have code offline with a few classes showing how to do this,
>     along with sorting columns, sort indicators, interactively resizable columns,
>     the whole nine yards. Thing is, it's not something I think is fully organized
>     for adding to FLTK in the way it exists, as I'm not sure it's implemented in
>     a flexible enough way (API wise, etc).. it's implemented in a way that worked
>     "for my application".
>
>     It's a bit of work I can tell you, but it's built around Fl_Tree and friends.
>     I couldn't fit it all into Fl_Tree, I wanted to keep that base widget relatively simple.
>
>     It'll take some time to rip it out of my offline application and make it into an
>     example, and when done, I'll add it to my cheat page at least, if not as a 'large'
>     example to FLTK.. depends on if I think it's clean enough to be a good example.

Sounds good.

Albrecht Schlosser

unread,
Mar 22, 2021, 1:40:51 PM3/22/21
to fltkc...@googlegroups.com
On 3/22/21 4:18 PM Michael Sweet wrote:
>> On Mar 22, 2021, at 11:06 AM, Albrecht Schlosser <Albrech...@online.de> wrote:
>> On 3/22/21 2:01 PM Michael Sweet wrote:
>>> My focus is on following the current system UI mode (light or dark) ...
>>
>> So what we get would be
>>
>> (a) a status info taken from the system which the program can query to know what the current mode is
>> (b) an FLTK event that would be triggered when the mode switches (i.e. when the system mode transitions from dark to light mode and vice versa).
>
> Yes.
>
>> Would it make sense to provide a "standard" FLTK method to do this background/gray ramp switch to support programmers in actually doing the switch in their applications? ...
>
> I'm thinking that "Fl::get_system_colors()" is probably the right (existing) API for this, we just need to wire it up to the light/dark mode APIs on each platform. Then the code that handles the OS notification (appearance change) can send the new "appearance" event.

Sounds good.

> The other API we should add is something to prevent appearance changes for apps that need that...

I'm not sure that we (only) need an API to *prevent* appearance changes
because many apps might not be prepared to deal with this if it's the
default - having set their own color scheme etc.. Maybe "apps that need
that" (prevent appearance changes) are the majority.

Hence I think there should be something (new code) required to *enable*
(automatic) appearance changes, at least in FLTK 1.4.0. In later
versions (1.5 ?) we might make it the default behavior. Or something
like that...

Bill Spitzak

unread,
Mar 22, 2021, 1:55:21 PM3/22/21
to fltkc...@googlegroups.com
It should respond to it (ie dark mode, and also the system settings which obviously they are not changing despite that being an easy way to get all old programs to do "dark mode"), but if the program sets the colors it should ignore it (basically because it initializes the colors depending on dark mode and system settings, then the program changes them).
There should be no need for a control as to whether it pays attention or not.

It amazes me that everybody is going crazy over "dark mode" when 30 years ago everybody pretty much agreed that there should be a readable configuration from the system as to the "default background color". And 30 years ago we could do 2^24 settings rather than 2.


--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkcoredev/9dfae09e-cfe0-668b-e92b-5189b1c26e1c%40online.de.

Greg Ercolano

unread,
Mar 22, 2021, 2:05:18 PM3/22/21
to fltkc...@googlegroups.com


On 3/22/21 5:50 AM, Albrecht Schlosser wrote:

ISTR that Greg posted some screenshots and even code for colored (not only "dark") themes. IIRC he changed the gray ramp and maybe some more internal colors. I'm not sure if he needed also widget changes (maybe setting colors explicitly "per theme").

I know that users have asked for "dark mode" or similar from time to time, hence I believe this could be an improvement.


    In my case I added a menu to the app that let the user pick from different color themes.
    The theme names (and colormap definitions) were in a text file that the user could edit
    to taste, and add new color theme names/maps, and they would appear in the menu.

    For a long time now "dark theme" has been a thing in the industry I work in (the film business),
    early examples being Softimage, Alias, and Shake. Shake was a popular compositing tool at the
    time which used a very dark theme because people who worked with the app were doing
    color timing, or basically color manipulation/matching, and worked in dark rooms..
    "bright" interfaces distracted from the process of color timing. Hence many requests
    for a dark theme in my interfaces. And indeed apps in this industry like Mudbox, Maya,
    and well just about everything now have dark or toned down interfaces for doing film/graphics.

    It's a careful game to try to get all the colors in the app to look right, given how the
    algorithms for active vs. inactive, and 'highlighted text' work, which is why I left it
    open to users to be able to edit the text files.

    There was the main text file definition of the themes in the app's resource directory,
    and then the user could have one in their ~/.<appname>/ directory to override or enhance
    the app's defaults.

Greg Ercolano

unread,
Mar 22, 2021, 2:07:57 PM3/22/21
to fltkc...@googlegroups.com

On 3/22/21 10:55 AM, Bill Spitzak wrote:

It should respond to it (ie dark mode, and also the system settings which obviously they are not changing despite that being an easy way to get all old programs to do "dark mode"), but if the program sets the colors it should ignore it (basically because it initializes the colors depending on dark mode and system settings, then the program changes them).
There should be no need for a control as to whether it pays attention or not.

It amazes me that everybody is going crazy over "dark mode" when 30 years ago everybody pretty much agreed that there should be a readable configuration from the system as to the "default background color". And 30 years ago we could do 2^24 settings rather than 2.


    I imagine in the Digital Domain version of Nuke (compositor) you must've ran into this;
    was your approach to define a custom colormap for dark mode, or some other technique?

Albrecht Schlosser

unread,
Mar 22, 2021, 3:03:28 PM3/22/21
to fltkc...@googlegroups.com
On 3/22/21 6:55 PM Bill Spitzak wrote:
> It should respond to it (ie dark mode, and also the system settings
> which obviously they are not changing despite that being an easy way to
> get all old programs to do "dark mode"), but if the program sets the
> colors it should ignore it (basically because it initializes the colors
> depending on dark mode and system settings, then the program changes them).

How can a program "ignore it" if the system and FLTK internals set the
system colors internally? Particularly if it's done when the first
window is shown (i.e. /after/ some other kind of initialization).

> There should be no need for a control as to whether it pays attention or
> not.

Not all programs set *all* colors in the FLTK color list (256)
explicitly to "their" values. If it happens that "the system" sets one
color value (be it background or foreground or whatever) to a value the
program uses for another purpose (or a similar color) you get a conflict
because there's little or no contrast.

You might be right with "there *should* be no need..." but *should*
doesn't mean there *is* no need.

That's why I'm proposing a control in the program (or a system FLTK
option, maybe) at least in FLTK 1.4 so programmers can make a smooth
transition. If the dark/light switch would be enforced by FLTK users
might say "this program doesn't work with FLTK 1.4" and raise issues and
complaints to the developer or drop usage of such programs.

You'd basically always run into issues if a program sets own background
colors for widgets but relies an the foreground (text) color to be
"dark". In dark mode this would result in no contrast. That's only *one*
example...

> It amazes me that everybody is going crazy over "dark mode" when 30
> years ago everybody pretty much agreed that there should be a readable
> configuration from the system as to the "default background color". And
> 30 years ago we could do 2^24 settings rather than 2.

Nobody ever had to use the "default background color", programmers could
always use their own colors. And if they did, that's why we need an
option/control.

As Mike wrote: "I'm just wondering if we want to make this opt-in or
opt-out?"

My answer is: opt-in, at least for FLTK 1.4.x. If we document it and
give users and programmers a chance to adjust their programs (color
schemes) then we can make it opt-out in a later version (1.5.x, maybe).

Greg Ercolano

unread,
Mar 22, 2021, 3:06:41 PM3/22/21
to fltkc...@googlegroups.com


On 3/22/21 9:34 AM, Michael Bäuerle wrote:
BTW:
On my screenshot you can see an ugly workaround for missing columns
with " | " separators. For flnews real columns in the tree are often
requested by users. I have seen a nice tree widget with columns
on your page <http://seriss.com/people/erco/fltk/#TreeWithColumns>.
Is there a chance that this widget will become part of FLTK 1.4?
    I have code offline with a few classes showing how to do this,
    along with sorting columns, sort indicators, interactively resizable columns,
    the whole nine yards. [..]

    It'll take some time to rip it out of my offline application and make it into an
    example [..]
Sounds good.

    Hmm, commercial software; copyright prevents me from just copy/pasting it.

    I'll see if I can rewrite it using a different technique.. might end up being
    lighter weight too, and will use std:: stuff instead of the custom arrays/strings
    my commercial app uses.

    Generally speaking, there's an outer group, e.g. "Fl_Column_Tree", which contains
    the header and an Fl_Tree instance.

    This group widget keeps track of the column widths, and handles interactive column
    resizing, e.g. when the mouse hovers over a column boundary and the user clicks
    down to move it.

    The Fl_Tree_Items have custom draw() code that gets the current column widths
    from the parent group, and draws each column's text accordingly with clipping,
    similar to the Fl_Browser approach.

    If you have specific requests for features beyond what I've described above, reply here,
    and I can maybe include for them, or at least design in such a way as to make them easier
    to add.

Albrecht Schlosser

unread,
Mar 22, 2021, 3:09:52 PM3/22/21
to fltkc...@googlegroups.com
On 3/22/21 2:31 PM Michael Sweet wrote:
> So this code:
>
>       Fl::background(50, 50, 50);
>       Fl::background2(23, 23, 23);
>       Fl::foreground(223, 223, 223);
>       Fl::set_color(FL_SELECTION_COLOR, 0, 87, 207);
>
> effectively transforms RasterView's standard UI on macOS:
>
> to a dark UI:

A very simple UI.

> Clearly we already have the support for changing colors, and I *think*
> there is general support for the idea of adding this to FLTK 1.4?
>
> I'm just wondering if we want to make this opt-in or opt-out?  IOW,
> Fl::get_system_colors() is currently run once when you show the main
> window, but on macOS[1] (at least) we would need to call it again when
> the system appearance changes.  But some applications won't want to
> follow the system colors...

Yep, I think this is the case. Programs that use their own colors may
have issues when the color scheme changes unexpectedly: new FLTK
version, completely different appearance. That's bad. Hence my vote is:

opt-in at least in FLTK 1.4.x (x = 0, 1, ... ?)

opt-out maybe in FLTK 1.4.N (N = ?) or 1.5.0 or any later version.

> [1]:
> https://developer.apple.com/documentation/xcode/supporting_dark_mode_in_your_interface

Thanks for the link.

Michael Sweet

unread,
Mar 22, 2021, 8:25:54 PM3/22/21
to fltkc...@googlegroups.com
How about the following APIs to opt-in to the behavior and to check the current behavior:

void Fl::dynamic_colors(bool on);
bool Fl::dynamic_colors();

When an application calls "Fl::dynamic_colors(true)" then FLTK will set the system colors and then track changes to the system appearance. The event name could be "FL_COLOR_CHANGE"...
> --
> You received this message because you are subscribed to a topic in the Google Groups "fltk.coredev" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/fltkcoredev/mqih66IFgTg/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to fltkcoredev...@googlegroups.com.
________________________
Michael Sweet



signature.asc

Lauri Kasanen

unread,
Mar 23, 2021, 3:06:00 AM3/23/21
to fltkc...@googlegroups.com
On Mon, 22 Mar 2021 20:25:51 -0400
Michael Sweet wrote:

> How about the following APIs to opt-in to the behavior and to check the current behavior:
>
> void Fl::dynamic_colors(bool on);
> bool Fl::dynamic_colors();
>
> When an application calls "Fl::dynamic_colors(true)" then FLTK will set the system colors and then track changes to the system appearance. The event name could be "FL_COLOR_CHANGE"...

I would prefer permanent opt-in, this is something that will bite even
new apps written after 1.5 or whatever.

- Lauri

Albrecht Schlosser

unread,
Mar 23, 2021, 12:02:34 PM3/23/21
to fltkc...@googlegroups.com
On 3/23/21 1:25 AM Michael Sweet wrote:
> How about the following APIs to opt-in to the behavior and to check the current behavior:
>
> void Fl::dynamic_colors(bool on);
> bool Fl::dynamic_colors();

+1 -- except a minor thing: the FLTK style is (still) to use int instead
of bool. In this case it could even be an advantage to have values like
-1, 0, 1, 2 or a bit flag if necessary. Maybe:

0 not initialized, default

1 accept dynamic colors (but send event to actually do it)

2 do automatic color changes (with or w/o event)

> When an application calls "Fl::dynamic_colors(true)" then FLTK will set the system colors and then track changes to the system appearance. The event name could be "FL_COLOR_CHANGE"...

+1 as well

>> On Mar 22, 2021, at 1:40 PM, Albrecht Schlosser <Albrech...@online.de> wrote:
>>
>> On 3/22/21 4:18 PM Michael Sweet wrote:
>>>> On Mar 22, 2021, at 11:06 AM, Albrecht Schlosser <Albrech...@online.de> wrote:
>>>> On 3/22/21 2:01 PM Michael Sweet wrote:
>>>>> My focus is on following the current system UI mode (light or dark) ...
>>>>
>>>> So what we get would be
>>>>
>>>> (a) a status info taken from the system which the program can query to know what the current mode is
>>>> (b) an FLTK event that would be triggered when the mode switches (i.e. when the system mode transitions from dark to light mode and vice versa).
>>> Yes.

We should probably also have an API to query the current system status
(0 = undefined/unknown | 1 = light mode | 2 = dark mode | anything else?).

On systems where we can't determine the current system mode we'd return 0.

Albrecht Schlosser

unread,
Mar 23, 2021, 12:31:25 PM3/23/21
to fltkc...@googlegroups.com
I'm not sure what you mean with "permanent opt-in". Can you explain?

My idea is to make this "dynamic_colors" stuff opt-in in FLTK 1.4.0 so
only programmers who prepare their apps and call Fl::dynamic_colors(1);
will use it. Old and unchanged programs will not be affected and work as
before.

Starting with a still to-be-defined version, let's say 1.5.0 (or 1.4.5
or one year after the release of 1.4.0 or whatever) the new behavior
would become the default and programmers would need to opt-out (i.e.
call Fl::dynamic_colors(0);) if they don't want the new behavior.

The theory behind this is that every developer has enough time to decide
and prepare their programs for the new behavior. If any program can't
deal with dynamic colors (or has its own features implemented) it could
call Fl::dynamic_colors(0); when "ported" to 1.4.0 and keep that call
forever.

I read in the docs Mike linked in this thread that Apple also gives
developers a chance to opt-out (since macOS 10.14 IIRC) but to follow
their guide you need to apply changes to your program anyway (in most
cases, I guess).

imm

unread,
Mar 23, 2021, 12:37:42 PM3/23/21
to coredev fltk
On Tue, 23 Mar 2021 at 07:06, Lauri Kasanen wrote:
>
>
> I would prefer permanent opt-in, this is something that will bite even
> new apps written after 1.5 or whatever.

Maybe "default on" but selectable-off if the programmer/user so
desires - but *not* permanent on...

imm

unread,
Mar 23, 2021, 12:49:20 PM3/23/21
to coredev fltk
On Tue, 23 Mar 2021 at 16:02, Albrecht Schlosser wrote:
>
> On systems where we can't determine the current system mode we'd return 0.
>

I assume, at least in the short term that we would need to load the OS
API for these capabilities dynamically, because I presume older WinXX
or OSX hosts would not even have the functions we are trying to
call... W still support OSX back to 10.old (10.4? Older?) and WinXX
back to XP or so (maybe older?) neither of which would have a Dark
Mode...
So if the attempt to load the relevant capability fails, that's when
we return 0 here.

Lauri Kasanen

unread,
Mar 23, 2021, 12:51:33 PM3/23/21
to fltkc...@googlegroups.com
On Tue, 23 Mar 2021 17:31:23 +0100
Albrecht Schlosser wrote:

> On 3/23/21 8:07 AM Lauri Kasanen wrote:
> > I would prefer permanent opt-in, this is something that will bite even
> > new apps written after 1.5 or whatever.
>
> I'm not sure what you mean with "permanent opt-in". Can you explain?
...
> Starting with a still to-be-defined version, let's say 1.5.0 (or 1.4.5
> or one year after the release of 1.4.0 or whatever) the new behavior
> would become the default and programmers would need to opt-out (i.e.
> call Fl::dynamic_colors(0);) if they don't want the new behavior.

I mean that this should not be done. It's an artifical bear trap that
will hit devs. "If you don't handle this case, your app will blow up
later when someone runs it on such a system with Dark Mode on". It's
inevitable many will forget or not know in the first place.

Adding such bear traps is bad for any library.

By keeping it opt-in, requiring that one line at program init etc, you
make sure not to cause trouble for existing and new devs, and make it
clear that adding this line adds the requirement to test on such
systems.

- Lauri

Albrecht Schlosser

unread,
Mar 23, 2021, 1:21:43 PM3/23/21
to fltkc...@googlegroups.com
Good points, thanks.

Personally I'm fine with keeping it opt-in forever. The only thing I
wanted to avoid was to make it opt-out in 1.4.0 or to have no option at
all. For the same reasons you mentioned.

Michael Bäuerle

unread,
Mar 24, 2021, 10:48:41 AM3/24/21
to fltkc...@googlegroups.com
Greg Ercolano wrote:
>
> [...]
>     Generally speaking, there's an outer group, e.g. "Fl_Column_Tree", which contains
>     the header and an Fl_Tree instance.
>
>     This group widget keeps track of the column widths, and handles interactive column
>     resizing, e.g. when the mouse hovers over a column boundary and the user clicks
>     down to move it.
>
>     The Fl_Tree_Items have custom draw() code that gets the current column widths
>     from the parent group, and draws each column's text accordingly with clipping,
>     similar to the Fl_Browser approach.
>
>     If you have specific requests for features beyond what I've described above, reply here,
>     and I can maybe include for them, or at least design in such a way as to make them easier
>     to add.

The first row should be special. It should show the column names
(like the blue line in your example) and should stay in place when
the vertical scrollbar is used.
Maybe separate buttons can be used as column headers, so that users
can click them separately (e.g. to request a different sorting order).

The user should be able to adjust the width of each column with the
mouse (as you described above).

An API to set and read out the current column width values would be
nice. flnews should store them in its configfile to configure the
widget on startup to the same layout as in the last session.

Greg Ercolano

unread,
Mar 24, 2021, 11:20:20 AM3/24/21
to fltkc...@googlegroups.com


On 3/24/21 7:48 AM, Michael Bäuerle wrote:
The first row should be special. It should show the column names
(like the blue line in your example) and should stay in place when
the vertical scrollbar is used.

Maybe separate buttons can be used as column headers, so that users
can click them separately (e.g. to request a different sorting order).

    Yes, what you're calling the first row I'd call "the column header",
    which runs along the top of the tree, would remain fixed during
    vertical scrolling, and would track the data during horizontal scrolling,
    and the header could be turned on or off via the API.

    Ditto for optional "row headers" which could run along the left edge,
    and operate similarly.

    And yes, the header cells could be clicked so as to operate like buttons
    to allow toggling sorting for that colum (for instance). I expect even the
    early API would support built in toggles for SORT_UP and SORT_DOWN
    and SORT_NONE (default) if a 'sorting' is enabled.

    Perhaps not in the first version, but in subsequent releases support could
    be added to allow dragging the column headers around, so columns can
    be re-ordered.

    To allow for that, the data would need to be managed as cells, similar
    to Fl_Table, so that e.g. text font/face/color can all be controlled by the
    user's own code, even custom draw code to draw graphics and such.

    In this way the tree items would not need to store data at all (like Fl_Table)
    so that /anything/ could be put into each cell, draw code provided by the
    user, and the widget wouldn't have to have complex data structures to
    manage all the possible types of user data.

    Subclasses could provide more use-specific ways to manage the data,
    so that arrays of complex data structures specific to the use case
    could be provided (such as just dealing with simple text, like a mail/news
    reader's message browser).

    I've been down this path already, as in my application I needed some complex
    structures inside the cells; progress bars were needed in one column that could
    animate as the progress of each item (row) changed over time, and collapsible
    child rows would contain, not data, but multi-column tables with tabs in each.
    Here's a screenshot of that widget which subclasses Fl_Tree, and has all the
    above features except interactively reordering columns by dragging:


    You'd almost not recognize it as an Fl_Tree application, it almost could have been implemented
    as Fl_Table (and this app is the reason I wrote Fl_Table years ago), but I really needed the
    parent/child concept, which is why I followed up with releasing Fl_Tree.

    And just to bring this thread around to its subject of "light/dark mode", what is shown here
    is this widget in "dark mode".
    is in "dark mode", lol, ju

Bill Spitzak

unread,
Mar 24, 2021, 11:31:51 AM3/24/21
to fltkc...@googlegroups.com
Absolutely drawing the cells should involve calling functions supplied by the application. I think the api could be limited to just what x+y cell is being drawn and how big it is.

Almost 100% of the bugs I see with updating user interfaces is due to code having to "synchronize" the so-called "model" which insists on using toolkit data structures with the real model that the application wants to use. This should be a drawing problem.

--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/fltkcoredev/bf8cf388-a28d-2c44-a533-a35b3bdf4958%40seriss.com.

Greg Ercolano

unread,
Mar 24, 2021, 12:15:25 PM3/24/21
to fltkc...@googlegroups.com


On 3/24/21 8:31 AM, Bill Spitzak wrote:
Absolutely drawing the cells should involve calling functions supplied by the application. I think the api could be limited to just what x+y cell is being drawn and how big it is.

Almost 100% of the bugs I see with updating user interfaces is due to code having to "synchronize" the so-called "model" which insists on using toolkit data structures with the real model that the application wants to use. This should be a drawing problem.

    Ya, Fl_Table is an example of MVP (model-view-controller) where it implements the view (graphics)
    and contoller (some events handling), and lets the user handle the model (data).

    I did this mainly because we don't have a way to manage data easily (STL being outlawed),
    but also it allows the widget to not have to be concerned with the details of how the user
    prefers to manage their data (e.g. in a database, or in arrays, or on demand off disk, etc),
    or be concerned with memory use at all for e.g. large data sets.

    Fl_Tree is perhaps a bit different, as it's more like Fl_Browser and uses "items", which is needed
    to manage parent/child relationships and state information (stowed vs. opened, selected or not, etc).

    Fl_Table doesn't have this concept, as the 'items' don't exist, the cells are simply drawing areas
    for a callback to handle.

    So if I create a subclass for Fl_Tree that handles columns, I'll try to keep the individual Fl_Tree_Items
    like Fl_Table in that the items would use a callback to draw the data in each row/column provided
    by the user. And this concept could be extended with further subclasses into something easier to use
    for those users who don't want to be concerned with drawing their content, and just want simple text,
    or to insert existing FLTK widgets, similar to how Fl_Table can also act as a "container" for FLTK widgets
    e.g. by making one instance of the widget common to all cells, and making them "appear" whereever
    the user clicks to interact with it, or making instances per cell, and managing them all.

    This is tricky business though, and is a lot of heavy coding to get right. I found Fl_Table and Fl_Tree
    pretty exhausting to write..! Not sure I have it in me to do Fl_Tree as I've described. Although I've
    already written commercial code that does this, the design was not generalized, but I can see the
    path to making it so as a complete rewrite.

Michael Sweet

unread,
Mar 26, 2021, 6:17:34 AM3/26/21
to fltk.coredev
[I'm not sure why my email responses are getting blocked, so I'm re-posting through the Google groups page...]

All,

To wrap up this discussion:

1. We have consensus that supporting the current light/dark mode themes for macOS, Linux, and Windows 10 would be good
2. Any functionality needs to be opt-in.
3. The code needs to fall back gracefully on older OS's.
4. The code should follow the system setting (dynamic)
5. There should be a way to query the current setting.

My updated proposed API is as follows:

   enum Fl_Dynamic_Color {
       FL_DYNAMIC_COLOR_OFF,   // Default/manual color theme
       FL_DYNAMIC_COLOR_AUTO,  // Automatic color theme based on time of day or ambient lighting
       FL_DYNAMIC_COLOR_LIGHT, // Light color theme
       FL_DYNAMIC_COLOR_DARK   // Dark color theme
   };

   void Fl::dynamic_color(Fl_Dynamic_Color mode);

   Sets the current dynamic color mode. When set to FL_DYNAMIC_COLOR_AUTO, FLTK will respond to appearance/theme changes and update the foreground, background, and selection colors to match the local desktop environment. In addition, the FL_DYNAMIC_COLOR_CHANGE event is sent to notify widgets that a color change has occurred.

   Fl_Dynamic_Color Fl::dynamic_color();

   Returns the current dynamic color value.

Comments?

....

FWIW, I've created a "darkmode" branch to prototype this without disrupting things on master...  If you've been following along at home, you'll notice that I have a preliminary implementation for macOS working already, and you can set the FL_DYNAMIC_COLOR environment variable (to anything) to change the default to FL_DYNAMIC_COLOR_AUTO (instead of FL_DYNAMIC_COLOR_OFF). Seems to work well with all of the test/demo programs.  Still to do are Windows 10 and Linux/X11 and sending the FL_DYNAMIC_COLOR_CHANGED event.

imm

unread,
Mar 26, 2021, 6:36:46 AM3/26/21
to coredev fltk
On Fri, 26 Mar 2021, 10:17 Michael Sweet wrote:
[I'm not sure why my email responses are getting blocked, so I'm re-posting through the Google groups page...]


Your posts don't appear to be going to the moderation folder, so it looks like they must be getting rejected "somewhere else" in the process...

 Still to do are Windows 10 and Linux/X11 and sending the FL_DYNAMIC_COLOR_CHANGED event.


I had a very brief look at the Win10 side, but it turns out to be a hideous mess. As usual.

It seems MS initially only implemented it for UWP applications, and then were "totally surprised" that nobody used or wanted UWP.

Some Win32 apps do support it, apparently by dint of reverse engineering the underlying window messages to implement it.

Apparently MS have got the message and their Project Reunion is going to bring this API to Win32. May already have done so, I'm not sure.

Anyway, actually implementing this for Win10 may not be painless...

Michael Sweet

unread,
Mar 26, 2021, 11:12:01 AM3/26/21
to fltkc...@googlegroups.com
Ian,

> On Mar 26, 2021, at 6:36 AM, imm <imaca...@gmail.com> wrote:
> ...
> I had a very brief look at the Win10 side, but it turns out to be a hideous mess. As usual.

Yeah, I had found a few pages that point to looking at a registry variable for this, which would make it easy to support across different Windows versions (registry functions are available all the way back to Win 95 😂) but I suspect Windows users might still want/expect manual control...

________________________
Michael Sweet



signature.asc

imm

unread,
Mar 26, 2021, 11:28:37 AM3/26/21
to coredev fltk
On Fri, 26 Mar 2021, 15:12 Michael Sweet wrote:
Ian,


> On Mar 26, 2021, at 6:36 AM, imm wrote:
> ...
> I had a very brief look at the Win10 side, but it turns out to be a hideous mess. As usual.


Yeah, I had found a few pages that point to looking at a registry variable for this, which would make it easy to support across different Windows versions (registry functions are available all the way back to Win 95 😂) but I suspect Windows users might still want/expect manual control...

AFAICT there seem to be two "workarounds" for Win32, the first being based around the registry like you say (and apparently you can register a hook function that'll notify you if that registry entry changes, so we wouldn't have to poll for changes...) Or folks have figured out the message codes and you can use those. There's a GitHub project that implements this method (that I can't find just now!)

However, the other part of the problem seems to be that there's no obvious place to find out what the "dark" colours are for a given host, even once you detect that the dark mode has been selected.

Great...

Michael Sweet

unread,
Mar 26, 2021, 11:34:51 AM3/26/21
to fltkc...@googlegroups.com
Ian,

> On Mar 26, 2021, at 11:28 AM, imm <imaca...@gmail.com> wrote:
> ...
> AFAICT there seem to be two "workarounds" for Win32, the first being based around the registry like you say (and apparently you can register a hook function that'll notify you if that registry entry changes, so we wouldn't have to poll for changes...) Or folks have figured out the message codes and you can use those. There's a GitHub project that implements this method (that I can't find just now!)

I saw the message codes project, too, but figured that was a little too deep in the old MFC path.

> However, the other part of the problem seems to be that there's no obvious place to find out what the "dark" colours are for a given host, even once you detect that the dark mode has been selected.
>
> Great...

Given that we never truly match the local controls anyways, I think it will be enough to provide our own default colors suitable for "dark mode", much like web sites provide their own CSS to respond to the dark mode media query. I'm personally happy to have applications choose something appropriate for themselves when the ambient light is low (the whole purpose of dark mode IMHO) rather than searing my eyes in a darkened room...

________________________
Michael Sweet



signature.asc
Reply all
Reply to author
Forward
0 new messages