[Git][wxwidgets/wxwidgets][master] 2 commits: Improvements for wxRendererNative when using wxMSW dark mode

1 view
Skip to first unread message

Vadim Zeitlin (@_VZ_)

unread,
Sep 28, 2025, 8:39:44 AMSep 28
to wx-commi...@googlegroups.com

Vadim Zeitlin pushed to branch master at wxWidgets / wxWidgets

Commits:

  • 0d3502e2
    by tmodes-dev at 2025-09-28T13:54:53+02:00
    Improvements for wxRendererNative when using wxMSW dark mode
    
    Fix DrawHeaderButton() with an updated theme name.
    
    Remove the manual switch for DrawCollapseButton(), reverting 64d75a55ed
    (Invert the themed collapsible pane button in dark mode, 2022-12-29).
    
    Use native drawing function in DrawTextCtrl() and DrawChoice() instead
    of manual drawing these controls.
    
    See #25792.
    
    Closes #25835.
    
  • 95bdc589
    by Daniel Kulp at 2025-09-28T14:18:39+02:00
    Fix wxGrid and wxPropertyGrid lines in macOS dark mode
    
    Introduce wxSYS_COLOUR_GRIDLINES, which allows to use NSColor gridColor
    on macOS, where wxSYS_COLOUR_BTNFACE can't be used for the lines as it's
    indistinguishable from the background colour in dark mode, and use it in
    wxGrid and wxPropertyGrid.
    
    Closes #25783.
    
    Closes #25785.
    

13 changed files:

Changes:

  • include/wx/msw/uxtheme.h
    ... ... @@ -190,10 +190,11 @@ public:
    190 190
         }
    
    191 191
     
    
    192 192
         // wxWindow pointer here must be valid and its DPI is always used.
    
    193
    -    wxUxThemeHandle(const wxWindow *win, const wchar_t *classes) :
    
    194
    -        wxUxThemeHandle(GetHwndOf(win), classes, win->GetDPI().y)
    
    195
    -    {
    
    196
    -    }
    
    193
    +    // If classesDark is non-nullptr and the dark mode is active, it's used
    
    194
    +    // instead of classes.
    
    195
    +    wxUxThemeHandle(const wxWindow* win,
    
    196
    +                    const wchar_t* classes,
    
    197
    +                    const wchar_t* classesDark = nullptr);
    
    197 198
     
    
    198 199
         wxUxThemeHandle(wxUxThemeHandle&& other)
    
    199 200
             : m_hTheme{other.m_hTheme}
    

  • include/wx/settings.h
    ... ... @@ -80,6 +80,7 @@ enum wxSystemColour
    80 80
         wxSYS_COLOUR_MENUBAR,
    
    81 81
         wxSYS_COLOUR_LISTBOXTEXT,
    
    82 82
         wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT,
    
    83
    +    wxSYS_COLOUR_GRIDLINES,
    
    83 84
     
    
    84 85
         wxSYS_COLOUR_MAX,
    
    85 86
     
    

  • interface/wx/settings.h
    ... ... @@ -115,6 +115,15 @@ enum wxSystemColour
    115 115
          */
    
    116 116
         wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT,
    
    117 117
     
    
    118
    +    /**
    
    119
    +        Colour of separator lines in grid-like controls.
    
    120
    +
    
    121
    +        On macOS, this maps to `[NSColor gridLines]`, on other platforms
    
    122
    +        it is currently the same as ::wxSYS_COLOUR_BTNFACE.
    
    123
    +
    
    124
    +        @since 3.3.2
    
    125
    +     */
    
    126
    +    wxSYS_COLOUR_GRIDLINES,
    
    118 127
     
    
    119 128
         // synonyms:
    
    120 129
     
    

  • src/generic/grid.cpp
    ... ... @@ -3206,7 +3206,7 @@ void wxGrid::Init()
    3206 3206
         m_minAcceptableColWidth  =
    
    3207 3207
         m_minAcceptableRowHeight = 0;
    
    3208 3208
     
    
    3209
    -    m_gridLineColour = wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE);
    
    3209
    +    m_gridLineColour = wxSystemSettings::GetColour(wxSYS_COLOUR_GRIDLINES);
    
    3210 3210
         m_gridLinesEnabled = true;
    
    3211 3211
         m_gridLinesClipHorz =
    
    3212 3212
         m_gridLinesClipVert = true;
    

  • src/gtk/settings.cpp
    ... ... @@ -764,6 +764,7 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index)
    764 764
             }
    
    765 765
             wxFALLTHROUGH;
    
    766 766
     #endif
    
    767
    +    case wxSYS_COLOUR_GRIDLINES:
    
    767 768
         case wxSYS_COLOUR_3DLIGHT:
    
    768 769
         case wxSYS_COLOUR_ACTIVEBORDER:
    
    769 770
         case wxSYS_COLOUR_BTNFACE:
    
    ... ... @@ -921,6 +922,7 @@ wxColour wxSystemSettingsNative::GetColour( wxSystemColour index )
    921 922
             case wxSYS_COLOUR_ACTIVEBORDER:
    
    922 923
             case wxSYS_COLOUR_INACTIVEBORDER:
    
    923 924
             case wxSYS_COLOUR_BTNFACE:
    
    925
    +        case wxSYS_COLOUR_GRIDLINES:
    
    924 926
             //case wxSYS_COLOUR_3DFACE:
    
    925 927
             case wxSYS_COLOUR_3DLIGHT:
    
    926 928
                 color = wxColor(ButtonStyle()->bg[GTK_STATE_NORMAL]);
    

  • src/msw/darkmode.cpp
    ... ... @@ -330,6 +330,7 @@ wxColour wxDarkModeSettings::GetColour(wxSystemColour index)
    330 330
             case wxSYS_COLOUR_MENU:
    
    331 331
                 return wxColour(0x2b2b2b);
    
    332 332
     
    
    333
    +        case wxSYS_COLOUR_GRIDLINES:
    
    333 334
             case wxSYS_COLOUR_BTNFACE:
    
    334 335
                 return wxColour(0x333333);
    
    335 336
     
    

  • src/msw/renderer.cpp
    ... ... @@ -24,7 +24,6 @@
    24 24
         #include "wx/window.h"
    
    25 25
         #include "wx/control.h"     // for wxControl::Ellipsize()
    
    26 26
         #include "wx/dc.h"
    
    27
    -    #include "wx/dcmemory.h"
    
    28 27
         #include "wx/settings.h"
    
    29 28
     #endif //WX_PRECOMP
    
    30 29
     
    
    ... ... @@ -38,8 +37,6 @@
    38 37
     #include "wx/msw/wrapcctl.h"
    
    39 38
     #include "wx/dynlib.h"
    
    40 39
     
    
    41
    -#include "wx/msw/private/darkmode.h"
    
    42
    -
    
    43 40
     // ----------------------------------------------------------------------------
    
    44 41
     // methods common to wxRendererMSW and wxRendererXP
    
    45 42
     // ----------------------------------------------------------------------------
    
    ... ... @@ -622,7 +619,7 @@ wxRendererXP::DrawComboBoxDropButton(wxWindow * win,
    622 619
                                           const wxRect& rect,
    
    623 620
                                           int flags)
    
    624 621
     {
    
    625
    -    wxUxThemeHandle hTheme(win, L"COMBOBOX");
    
    622
    +    wxUxThemeHandle hTheme(win, L"COMBOBOX", L"DarkMode_CFD::COMBOBOX");
    
    626 623
         if ( !hTheme )
    
    627 624
         {
    
    628 625
             m_rendererNative.DrawComboBoxDropButton(win, dc, rect, flags);
    
    ... ... @@ -654,7 +651,7 @@ wxRendererXP::DrawHeaderButton(wxWindow *win,
    654 651
                                    wxHeaderSortIconType sortArrow,
    
    655 652
                                    wxHeaderButtonParams* params)
    
    656 653
     {
    
    657
    -    wxUxThemeHandle hTheme(win, L"HEADER");
    
    654
    +    wxUxThemeHandle hTheme(win, L"Explorer::HEADER");
    
    658 655
         if ( !hTheme )
    
    659 656
         {
    
    660 657
             return m_rendererNative.DrawHeaderButton(win, dc, rect, flags, sortArrow, params);
    
    ... ... @@ -728,7 +725,7 @@ wxRendererXP::DoDrawCheckMark(int kind,
    728 725
                                   const wxRect& rect,
    
    729 726
                                   int flags)
    
    730 727
     {
    
    731
    -    wxUxThemeHandle hTheme(win, L"MENU");
    
    728
    +    wxUxThemeHandle hTheme(win, L"MENU", L"DarkMode::MENU");
    
    732 729
         if ( !hTheme )
    
    733 730
             return false;
    
    734 731
     
    
    ... ... @@ -915,39 +912,8 @@ wxRendererXP::DrawCollapseButton(wxWindow *win,
    915 912
                                      int flags)
    
    916 913
     {
    
    917 914
         RECT r = ConvertToRECT(dc, rect);
    
    918
    -
    
    919
    -    // Default theme draws the button on light background which looks very out
    
    920
    -    // of place when using dark mode, so invert it if necessary and fall back
    
    921
    -    // on the generic version if this fails.
    
    922
    -    //
    
    923
    -    // Ideal would be to find the theme drawing the version appropriate for the
    
    924
    -    // dark mode, but it's unknown if there is one providing this.
    
    925
    -    if ( wxMSWDarkMode::IsActive() )
    
    926
    -    {
    
    927
    -        wxBitmap bmp(rect.GetSize());
    
    928
    -
    
    929
    -        bool ok;
    
    930
    -        {
    
    931
    -            wxMemoryDC mdc(bmp);
    
    932
    -            ok = DoDrawCollapseButton(win, GetHdcOf(mdc), r, flags);
    
    933
    -        }
    
    934
    -
    
    935
    -        if ( ok )
    
    936
    -        {
    
    937
    -            wxBitmap bmpInv = wxMSWDarkMode::InvertBitmap(bmp);
    
    938
    -            if ( bmpInv.IsOk() )
    
    939
    -            {
    
    940
    -                dc.DrawBitmap(bmpInv, rect.GetPosition());
    
    941
    -                return;
    
    942
    -            }
    
    943
    -        }
    
    944
    -    }
    
    945
    -    else
    
    946
    -    {
    
    947
    -        if ( DoDrawCollapseButton(win, GetHdcOf(dc.GetTempHDC()), r, flags) )
    
    948
    -            return;
    
    949
    -    }
    
    950
    -
    
    915
    +    if ( DoDrawCollapseButton(win, GetHdcOf(dc.GetTempHDC()), r, flags) )
    
    916
    +        return;
    
    951 917
         m_rendererNative.DrawCollapseButton(win, dc, rect, flags);
    
    952 918
     }
    
    953 919
     
    
    ... ... @@ -1194,22 +1160,31 @@ void wxRendererXP::DrawTextCtrl(wxWindow* win,
    1194 1160
                                     const wxRect& rect,
    
    1195 1161
                                     int flags)
    
    1196 1162
     {
    
    1197
    -    wxUxThemeHandle hTheme(win, L"EDIT");
    
    1163
    +    wxUxThemeHandle hTheme(win, L"EDIT", L"DarkMode_CFD::Combobox");
    
    1198 1164
         if ( !hTheme )
    
    1199 1165
         {
    
    1200 1166
             m_rendererNative.DrawTextCtrl(win,dc,rect,flags);
    
    1201 1167
             return;
    
    1202 1168
         }
    
    1203 1169
     
    
    1204
    -    wxColour fill = hTheme.GetColour(EP_EDITTEXT, TMT_FILLCOLOR, ETS_NORMAL);
    
    1205
    -    wxColour bdr = hTheme.GetColour(EP_EDITTEXT, TMT_BORDERCOLOR,
    
    1206
    -                                    flags & wxCONTROL_DISABLED
    
    1207
    -                                        ? ETS_DISABLED
    
    1208
    -                                        : ETS_NORMAL);
    
    1170
    +    wxCHECK_RET(dc.GetImpl(), wxT("Invalid wxDC"));
    
    1171
    +
    
    1172
    +    RECT r = ConvertToRECT(dc, rect);
    
    1173
    +
    
    1174
    +    int state;
    
    1175
    +
    
    1176
    +    if (flags & wxCONTROL_DISABLED)
    
    1177
    +        state = CBB_DISABLED;
    
    1178
    +    else if (flags & wxCONTROL_FOCUSED)
    
    1179
    +        state = CBB_FOCUSED;
    
    1180
    +    else if (flags & wxCONTROL_CURRENT)
    
    1181
    +        state = CBB_HOT;
    
    1182
    +    else
    
    1183
    +        state = CBB_NORMAL;
    
    1184
    +
    
    1185
    +    hTheme.DrawBackground(GetHdcOf(dc.GetTempHDC()), r, CP_BACKGROUND);
    
    1186
    +    hTheme.DrawBackground(GetHdcOf(dc.GetTempHDC()), r, CP_BORDER, state);
    
    1209 1187
     
    
    1210
    -    wxDCPenChanger setPen(dc, bdr);
    
    1211
    -    wxDCBrushChanger setBrush(dc, fill);
    
    1212
    -    dc.DrawRectangle(rect);
    
    1213 1188
     }
    
    1214 1189
     
    
    1215 1190
     void wxRendererXP::DrawGauge(wxWindow* win,
    

  • src/msw/settings.cpp
    ... ... @@ -106,7 +106,12 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index)
    106 106
                 return colDark;
    
    107 107
         }
    
    108 108
     
    
    109
    -    if ( index == wxSYS_COLOUR_LISTBOXTEXT)
    
    109
    +    if ( index == wxSYS_COLOUR_GRIDLINES)
    
    110
    +    {
    
    111
    +        // there is no standard colour with this index, map to another one
    
    112
    +        index = wxSYS_COLOUR_BTNFACE;
    
    113
    +    }
    
    114
    +    else if ( index == wxSYS_COLOUR_LISTBOXTEXT)
    
    110 115
         {
    
    111 116
             // there is no standard colour with this index, map to another one
    
    112 117
             index = wxSYS_COLOUR_WINDOWTEXT;
    

  • src/msw/uxtheme.cpp
    ... ... @@ -32,6 +32,7 @@
    32 32
     #include "wx/dynlib.h"
    
    33 33
     
    
    34 34
     #include "wx/msw/uxtheme.h"
    
    35
    +#include "wx/msw/private/darkmode.h"
    
    35 36
     
    
    36 37
     bool wxUxThemeIsActive()
    
    37 38
     {
    
    ... ... @@ -44,6 +45,22 @@ bool wxUxThemeIsActive()
    44 45
         return s_isActive != 0;
    
    45 46
     }
    
    46 47
     
    
    48
    +wxUxThemeHandle::wxUxThemeHandle(const wxWindow* win,
    
    49
    +                                 const wchar_t* classes,
    
    50
    +                                 const wchar_t* classesDark)
    
    51
    +{
    
    52
    +    const bool useDark = classesDark && wxMSWDarkMode::IsActive();
    
    53
    +
    
    54
    +    // When using dark mode and using dark mode-specific classes we have to use
    
    55
    +    // the handle of a control which is *not* in dark mode, and as we don't
    
    56
    +    // have any, just use 0.
    
    57
    +    m_hTheme = DoOpenThemeData(
    
    58
    +        useDark ? 0 : GetHwndOf(win),
    
    59
    +        useDark ? classesDark : classes,
    
    60
    +        win->GetDPI().y
    
    61
    +    );
    
    62
    +}
    
    63
    +
    
    47 64
     /* static */
    
    48 65
     HTHEME
    
    49 66
     wxUxThemeHandle::DoOpenThemeData(HWND hwnd, const wchar_t *classes, int dpi)
    

  • src/osx/cocoa/settings.mm
    ... ... @@ -113,6 +113,9 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index)
    113 113
         case wxSYS_COLOUR_WINDOW:
    
    114 114
             sysColor = [NSColor controlBackgroundColor];
    
    115 115
             break;
    
    116
    +    case wxSYS_COLOUR_GRIDLINES:
    
    117
    +        sysColor = [NSColor gridColor];
    
    118
    +        break;
    
    116 119
         case wxSYS_COLOUR_BTNFACE:
    
    117 120
             if ( WX_IS_MACOS_AVAILABLE(10, 14 ) )
    
    118 121
                 sysColor = [NSColor windowBackgroundColor];
    

  • src/propgrid/propgrid.cpp
    ... ... @@ -1434,18 +1434,28 @@ void wxPropertyGrid::RegainColours()
    1434 1434
     {
    
    1435 1435
         if ( !(m_coloursCustomized & CustomColour_CaptionBg) )
    
    1436 1436
         {
    
    1437
    -        wxColour col = wxSystemSettings::GetColour( wxSYS_COLOUR_BTNFACE );
    
    1438
    -
    
    1439
    -        // Make sure colour is dark enough
    
    1440
    -    #ifdef __WXGTK__
    
    1441
    -        int colDec = wxPGGetColAvg(col) - 230;
    
    1442
    -    #else
    
    1443
    -        int colDec = wxPGGetColAvg(col) - 200;
    
    1444
    -    #endif
    
    1445
    -        if ( colDec > 0 )
    
    1446
    -            m_colCapBack = wxPGAdjustColour(col,-colDec);
    
    1437
    +        wxColour col = wxSystemSettings::GetColour( wxSYS_COLOUR_GRIDLINES );
    
    1438
    +    #ifdef __WXOSX__
    
    1439
    +        if ( wxSystemSettings::GetAppearance().IsDark() )
    
    1440
    +        {
    
    1441
    +            // Make sure colour is light enough
    
    1442
    +            int colDec = wxPGGetColAvg(col);
    
    1443
    +            if ( colDec < 30 )
    
    1444
    +                col = wxPGAdjustColour(col, 20);
    
    1445
    +        }
    
    1447 1446
             else
    
    1448
    -            m_colCapBack = col;
    
    1447
    +    #endif
    
    1448
    +        {
    
    1449
    +            // Make sure colour is dark enough
    
    1450
    +        #ifdef __WXGTK__
    
    1451
    +            int colDec = wxPGGetColAvg(col) - 230;
    
    1452
    +        #else
    
    1453
    +            int colDec = wxPGGetColAvg(col) - 200;
    
    1454
    +        #endif
    
    1455
    +            if ( colDec > 0 )
    
    1456
    +                col = wxPGAdjustColour(col,-colDec);
    
    1457
    +        }
    
    1458
    +        m_colCapBack = col;
    
    1449 1459
             m_categoryDefaultCell.GetData()->SetBgCol(m_colCapBack);
    
    1450 1460
         }
    
    1451 1461
     
    

  • src/qt/settings.cpp
    ... ... @@ -37,6 +37,7 @@ wxColour wxSystemSettingsNative::GetColour(wxSystemColour index)
    37 37
                 color = pal.color(QPalette::Light);
    
    38 38
                 break;
    
    39 39
     
    
    40
    +        case wxSYS_COLOUR_GRIDLINES:
    
    40 41
             case wxSYS_COLOUR_BTNFACE:
    
    41 42
                 color = pal.color(QPalette::Button);
    
    42 43
                 break;
    

  • src/univ/settingsuniv.cpp
    ... ... @@ -73,7 +73,8 @@ wxColour wxSystemSettings::GetColour(wxSystemColour index)
    73 73
             wxColourScheme::MAX /* wxSYS_COLOUR_MENUHILIGHT */,
    
    74 74
             wxColourScheme::MAX /* wxSYS_COLOUR_MENUBAR */,
    
    75 75
             wxColourScheme::CONTROL_TEXT /* wxSYS_COLOUR_LISTBOXTEXT */,
    
    76
    -        wxColourScheme::HIGHLIGHT_TEXT /* wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT */
    
    76
    +        wxColourScheme::HIGHLIGHT_TEXT /* wxSYS_COLOUR_LISTBOXHIGHLIGHTTEXT */,
    
    77
    +        wxColourScheme::CONTROL /* wxSYS_COLOUR_GRIDLINES */,
    
    77 78
         };
    
    78 79
     
    
    79 80
         wxCOMPILE_TIME_ASSERT( WXSIZEOF(s_mapSysToThemeCol) == wxSYS_COLOUR_MAX,
    

Reply all
Reply to author
Forward
0 new messages