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
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
@@ -185,6 +218,9 @@ public:
|
||||
// get a system-dependent metric
|
||||
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
|
||||
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
|
||||
|
||||
@@ -327,6 +376,13 @@ public:
|
||||
*/
|
||||
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.
|
||||
See the ::wxSystemFeature enum values.
|
||||
|
@@ -1623,6 +1623,22 @@ void MyCanvas::DrawSystemColours(wxDC& dc)
|
||||
int lineHeight = textSize.GetHeight();
|
||||
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);
|
||||
|
||||
static const struct {
|
||||
|
@@ -66,3 +66,36 @@ void wxSystemSettings::SetScreenType( wxSystemScreenType 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,
|
||||
wxHeaderButtonParams* params )
|
||||
{
|
||||
if ( WX_IS_MACOS_AVAILABLE(10, 14) )
|
||||
{
|
||||
if ( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW).Red() < 128 )
|
||||
return wxRendererNative::GetGeneric().DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
|
||||
}
|
||||
if ( wxSystemSettings::GetAppearance().IsDark() )
|
||||
return wxRendererNative::GetGeneric().DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
|
||||
|
||||
const wxCoord x = rect.x;
|
||||
const wxCoord y = rect.y;
|
||||
const wxCoord w = rect.width;
|
||||
@@ -391,13 +389,7 @@ void wxRendererMac::DrawSplitterSash( wxWindow *win,
|
||||
|
||||
if ( win->HasFlag(wxSP_3DSASH) )
|
||||
{
|
||||
bool doDraw;
|
||||
if ( WX_IS_MACOS_AVAILABLE(10, 14) )
|
||||
doDraw = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW).Red() > 128;
|
||||
else
|
||||
doDraw = true;
|
||||
|
||||
if ( doDraw )
|
||||
if ( !wxSystemSettings::GetAppearance().IsDark() )
|
||||
{
|
||||
HIThemeSplitterDrawInfo drawInfo;
|
||||
drawInfo.version = 0;
|
||||
|
@@ -88,7 +88,7 @@ void wxStatusBarMac::InitColours()
|
||||
m_textActive = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT);
|
||||
m_textInactive = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
|
||||
|
||||
if ( bg.Red() < 128 )
|
||||
if ( wxSystemSettings::GetAppearance().IsDark() )
|
||||
{
|
||||
// dark mode appearance
|
||||
m_textActive = wxColour(0xB0, 0xB0, 0xB0);
|
||||
|
@@ -42,6 +42,39 @@ static int wxOSXGetUserDefault(NSString* key, int defaultValue)
|
||||
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
|
||||
|
Reference in New Issue
Block a user