Initial framework for dynamic color support
- Fl_Dynamic_Color enum - Fl::dynamic_color() APIs - Fl_System_Driver::dynamic_color() API - FL_DYNAMIC_COLOR_CHANGED event - Add method for querying dark mode to macOS system and screen drivers. - Check/update mode whenever we get a layout change from macOS. - Add detection of dark mode on macOS by using the effectiveAppearance property. - Force redraw of all windows when changing the mode. - Update Cocoa set_system_colors method to override colors when dynamic mode isn't off. - Add (temporary) support for FL_DYNAMIC_COLOR environment variable to override default "off" mode for testing. To do: add dark mode detection on other platforms than macOS. Note: Branch 'darkmode' rebased, squashed, and extended by Albrecht-S on Dec 17, 2023.
This commit is contained in:
parent
469d3ef3d5
commit
4ab861aae2
@ -407,7 +407,11 @@ enum Fl_Event { // events
|
||||
/** A zoom event (ctrl/+/-/0/ or cmd/+/-/0/) was processed.
|
||||
Use Fl::add_handler() to be notified of this event.
|
||||
*/
|
||||
FL_ZOOM_EVENT = 27
|
||||
FL_ZOOM_EVENT = 27,
|
||||
/** The current dynamic color mode has changed.
|
||||
Call Fl::dynamic_color() to get the new mode.
|
||||
*/
|
||||
FL_DYNAMIC_COLOR_CHANGED = 28
|
||||
// DEV NOTE: Keep this list in sync with FL/names.h
|
||||
};
|
||||
|
||||
@ -1380,4 +1384,26 @@ enum Fl_Orientation {
|
||||
FL_ORIENT_SE = 0x07 ///< GUI element pointing SE (315°)
|
||||
};
|
||||
|
||||
/**
|
||||
Modern operating systems provide a pair of color themes suitable for use in
|
||||
light and dark ambient lighting. Automatic switching is normally provided
|
||||
either using the current time of day or with ambient lighting sensors.
|
||||
This enumeration lists the values for the Fl::dynamic_color() API, allowing
|
||||
applications to opt in to automatic color theme switching or specify that
|
||||
color switching is not desired.
|
||||
|
||||
\see Fl::dynamic_color()
|
||||
*/
|
||||
|
||||
enum Fl_Dynamic_Color { // dynamic color values
|
||||
/** Dynamic color themes are off/not supported/disabled */
|
||||
FL_DYNAMIC_COLOR_OFF,
|
||||
/** Automatically change color themes */
|
||||
FL_DYNAMIC_COLOR_AUTO,
|
||||
/** Use the light color theme */
|
||||
FL_DYNAMIC_COLOR_LIGHT,
|
||||
/** Use the dark color theme */
|
||||
FL_DYNAMIC_COLOR_DARK
|
||||
};
|
||||
|
||||
#endif
|
||||
|
23
FL/Fl.H
23
FL/Fl.H
@ -148,6 +148,8 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
static Fl_Dynamic_Color dynamic_color_;
|
||||
|
||||
static Fl_Screen_Driver *screen_driver();
|
||||
static Fl_System_Driver *system_driver();
|
||||
#ifdef __APPLE__ // deprecated in 1.4 - only for compatibility with 1.3
|
||||
@ -392,6 +394,27 @@ public:
|
||||
static void background(uchar, uchar, uchar);
|
||||
static void background2(uchar, uchar, uchar);
|
||||
|
||||
// dynamic color:
|
||||
/** Set the dynamic color theme mode.
|
||||
|
||||
Most applications should just call Fl::dynamic_color(FL_DYNAMIC_COLOR_AUTO)
|
||||
to use the user's preferred color theme. The default value is
|
||||
FL_DYNAMIC_COLOR_OFF for compatibility with prior versions of FLTK.
|
||||
|
||||
When set to FL_DYNAMIC_COLOR_AUTO, FLTK will monitor for appearance/theme
|
||||
changes. When the color theme changes, a FL_DYNAMIC_COLOR_CHANGED event is
|
||||
sent to allow widgets to update their colors as needed.
|
||||
*/
|
||||
static void dynamic_color(Fl_Dynamic_Color mode);
|
||||
/** Gets the current dynamic color theme.
|
||||
|
||||
Returns FL_DYNAMIC_COLOR_OFF if dynamic color themes are off or disabled
|
||||
(the default), FL_DYNAMIC_COLOR_LIGHT if the current color theme is for use
|
||||
in bright ambient light, or FL_DYNAMIC_COLOR_DARK is the current color
|
||||
theme is for use in dark ambient light.
|
||||
*/
|
||||
static Fl_Dynamic_Color dynamic_color();
|
||||
|
||||
// schemes:
|
||||
static int scheme(const char *name);
|
||||
/** See void scheme(const char *name) */
|
||||
|
@ -73,7 +73,7 @@ const char * const fl_eventnames[] =
|
||||
"FL_FULLSCREEN",
|
||||
"FL_ZOOM_GESTURE",
|
||||
"FL_ZOOM_EVENT",
|
||||
"FL_EVENT_28", // not yet defined, just in case it /will/ be defined ...
|
||||
"FL_DYNAMIC_COLOR_CHANGED",
|
||||
"FL_EVENT_29", // not yet defined, just in case it /will/ be defined ...
|
||||
"FL_EVENT_30" // not yet defined, just in case it /will/ be defined ...
|
||||
};
|
||||
|
@ -222,6 +222,7 @@ public:
|
||||
virtual const char *alt_name() { return "Alt"; }
|
||||
virtual const char *control_name() { return "Ctrl"; }
|
||||
virtual Fl_Sys_Menu_Bar_Driver *sys_menu_bar_driver() { return NULL; }
|
||||
virtual Fl_Dynamic_Color dynamic_color() { return FL_DYNAMIC_COLOR_LIGHT; }
|
||||
virtual void lock_ring() {}
|
||||
virtual void unlock_ring() {}
|
||||
virtual double wait(double); // must FL_OVERRIDE
|
||||
|
@ -580,6 +580,7 @@ void Fl_Cocoa_Screen_Driver::breakMacEventLoop()
|
||||
- (BOOL)process_keydown:(NSEvent*)theEvent;
|
||||
- (id)initWithFrame:(NSRect)frameRect;
|
||||
- (void)drawRect:(NSRect)rect;
|
||||
- (void)layout;
|
||||
- (BOOL)acceptsFirstResponder;
|
||||
- (BOOL)acceptsFirstMouse:(NSEvent*)theEvent;
|
||||
- (void)resetCursorRects;
|
||||
@ -2415,6 +2416,38 @@ static FLTextInputContext* fltextinputcontext_instance = nil;
|
||||
fl_unlock_function();
|
||||
}
|
||||
|
||||
- (void)layout
|
||||
{
|
||||
// Check to see whether the system appearance has changed...
|
||||
if (Fl::dynamic_color_ == FL_DYNAMIC_COLOR_AUTO) {
|
||||
Fl_Dynamic_Color mode = FL_DYNAMIC_COLOR_LIGHT;
|
||||
|
||||
if (@available(macOS 10.14, *)) {
|
||||
NSAppearanceName temp = [self.effectiveAppearance bestMatchFromAppearancesWithNames:@[
|
||||
NSAppearanceNameAqua,
|
||||
NSAppearanceNameDarkAqua
|
||||
]];
|
||||
|
||||
if ([temp isEqualToString:NSAppearanceNameDarkAqua])
|
||||
mode = FL_DYNAMIC_COLOR_DARK;
|
||||
}
|
||||
|
||||
Fl_Darwin_System_Driver *s = (Fl_Darwin_System_Driver *)Fl::system_driver();
|
||||
if (s->dynamic_color() != mode) {
|
||||
// Change the color mode and force all windows to redraw...
|
||||
s->dynamic_color(mode);
|
||||
Fl::get_system_colors();
|
||||
|
||||
Fl_Window *window;
|
||||
for (window = Fl::first_window(); window; window = Fl::next_window(window))
|
||||
window->redraw();
|
||||
}
|
||||
}
|
||||
|
||||
[super layout];
|
||||
}
|
||||
|
||||
|
||||
- (BOOL)acceptsFirstResponder
|
||||
{
|
||||
return [[self window] parentWindow] ? NO : YES; // 10.2
|
||||
|
@ -106,6 +106,27 @@ void Fl::get_system_colors()
|
||||
Fl::screen_driver()->get_system_colors();
|
||||
}
|
||||
|
||||
#ifndef FL_DOXYGEN
|
||||
Fl_Dynamic_Color Fl::dynamic_color_ = FL_DYNAMIC_COLOR_OFF;
|
||||
#endif // !FL_DOXYGEN
|
||||
|
||||
void Fl::dynamic_color(Fl_Dynamic_Color mode)
|
||||
{
|
||||
dynamic_color_ = mode;
|
||||
}
|
||||
|
||||
Fl_Dynamic_Color Fl::dynamic_color()
|
||||
{
|
||||
// TODO: Remove this
|
||||
if (getenv("FL_DYNAMIC_COLOR") && dynamic_color_ == FL_DYNAMIC_COLOR_OFF)
|
||||
dynamic_color_ = FL_DYNAMIC_COLOR_AUTO;
|
||||
|
||||
if (dynamic_color_ == FL_DYNAMIC_COLOR_AUTO)
|
||||
return Fl::system_driver()->dynamic_color();
|
||||
else
|
||||
return dynamic_color_;
|
||||
}
|
||||
|
||||
|
||||
//// Simple implementation of 2.0 Fl::scheme() interface...
|
||||
#define D1 BORDER_WIDTH
|
||||
|
@ -201,7 +201,11 @@ static void set_selection_color(uchar r, uchar g, uchar b)
|
||||
}
|
||||
|
||||
|
||||
// MacOS X currently supports two color schemes - Blue and Graphite.
|
||||
// macOS supports two basic color schemes - Light and Dark - with accent and
|
||||
// highlight colors. Older versions limited the accent colors to Blue and
|
||||
// Graphite but now you can pick from a rainbow of colors plus the old Graphite
|
||||
// gray.
|
||||
//
|
||||
// Since we aren't emulating the Aqua interface (even if Apple would
|
||||
// let us), we use some defaults that are similar to both. The
|
||||
// Fl::scheme("plastic") color/box scheme provides a usable Aqua-like
|
||||
@ -212,13 +216,30 @@ void Fl_Cocoa_Screen_Driver::get_system_colors()
|
||||
|
||||
Fl_Screen_Driver::get_system_colors();
|
||||
|
||||
if (!bg2_set) Fl::background2(0xff, 0xff, 0xff);
|
||||
if (!fg_set) Fl::foreground(0, 0, 0);
|
||||
if (!bg_set) Fl::background(0xd8, 0xd8, 0xd8);
|
||||
Fl_Dynamic_Color mode = Fl::dynamic_color();
|
||||
|
||||
if (!bg2_set || mode != FL_DYNAMIC_COLOR_OFF) {
|
||||
if (mode == FL_DYNAMIC_COLOR_DARK)
|
||||
Fl::background2(23, 23, 23);
|
||||
else
|
||||
Fl::background2(0xff, 0xff, 0xff);
|
||||
}
|
||||
if (!fg_set || mode != FL_DYNAMIC_COLOR_OFF) {
|
||||
if (mode == FL_DYNAMIC_COLOR_DARK)
|
||||
Fl::foreground(223, 223, 223);
|
||||
else
|
||||
Fl::foreground(0, 0, 0);
|
||||
}
|
||||
if (!bg_set || mode != FL_DYNAMIC_COLOR_OFF) {
|
||||
if (mode == FL_DYNAMIC_COLOR_DARK)
|
||||
Fl::background(50, 50, 50);
|
||||
else
|
||||
Fl::background(0xd8, 0xd8, 0xd8);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// this would be the correct code, but it does not run on all versions
|
||||
// of OS X. Also, setting a bright selection color would require
|
||||
// of macOS. Also, setting a bright selection color would require
|
||||
// some updates in Fl_Adjuster and Fl_Help_Browser
|
||||
OSStatus err;
|
||||
RGBColor c;
|
||||
@ -229,6 +250,7 @@ void Fl_Cocoa_Screen_Driver::get_system_colors()
|
||||
set_selection_color(c.red, c.green, c.blue);
|
||||
#else
|
||||
set_selection_color(0x00, 0x00, 0x80);
|
||||
//set_selection_color(0, 87, 207);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,8 @@
|
||||
|
||||
class Fl_Darwin_System_Driver : public Fl_Posix_System_Driver
|
||||
{
|
||||
Fl_Dynamic_Color dynamic_color_;
|
||||
|
||||
public:
|
||||
Fl_Darwin_System_Driver();
|
||||
int single_arg(const char *arg) FL_OVERRIDE;
|
||||
@ -82,6 +84,8 @@ public:
|
||||
Fl_Sys_Menu_Bar_Driver *sys_menu_bar_driver() FL_OVERRIDE;
|
||||
double wait(double time_to_wait) FL_OVERRIDE;
|
||||
int ready() FL_OVERRIDE;
|
||||
Fl_Dynamic_Color dynamic_color() FL_OVERRIDE;
|
||||
void dynamic_color(Fl_Dynamic_Color mode) { dynamic_color_ = mode; }
|
||||
};
|
||||
|
||||
#endif // FL_DARWIN_SYSTEM_DRIVER_H
|
||||
|
@ -53,6 +53,7 @@ Fl_Darwin_System_Driver::Fl_Darwin_System_Driver() : Fl_Posix_System_Driver() {
|
||||
if (fl_mac_os_version == 0) fl_mac_os_version = calc_mac_os_version();
|
||||
command_key = FL_META;
|
||||
control_key = FL_CTRL;
|
||||
dynamic_color_ = FL_DYNAMIC_COLOR_LIGHT;
|
||||
}
|
||||
|
||||
int Fl_Darwin_System_Driver::single_arg(const char *arg) {
|
||||
@ -404,3 +405,7 @@ Fl_Pixmap *Fl_Darwin_System_Driver::tree_closepixmap() {
|
||||
int Fl_Darwin_System_Driver::tree_connector_style() {
|
||||
return FL_TREE_CONNECTOR_NONE;
|
||||
}
|
||||
|
||||
Fl_Dynamic_Color Fl_Darwin_System_Driver::dynamic_color() {
|
||||
return dynamic_color_;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user