tdf#150676 sw a11y: Remove item from selection list on dispose
As reported in tdf#150676, selecting a table (or also just
simple text paragraphs) in Writer, then deleting the selection
would result in the following warning when using the gtk3
VCL plugin:
warn:legacy.osl:100403:100403:sw/source/core/access/acccontext.cxx:442: fire event for disposed frame?
This is because the code responsible for sending a11y events
for selection updates gets called after the a11y objects
of the previous selection have been disposed already and
wants to send an event that the object has been unselected:
> 1 SwAccessibleContext::FireAccessibleEvent acccontext.cxx 444 0x7f4ffc5be7a2
> 2 SwAccessibleContext::FireStateChangedEvent acccontext.cxx 475 0x7f4ffc5be8c2
> 3 SwAccessibleContext::SetSelectedState acccontext.cxx 1508 0x7f4ffc5c3752
> 4 SwAccessibleMap::InvalidateShapeInParaSelection accmap.cxx 1428 0x7f4ffc5ea0fd
> 5 SwAccessibleMap::InvalidateCursorPosition accmap.cxx 2671 0x7f4ffc5f119d
> 6 SwViewShellImp::InvalidateAccessibleCursorPosition viewimp.cxx 415 0x7f4ffd515c32
> 7 SwCursorShell::UpdateCursor crsrsh.cxx 2029 0x7f4ffc745e06
> 8 SwCursorShell::EndAction crsrsh.cxx 278 0x7f4ffc73d4a7
> 9 SwActContext::~SwActContext edws.cxx 169 0x7f4ffccd45d4
> 10 SwWrtShell::DelRight delete.cxx 322 0x7f4ffdc5a454
> 11 SwBaseShell::ExecDelete basesh.cxx 229 0x7f4ffd9e304d
> 12 SfxStubSwBaseShellExecDelete swslots.hxx 2173 0x7f4ffd9e2784
> 13 SfxDispatcher::Call_Impl dispatch.cxx 254 0x7f5039ab6f72
> 14 SfxDispatcher::Execute_ dispatch.cxx 753 0x7f5039aba37c
> 15 SfxBindings::Execute_Impl bindings.cxx 1060 0x7f5039aa62b7
> 16 SfxDispatchController_Impl::dispatch unoctitm.cxx 701 0x7f5039b7a55e
> 17 SfxOfficeDispatch::dispatch unoctitm.cxx 263 0x7f5039b7840d
> 18 svt::(anonymous namespace)::AsyncAccelExec::impl_ts_asyncCallback acceleratorexecute.cxx 481 0x7f5036a40cfc
> 19 svt::(anonymous namespace)::AsyncAccelExec::LinkStubimpl_ts_asyncCallback acceleratorexecute.cxx 473 0x7f5036a40c1d
> 20 Link<LinkParamNone *, void>::Call link.hxx 111 0x7f50336ac77f
> ...
To prevent that, remove the entry from the map of
selected frames as well right when the object gets
disposed.
If necessary, sending the corresponding event that
the item has been unselected should probably be done
here, but it currently seems to be of little value to me
when the object gets deleted anyway, so this commit
doesn't add sending an additional event here.
While at it, convert the `OSL_ENSURE` to a `SAL_WARN`.
Warning in case `FireAccessibleEvent` gets called
on an already disposed object generally seems reasonable
to me.
Change-Id: I879ba4e6399ffdc61e38093c5a9bd2ae620888e7
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139039
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
diff --git a/sw/source/core/access/acccontext.cxx b/sw/source/core/access/acccontext.cxx
index 40ede78..f9edaa8 100644
--- a/sw/source/core/access/acccontext.cxx
+++ b/sw/source/core/access/acccontext.cxx
@@ -439,9 +439,11 @@ void SwAccessibleContext::InvalidateFocus_()
void SwAccessibleContext::FireAccessibleEvent( AccessibleEventObject& rEvent )
{
OSL_ENSURE( GetFrame(), "fire event for disposed frame?" );
if( !GetFrame() )
{
SAL_WARN("sw.a11y", "SwAccessibleContext::FireAccessibleEvent called for already disposed frame?");
return;
}
if( !rEvent.Source.is() )
{
diff --git a/sw/source/core/access/accmap.cxx b/sw/source/core/access/accmap.cxx
index 6722253..7b8808e 100644
--- a/sw/source/core/access/accmap.cxx
+++ b/sw/source/core/access/accmap.cxx
@@ -2093,6 +2093,13 @@ void SwAccessibleMap::RemoveContext( const SwFrame *pFrame )
mpFrameMap->erase( aIter );
if (mpSelectedFrameMap)
{
SwAccessibleContextMap_Impl::iterator aSelectedIter = mpSelectedFrameMap->find(pFrame);
if (aSelectedIter != mpSelectedFrameMap->end())
mpSelectedFrameMap->erase(aSelectedIter);
}
// Remove reference to old caret object. Though mxCursorContext
// is a weak reference and cleared automatically, clearing it
// directly makes sure to not keep a non-functional object.