basctl/source/basicide/unomodel.cxx | 2 basic/source/basmgr/basicmanagerrepository.cxx | 2 basic/source/basmgr/basmgr.cxx | 18 basic/source/uno/scriptcont.cxx | 2 editeng/source/misc/svxacorr.cxx | 34 - embeddedobj/source/inc/oleembobj.hxx | 28 + embeddedobj/source/msole/olecomponent.cxx | 529 +++++++++++++---------- embeddedobj/source/msole/olecomponent.hxx | 12 embeddedobj/source/msole/oleembed.cxx | 28 - embeddedobj/source/msole/olepersist.cxx | 19 embeddedobj/source/msole/olevisual.cxx | 7 filter/source/msfilter/msdffimp.cxx | 30 - filter/source/msfilter/msoleexp.cxx | 8 filter/source/msfilter/rtfutil.cxx | 6 filter/source/msfilter/svdfppt.cxx | 22 filter/source/msfilter/svxmsbas2.cxx | 8 fpicker/source/win32/VistaFilePickerImpl.cxx | 1 include/editeng/svxacorr.hxx | 5 include/filter/msfilter/msdffimp.hxx | 6 include/filter/msfilter/svdfppt.hxx | 4 include/filter/msfilter/svxmsbas.hxx | 2 include/oox/ole/olehelper.hxx | 8 include/sfx2/event.hxx | 9 include/sfx2/objsh.hxx | 13 include/sot/object.hxx | 6 include/sot/storage.hxx | 6 include/svx/gallerybinaryengine.hxx | 4 include/vcl/scheduler.hxx | 7 include/vcl/svapp.hxx | 12 oox/source/ole/olehelper.cxx | 18 oox/source/ole/vbaexport.cxx | 12 sc/inc/global.hxx | 4 sc/inc/rangelst.hxx | 1 sc/inc/tablink.hxx | 7 sc/source/core/data/global.cxx | 2 sc/source/filter/excel/excel.cxx | 32 - sc/source/filter/excel/excimp8.cxx | 6 sc/source/filter/excel/expop2.cxx | 4 sc/source/filter/excel/xepivot.cxx | 4 sc/source/filter/excel/xeroot.cxx | 2 sc/source/filter/excel/xestream.cxx | 4 sc/source/filter/excel/xiescher.cxx | 2 sc/source/filter/excel/xipivot.cxx | 4 sc/source/filter/excel/xiroot.cxx | 2 sc/source/filter/excel/xlroot.cxx | 12 sc/source/filter/ftools/ftools.cxx | 16 sc/source/filter/inc/XclImpChangeTrack.hxx | 2 sc/source/filter/inc/ftools.hxx | 10 sc/source/filter/inc/xcl97esc.hxx | 2 sc/source/filter/inc/xeroot.hxx | 2 sc/source/filter/inc/xiescher.hxx | 2 sc/source/filter/inc/xiroot.hxx | 2 sc/source/filter/inc/xlroot.hxx | 16 sc/source/filter/xcl97/XclExpChangeTrack.cxx | 4 sc/source/filter/xcl97/XclImpChangeTrack.cxx | 2 sc/source/filter/xcl97/xcl97rec.cxx | 2 sc/source/ui/app/drwtrans.cxx | 15 sc/source/ui/app/seltrans.cxx | 6 sc/source/ui/app/transobj.cxx | 19 sc/source/ui/docshell/arealink.cxx | 5 sc/source/ui/docshell/docsh4.cxx | 3 sc/source/ui/docshell/externalrefmgr.cxx | 15 sc/source/ui/docshell/tablink.cxx | 18 sc/source/ui/inc/docsh.hxx | 2 sc/source/ui/inc/drwtrans.hxx | 2 sc/source/ui/inc/instbdlg.hxx | 5 sc/source/ui/inc/linkarea.hxx | 3 sc/source/ui/inc/transobj.hxx | 2 sc/source/ui/miscdlgs/instbdlg.cxx | 5 sc/source/ui/miscdlgs/linkarea.cxx | 9 sc/source/ui/unoobj/exceldetect.cxx | 2 sc/source/ui/unoobj/unodoc.cxx | 2 sc/source/ui/view/drawvie4.cxx | 6 sc/source/ui/view/viewfun3.cxx | 4 sd/inc/drawdoc.hxx | 2 sd/inc/sdfilter.hxx | 4 sd/inc/sdmod.hxx | 4 sd/source/filter/eppt/eppt.cxx | 20 sd/source/filter/eppt/eppt.hxx | 10 sd/source/filter/eppt/epptso.cxx | 4 sd/source/filter/ppt/pptin.cxx | 8 sd/source/filter/ppt/pptin.hxx | 4 sd/source/filter/ppt/propread.hxx | 3 sd/source/filter/sdpptwrp.cxx | 24 - sd/source/ui/app/sdmod.cxx | 4 sd/source/ui/app/sdmod1.cxx | 10 sd/source/ui/dlg/morphdlg.cxx | 4 sd/source/ui/dlg/vectdlg.cxx | 4 sd/source/ui/inc/DrawDocShell.hxx | 3 sd/source/ui/inc/sdtreelb.hxx | 2 sd/source/ui/unoidl/sddetect.cxx | 2 sd/source/ui/unoidl/unodoc.cxx | 4 sfx2/source/appl/appcfg.cxx | 10 sfx2/source/appl/appopen.cxx | 3 sfx2/source/appl/sfxpicklist.cxx | 6 sfx2/source/appl/xpackcreator.cxx | 4 sfx2/source/control/bindings.cxx | 1 sfx2/source/doc/objcont.cxx | 1 sfx2/source/doc/objxtor.cxx | 38 + sfx2/source/doc/oleprops.cxx | 4 sfx2/source/inc/objshimp.hxx | 4 sot/qa/cppunit/test_sot.cxx | 20 sot/source/base/object.cxx | 6 sot/source/sdstor/storage.cxx | 22 starmath/qa/cppunit/test_cursor.cxx | 2 starmath/qa/cppunit/test_node.cxx | 2 starmath/qa/cppunit/test_nodetotextvisitors.cxx | 2 starmath/qa/cppunit/test_parse.cxx | 2 starmath/qa/cppunit/test_starmath.cxx | 2 starmath/qa/extras/mmlexport-test.cxx | 2 starmath/qa/extras/mmlimport-test.cxx | 2 starmath/source/document.cxx | 2 starmath/source/eqnolefilehdr.cxx | 2 starmath/source/mathtype.cxx | 10 starmath/source/smdetect.cxx | 2 starmath/source/unodoc.cxx | 2 starmath/source/unofilter.cxx | 2 svtools/source/misc/imagemgr.cxx | 2 svx/source/gallery2/gallerybinaryengine.cxx | 22 sw/inc/doc.hxx | 2 sw/inc/shellio.hxx | 10 sw/qa/core/filters-test.cxx | 2 sw/qa/core/macros-test.cxx | 2 sw/qa/core/uwriter.cxx | 2 sw/qa/extras/htmlexport/htmlexport.cxx | 6 sw/qa/extras/layout/data/i84870.fodt | 61 ++ sw/qa/extras/layout/data/tdf160526.fodt | 47 ++ sw/qa/extras/layout/data/tdf160549.fodt | 60 ++ sw/qa/extras/layout/layout2.cxx | 29 + sw/source/core/doc/DocumentLayoutManager.cxx | 4 sw/source/core/doc/docnew.cxx | 4 sw/source/core/inc/SwXMLTextBlocks.hxx | 4 sw/source/core/ole/ndole.cxx | 8 sw/source/core/swg/SwXMLTextBlocks.cxx | 14 sw/source/core/text/frmform.cxx | 100 +++- sw/source/filter/basflt/iodetect.cxx | 4 sw/source/filter/basflt/shellio.cxx | 4 sw/source/filter/html/htmlplug.cxx | 2 sw/source/filter/html/htmlreqifreader.cxx | 16 sw/source/filter/writer/writer.cxx | 2 sw/source/filter/ww8/wrtw8esh.cxx | 6 sw/source/filter/ww8/wrtww8.cxx | 12 sw/source/filter/ww8/wrtww8.hxx | 6 sw/source/filter/ww8/wrtww8gr.cxx | 16 sw/source/filter/ww8/ww8glsy.cxx | 2 sw/source/filter/ww8/ww8glsy.hxx | 8 sw/source/filter/ww8/ww8par.cxx | 36 - sw/source/filter/ww8/ww8par.hxx | 10 sw/source/filter/ww8/ww8par4.cxx | 20 sw/source/filter/ww8/ww8par5.cxx | 6 sw/source/ui/uno/swdetect.cxx | 4 sw/source/uibase/app/apphdl.cxx | 2 sw/source/uibase/app/docsh.cxx | 4 sw/source/uibase/app/docsh2.cxx | 3 sw/source/uibase/dochdl/swdtflvr.cxx | 4 sw/source/uibase/inc/glosdoc.hxx | 4 sw/source/uibase/inc/unoatxt.hxx | 3 sw/source/uibase/misc/glshell.cxx | 4 sw/source/uibase/uno/unodoc.cxx | 6 sw/source/uibase/uno/unotxvw.cxx | 4 vcl/inc/svdata.hxx | 5 vcl/source/app/scheduler.cxx | 70 ++- vcl/source/app/svapp.cxx | 4 vcl/source/app/svmain.cxx | 3 vcl/win/dtrans/MtaOleClipb.cxx | 35 - vcl/win/dtrans/WinClipboard.cxx | 14 vcl/win/window/salframe.cxx | 10 writerperfect/source/common/WPXSvInputStream.cxx | 30 - 168 files changed, 1329 insertions(+), 815 deletions(-)
New commits: commit a49596248ac9004d57d8bb6752c114444bce5121 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 18:23:52 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Mon Apr 8 00:01:05 2024 +0500 tdf#160526, tdf#160549: fix split conditions at page start A single large object in a paragraph must be moved down, when the page has other content before this. On the other hand, there must not be moving down, when an unsuccessful attempt to move was already done (so the master frame is empty), or even the first time, when the frame is at the page body start. Change-Id: Ib8e2fe7b77c622d9cfac22722ca6b55dba7ad8ae Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165869 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/qa/extras/layout/data/tdf160526.fodt b/sw/qa/extras/layout/data/tdf160526.fodt new file mode 100644 index 000000000000..37cf73fb8e18 --- /dev/null +++ b/sw/qa/extras/layout/data/tdf160526.fodt @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:font-face-decls> + <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:start-line-spacing-horizontal="8pt" draw:start-line-spacing-vertical="8pt" draw:end-line-spacing-horizontal="8pt" draw:end-line-spacing-vertical="8pt" style:writing-mode="lr-tb" style:flow-with-text="false"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties style:punctuation-wrap="hanging" style:line-break="strict" style:writing-mode="page"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true" fo:hyphenate="false"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"/> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph"> + <style:paragraph-properties fo:text-align="center"/> + </style:style> + <style:style style:name="gr1" style:family="graphic"> + <style:graphic-properties draw:fill-color="#81d41a" draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="3cm" fo:min-width="12cm" style:run-through="foreground" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" style:flow-with-text="false"/> + <style:paragraph-properties style:writing-mode="lr-tb"/> + </style:style> + <style:style style:name="gr2" style:family="graphic"> + <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="25cm" fo:min-width="7cm" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="top" style:vertical-rel="baseline" style:horizontal-pos="from-left" style:horizontal-rel="paragraph" draw:wrap-influence-on-position="once-concurrent" style:flow-with-text="false"/> + </style:style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="210mm" fo:page-height="297mm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="20pt" style:layout-grid-ruby-height="10pt" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:footnote-max-height="0"/> + </style:page-layout> + <style:style style:name="dp1" style:family="drawing-page"/> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"/> + </office:master-styles> + <office:body> + <office:text> + <text:p><draw:custom-shape text:anchor-type="paragraph" draw:z-index="1" draw:name="Shape 1" draw:style-name="gr1" svg:width="12cm" svg:height="3cm" svg:x="4cm" svg:y="0cm"> + <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/> + </draw:custom-shape>Foo</text:p> + <text:p><draw:custom-shape text:anchor-type="as-char" draw:z-index="0" draw:name="Shape 2" draw:style-name="gr2" svg:width="7cm" svg:height="25cm"> + <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/> + </draw:custom-shape></text:p> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/layout/data/tdf160549.fodt b/sw/qa/extras/layout/data/tdf160549.fodt new file mode 100644 index 000000000000..fd8425eedd86 --- /dev/null +++ b/sw/qa/extras/layout/data/tdf160549.fodt @@ -0,0 +1,60 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:font-face-decls> + <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:start-line-spacing-horizontal="8pt" draw:start-line-spacing-vertical="8pt" draw:end-line-spacing-horizontal="8pt" draw:end-line-spacing-vertical="8pt" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="36pt" style:writing-mode="page"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"/> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0" svg:y="0" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph" draw:fill="none"/> + </style:style> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0" svg:y="0" fo:margin-left="2mm" fo:margin-right="2mm" fo:margin-top="2mm" fo:margin-bottom="2mm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" draw:fill="none" fo:padding="1.5mm" fo:border="0.06pt solid #000000"/> + </style:style> + <style:default-page-layout> + <style:page-layout-properties style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame"> + <style:graphic-properties fo:margin-left="0" fo:margin-right="0" fo:margin-top="0" fo:margin-bottom="0" style:wrap="none" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="right" style:horizontal-rel="page-content" fo:background-color="#ffffff" style:background-transparency="100%" draw:fill="solid" draw:fill-color="#ffffff" draw:opacity="0%" fo:padding="0pt" fo:border="none" style:writing-mode="lr-tb" draw:wrap-influence-on-position="once-successive"/> + </style:style> + <style:style style:name="fr2" style:family="graphic" style:parent-style-name="Graphics"> + <style:graphic-properties fo:margin-left="0" fo:margin-right="0" fo:margin-top="0" fo:margin-bottom="0" style:vertical-pos="top" style:vertical-rel="baseline" fo:border="none" style:mirror="none" fo:clip="rect(0pt, 0pt, 0pt, 0pt)" draw:luminance="0%" draw:contrast="0%" draw:red="0%" draw:green="0%" draw:blue="0%" draw:gamma="100%" draw:color-inversion="false" draw:image-opacity="100%" draw:color-mode="standard"/> + </style:style> + <style:page-layout style:name="pm1" style:page-usage="mirrored"> + <style:page-layout-properties fo:page-width="148mm" fo:page-height="210mm" style:num-format="1" style:print-orientation="landscape" fo:margin-top="15mm" fo:margin-bottom="15mm" fo:margin-left="15mm" fo:margin-right="15mm" style:writing-mode="lr-tb"/> + <style:header-style> + <style:header-footer-properties fo:min-height="5mm" fo:margin-bottom="1mm" style:dynamic-spacing="true"/> + </style:header-style> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"> + <style:header> + <text:p><draw:frame draw:style-name="fr1" draw:name="Frame1" text:anchor-type="paragraph" svg:y="1mm" draw:z-index="0"> + <draw:text-box fo:min-height="5mm" fo:min-width="4cm"> + <text:p>foobar</text:p> + </draw:text-box> + </draw:frame></text:p> + </style:header> + </style:master-page> + </office:master-styles> + <office:body> + <office:text> + <text:p><draw:custom-shape draw:style-name="fr2" draw:name="Image2" text:anchor-type="as-char" svg:width="8cm" svg:height="19cm" draw:z-index="1"> + <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/> + </draw:custom-shape><text:s/></text:p> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx index 55f2b966c6dc..ce6c7c56bb1e 100644 --- a/sw/qa/extras/layout/layout2.cxx +++ b/sw/qa/extras/layout/layout2.cxx @@ -2927,6 +2927,27 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, test_i84870) CPPUNIT_ASSERT_EQUAL(2, getPages()); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf160549) +{ + // Given a document with a large as-char object, alone in its paragraph, shifted down by a + // header object: it must not hang in a layout loop on import (similar to i84870, but not + // fixed by its fix) + createSwDoc("tdf160549.fodt"); + // The object is the first in the document; it must not move to the next page + CPPUNIT_ASSERT_EQUAL(1, getPages()); +} + +CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf160526) +{ + // Given a document with a large as-char object, alone in its paragraph, shifted down by + // another body object + createSwDoc("tdf160526.fodt"); + // It must move to the next page + CPPUNIT_ASSERT_EQUAL(2, getPages()); + auto pExportDump = parseLayoutDump(); + assertXPath(pExportDump, "//page[2]/body/txt/anchored/SwAnchoredDrawObject"); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx index 19dcb6e3ed5f..2e00f55f0988 100644 --- a/sw/source/core/text/frmform.cxx +++ b/sw/source/core/text/frmform.cxx @@ -1003,6 +1003,53 @@ void SwTextFrame::ChangeOffset( SwTextFrame* pFrame, TextFrameIndex nNew ) MoveFlyInCnt( pFrame, nNew, TextFrameIndex(COMPLETE_STRING) ); } +static bool isFirstVisibleFrameInBody(const SwTextFrame* pFrame) +{ + const SwFrame* pBodyFrame = pFrame->FindBodyFrame(); + if (!pBodyFrame) + return false; + for (const SwFrame* pCur = pFrame;;) + { + if (pCur->GetPrev()) + return false; + pCur = pCur->GetUpper(); + assert(pCur); // We found pBodyFrame, right? + if (pCur->IsBodyFrame()) + return true; + } +} + +static bool hasFly(const SwTextFrame* pFrame) +{ + if (auto pDrawObjs = pFrame->GetDrawObjs(); pDrawObjs && pDrawObjs->size()) + { + auto anchorId = (*pDrawObjs)[0]->GetFrameFormat().GetAnchor().GetAnchorId(); + if (anchorId == RndStdIds::FLY_AT_PARA || anchorId == RndStdIds::FLY_AT_CHAR) + return true; + } + return false; +} + +static bool hasAtPageFly(const SwFrame* pFrame) +{ + auto pPageFrame = pFrame->FindPageFrame(); + if (!pPageFrame) + return false; + auto pPageDrawObjs = pPageFrame->GetDrawObjs(); + if (pPageDrawObjs) + { + for (const auto pObject : *pPageDrawObjs) + if (pObject->GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AT_PAGE) + return true; + } + return false; +} + +static bool isReallyEmptyMaster(const SwTextFrame* pFrame) +{ + return pFrame->IsEmptyMaster() && (!pFrame->GetDrawObjs() || !pFrame->GetDrawObjs()->size()); +} + void SwTextFrame::FormatAdjust( SwTextFormatter &rLine, WidowsAndOrphans &rFrameBreak, TextFrameIndex const nStrLen, @@ -1028,20 +1075,48 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine, !rFrameBreak.IsInside( rLine ) ) : rFrameBreak.IsBreakNow( rLine ) ) ) ) ? 1 : 0; + + SwTextFormatInfo& rInf = rLine.GetInfo(); + const SwFrame* pBodyFrame = FindBodyFrame(); + // i#84870 // no split of text frame, which only contains an as-character anchored object - bool bOnlyContainsAsCharAnchoredObj = + bool bLoneAsCharAnchoredObj = + pBodyFrame && !IsFollow() && nStrLen == TextFrameIndex(1) && GetDrawObjs() && GetDrawObjs()->size() == 1 && (*GetDrawObjs())[0]->GetFrameFormat().GetAnchor().GetAnchorId() == RndStdIds::FLY_AS_CHAR; - // Still try split text frame if we have columns. - if (FindColFrame()) - bOnlyContainsAsCharAnchoredObj = false; - - if ( nNew && bOnlyContainsAsCharAnchoredObj ) + if (bLoneAsCharAnchoredObj) { - nNew = 0; + // Still try split text frame if we have columns. + if (FindColFrame()) + bLoneAsCharAnchoredObj = false; + // tdf#160526: only no split if there is no preceding frames on same page + else if (!isFirstVisibleFrameInBody(this)) + bLoneAsCharAnchoredObj = false; + else + nNew = 0; + } + else if (nNew) + { + if (IsFollow()) + { + // tdf#160549: do not split the frame at the very beginning again, if its master was empty + auto precede = static_cast<SwTextFrame*>(GetPrecede()); + assert(precede); + auto precedeText = precede->DynCastTextFrame(); + assert(precedeText); + if (isReallyEmptyMaster(precedeText)) + nNew = 0; + } + else + { + // Do not split immediately in the beginning of page (unless there is an at-para or + // at-char or at-page fly, which pushes the rest down) + if (isFirstVisibleFrameInBody(this) && !hasFly(this) && !hasAtPageFly(pBodyFrame)) + nNew = 0; + } } if ( nNew ) @@ -1049,8 +1124,6 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine, SplitFrame( nEnd ); } - const SwFrame *pBodyFrame = FindBodyFrame(); - const tools::Long nBodyHeight = pBodyFrame ? ( IsVertical() ? pBodyFrame->getFrameArea().Width() : pBodyFrame->getFrameArea().Height() ) : 0; @@ -1139,9 +1212,10 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine, // content or contains no content, but has a numbering. // i#84870 - No split, if text frame only contains one // as-character anchored object. - if ( !bOnlyContainsAsCharAnchoredObj && - (nStrLen > TextFrameIndex(0) || - bHasVisibleNumRule ) + if (!bLoneAsCharAnchoredObj + && (bHasVisibleNumRule + || (nStrLen > TextFrameIndex(0) + && (nEnd != rLine.GetStart() || rInf.GetRest()))) ) { SplitFrame( nEnd ); @@ -1165,7 +1239,7 @@ void SwTextFrame::FormatAdjust( SwTextFormatter &rLine, SwTwips nChg = rLine.CalcBottomLine() - nDocPrtTop - nOldHeight; //#i84870# - no shrink of text frame, if it only contains one as-character anchored object. - if ( nChg < 0 && !bDelta && bOnlyContainsAsCharAnchoredObj ) + if (nChg < 0 && !bDelta && bLoneAsCharAnchoredObj) { nChg = 0; } commit d0ecd460ded0e6dc0fe63f478614ff3f5956001e Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 17:55:10 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 23:04:11 2024 +0500 i#84870: Add a unit test I broke it during a work on a related problem, and that wasn't caught by existing tests - I only accidentally noticed that. Change-Id: I2e60970b09f8aaa52d2db8123996e349e53a46b9 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165867 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/qa/extras/layout/data/i84870.fodt b/sw/qa/extras/layout/data/i84870.fodt new file mode 100644 index 000000000000..3cac44cd62fe --- /dev/null +++ b/sw/qa/extras/layout/data/i84870.fodt @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:font-face-decls> + <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation Serif'" style:font-family-generic="roman" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#3465a4" draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:start-line-spacing-horizontal="8pt" draw:start-line-spacing-vertical="8pt" draw:end-line-spacing-horizontal="8pt" draw:end-line-spacing-vertical="8pt" style:writing-mode="lr-tb" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Liberation Serif" fo:font-size="12pt" style:letter-kerning="true" fo:hyphenate="false"/> + </style:default-style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0" svg:y="0" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph" fo:background-color="transparent" draw:fill="none" draw:fill-color="#729fcf"/> + </style:style> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0" svg:y="0" fo:margin-left="2mm" fo:margin-right="2mm" fo:margin-top="2mm" fo:margin-bottom="2mm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content" fo:background-color="transparent" draw:fill="none" draw:fill-color="#729fcf" fo:padding="1.5mm" fo:border="0.06pt solid #000000"/> + </style:style> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="fr1" style:family="graphic" style:parent-style-name="Frame"> + <style:graphic-properties fo:margin-left="0" fo:margin-right="0" fo:margin-top="0" fo:margin-bottom="0" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="from-top" style:vertical-rel="paragraph" style:horizontal-pos="right" style:horizontal-rel="page-content" fo:background-color="#ffffff" style:background-transparency="100%" draw:fill="solid" draw:fill-color="#ffffff" draw:opacity="0%" fo:padding="0pt" fo:border="none" style:writing-mode="lr-tb" draw:wrap-influence-on-position="once-successive"/> + </style:style> + <style:style style:name="gr1" style:family="graphic"> + <style:graphic-properties draw:textarea-horizontal-align="justify" draw:textarea-vertical-align="middle" draw:auto-grow-height="false" fo:min-height="452.69pt" fo:min-width="278.79pt" style:run-through="foreground" style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" style:vertical-pos="top" style:vertical-rel="baseline" style:horizontal-pos="from-left" style:horizontal-rel="paragraph"/> + </style:style> + <style:page-layout style:name="pm1" style:page-usage="mirrored"> + <style:page-layout-properties fo:page-width="148mm" fo:page-height="210mm" style:num-format="1" style:print-orientation="landscape" fo:margin-top="15mm" fo:margin-bottom="15mm" fo:margin-left="15mm" fo:margin-right="15mm"/> + <style:header-style> + <style:header-footer-properties fo:margin-left="0" fo:margin-right="0" fo:margin-bottom="1mm" style:dynamic-spacing="true"/> + </style:header-style> + </style:page-layout> + <style:style style:name="dp1" style:family="drawing-page"/> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"> + <style:header> + <text:p><draw:frame draw:style-name="fr1" draw:name="Frame1" text:anchor-type="paragraph" svg:y="1mm" draw:z-index="0"> + <draw:text-box fo:min-height="5mm" fo:min-width="4cm"> + <text:p>Frame in header</text:p> + </draw:text-box> + </draw:frame></text:p> + </style:header> + </style:master-page> + </office:master-styles> + <office:body> + <office:text> + <text:p/> + <text:p><draw:custom-shape text:anchor-type="as-char" draw:z-index="1" draw:name="Shape1" draw:style-name="gr1" svg:width="10cm" svg:height="18cm"> + <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" draw:mirror-horizontal="false" draw:mirror-vertical="false" draw:type="rectangle" draw:enhanced-path="M 0 0 L 21600 0 21600 21600 0 21600 0 0 Z N"/> + </draw:custom-shape></text:p> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx index a29664cf8a13..55f2b966c6dc 100644 --- a/sw/qa/extras/layout/layout2.cxx +++ b/sw/qa/extras/layout/layout2.cxx @@ -2919,6 +2919,14 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf156725) "/root/page[2]/body/txt/anchored/fly/column[2]/body/section/column[2]/body/txt", 1); } +CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, test_i84870) +{ + // Given a document with a large as-char object, alone in its paragraph, shifted down by a + // header object: it must not hang in a layout loop on import + createSwDoc("i84870.fodt"); + CPPUNIT_ASSERT_EQUAL(2, getPages()); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit de14690782fde134dd2c4c61219300d081beb215 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:16 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:16 2024 +0500 Reapply "Downgrade sfx::SfxBindings aAutoTimer to an idle" This reverts commit e95ada626ccf0c1e915a1582c372242ef9b9b59a. diff --git a/sfx2/source/control/bindings.cxx b/sfx2/source/control/bindings.cxx index 4ea06231562a..44fbbd10c2f0 100644 --- a/sfx2/source/control/bindings.cxx +++ b/sfx2/source/control/bindings.cxx @@ -146,6 +146,7 @@ SfxBindings::SfxBindings() // all caches are valid (no pending invalidate-job) // create the list of caches + pImpl->aAutoTimer.SetPriority(TaskPriority::HIGH_IDLE); pImpl->aAutoTimer.SetInvokeHandler( LINK(this, SfxBindings, NextJob) ); } commit 1d99e62a13dcde9faa8419d845cf6b3405b9eb02 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:16 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:16 2024 +0500 Reapply "Only hold clipboard mutexes to obtain the values, to avoid deadlocks" This reverts commit fb2be820d207c0090057ed6b7c24c538e1e02741. diff --git a/vcl/win/dtrans/MtaOleClipb.cxx b/vcl/win/dtrans/MtaOleClipb.cxx index 865025057dcc..19a37dc52e19 100644 --- a/vcl/win/dtrans/MtaOleClipb.cxx +++ b/vcl/win/dtrans/MtaOleClipb.cxx @@ -713,25 +713,32 @@ DWORD WINAPI CMtaOleClipboard::clipboardChangedNotifierThreadProc( _In_ LPVOID p MsgWaitForMultipleObjects(2, pInst->m_hClipboardChangedNotifierEvents, false, INFINITE, QS_ALLINPUT | QS_ALLPOSTMESSAGE); - ClearableMutexGuard aGuard2( pInst->m_ClipboardChangedEventCountMutex ); - - if ( pInst->m_ClipboardChangedEventCount > 0 ) + bool hadEvents; { - pInst->m_ClipboardChangedEventCount--; - if ( 0 == pInst->m_ClipboardChangedEventCount ) - ResetEvent( pInst->m_hClipboardChangedEvent ); - - aGuard2.clear( ); + ClearableMutexGuard aGuard2(pInst->m_ClipboardChangedEventCountMutex); + hadEvents = pInst->m_ClipboardChangedEventCount > 0; + if (hadEvents) + { + pInst->m_ClipboardChangedEventCount--; + if (0 == pInst->m_ClipboardChangedEventCount) + ResetEvent(pInst->m_hClipboardChangedEvent); + } + } - // nobody should touch m_pfncClipViewerCallback while we do - MutexGuard aClipViewerGuard( pInst->m_pfncClipViewerCallbackMutex ); + if (hadEvents) + { + LPFNC_CLIPVIEWER_CALLBACK_t pClipViewerCallback; + { + // nobody should touch m_pfncClipViewerCallback while we do + // but don't hold the mutex while calling the callback itself: it could deadlock + MutexGuard aClipViewerGuard(pInst->m_pfncClipViewerCallbackMutex); + pClipViewerCallback = pInst->m_pfncClipViewerCallback; + } // notify all clipboard listener - if ( pInst->m_pfncClipViewerCallback ) - pInst->m_pfncClipViewerCallback( ); + if (pClipViewerCallback) + pClipViewerCallback(); } - else - aGuard2.clear( ); } return 0; diff --git a/vcl/win/dtrans/WinClipboard.cxx b/vcl/win/dtrans/WinClipboard.cxx index c2fa269dfc5d..33c8023a925c 100644 --- a/vcl/win/dtrans/WinClipboard.cxx +++ b/vcl/win/dtrans/WinClipboard.cxx @@ -373,13 +373,17 @@ void CWinClipboard::unregisterClipboardViewer() { m_MtaOleClipboard.registerClip void WINAPI CWinClipboard::onClipboardContentChanged() { - osl::MutexGuard aGuard(s_aClipboardSingletonMutex); + rtl::Reference<CWinClipboard> pWinClipboard; + { + // Only hold the mutex to obtain a safe reference to the impl, to avoid deadlock + osl::MutexGuard aGuard(s_aClipboardSingletonMutex); + pWinClipboard.set(s_pCWinClipbImpl); + } - // reassociation to instance through static member - if (nullptr != s_pCWinClipbImpl) + if (pWinClipboard) { - s_pCWinClipbImpl->m_foreignContent.clear(); - s_pCWinClipbImpl->notifyAllClipboardListener(); + pWinClipboard->m_foreignContent.clear(); + pWinClipboard->notifyAllClipboardListener(); } } commit 2e594ced48a1edd15dfd64c060ae8f73026a766f Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:16 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:16 2024 +0500 Reapply "This assert was wrong" This reverts commit 5910bf0893a9c91240c40c15c41592e5650e5400. diff --git a/embeddedobj/source/msole/olecomponent.cxx b/embeddedobj/source/msole/olecomponent.cxx index 142d92ddf1c3..ca104a7c3425 100644 --- a/embeddedobj/source/msole/olecomponent.cxx +++ b/embeddedobj/source/msole/olecomponent.cxx @@ -200,7 +200,8 @@ private: template <typename T> void registerInterface(T* pInterface, DWORD& cookie) { - assert(cookie == 0); // do not set again + if (cookie != 0) // E.g., on subsequent RunObject calls + return; HRESULT hr = m_pGlobalTable->RegisterInterfaceInGlobal(pInterface, __uuidof(T), &cookie); SAL_WARN_IF(FAILED(hr), "embeddedobj.ole", "RegisterInterfaceInGlobal failed"); } commit 62c6322bd66d364556cccefbd7c51e091b8069dc Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:15 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:15 2024 +0500 Reapply "Set the condition, even when main thread message queue is empty" This reverts commit e2a97cc4719ea40b9a7f343cd000b2ae5ec6a28e. diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx index 61b82d21b984..f7075584924b 100644 --- a/vcl/source/app/scheduler.cxx +++ b/vcl/source/app/scheduler.cxx @@ -285,6 +285,9 @@ Scheduler::IdlesLockGuard::IdlesLockGuard() // condition to proceed. Only main thread returning to Application::Execute guarantees that // the flag really took effect. pSVData->m_inExecuteCondtion.reset(); + // Put an empty event to the application's queue, to make sure that it loops through the + // code that sets the condition, even when there's no other events in the queue + Application::PostUserEvent({}); SolarMutexReleaser releaser; pSVData->m_inExecuteCondtion.wait(); } commit 32f495ab369da6fb713a220e93e11f08a508e358 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:15 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:15 2024 +0500 Reapply "Relax SolarMutexReleaser precondition to not require SolarMutex lock" This reverts commit 9b0756f2dbd490d8516e132954badb5d7d7c26db. diff --git a/embeddedobj/source/msole/olecomponent.cxx b/embeddedobj/source/msole/olecomponent.cxx index da10b9d9d233..142d92ddf1c3 100644 --- a/embeddedobj/source/msole/olecomponent.cxx +++ b/embeddedobj/source/msole/olecomponent.cxx @@ -206,15 +206,6 @@ private: } }; -namespace -{ -struct SafeSolarMutexReleaser -{ - SolarMutexGuard guard; // To make sure we actually hold it prior to release - SolarMutexReleaser releaser; -}; -} - static DWORD GetAspectFromFlavor( const datatransfer::DataFlavor& aFlavor ) { if ( aFlavor.MimeType.indexOf( ";Aspect=THUMBNAIL" ) != -1 ) @@ -569,7 +560,7 @@ void OleComponent::RetrieveObjectDataFlavors_Impl() HRESULT hr; sal::systools::COMReference< IEnumFORMATETC > pFormatEnum; { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; hr = pDataObject->EnumFormatEtc(DATADIR_GET, &pFormatEnum); } if ( SUCCEEDED( hr ) && pFormatEnum ) @@ -859,7 +850,7 @@ void OleComponent::InitEmbeddedCopyOfLink( rtl::Reference<OleComponent> const & // the object must be already disconnected from the temporary URL auto pStorage(m_pNativeImpl->CreateNewStorage(getTempURL())); - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; auto pDataObject(pOleLinkComponentObj.QueryInterface<IDataObject>(sal::systools::COM_QUERY)); if ( pDataObject && SUCCEEDED( OleQueryCreateFromData( pDataObject ) ) ) @@ -987,7 +978,7 @@ void OleComponent::CloseObject() auto pOleObject(m_pNativeImpl->get<IOleObject>()); if (pOleObject && OleIsRunning(pOleObject)) { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; HRESULT hr = pOleObject->Close(OLECLOSE_NOSAVE); // must be saved before SAL_WARN_IF(FAILED(hr), "embeddedobj.ole", "IOleObject::Close failed"); } @@ -1005,7 +996,7 @@ uno::Sequence< embed::VerbDescriptor > OleComponent::GetVerbList() sal::systools::COMReference< IEnumOLEVERB > pEnum; HRESULT hr; { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; hr = pOleObject->EnumVerbs(&pEnum); } if (SUCCEEDED(hr)) @@ -1048,7 +1039,7 @@ void OleComponent::ExecuteVerb( sal_Int32 nVerbID ) if (!pOleObject) throw embed::WrongStateException(); // TODO - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; // TODO: probably extents should be set here and stored in aRect // TODO: probably the parent window also should be set @@ -1065,7 +1056,7 @@ void OleComponent::SetHostName( const OUString& aEmbDocName ) if (!pOleObject) throw embed::WrongStateException(); // TODO: the object is in wrong state - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; pOleObject->SetHostNames(L"app name", o3tl::toW(aEmbDocName.getStr())); } @@ -1081,7 +1072,7 @@ void OleComponent::SetExtent( const awt::Size& aVisAreaSize, sal_Int64 nAspect ) SIZEL aSize = { aVisAreaSize.Width, aVisAreaSize.Height }; HRESULT hr; { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; hr = pOleObject->SetExtent(nMSAspect, &aSize); } @@ -1117,7 +1108,7 @@ awt::Size OleComponent::GetExtent( sal_Int64 nAspect ) HRESULT hr; { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; hr = pDataObject->GetData(&aFormat, &aMedium); } @@ -1204,7 +1195,7 @@ awt::Size OleComponent::GetCachedExtent( sal_Int64 nAspect ) HRESULT hr; { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; hr = pViewObject2->GetExtent(nMSAspect, -1, nullptr, &aSize); } @@ -1235,7 +1226,7 @@ awt::Size OleComponent::GetRecommendedExtent( sal_Int64 nAspect ) SIZEL aSize; HRESULT hr; { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; hr = pOleObject->GetExtent(nMSAspect, &aSize); } if ( FAILED( hr ) ) @@ -1256,7 +1247,7 @@ sal_Int64 OleComponent::GetMiscStatus( sal_Int64 nAspect ) DWORD nResult = 0; { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; pOleObject->GetMiscStatus(static_cast<DWORD>(nAspect), &nResult); } return static_cast<sal_Int64>(nResult); // first 32 bits are for MS flags @@ -1272,7 +1263,7 @@ uno::Sequence< sal_Int8 > OleComponent::GetCLSID() GUID aCLSID; HRESULT hr; { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; hr = pOleObject->GetUserClassID(&aCLSID); } if ( FAILED( hr ) ) @@ -1295,7 +1286,7 @@ bool OleComponent::IsDirty() if ( !pPersistStorage ) throw io::IOException(); // TODO - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; HRESULT hr = pPersistStorage->IsDirty(); return ( hr != S_FALSE ); } @@ -1311,7 +1302,7 @@ void OleComponent::StoreOwnTmpIfNecessary() if ( !pPersistStorage ) throw io::IOException(); // TODO - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; if ( m_bWorkaroundActive || pPersistStorage->IsDirty() != S_FALSE ) { @@ -1573,7 +1564,7 @@ uno::Any SAL_CALL OleComponent::getTransferData( const datatransfer::DataFlavor& HRESULT hr; { - SafeSolarMutexReleaser releaser; + SolarMutexReleaser releaser; hr = pDataObject->GetData(&aFormat, &aMedium); } if ( SUCCEEDED( hr ) ) diff --git a/fpicker/source/win32/VistaFilePickerImpl.cxx b/fpicker/source/win32/VistaFilePickerImpl.cxx index 741fdadb621a..d1a0cdf8a5a9 100644 --- a/fpicker/source/win32/VistaFilePickerImpl.cxx +++ b/fpicker/source/win32/VistaFilePickerImpl.cxx @@ -965,7 +965,6 @@ void VistaFilePickerImpl::impl_sta_ShowDialogModal(Request& rRequest) { // tdf#146007: Make sure we don't hold solar mutex: COM may need to forward // the execution to the main thread, and holding solar mutex could deadlock - SolarMutexGuard g; // First acquire, to avoid releaser failure SolarMutexReleaser r; // show dialog and wait for user decision hResult = iDialog->Show(m_hParentWindow ? m_hParentWindow diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx index 398358f1bfad..7aef4926f9c2 100644 --- a/include/vcl/svapp.hxx +++ b/include/vcl/svapp.hxx @@ -1448,8 +1448,16 @@ class SolarMutexReleaser { const sal_uInt32 mnReleased; public: - SolarMutexReleaser(): mnReleased(Application::ReleaseSolarMutex()) {} - ~SolarMutexReleaser() { Application::AcquireSolarMutex( mnReleased ); } + SolarMutexReleaser() + : mnReleased( + Application::GetSolarMutex().IsCurrentThread() ? Application::ReleaseSolarMutex() : 0) + { + } + ~SolarMutexReleaser() + { + if (mnReleased) + Application::AcquireSolarMutex(mnReleased); + } }; VCL_DLLPUBLIC Application* GetpApp(); diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx index c0fc79d4ac5c..61b82d21b984 100644 --- a/vcl/source/app/scheduler.cxx +++ b/vcl/source/app/scheduler.cxx @@ -285,9 +285,7 @@ Scheduler::IdlesLockGuard::IdlesLockGuard() // condition to proceed. Only main thread returning to Application::Execute guarantees that // the flag really took effect. pSVData->m_inExecuteCondtion.reset(); - std::optional<SolarMutexReleaser> releaser; - if (pSVData->mpDefInst->GetYieldMutex()->IsCurrentThread()) - releaser.emplace(); + SolarMutexReleaser releaser; pSVData->m_inExecuteCondtion.wait(); } } diff --git a/vcl/source/helper/threadex.cxx b/vcl/source/helper/threadex.cxx index 1590b91f1167..cbd342bd28df 100644 --- a/vcl/source/helper/threadex.cxx +++ b/vcl/source/helper/threadex.cxx @@ -52,7 +52,6 @@ void SolarThreadExecutor::execute() m_aStart.reset(); m_aFinish.reset(); ImplSVEvent* nEvent = Application::PostUserEvent(LINK(this, SolarThreadExecutor, worker)); - SolarMutexGuard aGuard; SolarMutexReleaser aReleaser; if (m_aStart.wait() == osl::Condition::result_timeout) { commit 336bdbfe2bb23ab4d28511c660494c850cb5b0a7 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:15 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:15 2024 +0500 Reapply "Pass m_pOleComponent to lambda by copy" This reverts commit 77fe60bbac09b0b4ea0cf930f2260fa4b6496a3d. diff --git a/embeddedobj/source/msole/oleembed.cxx b/embeddedobj/source/msole/oleembed.cxx index b946fed792c8..657d27710ca3 100644 --- a/embeddedobj/source/msole/oleembed.cxx +++ b/embeddedobj/source/msole/oleembed.cxx @@ -620,8 +620,10 @@ uno::Sequence< sal_Int32 > SAL_CALL OleEmbeddedObject::getReachableStates() // the list of states can only be guessed based on standard verbs, // since there is no way to detect what additional verbs do + // Pass m_pOleComponent to the lambda by copy, to make sure it doesn't depend on possible + // destruction of 'this', while the lock is unset return GetReachableStatesList_Impl( - ExecUnlocked([this] { return m_pOleComponent->GetVerbList(); }, aGuard)); + ExecUnlocked([p = m_pOleComponent] { return p->GetVerbList(); }, aGuard)); } else #endif commit 87cfbf70399ea12a6c6d50fa009fc0e6ed3f7218 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:15 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:15 2024 +0500 Reapply "Release the mutex when calling the OLE method" This reverts commit e40df1a2504935797454eafc08380b787e3629f2. diff --git a/embeddedobj/source/inc/oleembobj.hxx b/embeddedobj/source/inc/oleembobj.hxx index cf7c5ebe4ab4..983f242308cf 100644 --- a/embeddedobj/source/inc/oleembobj.hxx +++ b/embeddedobj/source/inc/oleembobj.hxx @@ -468,4 +468,15 @@ private: osl::ResettableMutexGuard& m_guard; }; +namespace +{ +#if defined(_WIN32) +template <class Proc> auto ExecUnlocked(Proc proc, osl::ResettableMutexGuard& guard) +{ + ClearedMutexArea area(guard); + return proc(); +} +#endif +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/embeddedobj/source/msole/oleembed.cxx b/embeddedobj/source/msole/oleembed.cxx index 63d5f700b089..b946fed792c8 100644 --- a/embeddedobj/source/msole/oleembed.cxx +++ b/embeddedobj/source/msole/oleembed.cxx @@ -601,7 +601,7 @@ uno::Sequence< sal_Int32 > SAL_CALL OleEmbeddedObject::getReachableStates() } // end wrapping related part ==================== - ::osl::MutexGuard aGuard( m_aMutex ); + ::osl::ResettableMutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO @@ -620,7 +620,8 @@ uno::Sequence< sal_Int32 > SAL_CALL OleEmbeddedObject::getReachableStates() // the list of states can only be guessed based on standard verbs, // since there is no way to detect what additional verbs do - return GetReachableStatesList_Impl( m_pOleComponent->GetVerbList() ); + return GetReachableStatesList_Impl( + ExecUnlocked([this] { return m_pOleComponent->GetVerbList(); }, aGuard)); } else #endif diff --git a/embeddedobj/source/msole/olepersist.cxx b/embeddedobj/source/msole/olepersist.cxx index 381fc7b0d68c..e6af72fedccf 100644 --- a/embeddedobj/source/msole/olepersist.cxx +++ b/embeddedobj/source/msole/olepersist.cxx @@ -58,17 +58,6 @@ using namespace ::com::sun::star; using namespace ::comphelper; -namespace -{ -#if defined(_WIN32) -template <class Proc> auto ExecUnlocked(Proc proc, osl::ResettableMutexGuard& guard) -{ - ClearedMutexArea area(guard); - return proc(); -} -#endif -} - bool KillFile_Impl( const OUString& aURL, const uno::Reference< uno::XComponentContext >& xContext ) { commit 04bd9a4587bb41602a932444b0c6bfdeb0555de0 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:15 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:15 2024 +0500 Reapply "Make sure we hold the solar mutex before trying to release it" This reverts commit fb7612022c66781d91c782028a0d3affa578700a. diff --git a/vcl/source/helper/threadex.cxx b/vcl/source/helper/threadex.cxx index cbd342bd28df..1590b91f1167 100644 --- a/vcl/source/helper/threadex.cxx +++ b/vcl/source/helper/threadex.cxx @@ -52,6 +52,7 @@ void SolarThreadExecutor::execute() m_aStart.reset(); m_aFinish.reset(); ImplSVEvent* nEvent = Application::PostUserEvent(LINK(this, SolarThreadExecutor, worker)); + SolarMutexGuard aGuard; SolarMutexReleaser aReleaser; if (m_aStart.wait() == osl::Condition::result_timeout) { commit 8c4cf813affe409437d4acbae9b78b1f6438fd70 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:15 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:15 2024 +0500 Reapply "Convert an assert into a warning" This reverts commit ce79c71585f5fd5b30dc21517b405bcb37f7d142. diff --git a/vcl/win/window/salframe.cxx b/vcl/win/window/salframe.cxx index 6ab7bc61d673..91a4e6cc7e04 100644 --- a/vcl/win/window/salframe.cxx +++ b/vcl/win/window/salframe.cxx @@ -4106,8 +4106,14 @@ static void ImplHandleMoveMsg(HWND hWnd, LPARAM lParam) #ifdef NDEBUG (void) lParam; #endif - assert(IsIconic(hWnd) || (pFrame->maGeometry.x() == static_cast<sal_Int16>(LOWORD(lParam)))); - assert(IsIconic(hWnd) || (pFrame->maGeometry.y() == static_cast<sal_Int16>(HIWORD(lParam)))); + SAL_WARN_IF(!IsIconic(hWnd) && pFrame->maGeometry.x() != static_cast<sal_Int16>(LOWORD(lParam)), + "vcl", + "Unexpected X: " << pFrame->maGeometry.x() << " instead of " + << static_cast<sal_Int16>(LOWORD(lParam))); + SAL_WARN_IF(!IsIconic(hWnd) && pFrame->maGeometry.y() != static_cast<sal_Int16>(HIWORD(lParam)), + "vcl", + "Unexpected Y: " << pFrame->maGeometry.y() << " instead of " + << static_cast<sal_Int16>(HIWORD(lParam))); if (GetWindowStyle(hWnd) & WS_VISIBLE) pFrame->mbDefPos = false; commit e0e005adc93f92be01fb4aba70746618746fa053 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:15 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:15 2024 +0500 Reapply "Introduce a guard to delay processing of idles" This reverts commit 330c99dd7525cf1fd20b9b8fe388e02468ee2842. diff --git a/embeddedobj/source/inc/oleembobj.hxx b/embeddedobj/source/inc/oleembobj.hxx index 274ecfaf8847..cf7c5ebe4ab4 100644 --- a/embeddedobj/source/inc/oleembobj.hxx +++ b/embeddedobj/source/inc/oleembobj.hxx @@ -249,7 +249,8 @@ protected: const css::uno::Reference< css::embed::XStorage >& xStorage, const OUString& sEntName, const css::uno::Sequence< css::beans::PropertyValue >& lObjArgs, - bool bSaveAs ); + bool bSaveAs, + osl::ResettableMutexGuard& rGuard); #ifdef _WIN32 /// @throws css::uno::Exception void StoreObjectToStream( css::uno::Reference< css::io::XOutputStream > const & xOutStream ); diff --git a/embeddedobj/source/msole/olepersist.cxx b/embeddedobj/source/msole/olepersist.cxx index 86403f41bb3e..381fc7b0d68c 100644 --- a/embeddedobj/source/msole/olepersist.cxx +++ b/embeddedobj/source/msole/olepersist.cxx @@ -58,6 +58,17 @@ using namespace ::com::sun::star; using namespace ::comphelper; +namespace +{ +#if defined(_WIN32) +template <class Proc> auto ExecUnlocked(Proc proc, osl::ResettableMutexGuard& guard) +{ + ClearedMutexArea area(guard); + return proc(); +} +#endif +} + bool KillFile_Impl( const OUString& aURL, const uno::Reference< uno::XComponentContext >& xContext ) { @@ -1059,8 +1070,11 @@ void OleEmbeddedObject::StoreToLocation_Impl( const uno::Reference< embed::XStorage >& xStorage, const OUString& sEntName, const uno::Sequence< beans::PropertyValue >& lObjArgs, - bool bSaveAs ) + bool bSaveAs, osl::ResettableMutexGuard& rGuard) { +#ifndef _WIN32 + (void)rGuard; +#endif // TODO: use lObjArgs // TODO: exchange StoreVisualReplacement by SO file format version? @@ -1110,7 +1124,7 @@ void OleEmbeddedObject::StoreToLocation_Impl( #ifdef _WIN32 // if the object was NOT modified after storing it can be just copied // as if it was in loaded state - || ( m_pOleComponent && !m_pOleComponent->IsDirty() ) + || (m_pOleComponent && !ExecUnlocked([this] { return m_pOleComponent->IsDirty(); }, rGuard)) #endif ) { @@ -1482,13 +1496,13 @@ void SAL_CALL OleEmbeddedObject::storeToEntry( const uno::Reference< embed::XSto } // end wrapping related part ==================== - ::osl::MutexGuard aGuard( m_aMutex ); + ::osl::ResettableMutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); - StoreToLocation_Impl( xStorage, sEntName, lObjArgs, false ); + StoreToLocation_Impl( xStorage, sEntName, lObjArgs, false, aGuard ); // TODO: should the listener notification be done? } @@ -1509,13 +1523,13 @@ void SAL_CALL OleEmbeddedObject::storeAsEntry( const uno::Reference< embed::XSto } // end wrapping related part ==================== - ::osl::MutexGuard aGuard( m_aMutex ); + ::osl::ResettableMutexGuard aGuard( m_aMutex ); if ( m_bDisposed ) throw lang::DisposedException(); // TODO VerbExecutionControllerGuard aVerbGuard( m_aVerbExecutionController ); - StoreToLocation_Impl( xStorage, sEntName, lObjArgs, true ); + StoreToLocation_Impl( xStorage, sEntName, lObjArgs, true, aGuard ); // TODO: should the listener notification be done here or in saveCompleted? } @@ -1691,7 +1705,7 @@ void SAL_CALL OleEmbeddedObject::storeOwn() // ask container to store the object, the container has to make decision // to do so or not - osl::ClearableMutexGuard aGuard(m_aMutex); + osl::ResettableMutexGuard aGuard(m_aMutex); if ( m_bDisposed ) throw lang::DisposedException(); // TODO @@ -1717,7 +1731,7 @@ void SAL_CALL OleEmbeddedObject::storeOwn() bool bStoreLoaded = true; #ifdef _WIN32 - if ( m_nObjectState != embed::EmbedStates::LOADED && m_pOleComponent && m_pOleComponent->IsDirty() ) + if ( m_nObjectState != embed::EmbedStates::LOADED && m_pOleComponent && ExecUnlocked([this] { return m_pOleComponent->IsDirty(); }, aGuard) ) { bStoreLoaded = false; diff --git a/include/vcl/scheduler.hxx b/include/vcl/scheduler.hxx index 1b63404139bf..0181e52c33d2 100644 --- a/include/vcl/scheduler.hxx +++ b/include/vcl/scheduler.hxx @@ -81,6 +81,13 @@ public: static void SetDeterministicMode(bool bDeterministic); /// Return the current state of deterministic mode. static bool GetDeterministicMode(); + + // Makes sure that idles are not processed, until the guard is destroyed + struct VCL_DLLPUBLIC IdlesLockGuard final + { + IdlesLockGuard(); + ~IdlesLockGuard(); + }; }; #endif // INCLUDED_VCL_SCHEDULER_HXX diff --git a/sw/source/core/doc/DocumentLayoutManager.cxx b/sw/source/core/doc/DocumentLayoutManager.cxx index 75c8e86acdb2..425729833754 100644 --- a/sw/source/core/doc/DocumentLayoutManager.cxx +++ b/sw/source/core/doc/DocumentLayoutManager.cxx @@ -43,6 +43,7 @@ #include <svx/svdobj.hxx> #include <svx/svdpage.hxx> #include <osl/diagnose.h> +#include <vcl/scheduler.hxx> using namespace ::com::sun::star; @@ -191,6 +192,9 @@ SwFrameFormat *DocumentLayoutManager::MakeLayoutFormat( RndStdIds eRequest, cons /// Deletes the denoted format and its content. void DocumentLayoutManager::DelLayoutFormat( SwFrameFormat *pFormat ) { + // Do not paint, until the destruction is complete. Paint may access the layout and nodes + // while it's in inconsistent state, and crash. + Scheduler::IdlesLockGuard g; // A chain of frames needs to be merged, if necessary, // so that the Frame's contents are adjusted accordingly before we destroy the Frames. const SwFormatChain &rChain = pFormat->GetChain(); diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx index 06d0aeb9b9af..725f0cda4260 100644 --- a/vcl/inc/svdata.hxx +++ b/vcl/inc/svdata.hxx @@ -24,6 +24,7 @@ #include <o3tl/lru_map.hxx> #include <o3tl/hash_combine.hxx> +#include <osl/conditn.hxx> #include <tools/fldunit.hxx> #include <unotools/options.hxx> #include <vcl/bitmapex.hxx> @@ -383,6 +384,7 @@ struct ImplSchedulerContext std::mutex maMutex; ///< the "scheduler mutex" (see ///< vcl/README.scheduler) bool mbActive = true; ///< is the scheduler active? + oslInterlockedCount mnIdlesLockCount = 0; ///< temporary ignore idles }; struct ImplSVData @@ -424,6 +426,9 @@ struct ImplSVData css::uno::Reference<css::datatransfer::clipboard::XClipboard> m_xSystemClipboard; #endif + osl::Condition m_inExecuteCondtion; // Set when code returns to Application::Execute, + // i.e. no nested message loops run + Link<LinkParamNone*,void> maDeInitHook; // LOK & headless backend specific hooks diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx index 7afdfd0846e6..c0fc79d4ac5c 100644 --- a/vcl/source/app/scheduler.cxx +++ b/vcl/source/app/scheduler.cxx @@ -272,6 +272,32 @@ bool Scheduler::GetDeterministicMode() return g_bDeterministicMode; } +Scheduler::IdlesLockGuard::IdlesLockGuard() +{ + ImplSVData* pSVData = ImplGetSVData(); + ImplSchedulerContext& rSchedCtx = pSVData->maSchedCtx; + osl_atomic_increment(&rSchedCtx.mnIdlesLockCount); + if (!Application::IsMainThread()) + { + // Make sure that main thread has reached the main message loop, so no idles are executing. + // It is important to ensure this, because e.g. ProcessEventsToIdle could be executed in a + // nested event loop, while an active processed idle in the main thread is waiting for some + // condition to proceed. Only main thread returning to Application::Execute guarantees that + // the flag really took effect. + pSVData->m_inExecuteCondtion.reset(); + std::optional<SolarMutexReleaser> releaser; + if (pSVData->mpDefInst->GetYieldMutex()->IsCurrentThread()) + releaser.emplace(); + pSVData->m_inExecuteCondtion.wait(); + } +} + +Scheduler::IdlesLockGuard::~IdlesLockGuard() +{ + ImplSchedulerContext& rSchedCtx = ImplGetSVData()->maSchedCtx; + osl_atomic_decrement(&rSchedCtx.mnIdlesLockCount); +} + inline void Scheduler::UpdateSystemTimer( ImplSchedulerContext &rSchedCtx, const sal_uInt64 nMinPeriod, const bool bForce, const sal_uInt64 nTime ) @@ -458,8 +484,10 @@ void Scheduler::CallbackTaskScheduling() // Delay invoking tasks with idle priorities as long as there are user input or repaint events // in the OS event queue. This will often effectively compress such events and repaint only // once at the end, improving performance in cases such as repeated zooming with a complex document. - bool bDelayInvoking = bIsHighPriorityIdle && - Application::AnyInput( VclInputFlags::MOUSE | VclInputFlags::KEYBOARD | VclInputFlags::PAINT ); + bool bDelayInvoking + = bIsHighPriorityIdle + && (rSchedCtx.mnIdlesLockCount > 0 + || Application::AnyInput(VclInputFlags::MOUSE | VclInputFlags::KEYBOARD | VclInputFlags::PAINT)); /* * Current policy is that scheduler tasks aren't allowed to throw an exception. diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index d2c6294917f0..1f7831ea060b 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -450,7 +450,11 @@ void Application::Execute() std::abort(); } while (!pSVData->maAppData.mbAppQuit) + { Application::Yield(); + SolarMutexReleaser releaser; // Give a chance for the waiting threads to lock the mutex + pSVData->m_inExecuteCondtion.set(); + } } pSVData->maAppData.mbInAppExecute = false; commit 2fc2be9172ef5f2be84db380e4e1a5560cdbccab Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:15 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:15 2024 +0500 Reapply "Process pending events before ImplDeleteOnDeInit" This reverts commit a163ba398e760792570f01de7b62d3a3a133931c. diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx index 7c5505f364cb..a6dc00dcd9e9 100644 --- a/vcl/source/app/svmain.cxx +++ b/vcl/source/app/svmain.cxx @@ -440,6 +440,9 @@ void DeInitVCL() pSVData->mpBlendFrameCache->m_aLastResult.Clear(); pSVData->mbDeInit = true; + // Some events may need to access objects destroyed in ImplDeleteOnDeInit, so process them first + Scheduler::ProcessEventsToIdle(); + vcl::DeleteOnDeinitBase::ImplDeleteOnDeInit(); #if OSL_DEBUG_LEVEL > 0 commit 0c3c3fb8a269635c22249e3f2768f180d8c039bc Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:15 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:15 2024 +0500 Reapply "tdf#148434 - avoid strange OS/X deadlock around AnyInput." This reverts commit 0bf6b38c1e3fbfed7512a8677260e485f4fd9d9d. diff --git a/vcl/source/app/scheduler.cxx b/vcl/source/app/scheduler.cxx index f83a4bb04d32..7afdfd0846e6 100644 --- a/vcl/source/app/scheduler.cxx +++ b/vcl/source/app/scheduler.cxx @@ -426,24 +426,6 @@ void Scheduler::CallbackTaskScheduling() break; } -// tdf#148435 Apparently calling AnyInput on Mac and filtering for just input, gives -// you window creation / re-sizing events which then trigger idle paint -// events which then deadlock if called with the scheduler lock. -// So since this is an optimisation, just don't do this on mac. -#ifndef MACOSX - // Delay invoking tasks with idle priorities as long as there are user input or repaint events - // in the OS event queue. This will often effectively compress such events and repaint only - // once at the end, improving performance in cases such as repeated zooming with a complex document. - if ( pMostUrgent && pMostUrgent->mePriority >= TaskPriority::HIGH_IDLE - && Application::AnyInput( VclInputFlags::MOUSE | VclInputFlags::KEYBOARD | VclInputFlags::PAINT )) - { - SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() - << " idle priority task " << pMostUrgent << " delayed, system events pending" ); - pMostUrgent = nullptr; - nMinPeriod = 0; - } -#endif - if (InfiniteTimeoutMs != nMinPeriod) SAL_INFO("vcl.schedule", "Calculated minimum timeout as " << nMinPeriod << " of " << nTasks << " tasks"); @@ -459,9 +441,6 @@ void Scheduler::CallbackTaskScheduling() comphelper::ProfileZone aZone( pTask->GetDebugName() ); - // prepare Scheduler object for deletion after handling - pTask->SetDeletionFlags(); - assert(!pMostUrgent->mbInScheduler); pMostUrgent->mbInScheduler = true; @@ -471,8 +450,17 @@ void Scheduler::CallbackTaskScheduling() rSchedCtx.mpSchedulerStack = pMostUrgent; rSchedCtx.mpSchedulerStackTop = pMostUrgent; + bool bIsHighPriorityIdle = pMostUrgent->mePriority >= TaskPriority::HIGH_IDLE; + // invoke the task Unlock(); + + // Delay invoking tasks with idle priorities as long as there are user input or repaint events + // in the OS event queue. This will often effectively compress such events and repaint only + // once at the end, improving performance in cases such as repeated zooming with a complex document. + bool bDelayInvoking = bIsHighPriorityIdle && + Application::AnyInput( VclInputFlags::MOUSE | VclInputFlags::KEYBOARD | VclInputFlags::PAINT ); + /* * Current policy is that scheduler tasks aren't allowed to throw an exception. * Because otherwise the exception is caught somewhere totally unrelated. @@ -482,7 +470,16 @@ void Scheduler::CallbackTaskScheduling() */ try { - pTask->Invoke(); + if (bDelayInvoking) + SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() + << " idle priority task " << pTask->GetDebugName() + << " delayed, system events pending" ); + else + { + // prepare Scheduler object for deletion after handling + pTask->SetDeletionFlags(); + pTask->Invoke(); + } } catch (css::uno::Exception&) { commit b6c49a2850770ec7db3af0faedff90f22b25d112 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:14 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:14 2024 +0500 Reapply "Disallow closing document during generation of preview" This reverts commit 2bf752ad5912fc478a9bb036556bd7b224f0e19c. diff --git a/include/sfx2/objsh.hxx b/include/sfx2/objsh.hxx index 5d98cb0409af..d81727b4634f 100644 --- a/include/sfx2/objsh.hxx +++ b/include/sfx2/objsh.hxx @@ -821,6 +821,15 @@ public: } }; +class SfxCloseVetoLock +{ +public: + SfxCloseVetoLock(const SfxObjectShell& rDocShell); + ~SfxCloseVetoLock(); + +private: + const SfxObjectShell& m_rDocShell; +}; typedef rtl::Reference<SfxObjectShell> SfxObjectShellRef; diff --git a/sfx2/source/doc/objcont.cxx b/sfx2/source/doc/objcont.cxx index caf222c61d2d..a3b5226917d3 100644 --- a/sfx2/source/doc/objcont.cxx +++ b/sfx2/source/doc/objcont.cxx @@ -104,6 +104,7 @@ SfxObjectShell::GetPreviewMetaFile( bool bFullContent ) const BitmapEx SfxObjectShell::GetPreviewBitmap() const { + SfxCloseVetoLock lock(*this); ScopedVclPtrInstance< VirtualDevice > pDevice; pDevice->SetAntialiasing(AntialiasingFlags::Enable | pDevice->GetAntialiasing()); if(!CreatePreview_Impl(/*bFullContent*/false, pDevice, nullptr)) diff --git a/sfx2/source/doc/objxtor.cxx b/sfx2/source/doc/objxtor.cxx index ae6f713251ea..94c5cf54f600 100644 --- a/sfx2/source/doc/objxtor.cxx +++ b/sfx2/source/doc/objxtor.cxx @@ -28,6 +28,7 @@ #include <com/sun/star/util/XCloseable.hpp> #include <com/sun/star/frame/XComponentLoader.hpp> #include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/util/CloseVetoException.hpp> #include <com/sun/star/util/XCloseListener.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/frame/XTitle.hpp> @@ -135,8 +136,14 @@ public: } // namespace -void SAL_CALL SfxModelListener_Impl::queryClosing( const css::lang::EventObject& , sal_Bool ) +void SAL_CALL SfxModelListener_Impl::queryClosing( const css::lang::EventObject& , sal_Bool bDeliverOwnership) { + if (mpDoc->Get_Impl()->m_nClosingLockLevel) + { + if (bDeliverOwnership) + mpDoc->Get_Impl()->m_bCloseModelScheduled = true; + throw util::CloseVetoException("Closing document is blocked", {}); + } } void SAL_CALL SfxModelListener_Impl::notifyClosing( const css::lang::EventObject& ) @@ -301,8 +308,6 @@ SfxObjectShell::~SfxObjectShell() if ( pSfxApp && pSfxApp->GetDdeService() ) pSfxApp->RemoveDdeTopic( this ); - pImpl->pBaseModel.set( nullptr ); - // don't call GetStorage() here, in case of Load Failure it's possible that a storage was never assigned! if ( pMedium && pMedium->HasStorage_Impl() && pMedium->GetStorage( false ) == pImpl->m_xDocStorage ) pMedium->CanDisposeStorage_Impl( false ); @@ -337,6 +342,33 @@ SfxObjectShell::~SfxObjectShell() } } +SfxCloseVetoLock::SfxCloseVetoLock(const SfxObjectShell& rDocShell) + : m_rDocShell(rDocShell) +{ + osl_atomic_increment(&m_rDocShell.Get_Impl()->m_nClosingLockLevel); +} + +SfxCloseVetoLock::~SfxCloseVetoLock() +{ + if (osl_atomic_decrement(&m_rDocShell.Get_Impl()->m_nClosingLockLevel) == 0) + { + if (m_rDocShell.Get_Impl()->m_bCloseModelScheduled) + { + m_rDocShell.Get_Impl()->m_bCloseModelScheduled = false; // pass ownership + if (rtl::Reference model = static_cast<SfxBaseModel*>(m_rDocShell.GetBaseModel().get())) + { + try + { + model->close(true); + } + catch (const util::CloseVetoException&) + { + DBG_UNHANDLED_EXCEPTION("sfx.doc"); + } + } + } + } +} void SfxObjectShell::Stamp_SetPrintCancelState(bool bState) { diff --git a/sfx2/source/inc/objshimp.hxx b/sfx2/source/inc/objshimp.hxx index e5f67506cfda..cec0947cc3a9 100644 --- a/sfx2/source/inc/objshimp.hxx +++ b/sfx2/source/inc/objshimp.hxx @@ -135,6 +135,9 @@ struct SfxObjectShell_Impl final : public ::sfx2::IMacroDocumentAccess /// Holds Infobars until View is fully loaded std::vector<InfobarData> m_aPendingInfobars; + mutable oslInterlockedCount m_nClosingLockLevel = 0; + mutable bool m_bCloseModelScheduled = false; + SfxObjectShell_Impl( SfxObjectShell& _rDocShell ); virtual ~SfxObjectShell_Impl(); commit 174f724f595a2e63284fe4ad2d188370000e45b8 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Apr 7 21:54:14 2024 +0500 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Sun Apr 7 21:54:14 2024 +0500 Reapply "Use weak reference to SfxObjectShell in SfxEventHint to avoid use-after-free" This reverts commit 51c7be65ddd3de7ba98212e9f23230b4694b5e3e. diff --git a/basctl/source/basicide/unomodel.cxx b/basctl/source/basicide/unomodel.cxx index 4a9ee759f060..d4ce9544ce2d 100644 --- a/basctl/source/basicide/unomodel.cxx +++ b/basctl/source/basicide/unomodel.cxx @@ -123,7 +123,7 @@ com_sun_star_comp_basic_BasicID_get_implementation( { SolarMutexGuard aGuard; basctl::EnsureIde(); - SfxObjectShell* pShell = new basctl::DocShell(); + rtl::Reference<SfxObjectShell> pShell = new basctl::DocShell(); auto pModel = pShell->GetModel(); pModel->acquire(); return pModel.get(); diff --git a/basic/source/basmgr/basicmanagerrepository.cxx b/basic/source/basmgr/basicmanagerrepository.cxx index 7a2ed5efd20a..4ece6f6e2c7f 100644 --- a/basic/source/basmgr/basicmanagerrepository.cxx +++ b/basic/source/basmgr/basicmanagerrepository.cxx @@ -430,7 +430,7 @@ namespace basic OUString aAppBasicDir = SvtPathOptions().GetBasicPath(); // Storage and BaseURL are only needed by binary documents! - tools::SvRef<SotStorage> xDummyStor = new SotStorage( OUString() ); + rtl::Reference<SotStorage> xDummyStor = new SotStorage(OUString()); _out_rpBasicManager.reset(new BasicManager( *xDummyStor, u"" /* TODO/LATER: xStorage */, pAppBasic, &aAppBasicDir, true )); diff --git a/basic/source/basmgr/basmgr.cxx b/basic/source/basmgr/basmgr.cxx index 72776dd08153..71a937f81b5f 100644 --- a/basic/source/basmgr/basmgr.cxx +++ b/basic/source/basmgr/basmgr.cxx @@ -635,7 +635,7 @@ void BasicManager::ImpCreateStdLib( StarBASIC* pParentFromStdLib ) void BasicManager::LoadBasicManager( SotStorage& rStorage, std::u16string_view rBaseURL ) { - tools::SvRef<SotStorageStream> xManagerStream = rStorage.OpenSotStream( szManagerStream, eStreamReadMode ); + rtl::Reference<SotStorageStream> xManagerStream = rStorage.OpenSotStream( szManagerStream, eStreamReadMode ); OUString aStorName( rStorage.GetName() ); // #i13114 removed, DBG_ASSERT( aStorName.Len(), "No Storage Name!" ); @@ -727,7 +727,7 @@ void BasicManager::LoadBasicManager( SotStorage& rStorage, std::u16string_view r void BasicManager::LoadOldBasicManager( SotStorage& rStorage ) { - tools::SvRef<SotStorageStream> xManagerStream = rStorage.OpenSotStream( szOldManagerStream, eStreamReadMode ); + rtl::Reference<SotStorageStream> xManagerStream = rStorage.OpenSotStream( szOldManagerStream, eStreamReadMode ); OUString aStorName( rStorage.GetName() ); DBG_ASSERT( aStorName.getLength(), "No Storage Name!" ); @@ -780,7 +780,7 @@ void BasicManager::LoadOldBasicManager( SotStorage& rStorage ) aLibRelStorage = aLibRelStorage.smartRel2Abs( aLibRelStorageName, bWasAbsolute); DBG_ASSERT(!bWasAbsolute, "RelStorageName was absolute!" ); - tools::SvRef<SotStorage> xStorageRef; + rtl::Reference<SotStorage> xStorageRef; if ( aLibAbsStorage == aCurStorage || aLibRelStorageName == szImbedded ) { xStorageRef = &rStorage; @@ -841,7 +841,7 @@ bool BasicManager::ImpLoadLibrary( BasicLibInfo* pLibInfo, SotStorage* pCurStora { aStorageName = GetStorageName(); } - tools::SvRef<SotStorage> xStorage; + rtl::Reference<SotStorage> xStorage; // The current must not be opened again... if ( pCurStorage ) { @@ -864,7 +864,7 @@ bool BasicManager::ImpLoadLibrary( BasicLibInfo* pLibInfo, SotStorage* pCurStora { xStorage = new SotStorage( false, aStorageName, eStorageReadMode ); } - tools::SvRef<SotStorage> xBasicStorage = xStorage->OpenSotStorage( szBasicStorage, eStorageReadMode, false ); + rtl::Reference<SotStorage> xBasicStorage = xStorage->OpenSotStorage( szBasicStorage, eStorageReadMode, false ); if ( !xBasicStorage.is() || xBasicStorage->GetError() ) { @@ -874,7 +874,7 @@ bool BasicManager::ImpLoadLibrary( BasicLibInfo* pLibInfo, SotStorage* pCurStora else { // In the Basic-Storage every lib is in a Stream... - tools::SvRef<SotStorageStream> xBasicStream = xBasicStorage->OpenSotStream( pLibInfo->GetLibName(), eStreamReadMode ); + rtl::Reference<SotStorageStream> xBasicStream = xBasicStorage->OpenSotStream( pLibInfo->GetLibName(), eStreamReadMode ); if ( !xBasicStream.is() || xBasicStream->GetError() ) { StringErrorInfo* pErrInf = new StringErrorInfo( ERRCODE_BASMGR_LIBLOAD , pLibInfo->GetLibName(), DialogMask::ButtonsOk ); @@ -1096,7 +1096,7 @@ bool BasicManager::RemoveLib( sal_uInt16 nLib, bool bDelBasicFromStorage ) if (bDelBasicFromStorage && !(*itLibInfo)->IsReference() && (!(*itLibInfo)->IsExtern() || SotStorage::IsStorageFile((*itLibInfo)->GetStorageName()))) { - tools::SvRef<SotStorage> xStorage; + rtl::Reference<SotStorage> xStorage; try { if (!(*itLibInfo)->IsExtern()) @@ -1115,7 +1115,7 @@ bool BasicManager::RemoveLib( sal_uInt16 nLib, bool bDelBasicFromStorage ) if (xStorage.is() && xStorage->IsStorage(szBasicStorage)) { - tools::SvRef<SotStorage> xBasicStorage = xStorage->OpenSotStorage + rtl::Reference<SotStorage> xBasicStorage = xStorage->OpenSotStorage ( szBasicStorage, StreamMode::STD_READWRITE, false ); if ( !xBasicStorage.is() || xBasicStorage->GetError() ) @@ -1289,7 +1289,7 @@ StarBASIC* BasicManager::CreateLib( const OUString& rLibName, const OUString& Pa { try { - tools::SvRef<SotStorage> xStorage = new SotStorage(false, LinkTargetURL, StreamMode::READ | StreamMode::SHARE_DENYWRITE); + rtl::Reference<SotStorage> xStorage = new SotStorage(false, LinkTargetURL, StreamMode::READ | StreamMode::SHARE_DENYWRITE); if (!xStorage->GetError()) { pLib = AddLib(*xStorage, rLibName, true); diff --git a/basic/source/uno/scriptcont.cxx b/basic/source/uno/scriptcont.cxx index eea449ac47fc..3956c001ca31 100644 --- a/basic/source/uno/scriptcont.cxx +++ b/basic/source/uno/scriptcont.cxx @@ -334,7 +334,7 @@ rtl::Reference<SfxLibraryContainer> SfxScriptLibraryContainer::createInstanceImp void SfxScriptLibraryContainer::importFromOldStorage( const OUString& aFile ) { // TODO: move loading from old storage to binary filters? - auto xStorage = tools::make_ref<SotStorage>( false, aFile ); + rtl::Reference<SotStorage> xStorage(new SotStorage(false, aFile)); if( xStorage->GetError() == ERRCODE_NONE ) { auto pBasicManager = std::make_unique<BasicManager> ( *xStorage, aFile ); diff --git a/editeng/source/misc/svxacorr.cxx b/editeng/source/misc/svxacorr.cxx index 054011e2a390..c8ed7a6113b2 100644 --- a/editeng/source/misc/svxacorr.cxx +++ b/editeng/source/misc/svxacorr.cxx @@ -2228,7 +2228,7 @@ bool SvxAutoCorrectLanguageLists::IsFileChanged_Imp() void SvxAutoCorrectLanguageLists::LoadXMLExceptList_Imp( std::unique_ptr<SvStringsISortDtor>& rpLst, const OUString& sStrmName, - tools::SvRef<SotStorage>& rStg) + rtl::Reference<SotStorage>& rStg) { if( rpLst ) rpLst->clear(); @@ -2238,7 +2238,7 @@ void SvxAutoCorrectLanguageLists::LoadXMLExceptList_Imp( { if( rStg.is() && rStg->IsStream( sStrmName ) ) { - tools::SvRef<SotStorageStream> xStrm = rStg->OpenSotStream( sStrmName, + rtl::Reference<SotStorageStream> xStrm = rStg->OpenSotStream( sStrmName, ( StreamMode::READ | StreamMode::SHARE_DENYWRITE | StreamMode::NOCREATE ) ); if( ERRCODE_NONE != xStrm->GetError()) { @@ -2299,7 +2299,7 @@ void SvxAutoCorrectLanguageLists::LoadXMLExceptList_Imp( void SvxAutoCorrectLanguageLists::SaveExceptList_Imp( const SvStringsISortDtor& rLst, const OUString& sStrmName, - tools::SvRef<SotStorage> const &rStg, + rtl::Reference<SotStorage> const &rStg, bool bConvert ) { if( !rStg.is() ) @@ -2312,7 +2312,7 @@ void SvxAutoCorrectLanguageLists::SaveExceptList_Imp( } else { - tools::SvRef<SotStorageStream> xStrm = rStg->OpenSotStream( sStrmName, + rtl::Reference<SotStorageStream> xStrm = rStg->OpenSotStream( sStrmName, ( StreamMode::READ | StreamMode::WRITE | StreamMode::SHARE_DENYWRITE ) ); if( xStrm.is() ) { @@ -2431,7 +2431,7 @@ bool SvxAutoCorrectLanguageLists::AddToCplSttExceptList(const OUString& rNew) if( !rNew.isEmpty() && GetCplSttExceptList()->insert( rNew ).second ) { MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg ); @@ -2451,7 +2451,7 @@ bool SvxAutoCorrectLanguageLists::AddToWordStartExceptList(const OUString& rNew) if( !rNew.isEmpty() && GetWordStartExceptList()->insert( rNew ).second ) { MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); SaveExceptList_Imp( *pWordStart_ExcptLst, pXMLImplWordStart_ExcptLstStr, xStg ); @@ -2469,7 +2469,7 @@ SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadCplSttExceptList() { try { - tools::SvRef<SotStorage> xStg = new SotStorage( sShareAutoCorrFile, StreamMode::READ | StreamMode::SHARE_DENYNONE ); + rtl::Reference<SotStorage> xStg = new SotStorage( sShareAutoCorrFile, StreamMode::READ | StreamMode::SHARE_DENYNONE ); if( xStg.is() && xStg->IsContained( pXMLImplCplStt_ExcptLstStr ) ) LoadXMLExceptList_Imp( pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg ); } @@ -2482,7 +2482,7 @@ SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadCplSttExceptList() void SvxAutoCorrectLanguageLists::SaveCplSttExceptList() { MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg ); @@ -2498,7 +2498,7 @@ SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadWordStartExceptList() { try { - tools::SvRef<SotStorage> xStg = new SotStorage( sShareAutoCorrFile, StreamMode::READ | StreamMode::SHARE_DENYNONE ); + rtl::Reference<SotStorage> xStg = new SotStorage( sShareAutoCorrFile, StreamMode::READ | StreamMode::SHARE_DENYNONE ); if( xStg.is() && xStg->IsContained( pXMLImplWordStart_ExcptLstStr ) ) LoadXMLExceptList_Imp( pWordStart_ExcptLst, pXMLImplWordStart_ExcptLstStr, xStg ); } @@ -2512,7 +2512,7 @@ SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadWordStartExceptList() void SvxAutoCorrectLanguageLists::SaveWordStartExceptList() { MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); SaveExceptList_Imp( *pWordStart_ExcptLst, pXMLImplWordStart_ExcptLstStr, xStg ); @@ -2542,7 +2542,7 @@ void SvxAutoCorrectLanguageLists::RemoveStream_Imp( const OUString& rName ) { if( sShareAutoCorrFile != sUserAutoCorrFile ) { - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); if( xStg.is() && ERRCODE_NONE == xStg->GetError() && xStg->IsStream( rName ) ) { @@ -2604,8 +2604,8 @@ void SvxAutoCorrectLanguageLists::MakeUserStorage_Impl() } if (bConvert && !bError) { - tools::SvRef<SotStorage> xSrcStg = new SotStorage( aDest.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ), StreamMode::READ ); - tools::SvRef<SotStorage> xDstStg = new SotStorage( sUserAutoCorrFile, StreamMode::WRITE ); + rtl::Reference<SotStorage> xSrcStg = new SotStorage( aDest.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ), StreamMode::READ ); + rtl::Reference<SotStorage> xDstStg = new SotStorage(sUserAutoCorrFile, StreamMode::WRITE); if( xSrcStg.is() && xDstStg.is() ) { @@ -2653,7 +2653,7 @@ bool SvxAutoCorrectLanguageLists::MakeBlocklist_Imp( SotStorage& rStg ) bool bRet = true, bRemove = !pAutocorr_List || pAutocorr_List->empty(); if( !bRemove ) { - tools::SvRef<SotStorageStream> refList = rStg.OpenSotStream( pXMLImplAutocorr_ListStr, + rtl::Reference<SotStorageStream> refList = rStg.OpenSotStream( pXMLImplAutocorr_ListStr, ( StreamMode::READ | StreamMode::WRITE | StreamMode::SHARE_DENYWRITE ) ); if( refList.is() ) { @@ -2704,7 +2704,7 @@ bool SvxAutoCorrectLanguageLists::MakeCombinedChanges( std::vector<SvxAutocorrWo GetAutocorrWordList(); MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStorage = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStorage = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); bool bRet = xStorage.is() && ERRCODE_NONE == xStorage->GetError(); @@ -2773,7 +2773,7 @@ bool SvxAutoCorrectLanguageLists::PutText( const OUString& rShort, const OUStrin GetAutocorrWordList(); MakeUserStorage_Impl(); - tools::SvRef<SotStorage> xStg = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStg = new SotStorage(sUserAutoCorrFile, StreamMode::READWRITE); bool bRet = xStg.is() && ERRCODE_NONE == xStg->GetError(); @@ -2831,7 +2831,7 @@ void SvxAutoCorrectLanguageLists::PutText( const OUString& rShort, { if( pAutocorr_List->Insert( SvxAutocorrWord(rShort, sLong, false) ) ) { - tools::SvRef<SotStorage> xStor = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xStor = new SotStorage( sUserAutoCorrFile, StreamMode::READWRITE ); MakeBlocklist_Imp( *xStor ); } } diff --git a/filter/source/msfilter/msdffimp.cxx b/filter/source/msfilter/msdffimp.cxx index cdcad2778f6f..bfd141b4dc73 100644 --- a/filter/source/msfilter/msdffimp.cxx +++ b/filter/source/msfilter/msdffimp.cxx @@ -6756,7 +6756,7 @@ void SvxMSDffManager::ProcessClientAnchor2( SvStream& /* rSt */, DffRecordHeader // will be overridden by SJ in Draw } -bool SvxMSDffManager::GetOLEStorageName( sal_uInt32, OUString&, tools::SvRef<SotStorage>&, uno::Reference < embed::XStorage >& ) const +bool SvxMSDffManager::GetOLEStorageName( sal_uInt32, OUString&, rtl::Reference<SotStorage>&, uno::Reference < embed::XStorage >& ) const { return false; } @@ -6775,7 +6775,7 @@ rtl::Reference<SdrObject> SvxMSDffManager::ImportOLE( sal_uInt32 nOLEId, { rtl::Reference<SdrObject> pRet; OUString sStorageName; - tools::SvRef<SotStorage> xSrcStg; + rtl::Reference<SotStorage> xSrcStg; ErrCode nError = ERRCODE_NONE; uno::Reference < embed::XStorage > xDstStg; if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg )) @@ -6797,7 +6797,7 @@ rtl::Reference<SdrObject> SvxMSDffManager::ImportOLE( sal_uInt32 nOLEId, bool SvxMSDffManager::MakeContentStream( SotStorage * pStor, const GDIMetaFile & rMtf ) { - tools::SvRef<SotStorageStream> xStm = pStor->OpenSotStream(SVEXT_PERSIST_STREAM); + rtl::Reference<SotStorageStream> xStm = pStor->OpenSotStream(SVEXT_PERSIST_STREAM); xStm->SetVersion( pStor->GetVersion() ); xStm->SetBufferSize( 8192 ); @@ -6937,10 +6937,10 @@ const ClsIDs aClsIDs[] = { bool SvxMSDffManager::ConvertToOle2( SvStream& rStm, sal_uInt32 nReadLen, - const GDIMetaFile * pMtf, const tools::SvRef<SotStorage>& rDest ) + const GDIMetaFile * pMtf, const rtl::Reference<SotStorage>& rDest ) { bool bMtfRead = false; - tools::SvRef<SotStorageStream> xOle10Stm = rDest->OpenSotStream( "Ole10Native", + rtl::Reference<SotStorageStream> xOle10Stm = rDest->OpenSotStream( "Ole10Native", StreamMode::WRITE| StreamMode::SHARE_DENYALL ); if( xOle10Stm->GetError() ) return false; @@ -6986,7 +6986,7 @@ bool SvxMSDffManager::ConvertToOle2( SvStream& rStm, sal_uInt32 nReadLen, // write to ole10 stream xOle10Stm->WriteUInt32( nDataLen ); xOle10Stm->WriteBytes(pData.get(), nDataLen); - xOle10Stm = tools::SvRef<SotStorageStream>(); + xOle10Stm.clear(); // set the compobj stream const ClsIDs* pIds; @@ -7104,7 +7104,7 @@ OUString SvxMSDffManager::GetFilterNameFromClassID( const SvGlobalName& aGlobNam void SvxMSDffManager::ExtractOwnStream(SotStorage& rSrcStg, SvMemoryStream& rMemStream) { - tools::SvRef<SotStorageStream> xStr + rtl::Reference<SotStorageStream> xStr = rSrcStg.OpenSotStream("package_stream", StreamMode::STD_READ); xStr->ReadStream(rMemStream); } @@ -7177,7 +7177,7 @@ css::uno::Reference < css::embed::XEmbeddedObject > SvxMSDffManager::CheckForCo } else { - tools::SvRef<SotStorage> xStorage = new SotStorage( false, aMemStream ); + rtl::Reference<SotStorage> xStorage = new SotStorage(false, aMemStream); rSrcStg.CopyTo( xStorage.get() ); xStorage->Commit(); xStorage.clear(); @@ -7291,7 +7291,7 @@ css::uno::Reference < css::embed::XEmbeddedObject > SvxMSDffManager::CheckForCo rtl::Reference<SdrOle2Obj> SvxMSDffManager::CreateSdrOLEFromStorage( SdrModel& rSdrModel, const OUString& rStorageName, - tools::SvRef<SotStorage> const & rSrcStorage, + rtl::Reference<SotStorage> const & rSrcStorage, const uno::Reference < embed::XStorage >& xDestStorage, const Graphic& rGrf, const tools::Rectangle& rBoundRect, @@ -7314,12 +7314,12 @@ rtl::Reference<SdrOle2Obj> SvxMSDffManager::CreateSdrOLEFromStorage( OUString aDstStgName = MSO_OLE_Obj + OUString::number( ++nMSOleObjCntr ); { - tools::SvRef<SotStorage> xObjStg = rSrcStorage->OpenSotStorage( rStorageName ); + rtl::Reference<SotStorage> xObjStg = rSrcStorage->OpenSotStorage(rStorageName); if( xObjStg.is() ) { { sal_uInt8 aTestA[10]; // exist the CompObj-Stream ? - tools::SvRef<SotStorageStream> xSrcTst = xObjStg->OpenSotStream( "CompObj" ); + rtl::Reference<SotStorageStream> xSrcTst = xObjStg->OpenSotStream("CompObj"); bValidStorage = xSrcTst.is() && sizeof( aTestA ) == xSrcTst->ReadBytes(aTestA, sizeof(aTestA)); if( !bValidStorage ) @@ -7340,7 +7340,7 @@ rtl::Reference<SdrOle2Obj> SvxMSDffManager::CreateSdrOLEFromStorage( // is a kind of embedded objects in Word documents // TODO/LATER: should the caller be notified if the aspect changes in future? - tools::SvRef<SotStorageStream> xObjInfoSrc = xObjStg->OpenSotStream( + rtl::Reference<SotStorageStream> xObjInfoSrc = xObjStg->OpenSotStream( "ObjInfo", StreamMode::STD_READ ); if ( xObjInfoSrc.is() && !xObjInfoSrc->GetError() ) { @@ -7382,11 +7382,11 @@ rtl::Reference<SdrOle2Obj> SvxMSDffManager::CreateSdrOLEFromStorage( if( bValidStorage ) { // object is not an own object - tools::SvRef<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName, StreamMode::READWRITE ); + rtl::Reference<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName, StreamMode::READWRITE ); if ( xObjStor.is() ) { - tools::SvRef<SotStorage> xSrcStor = rSrcStorage->OpenSotStorage( rStorageName, StreamMode::READ ); + rtl::Reference<SotStorage> xSrcStor = rSrcStorage->OpenSotStorage( rStorageName, StreamMode::READ ); xSrcStor->CopyTo( xObjStor.get() ); if( !xObjStor->GetError() ) @@ -7413,7 +7413,7 @@ rtl::Reference<SdrOle2Obj> SvxMSDffManager::CreateSdrOLEFromStorage( else { // or is it an OLE-1 Stream in the DataStream? - tools::SvRef<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName ); + rtl::Reference<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName ); //TODO/MBA: remove metafile conversion from ConvertToOle2 //when is this code used?! GDIMetaFile aMtf; diff --git a/filter/source/msfilter/msoleexp.cxx b/filter/source/msfilter/msoleexp.cxx index cd9f521da605..3229bf57ec54 100644 --- a/filter/source/msfilter/msoleexp.cxx +++ b/filter/source/msfilter/msoleexp.cxx @@ -203,7 +203,7 @@ void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef const & rObj } catch( const uno::Exception& ) {} // #TODO really handle exceptions - interactionalhandler etc. ? - tools::SvRef<SotStorage> xOLEStor = new SotStorage( pStream, true ); + rtl::Reference<SotStorage> xOLEStor = new SotStorage( pStream, true ); xOLEStor->CopyTo( &rDestStg ); rDestStg.Commit(); } @@ -224,7 +224,7 @@ void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef const & rObj rDestStg.SetClass( aEmbName, SotClipboardFormatId::EMBEDDED_OBJ_OLE, GetStorageType( aEmbName ) ); - tools::SvRef<SotStorageStream> xExtStm = rDestStg.OpenSotStream( + rtl::Reference<SotStorageStream> xExtStm = rDestStg.OpenSotStream( "properties_stream"); bool bExtentSuccess = false; @@ -279,7 +279,7 @@ void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef const & rObj if ( bExtentSuccess ) { - tools::SvRef<SotStorageStream> xEmbStm = rDestStg.OpenSotStream( + rtl::Reference<SotStorageStream> xEmbStm = rDestStg.OpenSotStream( "package_stream"); if( !xEmbStm->GetError() ) { @@ -326,7 +326,7 @@ void SvxMSExportOLEObjects::ExportOLEObject( svt::EmbeddedObjectRef const & rObj catch ( const uno::Exception& ) {} - tools::SvRef<SotStorage> xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, StreamMode::STD_READ ); + rtl::Reference<SotStorage> xOLEStor = SotStorage::OpenOLEStorage( xStor, aTempName, StreamMode::STD_READ ); xOLEStor->CopyTo( &rDestStg ); rDestStg.Commit(); } diff --git a/filter/source/msfilter/rtfutil.cxx b/filter/source/msfilter/rtfutil.cxx index 75f453c347c9..f9881c86a2b9 100644 --- a/filter/source/msfilter/rtfutil.cxx +++ b/filter/source/msfilter/rtfutil.cxx @@ -26,7 +26,7 @@ namespace void WrapOle1InOle2(SvStream& rOle1, sal_uInt32 nOle1Size, SvStream& rOle2, const OString& rClassName) { - tools::SvRef<SotStorage> pStorage = new SotStorage(rOle2); + rtl::Reference<SotStorage> pStorage = new SotStorage(rOle2); OString aAnsiUserType; SvGlobalName aName; if (rClassName == "PBrush") @@ -46,7 +46,7 @@ void WrapOle1InOle2(SvStream& rOle1, sal_uInt32 nOle1Size, SvStream& rOle2, pStorage->SetClass(aName, SotClipboardFormatId::NONE, ""); // [MS-OLEDS] 2.3.7 CompObjHeader - tools::SvRef<SotStorageStream> pCompObj = pStorage->OpenSotStream("CompObj"); + rtl::Reference<SotStorageStream> pCompObj = pStorage->OpenSotStream("CompObj"); // Reserved1 pCompObj->WriteUInt32(0xfffe0001); // Version @@ -80,7 +80,7 @@ void WrapOle1InOle2(SvStream& rOle1, sal_uInt32 nOle1Size, SvStream& rOle2, pCompObj.clear(); // [MS-OLEDS] 2.3.6 OLENativeStream - tools::SvRef<SotStorageStream> pOleNative = pStorage->OpenSotStream("Ole10Native"); + rtl::Reference<SotStorageStream> pOleNative = pStorage->OpenSotStream("Ole10Native"); // NativeDataSize pOleNative->WriteUInt32(nOle1Size); pOleNative->WriteStream(rOle1, nOle1Size); diff --git a/filter/source/msfilter/svdfppt.cxx b/filter/source/msfilter/svdfppt.cxx index cb6381fb6fd3..5f74aa47eea2 100644 --- a/filter/source/msfilter/svdfppt.cxx +++ b/filter/source/msfilter/svdfppt.cxx @@ -1677,7 +1677,7 @@ SdrPowerPointImport::~SdrPowerPointImport() m_pNotePages.reset(); } -bool PPTConvertOCXControls::ReadOCXStream( tools::SvRef<SotStorage>& rSrc, +bool PPTConvertOCXControls::ReadOCXStream( rtl::Reference<SotStorage>& rSrc, css::uno::Reference< css::drawing::XShape > *pShapeRef ) { bool bRes = false; @@ -1856,14 +1856,14 @@ rtl::Reference<SdrObject> SdrPowerPointImport::ImportOLE( sal_uInt32 nOLEId, { pDest->Seek(0); Storage* pObjStor = new Storage(*pDest, false); - tools::SvRef<SotStorage> xObjStor( new SotStorage( pObjStor ) ); + rtl::Reference<SotStorage> xObjStor(new SotStorage(pObjStor)); if ( xObjStor.is() && !xObjStor->GetError() ) { if ( xObjStor->GetClassName() == SvGlobalName() ) { xObjStor->SetClass( SvGlobalName( pObjStor->GetClassId() ), pObjStor->GetFormat(), pObjStor->GetUserName() ); } - tools::SvRef<SotStorageStream> xSrcTst = xObjStor->OpenSotStream( "Ole" ); + rtl::Reference<SotStorageStream> xSrcTst = xObjStor->OpenSotStream("Ole"); if ( xSrcTst.is() ) { sal_uInt8 aTestA[ 10 ]; @@ -1914,7 +1914,7 @@ rtl::Reference<SdrObject> SdrPowerPointImport::ImportOLE( sal_uInt32 nOLEId, const css::uno::Reference < css::embed::XStorage >& rStorage = rOe.pShell->GetStorage(); if (rStorage.is()) { - tools::SvRef<SotStorage> xTarget = SotStorage::OpenOLEStorage(rStorage, aNm, StreamMode::READWRITE); + rtl::Reference<SotStorage> xTarget = SotStorage::OpenOLEStorage(rStorage, aNm, StreamMode::READWRITE); if (xObjStor.is() && xTarget.is()) { xObjStor->CopyTo(xTarget.get()); @@ -2035,16 +2035,16 @@ void SdrPowerPointImport::SeekOle( SfxObjectShell* pShell, sal_uInt32 nFilterOpt std::unique_ptr<SvMemoryStream> pBas = ImportExOleObjStg( nPersistPtr, nOleId ); if ( pBas ) { - tools::SvRef<SotStorage> xSource( new SotStorage( pBas.release(), true ) ); - tools::SvRef<SotStorage> xDest( new SotStorage( new SvMemoryStream(), true ) ); + rtl::Reference<SotStorage> xSource(new SotStorage(pBas.release(), true)); + rtl::Reference<SotStorage> xDest( new SotStorage( new SvMemoryStream(), true ) ); if ( xSource.is() && xDest.is() ) { // is this a visual basic storage ? - tools::SvRef<SotStorage> xSubStorage = xSource->OpenSotStorage( "VBA", + rtl::Reference<SotStorage> xSubStorage = xSource->OpenSotStorage( "VBA", StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL ); if( xSubStorage.is() && ( ERRCODE_NONE == xSubStorage->GetError() ) ) { - tools::SvRef<SotStorage> xMacros = xDest->OpenSotStorage( "MACROS" ); + rtl::Reference<SotStorage> xMacros = xDest->OpenSotStorage( "MACROS" ); if ( xMacros.is() ) { SvStorageInfoList aList; @@ -2063,13 +2063,13 @@ void SdrPowerPointImport::SeekOle( SfxObjectShell* pShell, sal_uInt32 nFilterOpt uno::Reference < embed::XStorage > xDoc( pShell->GetStorage() ); if ( xDoc.is() ) { - tools::SvRef<SotStorage> xVBA = SotStorage::OpenOLEStorage( xDoc, SvxImportMSVBasic::GetMSBasicStorageName() ); + rtl::Reference<SotStorage> xVBA = SotStorage::OpenOLEStorage( xDoc, SvxImportMSVBasic::GetMSBasicStorageName() ); if ( xVBA.is() && ( xVBA->GetError() == ERRCODE_NONE ) ) { - tools::SvRef<SotStorage> xSubVBA = xVBA->OpenSotStorage( "_MS_VBA_Overhead" ); + rtl::Reference<SotStorage> xSubVBA = xVBA->OpenSotStorage( "_MS_VBA_Overhead" ); if ( xSubVBA.is() && ( xSubVBA->GetError() == ERRCODE_NONE ) ) { - tools::SvRef<SotStorageStream> xOriginal = xSubVBA->OpenSotStream( "_MS_VBA_Overhead2" ); + rtl::Reference<SotStorageStream> xOriginal = xSubVBA->OpenSotStream( "_MS_VBA_Overhead2" ); if ( xOriginal.is() && ( xOriginal->GetError() == ERRCODE_NONE ) ) { if ( nPersistPtr && ( nPersistPtr < m_nPersistPtrCnt ) ) diff --git a/filter/source/msfilter/svxmsbas2.cxx b/filter/source/msfilter/svxmsbas2.cxx index 8a4ce43f1914..71ac50fd3928 100644 --- a/filter/source/msfilter/svxmsbas2.cxx +++ b/filter/source/msfilter/svxmsbas2.cxx @@ -33,7 +33,7 @@ ErrCode SvxImportMSVBasic::SaveOrDelMSVBAStorage( bool bSaveInto, ErrCode nRet = ERRCODE_NONE; uno::Reference < embed::XStorage > xSrcRoot( rDocSh.GetStorage() ); OUString aDstStgName( GetMSBasicStorageName() ); - tools::SvRef<SotStorage> xVBAStg( SotStorage::OpenOLEStorage( xSrcRoot, aDstStgName, + rtl::Reference<SotStorage> xVBAStg( SotStorage::OpenOLEStorage( xSrcRoot, aDstStgName, StreamMode::READWRITE | StreamMode::NOCREATE | StreamMode::SHARE_DENYALL ) ); if( xVBAStg.is() && !xVBAStg->GetError() ) { -e ... etc. - the rest is truncated