Render statusbar natively on macOS

Instead of trying to mimic native statusbar background rendering in our
own code, use NSWindow setContentBorderThickness:forEdge: to extend the
border that is drawn by the system. This is the canonical way of doing
statusbars ("bottom bar") in AppKit.

The text is still drawn generically, but that's a much smaller issue
than trying to match the border gradient.
This commit is contained in:
Václav Slavík
2020-12-31 18:51:46 +01:00
parent 5ebd76c5db
commit e687d0c4f6
7 changed files with 27 additions and 48 deletions

View File

@@ -329,6 +329,8 @@ public :
virtual void SetRepresentedFilename(const wxString& filename) wxOVERRIDE; virtual void SetRepresentedFilename(const wxString& filename) wxOVERRIDE;
virtual void SetBottomBorderThickness(int thickness) wxOVERRIDE;
wxNonOwnedWindow* GetWXPeer() { return m_wxPeer; } wxNonOwnedWindow* GetWXPeer() { return m_wxPeer; }
CGWindowLevel GetWindowLevel() const wxOVERRIDE { return m_macWindowLevel; } CGWindowLevel GetWindowLevel() const wxOVERRIDE { return m_macWindowLevel; }

View File

@@ -984,6 +984,8 @@ public :
virtual void SetRepresentedFilename(const wxString& WXUNUSED(filename)) { } virtual void SetRepresentedFilename(const wxString& WXUNUSED(filename)) { }
virtual void SetBottomBorderThickness(int WXUNUSED(thickness)) { }
#if wxOSX_USE_IPHONE #if wxOSX_USE_IPHONE
virtual CGFloat GetWindowLevel() const { return 0.0; } virtual CGFloat GetWindowLevel() const { return 0.0; }
#else #else

View File

@@ -71,6 +71,8 @@ public:
long style = wxSTB_DEFAULT_STYLE, long style = wxSTB_DEFAULT_STYLE,
wxWindowID id = 0, wxWindowID id = 0,
const wxString& name = wxASCII_STR(wxStatusLineNameStr)) wxOVERRIDE; const wxString& name = wxASCII_STR(wxStatusLineNameStr)) wxOVERRIDE;
virtual void SetStatusBar(wxStatusBar *statbar) wxOVERRIDE;
#endif // wxUSE_STATUSBAR #endif // wxUSE_STATUSBAR
void PositionBars(); void PositionBars();

View File

@@ -38,9 +38,7 @@ protected:
virtual void InitColours() wxOVERRIDE; virtual void InitColours() wxOVERRIDE;
private: private:
wxColour m_textActive, m_textInactive, wxColour m_textActive, m_textInactive;
m_bgActiveFrom, m_bgActiveTo,
m_borderActive, m_borderInactive;
wxDECLARE_DYNAMIC_CLASS(wxStatusBarMac); wxDECLARE_DYNAMIC_CLASS(wxStatusBarMac);
wxDECLARE_EVENT_TABLE(); wxDECLARE_EVENT_TABLE();

View File

@@ -112,6 +112,12 @@ wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id,
return statusBar; return statusBar;
} }
void wxFrame::SetStatusBar(wxStatusBar *statbar)
{
wxFrameBase::SetStatusBar(statbar);
m_nowpeer->SetBottomBorderThickness(statbar ? WX_MAC_STATUSBAR_HEIGHT : 0);
}
void wxFrame::PositionStatusBar() void wxFrame::PositionStatusBar()
{ {
if (m_frameStatusBar && m_frameStatusBar->IsShown() ) if (m_frameStatusBar && m_frameStatusBar->IsShown() )

View File

@@ -78,42 +78,22 @@ void wxStatusBarMac::InitColours()
{ {
if ( WX_IS_MACOS_AVAILABLE(10, 14) ) if ( WX_IS_MACOS_AVAILABLE(10, 14) )
{ {
// FIXME: None of this is correct and is only very loose
// approximation. 10.14's dark mode uses dynamic colors that
// use desktop tinting. The only correct way to render the
// statusbar is to use windowBackgroundColor in a NSBox.
wxColour bg = wxSystemSettings::GetColour(wxSYS_COLOUR_APPWORKSPACE);
m_textActive = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNTEXT);
m_textInactive = wxSystemSettings::GetColour(wxSYS_COLOUR_GRAYTEXT);
if ( wxSystemSettings::GetAppearance().IsDark() ) if ( wxSystemSettings::GetAppearance().IsDark() )
{ {
// dark mode appearance m_textActive = wxColour(0xA9, 0xA9, 0xA9);
m_textActive = wxColour(0xB0, 0xB0, 0xB0); m_textInactive = wxColour(0x67, 0x67, 0x67);
m_bgActiveFrom = wxColour(0x32, 0x32, 0x34);
m_bgActiveTo = wxColour(0x29, 0x29, 0x2A);
m_borderActive = wxColour(0x00, 0x00, 0x00);
m_borderInactive = wxColour(0x00, 0x00, 0x00);
} }
else else
{ {
m_bgActiveFrom = wxColour(0xE9, 0xE7, 0xEA); m_textActive = wxColour(0x4B, 0x4B, 0x4B);
m_bgActiveTo = wxColour(0xCD, 0xCB, 0xCE); m_textInactive = wxColour(0xB1, 0xB1, 0xB1);
m_borderActive = wxColour(0xBA, 0xB8, 0xBB);
m_borderInactive = wxColour(0xC3, 0xC3, 0xC3);
} }
SetBackgroundColour(bg); // inactive bg
} }
else else // 10.10 Yosemite to 10.13:
{ {
// 10.10 Yosemite to 10.13 :
m_textActive = wxColour(0x40, 0x40, 0x40); m_textActive = wxColour(0x40, 0x40, 0x40);
m_textInactive = wxColour(0x4B, 0x4B, 0x4B); m_textInactive = wxColour(0x4B, 0x4B, 0x4B);
m_bgActiveFrom = wxColour(0xE9, 0xE7, 0xEA);
m_bgActiveTo = wxColour(0xCD, 0xCB, 0xCE);
m_borderActive = wxColour(0xBA, 0xB8, 0xBB);
m_borderInactive = wxColour(0xC3, 0xC3, 0xC3);
SetBackgroundColour(wxColour(0xF4, 0xF4, 0xF4)); // inactive bg
} }
} }
@@ -165,10 +145,6 @@ void wxStatusBarMac::DoUpdateStatusText(int number)
void wxStatusBarMac::OnPaint(wxPaintEvent& WXUNUSED(event)) void wxStatusBarMac::OnPaint(wxPaintEvent& WXUNUSED(event))
{ {
wxPaintDC dc(this); wxPaintDC dc(this);
dc.Clear();
int w, h;
GetSize( &w, &h );
// Notice that wxOSXGetKeyWindow (aka [NSApp keyWindow] used below is // Notice that wxOSXGetKeyWindow (aka [NSApp keyWindow] used below is
// subtly different from IsActive() (aka [NSWindow iskeyWindow]): the // subtly different from IsActive() (aka [NSWindow iskeyWindow]): the
@@ -188,22 +164,9 @@ void wxStatusBarMac::OnPaint(wxPaintEvent& WXUNUSED(event))
break; break;
} }
if ( tlw == keyWindow ) // Don't paint any background, that's handled by the OS. Only draw text:
{
dc.GradientFillLinear(dc.GetSize(), m_bgActiveFrom, m_bgActiveTo, wxBOTTOM);
// Finder statusbar border color dc.SetTextForeground(tlw == keyWindow ? m_textActive : m_textInactive);
dc.SetPen(wxPen(m_borderActive, 2, wxPENSTYLE_SOLID));
dc.SetTextForeground(m_textActive);
}
else
{
// Finder statusbar border color
dc.SetPen(wxPen(m_borderInactive, 2, wxPENSTYLE_SOLID));
dc.SetTextForeground(m_textInactive);
}
dc.DrawLine(0, 0, w, 0);
if ( GetFont().IsOk() ) if ( GetFont().IsOk() )
dc.SetFont(GetFont()); dc.SetFont(GetFont());

View File

@@ -1288,6 +1288,12 @@ void wxNonOwnedWindowCocoaImpl::SetRepresentedFilename(const wxString& filename)
[m_macWindow setRepresentedFilename:wxCFStringRef(filename).AsNSString()]; [m_macWindow setRepresentedFilename:wxCFStringRef(filename).AsNSString()];
} }
void wxNonOwnedWindowCocoaImpl::SetBottomBorderThickness(int thickness)
{
[m_macWindow setAutorecalculatesContentBorderThickness:(thickness ? NO : YES) forEdge:NSMinYEdge];
[m_macWindow setContentBorderThickness:thickness forEdge:NSMinYEdge];
}
void wxNonOwnedWindowCocoaImpl::RestoreWindowLevel() void wxNonOwnedWindowCocoaImpl::RestoreWindowLevel()
{ {
if ( [m_macWindow level] != m_macWindowLevel ) if ( [m_macWindow level] != m_macWindowLevel )