vcl/inc/win/salinst.h | 9 ++++++ vcl/win/app/salinst.cxx | 45 +++++++++++++++++++--------------- vcl/win/gdi/salnativewidgets-luna.cxx | 39 +++++++++++++++-------------- 3 files changed, 56 insertions(+), 37 deletions(-)
New commits: commit a43b5e3de41856407dbad337dac8e96d7e966429 Author: Michael Weghorn <[email protected]> AuthorDate: Tue Nov 5 12:31:51 2024 +0000 Commit: Michael Weghorn <[email protected]> CommitDate: Wed Nov 6 14:06:27 2024 +0100 win: Prefer integers instead of strings for OS version comparison * Add a WinOSVersionInfo struct holding the major and minor version and build number for a Windows release. * Extract a static WinSalInstance::getWinOSVersionInfo from WinSalInstance::getOSVersion that returns a corresponding version info. * Adjust the local getOSVersionString helper to take integers for major and minor version instead of an "NT version" string that is a dot-separated version number containing both of these. * Use WinSalInstance::getWinOSVersionInfo in ImplDrawNativeControl to compare the major version + build number to identify Windows 11 instead of relying on WinSalInstance::getOSVersion to return a string starting with "Windows 11". Change-Id: I6fe727c1c0f928c03216e406cdb1b7735c1ab3ad Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176059 Tested-by: Jenkins Reviewed-by: Michael Weghorn <[email protected]> diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h index 9c6ca82d38bd..8bff74b865d5 100644 --- a/vcl/inc/win/salinst.h +++ b/vcl/inc/win/salinst.h @@ -24,9 +24,17 @@ #include <osl/conditn.hxx> #include <salinst.hxx> +#include <win/salframe.h> class SalYieldMutex; +struct WinOSVersionInfo +{ + DWORD m_nMajorVersion = 0; + DWORD m_nMinorVersion = 0; + DWORD m_nBuildNumber = 0; +}; + class WinSalInstance : public SalInstance { public: @@ -72,6 +80,7 @@ public: virtual OUString GetConnectionIdentifier() override; virtual void AddToRecentDocumentList(const OUString& rFileUrl, const OUString& rMimeType, const OUString& rDocumentService) override; + static WinOSVersionInfo getWinOSVersionInfo(); virtual OUString getOSVersion() override; virtual void BeforeAbort(const OUString&, bool) override; diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index 8dbe2428b7e4..8ef06b692457 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -1045,16 +1045,16 @@ static OUString getWinArch() } } -static OUString getOSVersionString(const OUString& aNtVersionString, DWORD nBuildNumber) +static OUString getOSVersionString(DWORD nMajorVersion, DWORD nMinorVersion, DWORD nBuildNumber) { OUStringBuffer result = u"Windows"; - if (aNtVersionString == "6.1") + if (nMajorVersion == 6 && nMinorVersion == 1) result.append(" 7 Service Pack 1"); - else if (aNtVersionString == "6.2") + else if (nMajorVersion == 6 && nMinorVersion == 2) result.append(" 8"); - else if (aNtVersionString == "6.3") + else if (nMajorVersion == 6 && nMinorVersion == 3) result.append(" 8.1"); - else if (aNtVersionString == "10.0") + else if (nMajorVersion == 10 && nMinorVersion == 0) { if (nBuildNumber >= 22000) result.append(" 11"); @@ -1066,12 +1066,12 @@ static OUString getOSVersionString(const OUString& aNtVersionString, DWORD nBuil result.append(getWinArch()); - if (!aNtVersionString.isEmpty() || nBuildNumber) + if (nMajorVersion || nMinorVersion || nBuildNumber) { result.append(" ("); - if (!aNtVersionString.isEmpty()) + if (nMajorVersion || nMinorVersion) { - result.append(aNtVersionString); + result.append(OUString::number(nMajorVersion) + u"." + OUString::number(nMinorVersion)); if (nBuildNumber) result.append(" "); } @@ -1083,10 +1083,11 @@ static OUString getOSVersionString(const OUString& aNtVersionString, DWORD nBuil return result.makeStringAndClear(); } -OUString WinSalInstance::getOSVersion() +WinOSVersionInfo WinSalInstance::getWinOSVersionInfo() { - static const OUString result = [] + static const WinOSVersionInfo aResult = [] { + WinOSVersionInfo aVersion; // GetVersion(Ex) and VersionHelpers (based on VerifyVersionInfo) API are // subject to manifest-based behavior since Windows 8.1, so give wrong results. // Another approach would be to use NetWkstaGetInfo, but that has some small @@ -1094,7 +1095,6 @@ OUString WinSalInstance::getOSVersion() // poor network connections. // So go with a solution described at https://msdn.microsoft.com/en-us/library/ms724429 bool bHaveVerFromKernel32 = false; - OUString aNtVersion; if (HMODULE h_kernel32 = GetModuleHandleW(L"kernel32.dll")) { wchar_t szPath[MAX_PATH]; @@ -1113,8 +1113,8 @@ OUString WinSalInstance::getOSVersion() && dwBlockSz >= sizeof(VS_FIXEDFILEINFO)) { VS_FIXEDFILEINFO* vi1 = static_cast<VS_FIXEDFILEINFO*>(pBlock); - aNtVersion = (OUString::number(HIWORD(vi1->dwProductVersionMS)) + "." - + OUString::number(LOWORD(vi1->dwProductVersionMS))); + aVersion.m_nMajorVersion = HIWORD(vi1->dwProductVersionMS); + aVersion.m_nMinorVersion = LOWORD(vi1->dwProductVersionMS); bHaveVerFromKernel32 = true; } } @@ -1123,7 +1123,6 @@ OUString WinSalInstance::getOSVersion() } // Now use RtlGetVersion (which is not subject to deprecation for GetVersion(Ex) API) // to get build number and SP info - DWORD nBuildNumber = 0; if (HMODULE h_ntdll = GetModuleHandleW(L"ntdll.dll")) { if (auto RtlGetVersion @@ -1134,15 +1133,23 @@ OUString WinSalInstance::getOSVersion() if (STATUS_SUCCESS == RtlGetVersion(&vi2)) { if (!bHaveVerFromKernel32) // we failed above; let's hope this would be useful - aNtVersion = (OUString::number(vi2.dwMajorVersion) + "." - + OUString::number(vi2.dwMinorVersion)); - nBuildNumber = vi2.dwBuildNumber; + { + aVersion.m_nMajorVersion = vi2.dwMajorVersion; + aVersion.m_nMinorVersion = vi2.dwMinorVersion; + } + aVersion.m_nBuildNumber = vi2.dwBuildNumber; } } } - return getOSVersionString(aNtVersion, nBuildNumber); + return aVersion; }(); - return result; + return aResult; +} + +OUString WinSalInstance::getOSVersion() +{ + WinOSVersionInfo aInfo = getWinOSVersionInfo(); + return getOSVersionString(aInfo.m_nMajorVersion, aInfo.m_nMinorVersion, aInfo.m_nBuildNumber); } void WinSalInstance::BeforeAbort(const OUString&, bool) diff --git a/vcl/win/gdi/salnativewidgets-luna.cxx b/vcl/win/gdi/salnativewidgets-luna.cxx index 4daad8eadc9b..53f835fbdd8a 100644 --- a/vcl/win/gdi/salnativewidgets-luna.cxx +++ b/vcl/win/gdi/salnativewidgets-luna.cxx @@ -47,6 +47,7 @@ #include <win/salgdi.h> #include <win/saldata.hxx> #include <win/salframe.h> +#include <win/salinst.h> #include <win/scoped_gdi.hxx> #include <win/wingdiimpl.hxx> @@ -911,25 +912,27 @@ static bool ImplDrawNativeControl( HDC hDC, HTHEME hTheme, RECT rc, else iState = bChecked ? TS_CHECKED : TS_NORMAL; - if (bUseDarkMode && GetSalInstance()->getOSVersion().startsWith(u"Windows 11") - && (bChecked - || (nState & (ControlState::PRESSED) || (nState & ControlState::ROLLOVER)))) + if (bUseDarkMode && (bChecked || (nState & (ControlState::PRESSED) || (nState & ControlState::ROLLOVER)))) { - // tdf#152534 workaround bug with Windows 11 Dark theme using - // light blue as highlight color which gives insufficient - // contrast for hovered-over or pressed/checked toolbar buttons: - // manually draw background (using color a bit lighter than background - // for non-highlighted items) and draw a frame around it - ScopedHBRUSH aBgColorBrush(CreateSolidBrush(RGB(38, 38, 38))); - FillRect(hDC, &rc, aBgColorBrush.get()); - const Color aFrameColor = Application::GetSettings().GetStyleSettings().GetDisableColor(); - ScopedHBRUSH aFrameBrush(CreateSolidBrush( - RGB(aFrameColor.GetRed(), aFrameColor.GetGreen(), aFrameColor.GetBlue()))); - FrameRect(hDC, &rc, aFrameBrush.get()); - - DrawThemeText(hTheme, hDC, iPart, iState, o3tl::toW(aCaption.getStr()), -1, - DT_CENTER | DT_VCENTER | DT_SINGLELINE, 0, &rc); - return true; + const WinOSVersionInfo aVersion = WinSalInstance::getWinOSVersionInfo(); + if (aVersion.m_nMajorVersion == 10 && aVersion.m_nBuildNumber >= 22000) + { + // tdf#152534 workaround bug with Windows 11 Dark theme using + // light blue as highlight color which gives insufficient + // contrast for hovered-over or pressed/checked toolbar buttons: + // manually draw background (using color a bit lighter than background + // for non-highlighted items) and draw a frame around it + ScopedHBRUSH aBgColorBrush(CreateSolidBrush(RGB(38, 38, 38))); + FillRect(hDC, &rc, aBgColorBrush.get()); + const Color aFrameColor = Application::GetSettings().GetStyleSettings().GetDisableColor(); + ScopedHBRUSH aFrameBrush(CreateSolidBrush( + RGB(aFrameColor.GetRed(), aFrameColor.GetGreen(), aFrameColor.GetBlue()))); + FrameRect(hDC, &rc, aFrameBrush.get()); + + DrawThemeText(hTheme, hDC, iPart, iState, o3tl::toW(aCaption.getStr()), -1, + DT_CENTER | DT_VCENTER | DT_SINGLELINE, 0, &rc); + return true; + } } return ImplDrawTheme( hTheme, hDC, iPart, iState, rc, aCaption);
