Merge branch 'dark-mode-fixes'
Various cosmetic -- but rather important -- fixes for MSW dark mode. See #23570.
This commit is contained in:
commit
fff31e01b7
5 changed files with 127 additions and 32 deletions
|
|
@ -47,6 +47,11 @@ protected:
|
|||
int sizeFlags = wxSIZE_AUTO) override;
|
||||
virtual wxSize DoGetBestClientSize() const override;
|
||||
|
||||
virtual bool MSWHandleMessage(WXLRESULT *result,
|
||||
WXUINT message,
|
||||
WXWPARAM wParam,
|
||||
WXLPARAM lParam) override;
|
||||
|
||||
virtual wxString WXGetVisibleLabel() const override;
|
||||
virtual void WXSetVisibleLabel(const wxString& str) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -2603,8 +2603,9 @@ void wxDataViewMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
|
|||
const wxColour bgColour = m_owner->GetBackgroundColour();
|
||||
|
||||
// Depending on the background, alternate row color
|
||||
// will be 3% more dark or 50% brighter.
|
||||
int alpha = bgColour.GetRGB() > 0x808080 ? 97 : 150;
|
||||
// will be 3% more dark or 10% brighter -- because 3% brighter
|
||||
// would be unnoticeable.
|
||||
int alpha = bgColour.GetRGB() > 0x808080 ? 97 : 110;
|
||||
altRowColour = bgColour.ChangeLightness(alpha);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -340,13 +340,13 @@ wxColour wxDarkModeSettings::GetMenuColour(wxMenuColour which)
|
|||
return wxColour(0xffffff);
|
||||
|
||||
case wxMenuColour::StandardBg:
|
||||
return wxColour(0x6d6d6d);
|
||||
return GetColour(wxSYS_COLOUR_MENU);
|
||||
|
||||
case wxMenuColour::DisabledFg:
|
||||
return wxColour(0x414141);
|
||||
return wxColour(0x6d6d6d);
|
||||
|
||||
case wxMenuColour::HotBg:
|
||||
return wxColour(0x2b2b2b);
|
||||
return wxColour(0x414141);
|
||||
}
|
||||
|
||||
wxFAIL_MSG( "unreachable" );
|
||||
|
|
|
|||
|
|
@ -621,14 +621,20 @@ void wxListCtrl::SetWindowStyleFlag(long flag)
|
|||
|
||||
bool wxListCtrl::MSWGetDarkModeSupport(MSWDarkModeSupport& support) const
|
||||
{
|
||||
// There doesn't seem to be any theme that works well here:
|
||||
// There doesn't seem to be any theme that works well out of the box:
|
||||
//
|
||||
// - "Explorer" draws bluish hover highlight rectangle which is not at
|
||||
// all like the greyish one used by the actual Explorer in dark mode.
|
||||
// It also draws vertical separator lines, unlike the Explorer itself,
|
||||
// which wouldn't be too bad if they were not misaligned with the
|
||||
// separators drawn in the header, when it is used, which looks ugly.
|
||||
// - "DarkMode_Explorer" uses the same selection colours as the light mode
|
||||
// and doesn't draw hover rectangle at all.
|
||||
// - "ItemsView", which we use currently, draws the selection and hover as
|
||||
// expected, but uses light mode scrollbars.
|
||||
support.themeName = L"ItemsView";
|
||||
// - "ItemsView" draws the selection and hover as expected, but uses light
|
||||
// mode scrollbars and also misaligned vertical separators.
|
||||
//
|
||||
// We currently use DarkMode_Explorer and override selection drawing.
|
||||
support.themeName = L"DarkMode_Explorer";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -3016,7 +3022,10 @@ bool wxListCtrl::MSWOnNotify(int idCtrl, WXLPARAM lParam, WXLPARAM *result)
|
|||
// custom draw stuff
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
static RECT GetCustomDrawnItemRect(const NMCUSTOMDRAW& nmcd)
|
||||
namespace
|
||||
{
|
||||
|
||||
RECT GetCustomDrawnItemRect(const NMCUSTOMDRAW& nmcd)
|
||||
{
|
||||
RECT rc;
|
||||
wxGetListCtrlItemRect(nmcd.hdr.hwndFrom, nmcd.dwItemSpec, LVIR_BOUNDS, rc);
|
||||
|
|
@ -3031,7 +3040,6 @@ static RECT GetCustomDrawnItemRect(const NMCUSTOMDRAW& nmcd)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static
|
||||
bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
|
||||
{
|
||||
NMCUSTOMDRAW& nmcd = pLVCD->nmcd;
|
||||
|
|
@ -3055,13 +3063,13 @@ bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
|
|||
RECT rc2;
|
||||
wxGetListCtrlSubItemRect(hwndList, item, 1, LVIR_BOUNDS, rc2);
|
||||
rc.right = rc2.left;
|
||||
rc.left += 4;
|
||||
}
|
||||
else // not first subitem
|
||||
{
|
||||
rc.left += 6;
|
||||
}
|
||||
|
||||
// This mysterious offset is necessary for the owner drawn items to align
|
||||
// with the non-owner-drawn ones. Note that it's intentionally *not* scaled
|
||||
// by DPI factor because it doesn't seem to depend on the resolution.
|
||||
rc.left += 6;
|
||||
|
||||
// get the image and text to draw
|
||||
wxChar text[512];
|
||||
LV_ITEM it;
|
||||
|
|
@ -3131,19 +3139,35 @@ bool HandleSubItemPrepaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int colCount)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void HandleItemPostpaint(NMCUSTOMDRAW nmcd)
|
||||
void HandleItemPostpaint(NMCUSTOMDRAW nmcd)
|
||||
{
|
||||
// The control seems to always draw its own focus rectangle when not using
|
||||
// dark mode, so don't draw another one.
|
||||
if ( !wxMSWDarkMode::IsActive() )
|
||||
return;
|
||||
|
||||
if ( nmcd.uItemState & CDIS_FOCUS )
|
||||
{
|
||||
RECT rc = GetCustomDrawnItemRect(nmcd);
|
||||
|
||||
// don't use the provided HDC, it's in some strange state by now
|
||||
::DrawFocusRect(ClientHDC(nmcd.hdr.hwndFrom), &rc);
|
||||
::DrawFocusRect(nmcd.hdc, &rc);
|
||||
}
|
||||
}
|
||||
|
||||
// Flags for HandleItemPaint()
|
||||
enum
|
||||
{
|
||||
Paint_Default = 0,
|
||||
Paint_OnlySelected = 1
|
||||
};
|
||||
|
||||
// This function is normally called only if we use custom colours, but it's
|
||||
// also called when using dark mode to draw the item if it's selected. In this
|
||||
// case, Paint_OnlySelected is used and we do nothing and return false if the
|
||||
// item is not selected.
|
||||
//
|
||||
// pLVCD->clrText and clrTextBk should contain the colours to use
|
||||
static void HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
|
||||
bool HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont, int flags = 0)
|
||||
{
|
||||
NMCUSTOMDRAW& nmcd = pLVCD->nmcd; // just a shortcut
|
||||
|
||||
|
|
@ -3184,25 +3208,31 @@ static void HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
|
|||
|
||||
if ( nmcd.uItemState & CDIS_SELECTED )
|
||||
{
|
||||
int syscolFg, syscolBg;
|
||||
wxSystemColour syscolFg, syscolBg;
|
||||
if ( ::GetFocus() == hwndList )
|
||||
{
|
||||
syscolFg = COLOR_HIGHLIGHTTEXT;
|
||||
syscolBg = COLOR_HIGHLIGHT;
|
||||
syscolFg = wxSYS_COLOUR_HIGHLIGHTTEXT;
|
||||
syscolBg = wxSYS_COLOUR_HIGHLIGHT;
|
||||
}
|
||||
else // selected but unfocused
|
||||
{
|
||||
syscolFg = COLOR_WINDOWTEXT;
|
||||
syscolBg = COLOR_BTNFACE;
|
||||
syscolFg = wxSYS_COLOUR_WINDOWTEXT;
|
||||
syscolBg = wxSYS_COLOUR_BTNFACE;
|
||||
|
||||
// don't grey out the icon in this case either
|
||||
nmcd.uItemState &= ~CDIS_SELECTED;
|
||||
}
|
||||
|
||||
pLVCD->clrText = ::GetSysColor(syscolFg);
|
||||
pLVCD->clrTextBk = ::GetSysColor(syscolBg);
|
||||
pLVCD->clrText = wxColourToRGB(wxSystemSettings::GetColour(syscolFg));
|
||||
pLVCD->clrTextBk = wxColourToRGB(wxSystemSettings::GetColour(syscolBg));
|
||||
}
|
||||
else // not selected
|
||||
{
|
||||
if ( flags & Paint_OnlySelected )
|
||||
return false;
|
||||
|
||||
// Continue and use normal colours from pLVCD
|
||||
}
|
||||
//else: not selected, use normal colours from pLVCD
|
||||
|
||||
HDC hdc = nmcd.hdc;
|
||||
RECT rc = GetCustomDrawnItemRect(nmcd);
|
||||
|
|
@ -3220,14 +3250,25 @@ static void HandleItemPaint(LPNMLVCUSTOMDRAW pLVCD, HFONT hfont)
|
|||
}
|
||||
|
||||
HandleItemPostpaint(nmcd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
|
||||
LPNMLVCUSTOMDRAW pLVCD,
|
||||
wxItemAttr *attr)
|
||||
WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
|
||||
LPNMLVCUSTOMDRAW pLVCD,
|
||||
wxItemAttr *attr)
|
||||
{
|
||||
if ( !attr )
|
||||
{
|
||||
if ( wxMSWDarkMode::IsActive() )
|
||||
{
|
||||
// We need to always paint selected items ourselves as they come
|
||||
// out completely wrong in DarkMode_Explorer theme, see the comment
|
||||
// before MSWGetDarkModeSupport().
|
||||
if ( HandleItemPaint(pLVCD, nullptr, Paint_OnlySelected) )
|
||||
return CDRF_SKIPDEFAULT;
|
||||
}
|
||||
|
||||
// nothing to do for this item
|
||||
return CDRF_DODEFAULT;
|
||||
}
|
||||
|
|
@ -3280,6 +3321,8 @@ static WXLPARAM HandleItemPrepaint(wxListCtrl *listctrl,
|
|||
return CDRF_DODEFAULT;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
WXLPARAM wxListCtrl::OnCustomDraw(WXLPARAM lParam)
|
||||
{
|
||||
LPNMLVCUSTOMDRAW pLVCD = (LPNMLVCUSTOMDRAW)lParam;
|
||||
|
|
@ -3292,7 +3335,7 @@ WXLPARAM wxListCtrl::OnCustomDraw(WXLPARAM lParam)
|
|||
//
|
||||
// for virtual controls, always suppose that we have attributes as
|
||||
// there is no way to check for this
|
||||
if ( IsVirtual() || m_hasAnyAttr )
|
||||
if ( IsVirtual() || m_hasAnyAttr || wxMSWDarkMode::IsActive() )
|
||||
return CDRF_NOTIFYITEMDRAW;
|
||||
break;
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,9 @@
|
|||
#include "wx/settings.h"
|
||||
#endif
|
||||
|
||||
#include "wx/msw/darkmode.h"
|
||||
#include "wx/msw/private.h"
|
||||
#include "wx/msw/private/darkmode.h"
|
||||
#include "wx/msw/private/winstyle.h"
|
||||
|
||||
bool wxStaticText::Create(wxWindow *parent,
|
||||
|
|
@ -145,6 +147,50 @@ void wxStaticText::DoSetSize(int x, int y, int w, int h, int sizeFlags)
|
|||
Refresh();
|
||||
}
|
||||
|
||||
bool
|
||||
wxStaticText::MSWHandleMessage(WXLRESULT *result,
|
||||
WXUINT message,
|
||||
WXWPARAM wParam,
|
||||
WXLPARAM lParam)
|
||||
{
|
||||
if ( wxStaticTextBase::MSWHandleMessage(result, message, wParam, lParam) )
|
||||
return true;
|
||||
|
||||
switch ( message )
|
||||
{
|
||||
case WM_PAINT:
|
||||
// We only customize drawing of disabled labels in dark mode.
|
||||
if ( IsEnabled() || !wxMSWDarkMode::IsActive() )
|
||||
break;
|
||||
|
||||
// For them, the default "greying out" of the text for the disabled
|
||||
// controls looks ugly and unreadable in dark mode, so we draw it
|
||||
// as normal text but use a different colour for it.
|
||||
//
|
||||
// We could alternatively make the control owner-drawn, which would
|
||||
// be slightly cleaner, but would require more effort.
|
||||
wxMSWWinStyleUpdater updateStyle(GetHwnd());
|
||||
updateStyle.TurnOff(WS_DISABLED).Apply();
|
||||
|
||||
// Don't use Get/SetForegroundColour() here as they do more than we
|
||||
// need, we just want to change m_foregroundColour temporarily
|
||||
// without any side effects.
|
||||
const auto colFgOrig = m_foregroundColour;
|
||||
wxDarkModeSettings darkModeSettings;
|
||||
m_foregroundColour = darkModeSettings.GetMenuColour(wxMenuColour::DisabledFg);
|
||||
|
||||
*result = MSWDefWindowProc(WM_PAINT, wParam, lParam);
|
||||
|
||||
updateStyle.TurnOn(WS_DISABLED).Apply();
|
||||
if ( m_hasFgCol )
|
||||
m_foregroundColour = colFgOrig;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void wxStaticText::SetLabel(const wxString& label)
|
||||
{
|
||||
// If the label doesn't really change, avoid flicker by not doing anything.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue