cui/source/tabpages/numpages.cxx | 4 ++-- include/svx/dialog/ThemeColorsPaneBase.hxx | 2 +- include/svx/svxbmpnumiconview.hxx | 6 +++--- sd/source/ui/sidebar/LayoutMenu.cxx | 4 ++-- sd/source/ui/sidebar/LayoutMenu.hxx | 2 +- sd/source/ui/sidebar/MasterPagesSelector.cxx | 8 ++++---- sd/source/ui/sidebar/MasterPagesSelector.hxx | 2 +- svx/source/dialog/ThemeColorsPaneBase.cxx | 7 ++++--- svx/source/dialog/svxbmpnumiconview.cxx | 22 +++++++++++----------- svx/source/tbxctrls/bulletsnumbering.cxx | 4 ++-- svx/source/tbxctrls/fontworkgallery.cxx | 2 ++ svx/source/tbxctrls/tbcontrl.cxx | 18 +++++++++--------- 12 files changed, 42 insertions(+), 39 deletions(-)
New commits: commit e9392c0c86fcf373e00ede92f8ceeee2c7efd233 Author: Andras Timar <[email protected]> AuthorDate: Sat Feb 21 08:41:42 2026 +0100 Commit: Mike Kaganski <[email protected]> CommitDate: Sat Feb 21 11:25:14 2026 +0100 fix VirtualDevice GDI handle leaks across IconView callers Follow-up to c5f6227d8e71 ("use ScopedVclPtr to avoid leaks"). Change factory functions that create VirtualDevices for IconView previews to return ScopedVclPtr<VirtualDevice> instead of plain VclPtr, so callers automatically dispose the GDI resources when the ScopedVclPtr goes out of scope. Affected APIs: - SvxBmpNumIconView::CreatePreviewFromUserDraw - SvxBmpNumIconView::CreateCustomBulletPreview - SvxBmpNumIconView::CreateBitmapBulletPreview - ThemeColorsPaneBase::CreateColorSetPreview - LineListBox::GetVirtualDevice - SvxFrameWindow_Impl::GetVirtualDevice - LayoutMenu::GetVirtualDevice - MasterPagesSelector::GetVirtualDevice For FontWorkGalleryDialog, where VDs are stored in a std::vector (incompatible with non-copyable ScopedVclPtr), add explicit disposal in the destructor instead. Change-Id: I5b3a4c94f6c4781c8eafa4d7a32696ec9fbb2dd3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/199923 Tested-by: Jenkins CollaboraOffice <[email protected]> Reviewed-by: Mike Kaganski <[email protected]> diff --git a/cui/source/tabpages/numpages.cxx b/cui/source/tabpages/numpages.cxx index ec43d7d21411..77ac59eaf3b5 100644 --- a/cui/source/tabpages/numpages.cxx +++ b/cui/source/tabpages/numpages.cxx @@ -881,7 +881,7 @@ SvxBitmapPickTabPage::SvxBitmapPickTabPage(weld::Container* pPage, weld::DialogC size_t i = 0; for (auto & grfName : aGrfNames) { - VclPtr<VirtualDevice> pVDev = SvxBmpNumIconView::CreateBitmapBulletPreview(i); + auto pVDev = SvxBmpNumIconView::CreateBitmapBulletPreview(i); INetURLObject aObj(grfName); if (aObj.GetProtocol() == INetProtocol::File) @@ -1147,7 +1147,7 @@ IMPL_LINK_NOARG(SvxBitmapPickTabPage, ClickAddBrowseHdl_Impl, weld::Button&, voi size_t i = 0; for (auto & grfName : aGrfNames) { - VclPtr<VirtualDevice> pVDev = SvxBmpNumIconView::CreateBitmapBulletPreview(i); + auto pVDev = SvxBmpNumIconView::CreateBitmapBulletPreview(i); INetURLObject aObj(grfName); if (aObj.GetProtocol() == INetProtocol::File) diff --git a/include/svx/dialog/ThemeColorsPaneBase.hxx b/include/svx/dialog/ThemeColorsPaneBase.hxx index 22fe401279c0..e3f00943fe24 100644 --- a/include/svx/dialog/ThemeColorsPaneBase.hxx +++ b/include/svx/dialog/ThemeColorsPaneBase.hxx @@ -33,7 +33,7 @@ protected: std::shared_ptr<model::ColorSet> mpCurrentColorSet; void initColorSets(model::Theme* pTheme = nullptr); - static VclPtr<VirtualDevice> CreateColorSetPreview(const model::ColorSet& rColorSet); + static ScopedVclPtr<VirtualDevice> CreateColorSetPreview(const model::ColorSet& rColorSet); public: explicit ThemeColorsPaneBase(std::unique_ptr<weld::IconView> xIconView); diff --git a/include/svx/svxbmpnumiconview.hxx b/include/svx/svxbmpnumiconview.hxx index 44c6cc583cda..fa4838ebf133 100644 --- a/include/svx/svxbmpnumiconview.hxx +++ b/include/svx/svxbmpnumiconview.hxx @@ -40,7 +40,7 @@ public: Reference<XNumberingFormatter> const& xFormatter = nullptr, const Locale& rLocale = Locale()); - static VclPtr<VirtualDevice> CreatePreviewFromUserDraw( + static ScopedVclPtr<VirtualDevice> CreatePreviewFromUserDraw( NumberingPageType ePageType, sal_Int32 nIndex, Size previewSize, @@ -50,7 +50,7 @@ public: const Locale& rLocale = Locale(), const std::vector<std::pair<OUString, OUString>>& rCustomBullets = std::vector<std::pair<OUString, OUString>>()); - static VclPtr<VirtualDevice> CreateCustomBulletPreview(const OUString& rBulletChar, const OUString& rFontName); + static ScopedVclPtr<VirtualDevice> CreateCustomBulletPreview(const OUString& rBulletChar, const OUString& rFontName); static OUString GetNumberingDescription(NumberingPageType ePageType, sal_Int32 nIndex); static void SetNumberingSettings( @@ -69,7 +69,7 @@ public: const Locale& rLocale, std::vector<std::pair<OUString, OUString>> maCustomBullets = std::vector<std::pair<OUString, OUString>>()); - static VclPtr<VirtualDevice> CreateBitmapBulletPreview(sal_uInt32 nGalleryIndex); + static ScopedVclPtr<VirtualDevice> CreateBitmapBulletPreview(sal_uInt32 nGalleryIndex); static void PopulateBitmapIconView(weld::IconView* pIconView); }; diff --git a/sd/source/ui/sidebar/LayoutMenu.cxx b/sd/source/ui/sidebar/LayoutMenu.cxx index 7a62f0f41099..b8e736d29508 100644 --- a/sd/source/ui/sidebar/LayoutMenu.cxx +++ b/sd/source/ui/sidebar/LayoutMenu.cxx @@ -438,7 +438,7 @@ SfxRequest LayoutMenu::CreateRequest ( return aRequest; } -VclPtr<VirtualDevice> LayoutMenu::GetVirtualDevice(Image pImage) +ScopedVclPtr<VirtualDevice> LayoutMenu::GetVirtualDevice(Image pImage) { BitmapEx aPreviewBitmap = pImage.GetBitmapEx(); VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create(); @@ -511,7 +511,7 @@ void LayoutMenu::Fill() if (aImg.GetSizePixel().Width() > 0) { OUString sId = OUString::number(static_cast<int>(elem.maAutoLayout)); - VclPtr<VirtualDevice> aVDev = GetVirtualDevice(aImg); + auto aVDev = GetVirtualDevice(aImg); OUString sLayoutName = SdResId(elem.mpStrResId); if (!mxLayoutIconView->get_id(id).isEmpty()) { diff --git a/sd/source/ui/sidebar/LayoutMenu.hxx b/sd/source/ui/sidebar/LayoutMenu.hxx index d17ee1f6d2b7..8d914d1d9dbc 100644 --- a/sd/source/ui/sidebar/LayoutMenu.hxx +++ b/sd/source/ui/sidebar/LayoutMenu.hxx @@ -173,7 +173,7 @@ private: DECL_LINK(MenuSelectAsyncHdl, void*, void); DECL_LINK(OnPopupEnd, const OUString&, void); - static VclPtr<VirtualDevice> GetVirtualDevice(Image pPreview); + static ScopedVclPtr<VirtualDevice> GetVirtualDevice(Image pPreview); void HandleMenuSelect(std::u16string_view rIdent); TranslateId GetStringResourceIdForLayout(AutoLayout aLayout) const; diff --git a/sd/source/ui/sidebar/MasterPagesSelector.cxx b/sd/source/ui/sidebar/MasterPagesSelector.cxx index 166deb192780..0d3d8470d361 100644 --- a/sd/source/ui/sidebar/MasterPagesSelector.cxx +++ b/sd/source/ui/sidebar/MasterPagesSelector.cxx @@ -362,7 +362,7 @@ void MasterPagesSelector::NotifyContainerChangeEvent (const MasterPageContainerC Image aPreview(mpContainer->GetPreviewForToken(rEvent.maChildToken)); if (aPreview.GetSizePixel().Width() > 0) { - VclPtr<VirtualDevice> aDev = GetVirtualDevice(aPreview); + auto aDev = GetVirtualDevice(aPreview); mxPreviewIconView->set_image(nIndex, aDev); } } @@ -419,7 +419,7 @@ void MasterPagesSelector::SetItem ( if (aPreview.GetSizePixel().Width() > 0) { - VclPtr<VirtualDevice> aVDev = GetVirtualDevice(aPreview); + auto aVDev = GetVirtualDevice(aPreview); if (!mxPreviewIconView->get_id(nIndex).isEmpty()) { mxPreviewIconView->set_image(nIndex, aVDev); @@ -493,7 +493,7 @@ void MasterPagesSelector::InvalidatePreview (const SdPage* pPage) } } -VclPtr<VirtualDevice> MasterPagesSelector::GetVirtualDevice(Image pImage) +ScopedVclPtr<VirtualDevice> MasterPagesSelector::GetVirtualDevice(Image pImage) { BitmapEx aPreviewBitmap = pImage.GetBitmapEx(); VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create(); @@ -520,7 +520,7 @@ void MasterPagesSelector::UpdateAllPreviews() Image aPreview(mpContainer->GetPreviewForToken(aToken)); if (aPreview.GetSizePixel().Width() > 0) { - VclPtr<VirtualDevice> pVDev = GetVirtualDevice(aPreview); + auto pVDev = GetVirtualDevice(aPreview); mxPreviewIconView->set_image(aIndex, pVDev); } else if (mpContainer->GetPreviewState(aToken) == MasterPageContainer::PS_CREATABLE) diff --git a/sd/source/ui/sidebar/MasterPagesSelector.hxx b/sd/source/ui/sidebar/MasterPagesSelector.hxx index 89584ad202fa..83d4a4cbb743 100644 --- a/sd/source/ui/sidebar/MasterPagesSelector.hxx +++ b/sd/source/ui/sidebar/MasterPagesSelector.hxx @@ -197,7 +197,7 @@ private: sal_uInt16 nIndex, MasterPageContainer::Token aToken); - static VclPtr<VirtualDevice> GetVirtualDevice(Image pPreview); + static ScopedVclPtr<VirtualDevice> GetVirtualDevice(Image pPreview); }; } // end of namespace sd::sidebar diff --git a/svx/source/dialog/ThemeColorsPaneBase.cxx b/svx/source/dialog/ThemeColorsPaneBase.cxx index d337e810e5e8..38554d25ffc2 100644 --- a/svx/source/dialog/ThemeColorsPaneBase.cxx +++ b/svx/source/dialog/ThemeColorsPaneBase.cxx @@ -47,11 +47,11 @@ void ThemeColorsPaneBase::initColorSets(model::Theme* pTheme) for (size_t i = 0; i < maColorSets.size(); ++i) { auto const& rColorSet = maColorSets[i]; - VclPtr<VirtualDevice> pVirDev = CreateColorSetPreview(rColorSet); + auto pVirDev = CreateColorSetPreview(rColorSet); OUString sId = OUString::number(i); OUString sName = rColorSet.getName(); - mxIconViewThemeColors->insert(-1, &sName, &sId, pVirDev, nullptr); + mxIconViewThemeColors->insert(-1, &sName, &sId, pVirDev.get(), nullptr); } if (!maColorSets.empty()) @@ -62,7 +62,8 @@ void ThemeColorsPaneBase::initColorSets(model::Theme* pTheme) } } -VclPtr<VirtualDevice> ThemeColorsPaneBase::CreateColorSetPreview(const model::ColorSet& rColorSet) +ScopedVclPtr<VirtualDevice> +ThemeColorsPaneBase::CreateColorSetPreview(const model::ColorSet& rColorSet) { VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create(); const Size aSize(100, 50); diff --git a/svx/source/dialog/svxbmpnumiconview.cxx b/svx/source/dialog/svxbmpnumiconview.cxx index ae8a48655e60..04a8c98aeea0 100644 --- a/svx/source/dialog/svxbmpnumiconview.cxx +++ b/svx/source/dialog/svxbmpnumiconview.cxx @@ -98,15 +98,15 @@ void SvxBmpNumIconView::PopulateIconView( for (sal_Int32 i = 0; i < std::min(aBulletSymbols.getLength(), sal_Int32(8)); ++i) { - VclPtr<VirtualDevice> pVDev = CreatePreviewFromUserDraw(NumberingPageType::BULLET, i, previewSize, rNumSettings, rOutlineSettings, xFormatter, rLocale); + auto pVDev = CreatePreviewFromUserDraw(NumberingPageType::BULLET, i, previewSize, rNumSettings, rOutlineSettings, xFormatter, rLocale); OUString sId = OUString::number(i); OUString sText = GetNumberingDescription(ePageType, i); - pIconView->insert(-1, &sText, &sId, pVDev, nullptr); + pIconView->insert(-1, &sText, &sId, pVDev.get(), nullptr); } } } -VclPtr<VirtualDevice> SvxBmpNumIconView::CreatePreviewFromUserDraw( +ScopedVclPtr<VirtualDevice> SvxBmpNumIconView::CreatePreviewFromUserDraw( NumberingPageType ePageType, sal_Int32 nIndex, Size previewSize, @@ -421,7 +421,7 @@ VclPtr<VirtualDevice> SvxBmpNumIconView::CreatePreviewFromUserDraw( return pVDev; } -VclPtr<VirtualDevice> SvxBmpNumIconView::CreateCustomBulletPreview(const OUString& rBulletChar, const OUString& rFontName) +ScopedVclPtr<VirtualDevice> SvxBmpNumIconView::CreateCustomBulletPreview(const OUString& rBulletChar, const OUString& rFontName) { VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create(); Size aSize(80, 100); @@ -505,13 +505,13 @@ void SvxBmpNumIconView::SetNumberingSettings( for (sal_Int32 i = 0; i < aNum.getLength(); ++i) { - VclPtr<VirtualDevice> pVDev = CreatePreviewFromUserDraw( + auto pVDev = CreatePreviewFromUserDraw( NumberingPageType::SINGLENUM, i, previewSize, aNum, Sequence<Reference<XIndexAccess>>(), xFormat, rLocale, maCustomBullets); OUString sId = OUString::number(i); OUString sText = GetNumberingDescription(NumberingPageType::SINGLENUM, i); - mxIconView->insert(-1, &sText, &sId, pVDev, nullptr); + mxIconView->insert(-1, &sText, &sId, pVDev.get(), nullptr); } } @@ -527,17 +527,17 @@ void SvxBmpNumIconView::SetOutlineNumberingSettings( for (sal_Int32 i = 0; i < rOutline.getLength(); ++i) { - VclPtr<VirtualDevice> pVDev = CreatePreviewFromUserDraw( + auto pVDev = CreatePreviewFromUserDraw( NumberingPageType::OUTLINE, i, previewSize, Sequence<Sequence<PropertyValue>>(), rOutline, xFormat, rLocale, maCustomBullets); OUString sId = OUString::number(i); OUString sText = GetNumberingDescription(NumberingPageType::OUTLINE, i); - mxIconView->insert(-1, &sText, &sId, pVDev, nullptr); + mxIconView->insert(-1, &sText, &sId, pVDev.get(), nullptr); } } -VclPtr<VirtualDevice> SvxBmpNumIconView::CreateBitmapBulletPreview(sal_uInt32 nGalleryIndex) +ScopedVclPtr<VirtualDevice> SvxBmpNumIconView::CreateBitmapBulletPreview(sal_uInt32 nGalleryIndex) { VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create(); Size aRectSize(150, 200); @@ -599,9 +599,9 @@ void SvxBmpNumIconView::PopulateBitmapIconView(weld::IconView* pIconView) for (sal_uInt32 i = 0; i < std::min(nCount, sal_uInt32(8)); ++i) { - VclPtr<VirtualDevice> pVDev = CreateBitmapBulletPreview(i); + auto pVDev = CreateBitmapBulletPreview(i); OUString sId = OUString::number(i); - pIconView->insert(-1, nullptr, &sId, pVDev, nullptr); + pIconView->insert(-1, nullptr, &sId, pVDev.get(), nullptr); } } diff --git a/svx/source/tbxctrls/bulletsnumbering.cxx b/svx/source/tbxctrls/bulletsnumbering.cxx index 9e16d687a581..fc8beb150d33 100644 --- a/svx/source/tbxctrls/bulletsnumbering.cxx +++ b/svx/source/tbxctrls/bulletsnumbering.cxx @@ -183,9 +183,9 @@ void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent& rEvent if (lcl_BulletIsDefault(sBullet, sFont)) continue; - VclPtr<VirtualDevice> pVDev = SvxBmpNumIconView::CreateCustomBulletPreview(sBullet, sFont); + auto pVDev = SvxBmpNumIconView::CreateCustomBulletPreview(sBullet, sFont); OUString sId = OUString::number(aList.size()); - mxIconViewDoc->insert(-1, nullptr, &sId, pVDev, nullptr); + mxIconViewDoc->insert(-1, nullptr, &sId, pVDev.get(), nullptr); aList.emplace_back(sBullet, sFont); } diff --git a/svx/source/tbxctrls/fontworkgallery.cxx b/svx/source/tbxctrls/fontworkgallery.cxx index 746afd8a0400..3b8af2b8c65c 100644 --- a/svx/source/tbxctrls/fontworkgallery.cxx +++ b/svx/source/tbxctrls/fontworkgallery.cxx @@ -82,6 +82,8 @@ FontWorkGalleryDialog::FontWorkGalleryDialog(weld::Window* pParent, SdrView& rSd FontWorkGalleryDialog::~FontWorkGalleryDialog() { + for (auto& pVDev : maFavoritesHorizontal) + pVDev.disposeAndClear(); } void FontWorkGalleryDialog::initFavorites(sal_uInt16 nThemeId) diff --git a/svx/source/tbxctrls/tbcontrl.cxx b/svx/source/tbxctrls/tbcontrl.cxx index 93d5ddd12090..047f694734ae 100644 --- a/svx/source/tbxctrls/tbcontrl.cxx +++ b/svx/source/tbxctrls/tbcontrl.cxx @@ -483,7 +483,7 @@ private: void SetDiagonalDownBorder(const SvxLineItem& dDownLineItem); void SetDiagonalUpBorder(const SvxLineItem& dUpLineItem); - static VclPtr<VirtualDevice> GetVirtualDevice(BitmapEx aPreviewBitmap); + static ScopedVclPtr<VirtualDevice> GetVirtualDevice(BitmapEx aPreviewBitmap); public: SvxFrameWindow_Impl(SvxFrameToolBoxControl* pControl, weld::Widget* pParent); @@ -559,7 +559,7 @@ private: void UpdatePaintLineColor(); // returns sal_True if maPaintCol has changed - static VclPtr<VirtualDevice> GetVirtualDevice(Image pImage); + static ScopedVclPtr<VirtualDevice> GetVirtualDevice(Image pImage); sal_Int32 GetStylePos( sal_Int32 nListPos, tools::Long nWidth ); const Color& GetPaintColor() const @@ -728,7 +728,7 @@ private: return nullptr; } - VclPtr<VirtualDevice> LineListBox::GetVirtualDevice(Image pImage) + ScopedVclPtr<VirtualDevice> LineListBox::GetVirtualDevice(Image pImage) { constexpr tools::Long nMarginTopBottom = 5; constexpr tools::Long nMarginLeftRight = 2; @@ -764,7 +764,7 @@ private: if (!m_sNone.isEmpty()) { Size aPreviewSize = getPreviewSize(rIconView); - VclPtr<VirtualDevice> pVDevNone = GetVirtualDevice(Image()); + auto pVDevNone = GetVirtualDevice(Image()); pVDevNone->SetOutputSizePixel(aPreviewSize); rIconView.append("0", m_sNone, pVDevNone.get()); @@ -789,7 +789,7 @@ private: GetColorDist( n ), pData->GetStyle(), aBmp ); - VclPtr<VirtualDevice> pVDev = GetVirtualDevice(Image(aBmp)); + auto pVDev = GetVirtualDevice(Image(aBmp)); OUString sStyleName = SvtLineListBox::GetLineStyleName(pData->GetStyle()); OUString sId = OUString::number(n + 1); @@ -2585,7 +2585,7 @@ SvxFrameWindow_Impl::SvxFrameWindow_Impl(SvxFrameToolBoxControl* pControl, weld: // Writer uses 8 of them - for a single cell. for ( i=1; i < (m_bIsCalc ? 11 : 9); i++ ) { - VclPtr<VirtualDevice> pVDev = GetVirtualDevice(aImgVec[i-1].first); + auto pVDev = GetVirtualDevice(aImgVec[i-1].first); mxFrameIV->append(OUString::number(i), aImgVec[i-1].second, pVDev.get()); } @@ -2595,7 +2595,7 @@ SvxFrameWindow_Impl::SvxFrameWindow_Impl(SvxFrameToolBoxControl* pControl, weld: // Writer has 12 border types and Calc has 15 of them. for ( i = (m_bIsCalc ? 11 : 9); i < (m_bIsCalc ? 16 : 13); i++ ) { - VclPtr<VirtualDevice> pVDev = GetVirtualDevice(aImgVec[i-1].first); + auto pVDev = GetVirtualDevice(aImgVec[i-1].first); mxFrameIV->append(OUString::number(i), aImgVec[i-1].second, pVDev.get()); } @@ -2849,7 +2849,7 @@ IMPL_LINK(SvxFrameWindow_Impl, KeyReleaseHdl, const KeyEvent&, /*rKEvt*/, bool) return true; } -VclPtr<VirtualDevice> SvxFrameWindow_Impl::GetVirtualDevice(BitmapEx aPreviewBitmap) +ScopedVclPtr<VirtualDevice> SvxFrameWindow_Impl::GetVirtualDevice(BitmapEx aPreviewBitmap) { VclPtr<VirtualDevice> pVDev = VclPtr<VirtualDevice>::Create(); const Point aNull(0, 0); @@ -2931,7 +2931,7 @@ void SvxFrameWindow_Impl::statusChanged( const css::frame::FeatureStateEvent& rE { for ( sal_uInt16 i = (m_bIsWriter ? 9 : 11); i < (m_bIsWriter ? 13 : 16); i++ ) { - VclPtr<VirtualDevice> pVDev = GetVirtualDevice(aImgVec[i-1].first); + auto pVDev = GetVirtualDevice(aImgVec[i-1].first); OUString sId = OUString::number(i); mxFrameIV->insert(i - 1, &aImgVec[i-1].second, &sId, pVDev.get(), nullptr); }
