vcl/inc/win/salframe.h      |    2 
 vcl/win/window/salframe.cxx |  110 +++++++++++++++++++++++---------------------
 2 files changed, 58 insertions(+), 54 deletions(-)

New commits:
commit 46f1585d5320164a55347aeaaed25f40a68abdcd
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Mon Jul 14 11:04:49 2025 +0200
Commit:     Noel Grandin <noelgran...@gmail.com>
CommitDate: Tue Jul 15 12:45:03 2025 +0200

    inline Init/ReleaseFrameGraphicsDC
    
    which makes it much more obvious which logic belongs where.
    
    Which fixes leaking WinSalGraphics objects on on error paths.
    
    Change-Id: Ib08c5b365e993d46fdc38a56e20e12c2833a1f85
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187851
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/vcl/inc/win/salframe.h b/vcl/inc/win/salframe.h
index 9d356a11bc45..c481cf49187d 100644
--- a/vcl/inc/win/salframe.h
+++ b/vcl/inc/win/salframe.h
@@ -92,8 +92,6 @@ public:
 
 private:
     void ImplSetParentFrame( HWND hNewParentWnd, bool bAsChild );
-    bool InitFrameGraphicsDC( WinSalGraphics *pGraphics, HDC hDC, HWND hWnd );
-    bool ReleaseFrameGraphicsDC( WinSalGraphics* pGraphics );
 
 public:
     WinSalFrame();
diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx
index f2b78ea3bf05..9fd8d2fd6f7b 100644
--- a/vcl/win/window/salframe.cxx
+++ b/vcl/win/window/salframe.cxx
@@ -937,19 +937,6 @@ void WinSalFrame::updateScreenNumber()
     }
 }
 
-bool WinSalFrame::ReleaseFrameGraphicsDC( WinSalGraphics* pGraphics )
-{
-    assert( pGraphics );
-    SalData* pSalData = GetSalData();
-    HDC hDC = pGraphics->getHDC();
-    if ( !hDC )
-        return false;
-    pGraphics->setHDC(nullptr);
-    SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC,
-        reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) );
-    return true;
-}
-
 WinSalFrame::~WinSalFrame()
 {
     SalData* pSalData = GetSalData();
@@ -967,7 +954,13 @@ WinSalFrame::~WinSalFrame()
     // destroy the thread SalGraphics
     if ( mpThreadGraphics )
     {
-        ReleaseFrameGraphicsDC( mpThreadGraphics );
+        HDC hDC = mpThreadGraphics->getHDC();
+        if (hDC)
+        {
+            mpThreadGraphics->setHDC(nullptr);
+            SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC,
+                reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) 
);
+        }
         delete mpThreadGraphics;
         mpThreadGraphics = nullptr;
     }
@@ -975,7 +968,9 @@ WinSalFrame::~WinSalFrame()
     // destroy the local SalGraphics
     if ( mpLocalGraphics )
     {
-        ReleaseFrameGraphicsDC( mpLocalGraphics );
+        HDC hDC = mpLocalGraphics->getHDC();
+        mpLocalGraphics->setHDC(nullptr);
+        ReleaseDC(mhWnd, hDC);
         delete mpLocalGraphics;
         mpLocalGraphics = nullptr;
     }
@@ -1005,61 +1000,58 @@ WinSalFrame::~WinSalFrame()
     }
 }
 
-bool WinSalFrame::InitFrameGraphicsDC( WinSalGraphics *pGraphics, HDC hDC, 
HWND hWnd )
-{
-    assert( pGraphics );
-    pGraphics->setHWND( hWnd );
-
-    HDC hCurrentDC = pGraphics->getHDC();
-    assert( !hCurrentDC || (hCurrentDC == hDC) );
-    if ( hCurrentDC )
-        return true;
-    pGraphics->setHDC( hDC );
-
-    if ( !hDC )
-        return false;
-    return true;
-}
-
 SalGraphics* WinSalFrame::AcquireGraphics()
 {
     if ( mbGraphicsAcquired || !mhWnd )
         return nullptr;
 
     SalData* pSalData = GetSalData();
-    WinSalGraphics* pGraphics;
-    HDC hDC;
 
     // Other threads get an own DC, because Windows modify in the
     // other case our DC (changing clip region), when they send a
     // WM_ERASEBACKGROUND message
     if ( !pSalData->mpInstance->IsMainThread() )
     {
+        HDC hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>(SendMessageW( 
pSalData->mpInstance->mhComWnd,
+                                    SAL_MSG_GETCACHEDDC, 
reinterpret_cast<WPARAM>(mhWnd), 0 )));
+        if ( !hDC )
+            return nullptr;
+
         if ( !mpThreadGraphics )
             mpThreadGraphics = new WinSalGraphics(WinSalGraphics::WINDOW, 
true, mhWnd, this);
-        pGraphics = mpThreadGraphics;
-        assert( !pGraphics->getHDC() );
-        hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>(SendMessageW( 
pSalData->mpInstance->mhComWnd,
-                                    SAL_MSG_GETCACHEDDC, 
reinterpret_cast<WPARAM>(mhWnd), 0 )));
+
+        assert(!mpThreadGraphics->getHDC() && "this is supposed to be zeroed 
when ReleaseGraphics is called");
+        mpThreadGraphics->setHDC( hDC );
+
+        mbGraphicsAcquired = true;
+        return mpThreadGraphics;
     }
     else
     {
         if ( !mpLocalGraphics )
+        {
+            HDC hDC = GetDC( mhWnd );
+            if ( !hDC )
+                return nullptr;
             mpLocalGraphics = new WinSalGraphics(WinSalGraphics::WINDOW, true, 
mhWnd, this);
-        pGraphics = mpLocalGraphics;
-        hDC = pGraphics->getHDC();
-        if ( !hDC )
-            hDC = GetDC( mhWnd );
+            mpLocalGraphics->setHDC( hDC );
+        }
+        mbGraphicsAcquired = true;
+        return mpLocalGraphics;
     }
-
-    mbGraphicsAcquired = InitFrameGraphicsDC( pGraphics, hDC, mhWnd );
-    return mbGraphicsAcquired ? pGraphics : nullptr;
 }
 
 void WinSalFrame::ReleaseGraphics( SalGraphics* pGraphics )
 {
     if ( mpThreadGraphics == pGraphics )
-        ReleaseFrameGraphicsDC( mpThreadGraphics );
+    {
+        SalData* pSalData = GetSalData();
+        HDC hDC = mpThreadGraphics->getHDC();
+        assert(hDC);
+        mpThreadGraphics->setHDC(nullptr);
+        SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC,
+            reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) );
+    }
     mbGraphicsAcquired = false;
 }
 
@@ -1496,20 +1488,28 @@ void WinSalFrame::ImplSetParentFrame( HWND 
hNewParentWnd, bool bAsChild )
     {
         // save current gdi objects before hdc is gone
         HDC hDC = mpThreadGraphics->getHDC();
-        if ( hDC )
+        if (hDC)
         {
             hFont  = static_cast<HFONT>(GetCurrentObject( hDC, OBJ_FONT ));
             hPen   = static_cast<HPEN>(GetCurrentObject( hDC, OBJ_PEN ));
             hBrush = static_cast<HBRUSH>(GetCurrentObject( hDC, OBJ_BRUSH ));
-        }
 
-        bHadThreadGraphics = ReleaseFrameGraphicsDC( mpThreadGraphics );
-        assert( (bHadThreadGraphics && hDC) || (!bHadThreadGraphics && !hDC) );
+            mpThreadGraphics->setHDC(nullptr);
+            SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC,
+                reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) 
);
+
+            bHadThreadGraphics = true;
+        }
     }
 
     // release the local DC
     if ( mpLocalGraphics )
-        bHadLocalGraphics = ReleaseFrameGraphicsDC( mpLocalGraphics );
+    {
+        bHadLocalGraphics = true;
+        HDC hDC = mpLocalGraphics->getHDC();
+        mpLocalGraphics->setHDC(nullptr);
+        ReleaseDC(mhWnd, hDC);
+    }
 
     // create a new hwnd with the same styles
     HWND hWndParent = hNewParentWnd;
@@ -1524,12 +1524,13 @@ void WinSalFrame::ImplSetParentFrame( HWND 
hNewParentWnd, bool bAsChild )
     // re-create thread DC
     if( bHadThreadGraphics )
     {
+        mpThreadGraphics->setHWND( hWnd );
         HDC hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>(
                     SendMessageW( pSalData->mpInstance->mhComWnd,
                         SAL_MSG_GETCACHEDDC, reinterpret_cast<WPARAM>(hWnd), 0 
)));
-        InitFrameGraphicsDC( mpThreadGraphics, hDC, hWnd );
         if ( hDC )
         {
+            mpThreadGraphics->setHDC( hDC );
             // re-select saved gdi objects
             if( hFont )
                 SelectObject( hDC, hFont );
@@ -1542,7 +1543,12 @@ void WinSalFrame::ImplSetParentFrame( HWND 
hNewParentWnd, bool bAsChild )
 
     // re-create local DC
     if( bHadLocalGraphics )
-        InitFrameGraphicsDC( mpLocalGraphics, GetDC( hWnd ), hWnd );
+    {
+        mpLocalGraphics->setHWND( hWnd );
+        HDC hDC = GetDC( hWnd );
+        if (hDC)
+            mpLocalGraphics->setHDC( hDC );
+    }
 
     // TODO: add SetParent() call for SalObjects
     SAL_WARN_IF( !systemChildren.empty(), "vcl", "WinSalFrame::SetParent() 
parent of living system child window will be destroyed!");

Reply via email to