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);

Reply via email to