Merge branch 'sys-appearance'
Add wxSystemAppearance for dark mode checks under macOS. Closes https://github.com/wxWidgets/wxWidgets/pull/1292
This commit is contained in:
@@ -162,6 +162,39 @@ enum wxSystemScreenType
|
|||||||
wxSYS_SCREEN_DESKTOP // >= 800x600
|
wxSYS_SCREEN_DESKTOP // >= 800x600
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxSystemAppearance: describes the global appearance used for the UI
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class WXDLLIMPEXP_CORE wxSystemAppearance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Return the name if available or empty string otherwise.
|
||||||
|
wxString GetName() const;
|
||||||
|
|
||||||
|
// Return true if the current system there is explicitly recognized as
|
||||||
|
// being a dark theme or if the default window background is dark.
|
||||||
|
bool IsDark() const;
|
||||||
|
|
||||||
|
// Return true if the background is darker than foreground. This is used by
|
||||||
|
// IsDark() if there is no platform-specific way to determine whether a
|
||||||
|
// dark mode is being used.
|
||||||
|
bool IsUsingDarkBackground() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class wxSystemSettingsNative;
|
||||||
|
|
||||||
|
// Ctor is private, even though it's trivial, because objects of this type
|
||||||
|
// are only supposed to be created by wxSystemSettingsNative.
|
||||||
|
wxSystemAppearance() { }
|
||||||
|
|
||||||
|
// Currently this class doesn't have any internal state because the only
|
||||||
|
// available implementation doesn't need it. If we do need it later, we
|
||||||
|
// could add some "wxSystemAppearanceImpl* const m_impl" here, which we'd
|
||||||
|
// forward our public functions to (we'd also need to add the copy ctor and
|
||||||
|
// dtor to clone/free it).
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxSystemSettingsNative: defines the API for wxSystemSettings class
|
// wxSystemSettingsNative: defines the API for wxSystemSettings class
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -185,6 +218,9 @@ public:
|
|||||||
// get a system-dependent metric
|
// get a system-dependent metric
|
||||||
static int GetMetric(wxSystemMetric index, wxWindow * win = NULL);
|
static int GetMetric(wxSystemMetric index, wxWindow * win = NULL);
|
||||||
|
|
||||||
|
// get the object describing the current system appearance
|
||||||
|
static wxSystemAppearance GetAppearance();
|
||||||
|
|
||||||
// return true if the port has certain feature
|
// return true if the port has certain feature
|
||||||
static bool HasFeature(wxSystemFeature index);
|
static bool HasFeature(wxSystemFeature index);
|
||||||
};
|
};
|
||||||
|
@@ -254,6 +254,55 @@ enum wxSystemScreenType
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Provides information about the current system appearance.
|
||||||
|
|
||||||
|
An object of this class can be retrieved using
|
||||||
|
wxSystemSettings::GetAppearance() and can then be queried for some aspects
|
||||||
|
of the current system appearance, notably whether the system is using a
|
||||||
|
dark theme, i.e. a theme with predominantly dark background.
|
||||||
|
|
||||||
|
This is useful for custom controls that don't use the standard system
|
||||||
|
colours, as they need to adjust the colours used for drawing them to fit in
|
||||||
|
the system look.
|
||||||
|
|
||||||
|
@since 3.1.3
|
||||||
|
*/
|
||||||
|
class wxSystemAppearance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Return the name if available or empty string otherwise.
|
||||||
|
|
||||||
|
This is currently only implemented for macOS 10.9 or later and returns
|
||||||
|
a not necessarily user-readable string such as "NSAppearanceNameAqua"
|
||||||
|
there and an empty string under all the other platforms.
|
||||||
|
*/
|
||||||
|
wxString GetName() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return true if the current system there is explicitly recognized as
|
||||||
|
being a dark theme or if the default window background is dark.
|
||||||
|
|
||||||
|
This method should be used to check whether custom colours more
|
||||||
|
appropriate for the default (light) or dark appearance should be used.
|
||||||
|
*/
|
||||||
|
bool IsDark() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return true if the default window background is significantly darker
|
||||||
|
than foreground.
|
||||||
|
|
||||||
|
This is used by IsDark() if there is no platform-specific way to
|
||||||
|
determine whether a dark mode is being used and is generally not very
|
||||||
|
useful to call directly.
|
||||||
|
|
||||||
|
@see wxColour::GetLuminance()
|
||||||
|
*/
|
||||||
|
bool IsUsingDarkBackground() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class wxSystemSettings
|
@class wxSystemSettings
|
||||||
|
|
||||||
@@ -327,6 +376,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
static wxSystemScreenType GetScreenType();
|
static wxSystemScreenType GetScreenType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
Returns the object describing the current system appearance.
|
||||||
|
|
||||||
|
@since 3.1.3
|
||||||
|
*/
|
||||||
|
static wxSystemAppearance GetAppearance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Returns @true if the port has certain feature.
|
Returns @true if the port has certain feature.
|
||||||
See the ::wxSystemFeature enum values.
|
See the ::wxSystemFeature enum values.
|
||||||
|
@@ -1623,6 +1623,22 @@ void MyCanvas::DrawSystemColours(wxDC& dc)
|
|||||||
int lineHeight = textSize.GetHeight();
|
int lineHeight = textSize.GetHeight();
|
||||||
wxRect r(textSize.GetWidth() + 10, 10, 100, lineHeight);
|
wxRect r(textSize.GetWidth() + 10, 10, 100, lineHeight);
|
||||||
|
|
||||||
|
wxString title = "System colours";
|
||||||
|
|
||||||
|
const wxSystemAppearance appearance = wxSystemSettings::GetAppearance();
|
||||||
|
const wxString appearanceName = appearance.GetName();
|
||||||
|
if ( !appearanceName.empty() )
|
||||||
|
title += wxString::Format(" for \"%s\"", appearanceName);
|
||||||
|
if ( appearance.IsDark() )
|
||||||
|
title += " (using dark system theme)";
|
||||||
|
dc.DrawText(title, 10, r.y);
|
||||||
|
r.y += 2*lineHeight;
|
||||||
|
dc.DrawText(wxString::Format("Window background is %s",
|
||||||
|
appearance.IsUsingDarkBackground() ? "dark"
|
||||||
|
: "light"),
|
||||||
|
10, r.y);
|
||||||
|
r.y += 3*lineHeight;
|
||||||
|
|
||||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
|
@@ -66,3 +66,36 @@ void wxSystemSettings::SetScreenType( wxSystemScreenType screen )
|
|||||||
{
|
{
|
||||||
ms_screen = screen;
|
ms_screen = screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Trivial wxSystemAppearance implementation
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#if !defined(__WXOSX__)
|
||||||
|
|
||||||
|
wxString wxSystemAppearance::GetName() const
|
||||||
|
{
|
||||||
|
return wxString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxSystemAppearance::IsDark() const
|
||||||
|
{
|
||||||
|
return IsUsingDarkBackground();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // !__WXOSX__
|
||||||
|
|
||||||
|
bool wxSystemAppearance::IsUsingDarkBackground() const
|
||||||
|
{
|
||||||
|
const wxColour bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
|
||||||
|
const wxColour fg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
|
||||||
|
|
||||||
|
// The threshold here is rather arbitrary, but it seems that using just
|
||||||
|
// inequality would be wrong as it could result in false positivies.
|
||||||
|
return fg.GetLuminance() - bg.GetLuminance() > 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxSystemAppearance wxSystemSettingsNative::GetAppearance()
|
||||||
|
{
|
||||||
|
return wxSystemAppearance();
|
||||||
|
}
|
||||||
|
@@ -173,11 +173,9 @@ int wxRendererMac::DrawHeaderButton( wxWindow *win,
|
|||||||
wxHeaderSortIconType sortArrow,
|
wxHeaderSortIconType sortArrow,
|
||||||
wxHeaderButtonParams* params )
|
wxHeaderButtonParams* params )
|
||||||
{
|
{
|
||||||
if ( WX_IS_MACOS_AVAILABLE(10, 14) )
|
if ( wxSystemSettings::GetAppearance().IsDark() )
|
||||||
{
|
return wxRendererNative::GetGeneric().DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
|
||||||
if ( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW).Red() < 128 )
|
|
||||||
return wxRendererNative::GetGeneric().DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
|
|
||||||
}
|
|
||||||
const wxCoord x = rect.x;
|
const wxCoord x = rect.x;
|
||||||
const wxCoord y = rect.y;
|
const wxCoord y = rect.y;
|
||||||
const wxCoord w = rect.width;
|
const wxCoord w = rect.width;
|
||||||
@@ -391,13 +389,7 @@ void wxRendererMac::DrawSplitterSash( wxWindow *win,
|
|||||||
|
|
||||||
if ( win->HasFlag(wxSP_3DSASH) )
|
if ( win->HasFlag(wxSP_3DSASH) )
|
||||||
{
|
{
|
||||||
bool doDraw;
|
if ( !wxSystemSettings::GetAppearance().IsDark() )
|
||||||
if ( WX_IS_MACOS_AVAILABLE(10, 14) )
|
|
||||||
doDraw = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW).Red() > 128;
|
|
||||||
else
|
|
||||||
doDraw = true;
|
|
||||||
|
|
||||||
if ( doDraw )
|
|
||||||
{
|
{
|
||||||
HIThemeSplitterDrawInfo drawInfo;
|
HIThemeSplitterDrawInfo drawInfo;
|
||||||
drawInfo.version = 0;
|
drawInfo.version = 0;
|
||||||
|
@@ -88,7 +88,7 @@ void wxStatusBarMac::InitColours()
|
|||||||
m_textActive = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT);
|
m_textActive = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT);
|
||||||
m_textInactive = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
|
m_textInactive = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
|
||||||
|
|
||||||
if ( bg.Red() < 128 )
|
if ( wxSystemSettings::GetAppearance().IsDark() )
|
||||||
{
|
{
|
||||||
// dark mode appearance
|
// dark mode appearance
|
||||||
m_textActive = wxColour(0xB0, 0xB0, 0xB0);
|
m_textActive = wxColour(0xB0, 0xB0, 0xB0);
|
||||||
|
@@ -42,6 +42,39 @@ static int wxOSXGetUserDefault(NSString* key, int defaultValue)
|
|||||||
return [setting intValue];
|
return [setting intValue];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// wxSystemAppearance
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
wxString wxSystemAppearance::GetName() const
|
||||||
|
{
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
|
||||||
|
if ( WX_IS_MACOS_AVAILABLE(10, 9) )
|
||||||
|
{
|
||||||
|
return wxStringWithNSString([[NSApp effectiveAppearance] name]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return wxString();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wxSystemAppearance::IsDark() const
|
||||||
|
{
|
||||||
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_14
|
||||||
|
if ( WX_IS_MACOS_AVAILABLE(10, 14) )
|
||||||
|
{
|
||||||
|
const NSAppearanceName
|
||||||
|
appearanceName = [[NSApp effectiveAppearance]
|
||||||
|
bestMatchFromAppearancesWithNames:
|
||||||
|
@[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];
|
||||||
|
|
||||||
|
return [appearanceName isEqualToString:NSAppearanceNameDarkAqua];
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Fall back on the generic method when not running under 10.14.
|
||||||
|
return IsUsingDarkBackground();
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxSystemSettingsNative
|
// wxSystemSettingsNative
|
||||||
|
Reference in New Issue
Block a user