Improve wxStatusBar appearance on macOS 11-26 Update rendering code to closely match native appearance (i.e. Finder) on macOS 11 through 15, and on macOS 26 Tahoe. Starting with macOS 11, toolbar isn't rendered as part of extended window border. Starting with macOS 26, it doesn't even have different color and inherits the window's appearance (which is now an effects view with subtly changing color under the hood).
Don't put wxStatusBar fields into corners on macOS macOS 26 (and to lesser extent, macOS 11+) uses rounded corners for windows and status bar fields were rendered into the corner. Improve the appearance by offsetting the fields are appropriately to look better. Also add a way to customize the offset from user code, because the default could be unsuitable when e.g. the window uses larger corner radius (possible on macOS 26), or when user code wants to do smarter placement of the fields to mimic Finder (which centers the statusbar, but not under the entire window, but under the main area sans the sidebar).
Merge branch 'devel/tahoe-statusbar' of github.com:vslavik/wxWidgets Improve wxStatusBar appearance on macOS 11-26. See #25766.
... | ... | @@ -87,6 +87,9 @@ protected: |
87 | 87 | // returns the position and the size of the size grip
|
88 | 88 | wxRect GetSizeGripRect() const;
|
89 | 89 | |
90 | + // returns the width available for fields drawing given total width
|
|
91 | + virtual int GetAvailableWidthForFields(int width) const;
|
|
92 | + |
|
90 | 93 | // common part of all ctors
|
91 | 94 | void Init();
|
92 | 95 |
... | ... | @@ -28,14 +28,23 @@ public: |
28 | 28 | // Implementation
|
29 | 29 | virtual void MacHiliteChanged() override;
|
30 | 30 | void OnPaint(wxPaintEvent& event);
|
31 | + virtual bool GetFieldRect(int i, wxRect& rect) const override;
|
|
32 | + |
|
33 | + void MacSetCornerInset(int inset);
|
|
34 | + int MacGetCornerInset() const { return m_cornerInset; }
|
|
31 | 35 | |
32 | 36 | protected:
|
33 | 37 | virtual int GetEffectiveFieldStyle(int WXUNUSED(i)) const override { return wxSB_NORMAL; }
|
34 | 38 | |
35 | 39 | virtual void InitColours() override;
|
36 | 40 | |
41 | + void InitCornerInset();
|
|
42 | + |
|
43 | + virtual int GetAvailableWidthForFields(int width) const override;
|
|
44 | + |
|
37 | 45 | private:
|
38 | - wxColour m_textActive, m_textInactive;
|
|
46 | + int m_cornerInset;
|
|
47 | + wxColour m_textActive, m_textInactive, m_bgActive, m_bgInactive, m_separator;
|
|
39 | 48 | |
40 | 49 | wxDECLARE_DYNAMIC_CLASS(wxStatusBarMac);
|
41 | 50 | wxDECLARE_EVENT_TABLE();
|
... | ... | @@ -177,13 +177,19 @@ void wxStatusBarGeneric::SetStatusWidths(int n, const int widths_field[]) |
177 | 177 | DoUpdateFieldWidths();
|
178 | 178 | }
|
179 | 179 | |
180 | +int wxStatusBarGeneric::GetAvailableWidthForFields(int width) const
|
|
181 | +{
|
|
182 | + if ( ShowsSizeGrip() )
|
|
183 | + width -= GetSizeGripRect().width;
|
|
184 | + |
|
185 | + return width;
|
|
186 | +}
|
|
187 | + |
|
180 | 188 | void wxStatusBarGeneric::DoUpdateFieldWidths()
|
181 | 189 | {
|
182 | 190 | m_lastClientSize = GetClientSize();
|
183 | 191 | |
184 | - int width = m_lastClientSize.x;
|
|
185 | - if ( ShowsSizeGrip() )
|
|
186 | - width -= GetSizeGripRect().width;
|
|
192 | + const int width = GetAvailableWidthForFields(m_lastClientSize.x);
|
|
187 | 193 | |
188 | 194 | // recompute the cache of the field widths if the status bar width has changed
|
189 | 195 | m_widthsAbs = CalculateAbsWidths(width);
|
... | ... | @@ -128,7 +128,14 @@ wxStatusBar *wxFrame::OnCreateStatusBar(int number, long style, wxWindowID id, |
128 | 128 | void wxFrame::SetStatusBar(wxStatusBar *statbar)
|
129 | 129 | {
|
130 | 130 | wxFrameBase::SetStatusBar(statbar);
|
131 | - m_nowpeer->SetBottomBorderThickness(statbar ? GetMacStatusbarHeight() : 0);
|
|
131 | + if ( WX_IS_MACOS_AVAILABLE(11, 0) )
|
|
132 | + {
|
|
133 | + // textured borders are unwanted, statusbar renders w/o them
|
|
134 | + }
|
|
135 | + else
|
|
136 | + {
|
|
137 | + m_nowpeer->SetBottomBorderThickness(statbar ? GetMacStatusbarHeight() : 0);
|
|
138 | + }
|
|
132 | 139 | }
|
133 | 140 | |
134 | 141 | void wxFrame::PositionStatusBar()
|
... | ... | @@ -25,9 +25,6 @@ |
25 | 25 | #include "wx/osx/private.h"
|
26 | 26 | #include "wx/osx/private/available.h"
|
27 | 27 | |
28 | -// Margin between the field text and the field rect
|
|
29 | -#define wxFIELD_TEXT_MARGIN 2
|
|
30 | - |
|
31 | 28 | |
32 | 29 | wxBEGIN_EVENT_TABLE(wxStatusBarMac, wxStatusBarGeneric)
|
33 | 30 | EVT_PAINT(wxStatusBarMac::OnPaint)
|
... | ... | @@ -69,13 +66,52 @@ bool wxStatusBarMac::Create(wxWindow *parent, wxWindowID id, |
69 | 66 | SetWindowVariant( wxWINDOW_VARIANT_SMALL );
|
70 | 67 | |
71 | 68 | InitColours();
|
69 | + InitCornerInset();
|
|
72 | 70 | |
73 | 71 | return true;
|
74 | 72 | }
|
75 | 73 | |
76 | 74 | void wxStatusBarMac::InitColours()
|
77 | 75 | {
|
78 | - if ( WX_IS_MACOS_AVAILABLE(10, 14) )
|
|
76 | + if ( WX_IS_MACOS_AVAILABLE(26, 0) )
|
|
77 | + {
|
|
78 | + if ( wxSystemSettings::GetAppearance().IsDark() )
|
|
79 | + {
|
|
80 | + m_textActive = wxColour(0x9B, 0x9F, 0x9F);
|
|
81 | + m_textInactive = wxColour(0x59, 0x5F, 0x60);
|
|
82 | + // native separator uses hairline black plus some shading,
|
|
83 | + // this approximates it well visually:
|
|
84 | + m_separator = wxColour(0x18, 0x18, 0x18);
|
|
85 | + }
|
|
86 | + else
|
|
87 | + {
|
|
88 | + m_textActive = wxColour(0x80, 0x80, 0x80);
|
|
89 | + m_textInactive = wxColour(0xB8, 0xB8, 0xB8);
|
|
90 | + m_separator = wxColour(0xD9, 0xD9, 0xD9);
|
|
91 | + }
|
|
92 | + }
|
|
93 | + else if ( WX_IS_MACOS_AVAILABLE(11, 0) )
|
|
94 | + {
|
|
95 | + if ( wxSystemSettings::GetAppearance().IsDark() )
|
|
96 | + {
|
|
97 | + m_textActive = wxColour(0xB1, 0xB2, 0xB2);
|
|
98 | + m_textInactive = wxColour(0x68, 0x69, 0x6A);
|
|
99 | + m_bgActive = wxColour(0x35, 0x36, 0x36);
|
|
100 | + m_bgInactive = wxColour(0x27, 0x28, 0x29);
|
|
101 | + // native separator uses hairline black plus some shading,
|
|
102 | + // this approximates it well visually:
|
|
103 | + m_separator = wxColour(0x18, 0x18, 0x18);
|
|
104 | + }
|
|
105 | + else
|
|
106 | + {
|
|
107 | + m_textActive = wxColour(0x73, 0x74, 0x74);
|
|
108 | + m_textInactive = wxColour(0xA5, 0xA6, 0xA6);
|
|
109 | + m_bgActive = wxColour(0xF3, 0xF3, 0xF3);
|
|
110 | + m_bgInactive = wxColour(0xE6, 0xE6, 0xE6);
|
|
111 | + m_separator = wxColour(0xCC, 0xCC, 0xCC);
|
|
112 | + }
|
|
113 | + }
|
|
114 | + else if ( WX_IS_MACOS_AVAILABLE(10, 14) )
|
|
79 | 115 | {
|
80 | 116 | if ( wxSystemSettings::GetAppearance().IsDark() )
|
81 | 117 | {
|
... | ... | @@ -90,7 +126,6 @@ void wxStatusBarMac::InitColours() |
90 | 126 | }
|
91 | 127 | else // 10.10 Yosemite to 10.13:
|
92 | 128 | {
|
93 | - |
|
94 | 129 | m_textActive = wxColour(0x40, 0x40, 0x40);
|
95 | 130 | m_textInactive = wxColour(0x4B, 0x4B, 0x4B);
|
96 | 131 | }
|
... | ... | @@ -118,7 +153,27 @@ void wxStatusBarMac::OnPaint(wxPaintEvent& WXUNUSED(event)) |
118 | 153 | break;
|
119 | 154 | }
|
120 | 155 | |
121 | - // Don't paint any background, that's handled by the OS. Only draw text:
|
|
156 | + if ( WX_IS_MACOS_AVAILABLE(26, 0) )
|
|
157 | + {
|
|
158 | + // don't paint the background, handled by the OS
|
|
159 | + }
|
|
160 | + else if ( WX_IS_MACOS_AVAILABLE(11, 0) )
|
|
161 | + {
|
|
162 | + // we _do_ need to paint the background on Big Sur up to Tahoe
|
|
163 | + // to match Finder's appearance:
|
|
164 | + dc.SetBackground(tlw == keyWindow ? m_bgActive : m_bgInactive);
|
|
165 | + dc.Clear();
|
|
166 | + }
|
|
167 | + // else: background is rendered by OS, it is part of NSWindow border
|
|
168 | + |
|
169 | + // Draw horizontal separator above the status bar:
|
|
170 | + if ( WX_IS_MACOS_AVAILABLE(11, 0) )
|
|
171 | + {
|
|
172 | + dc.SetPen(m_separator);
|
|
173 | + dc.DrawLine(0, 0, GetSize().x, 0);
|
|
174 | + }
|
|
175 | + |
|
176 | + // Draw the text:
|
|
122 | 177 | |
123 | 178 | dc.SetTextForeground(tlw == keyWindow ? m_textActive : m_textInactive);
|
124 | 179 | |
... | ... | @@ -131,6 +186,38 @@ void wxStatusBarMac::OnPaint(wxPaintEvent& WXUNUSED(event)) |
131 | 186 | DrawField(dc, i, textHeight);
|
132 | 187 | }
|
133 | 188 | |
189 | +void wxStatusBarMac::InitCornerInset()
|
|
190 | +{
|
|
191 | + if ( WX_IS_MACOS_AVAILABLE(26, 0) )
|
|
192 | + m_cornerInset = 8;
|
|
193 | + else if ( WX_IS_MACOS_AVAILABLE(11, 0) )
|
|
194 | + m_cornerInset = 4;
|
|
195 | + else
|
|
196 | + m_cornerInset = 0;
|
|
197 | +}
|
|
198 | + |
|
199 | +void wxStatusBarMac::MacSetCornerInset(int inset)
|
|
200 | +{
|
|
201 | + m_cornerInset = inset;
|
|
202 | + // force recalculation of the fields:
|
|
203 | + m_lastClientSize = wxDefaultSize;
|
|
204 | + Refresh();
|
|
205 | +}
|
|
206 | + |
|
207 | +int wxStatusBarMac::GetAvailableWidthForFields(int width) const
|
|
208 | +{
|
|
209 | + return wxStatusBarGeneric::GetAvailableWidthForFields(width) - 2 * m_cornerInset;
|
|
210 | +}
|
|
211 | + |
|
212 | +bool wxStatusBarMac::GetFieldRect(int i, wxRect& rect) const
|
|
213 | +{
|
|
214 | + if ( !wxStatusBarGeneric::GetFieldRect(i, rect) )
|
|
215 | + return false;
|
|
216 | + |
|
217 | + rect.x += MacGetCornerInset();
|
|
218 | + return true;
|
|
219 | +}
|
|
220 | + |
|
134 | 221 | void wxStatusBarMac::MacHiliteChanged()
|
135 | 222 | {
|
136 | 223 | Refresh();
|
—
View it on GitLab.
You're receiving this email because of your account on gitlab.com. Manage all notifications · Help