vcl/inc/win/salinst.h | 9 +++++++++ vcl/win/app/salinst.cxx | 28 +++++++++++++++++++++++----- vcl/win/window/salframe.cxx | 32 ++++++++++++++++---------------- 3 files changed, 48 insertions(+), 21 deletions(-)
New commits: commit 23afeaedf4d4a03943338fc39ae41f5c423e5997 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Thu Sep 18 21:04:00 2025 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Thu Sep 18 22:34:27 2025 +0200 tdf#168431: Release solar mutex when sending window message to main thread It started after commit 1e2e51607a163021ef1fb1fb0d217266bd448173 for some reason, but the problem is, that the caller code from some thread holds the solar mutex, and the code that handles the message in main VCL thread tries to lock solar mutex; and that didn't change. This change introduces some methods in WinSalInstance, that wrap calls to SendMessageW, and release solar mutex if the functions are not in the main thread. Change-Id: Iac8690acbd306273c92534c6d319cbdf4b799860 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/191147 Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Tested-by: Jenkins diff --git a/vcl/inc/win/salinst.h b/vcl/inc/win/salinst.h index 0a0f133df89e..398efdc1888d 100644 --- a/vcl/inc/win/salinst.h +++ b/vcl/inc/win/salinst.h @@ -87,6 +87,15 @@ public: ImplCreateDragSource(const SystemEnvData& rSysEnv) override; virtual css::uno::Reference<css::datatransfer::dnd::XDropTarget> ImplCreateDropTarget(const SystemEnvData& rSysEnv) override; + + // Sends a message to a window, making sure to unlock solar mutex if necessary + static LRESULT SendWndMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam); + // Sends a message to mhComWnd, making sure to unlock solar mutex if necessary + LRESULT SendComWndMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const; + +private: + // Sends a message to a window, making sure to unlock solar mutex if necessary + LRESULT SendWndMessage_impl(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) const; }; SalFrame* ImplSalCreateFrame( WinSalInstance* pInst, HWND hWndParent, SalFrameStyleFlags nSalFrameStyle ); diff --git a/vcl/win/app/salinst.cxx b/vcl/win/app/salinst.cxx index aa36856ec78e..aa0cbfd12bb2 100644 --- a/vcl/win/app/salinst.cxx +++ b/vcl/win/app/salinst.cxx @@ -763,10 +763,28 @@ bool WinSalInstance::AnyInput( VclInputFlags nType ) return false; } +LRESULT WinSalInstance::SendWndMessage_impl(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) const +{ + std::optional<SolarMutexReleaser> oReleaser; + if (!IsMainThread()) + oReleaser.emplace(); + return SendMessageW(hWnd, Msg, wParam, lParam); +} + +LRESULT WinSalInstance::SendWndMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + return GetSalData()->mpInstance->SendWndMessage_impl(hWnd, Msg, wParam, lParam); +} + +LRESULT WinSalInstance::SendComWndMessage(UINT Msg, WPARAM wParam, LPARAM lParam) const +{ + return SendWndMessage_impl(mhComWnd, Msg, wParam, lParam); +} + SalFrame* WinSalInstance::CreateChildFrame( SystemParentData* pSystemParentData, SalFrameStyleFlags nSalFrameStyle ) { // to switch to Main-Thread - return reinterpret_cast<SalFrame*>(static_cast<sal_IntPtr>(SendMessageW( mhComWnd, SAL_MSG_CREATEFRAME, static_cast<WPARAM>(nSalFrameStyle), reinterpret_cast<LPARAM>(pSystemParentData->hWnd) ))); + return reinterpret_cast<SalFrame*>(static_cast<sal_IntPtr>(SendComWndMessage( SAL_MSG_CREATEFRAME, static_cast<WPARAM>(nSalFrameStyle), reinterpret_cast<LPARAM>(pSystemParentData->hWnd) ))); } SalFrame* WinSalInstance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nSalFrameStyle ) @@ -777,13 +795,13 @@ SalFrame* WinSalInstance::CreateFrame( SalFrame* pParent, SalFrameStyleFlags nSa hWndParent = static_cast<WinSalFrame*>(pParent)->mhWnd; else hWndParent = nullptr; - return reinterpret_cast<SalFrame*>(static_cast<sal_IntPtr>(SendMessageW( mhComWnd, SAL_MSG_CREATEFRAME, static_cast<WPARAM>(nSalFrameStyle), reinterpret_cast<LPARAM>(hWndParent) ))); + return reinterpret_cast<SalFrame*>(static_cast<sal_IntPtr>(SendComWndMessage( SAL_MSG_CREATEFRAME, static_cast<WPARAM>(nSalFrameStyle), reinterpret_cast<LPARAM>(hWndParent) ))); } void WinSalInstance::DestroyFrame( SalFrame* pFrame ) { OpenGLContext::prepareForYield(); - SendMessageW( mhComWnd, SAL_MSG_DESTROYFRAME, 0, reinterpret_cast<LPARAM>(pFrame) ); + SendComWndMessage(SAL_MSG_DESTROYFRAME, 0, reinterpret_cast<LPARAM>(pFrame)); } SalObject* WinSalInstance::CreateObject( SalFrame* pParent, @@ -791,12 +809,12 @@ SalObject* WinSalInstance::CreateObject( SalFrame* pParent, bool /*bShow*/ ) { // to switch to Main-Thread - return reinterpret_cast<SalObject*>(static_cast<sal_IntPtr>(SendMessageW( mhComWnd, SAL_MSG_CREATEOBJECT, 0, reinterpret_cast<LPARAM>(static_cast<WinSalFrame*>(pParent)) ))); + return reinterpret_cast<SalObject*>(static_cast<sal_IntPtr>(SendComWndMessage( SAL_MSG_CREATEOBJECT, 0, reinterpret_cast<LPARAM>(static_cast<WinSalFrame*>(pParent)) ))); } void WinSalInstance::DestroyObject( SalObject* pObject ) { - SendMessageW( mhComWnd, SAL_MSG_DESTROYOBJECT, 0, reinterpret_cast<LPARAM>(pObject) ); + SendComWndMessage(SAL_MSG_DESTROYOBJECT, 0, reinterpret_cast<LPARAM>(pObject)); } /** Add a file to the system shells recent document list if there is any. diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx index e5a3a38bb4fb..76572eb4fa08 100644 --- a/vcl/win/window/salframe.cxx +++ b/vcl/win/window/salframe.cxx @@ -958,7 +958,7 @@ WinSalFrame::~WinSalFrame() if (hDC) { mpThreadGraphics->setHDC(nullptr); - SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC, + pSalData->mpInstance->SendComWndMessage(SAL_MSG_RELEASEDC, reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) ); } delete mpThreadGraphics; @@ -1012,7 +1012,7 @@ SalGraphics* WinSalFrame::AcquireGraphics() // WM_ERASEBACKGROUND message if ( !pSalData->mpInstance->IsMainThread() ) { - HDC hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>(SendMessageW( pSalData->mpInstance->mhComWnd, + HDC hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>(pSalData->mpInstance->SendComWndMessage( SAL_MSG_GETCACHEDDC, reinterpret_cast<WPARAM>(mhWnd), 0 ))); if ( !hDC ) return nullptr; @@ -1049,7 +1049,7 @@ void WinSalFrame::ReleaseGraphics( SalGraphics* pGraphics ) HDC hDC = mpThreadGraphics->getHDC(); assert(hDC); mpThreadGraphics->setHDC(nullptr); - SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC, + pSalData->mpInstance->SendComWndMessage(SAL_MSG_RELEASEDC, reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) ); } mbGraphicsAcquired = false; @@ -1068,7 +1068,7 @@ void WinSalFrame::SetTitle( const OUString& rTitle ) { static_assert( sizeof( WCHAR ) == sizeof( sal_Unicode ), "must be the same size" ); - SetWindowTextW( mhWnd, o3tl::toW(rTitle.getStr()) ); + WinSalInstance::SendWndMessage(mhWnd, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(rTitle.getStr())); } void WinSalFrame::SetIcon( sal_uInt16 nIcon ) @@ -1087,8 +1087,8 @@ void WinSalFrame::SetIcon( sal_uInt16 nIcon ) SAL_WARN_IF( !hIcon , "vcl", "WinSalFrame::SetIcon(): Could not load large icon !" ); SAL_WARN_IF( !hSmIcon , "vcl", "WinSalFrame::SetIcon(): Could not load small icon !" ); - SendMessageW( mhWnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(hIcon) ); - SendMessageW( mhWnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(hSmIcon) ); + WinSalInstance::SendWndMessage(mhWnd, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(hIcon)); + WinSalInstance::SendWndMessage(mhWnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(hSmIcon)); } void WinSalFrame::SetMenu( SalMenu* pSalMenu ) @@ -1495,7 +1495,7 @@ void WinSalFrame::ImplSetParentFrame( HWND hNewParentWnd, bool bAsChild ) hBrush = static_cast<HBRUSH>(GetCurrentObject( hDC, OBJ_BRUSH )); mpThreadGraphics->setHDC(nullptr); - SendMessageW( pSalData->mpInstance->mhComWnd, SAL_MSG_RELEASEDC, + pSalData->mpInstance->SendComWndMessage(SAL_MSG_RELEASEDC, reinterpret_cast<WPARAM>(mhWnd), reinterpret_cast<LPARAM>(hDC) ); bHadThreadGraphics = true; @@ -1514,7 +1514,7 @@ void WinSalFrame::ImplSetParentFrame( HWND hNewParentWnd, bool bAsChild ) // create a new hwnd with the same styles HWND hWndParent = hNewParentWnd; // forward to main thread - HWND hWnd = reinterpret_cast<HWND>(static_cast<sal_IntPtr>(SendMessageW( pSalData->mpInstance->mhComWnd, + HWND hWnd = reinterpret_cast<HWND>(static_cast<sal_IntPtr>(pSalData->mpInstance->SendComWndMessage( bAsChild ? SAL_MSG_RECREATECHILDHWND : SAL_MSG_RECREATEHWND, reinterpret_cast<WPARAM>(hWndParent), reinterpret_cast<LPARAM>(mhWnd) ))); @@ -1526,7 +1526,7 @@ void WinSalFrame::ImplSetParentFrame( HWND hNewParentWnd, bool bAsChild ) { mpThreadGraphics->setHWND( hWnd ); HDC hDC = reinterpret_cast<HDC>(static_cast<sal_IntPtr>( - SendMessageW( pSalData->mpInstance->mhComWnd, + pSalData->mpInstance->SendComWndMessage( SAL_MSG_GETCACHEDDC, reinterpret_cast<WPARAM>(hWnd), 0 ))); if ( hDC ) { @@ -1561,7 +1561,7 @@ void WinSalFrame::ImplSetParentFrame( HWND hNewParentWnd, bool bAsChild ) systemChildren.clear(); // Now destroy original HWND in the thread where it was created. - SendMessageW( GetSalData()->mpInstance->mhComWnd, + pSalData->mpInstance->SendComWndMessage( SAL_MSG_DESTROYHWND, WPARAM(0), reinterpret_cast<LPARAM>(hWndOld)); } @@ -2163,7 +2163,7 @@ void WinSalFrame::CaptureMouse( bool bCapture ) nMsg = SAL_MSG_CAPTUREMOUSE; else nMsg = SAL_MSG_RELEASEMOUSE; - SendMessageW( mhWnd, nMsg, 0, 0 ); + WinSalInstance::SendWndMessage(mhWnd, nMsg, 0, 0); } void WinSalFrame::SetPointerPos( tools::Long nX, tools::Long nY ) @@ -2253,7 +2253,7 @@ static void ImplSalFrameSetInputContext( HWND hWnd, const SalInputContext* pCont void WinSalFrame::SetInputContext( SalInputContext* pContext ) { // Must be called in the main thread! - SendMessageW( mhWnd, SAL_MSG_SETINPUTCONTEXT, 0, reinterpret_cast<LPARAM>(pContext) ); + WinSalInstance::SendWndMessage(mhWnd, SAL_MSG_SETINPUTCONTEXT, 0, reinterpret_cast<LPARAM>(pContext)); } static void ImplSalFrameEndExtTextInput( HWND hWnd, EndExtTextInputFlags nFlags ) @@ -2275,7 +2275,7 @@ static void ImplSalFrameEndExtTextInput( HWND hWnd, EndExtTextInputFlags nFlags void WinSalFrame::EndExtTextInput( EndExtTextInputFlags nFlags ) { // Must be called in the main thread! - SendMessageW( mhWnd, SAL_MSG_ENDEXTTEXTINPUT, static_cast<WPARAM>(nFlags), 0 ); + WinSalInstance::SendWndMessage(mhWnd, SAL_MSG_ENDEXTTEXTINPUT, static_cast<WPARAM>(nFlags), 0); } static void ImplGetKeyNameText(UINT lParam, OUStringBuffer& rBuf, const char* pReplace) @@ -3300,7 +3300,7 @@ static bool ImplHandleMouseMsg( HWND hWnd, UINT nMsg, SalData* pSalData = GetSalData(); // Test for MouseLeave if ( pSalData->mhWantLeaveMsg && (pSalData->mhWantLeaveMsg != hWnd) ) - SendMessageW( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos() ); + WinSalInstance::SendWndMessage(pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, GetMessagePos()); pSalData->mhWantLeaveMsg = hWnd; aMouseEvt.mnButton = 0; @@ -5697,7 +5697,7 @@ void SalTestMouseLeave() cachedPoint = aPt; if ( pSalData->mhWantLeaveMsg != WindowFromPoint( aPt ) ) - SendMessageW( pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM( aPt.x, aPt.y ) ); + WinSalInstance::SendWndMessage(pSalData->mhWantLeaveMsg, SAL_MSG_MOUSELEAVE, 0, MAKELPARAM(aPt.x, aPt.y)); } } @@ -5722,7 +5722,7 @@ static bool ImplSalWheelMousePos( HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lP if ( hWheelWnd && (hWheelWnd != hWnd) && (hWheelWnd != ::GetFocus()) && IsWindowEnabled( hWheelWnd ) ) { - rResult = SendMessageW( hWheelWnd, nMsg, wParam, lParam ); + rResult = WinSalInstance::SendWndMessage(hWheelWnd, nMsg, wParam, lParam); return false; }