diff --git a/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx b/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx index 14c8f7117962..5cf595fced13 100644 --- a/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx +++ b/sd/source/ui/accessibility/AccessibleSlideSorterView.cxx @@ -62,6 +62,14 @@ using namespace ::com::sun::star::accessibility; namespace accessibility { +/** Inner implementation class of the AccessibleSlideSorterView. + + Note that some event broadcasting is done asynchronously because + otherwise it could lead to deadlocks on (at lease) some Solaris + machines. Probably (but unverified) this can happen on all GTK based + systems. The asynchronous broadcasting is just a workaround for a + poorly understood problem. +*/ class AccessibleSlideSorterView::Implementation : public SfxListener { @@ -72,7 +80,7 @@ public: ::Window* pWindow); ~Implementation (void); - void UpdateChildren (void); + void RequestUpdateChildren (void); void Clear (void); sal_Int32 GetVisibleChildCount (void) const; AccessibleSlideSorterObject* GetAccessibleChild (sal_Int32 nIndex); @@ -83,8 +91,9 @@ public: void Notify (SfxBroadcaster& rBroadcaster, const SfxHint& rHint); DECL_LINK(WindowEventListener, VclWindowEvent*); DECL_LINK(SelectionChangeListener, void*); + DECL_LINK(BroadcastSelectionChange, void*); DECL_LINK(FocusChangeListener, void*); - DECL_LINK(VisibilityChangeListener, void*); + DECL_LINK(UpdateChildrenCallback, void*); private: AccessibleSlideSorterView& mrAccessibleSlideSorter; @@ -97,6 +106,10 @@ private: ::Window* mpWindow; sal_Int32 mnFocusedIndex; bool mbModelChangeLocked; + ULONG mnUpdateChildrenUserEventId; + ULONG mnSelectionChangeUserEventId; + + void UpdateChildren (void); }; @@ -115,7 +128,6 @@ AccessibleSlideSorterView::AccessibleSlideSorterView( mnClientId(0), mpContentWindow(pContentWindow) { - OSL_TRACE("creating AccessibleSlideSorterView"); } @@ -771,6 +783,9 @@ sal_Bool AccessibleSlideSorterView::IsDisposed (void) return (rBHelper.bDisposed || rBHelper.bInDispose); } + + + //===== AccessibleSlideSorterView::Implementation ============================= AccessibleSlideSorterView::Implementation::Implementation ( @@ -785,7 +800,9 @@ AccessibleSlideSorterView::Implementation::Implementation ( mbListeningToDocument(false), mpWindow(pWindow), mnFocusedIndex(-1), - mbModelChangeLocked(false) + mbModelChangeLocked(false), + mnUpdateChildrenUserEventId(0), + mnSelectionChangeUserEventId(0) { ConnectListeners(); UpdateChildren(); @@ -796,6 +813,10 @@ AccessibleSlideSorterView::Implementation::Implementation ( AccessibleSlideSorterView::Implementation::~Implementation (void) { + if (mnUpdateChildrenUserEventId != 0) + Application::RemoveUserEvent(mnUpdateChildrenUserEventId); + if (mnSelectionChangeUserEventId != 0) + Application::RemoveUserEvent(mnSelectionChangeUserEventId); ReleaseListeners(); Clear(); } @@ -803,6 +824,17 @@ AccessibleSlideSorterView::Implementation::~Implementation (void) +void AccessibleSlideSorterView::Implementation::RequestUpdateChildren (void) +{ + if (mnUpdateChildrenUserEventId == 0) + mnUpdateChildrenUserEventId = Application::PostUserEvent( + LINK(this, AccessibleSlideSorterView::Implementation, + UpdateChildrenCallback)); +} + + + + void AccessibleSlideSorterView::Implementation::UpdateChildren (void) { if (mbModelChangeLocked) @@ -928,7 +960,7 @@ void AccessibleSlideSorterView::Implementation::ConnectListeners (void) mrSlideSorter.GetController().GetFocusManager().AddFocusChangeListener( LINK(this,AccessibleSlideSorterView::Implementation,FocusChangeListener)); mrSlideSorter.GetView().AddVisibilityChangeListener( - LINK(this,AccessibleSlideSorterView::Implementation,VisibilityChangeListener)); + LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback)); } @@ -941,7 +973,7 @@ void AccessibleSlideSorterView::Implementation::ReleaseListeners (void) mrSlideSorter.GetController().GetSelectionManager()->RemoveSelectionChangeListener( LINK(this,AccessibleSlideSorterView::Implementation,SelectionChangeListener)); mrSlideSorter.GetView().RemoveVisibilityChangeListener( - LINK(this,AccessibleSlideSorterView::Implementation,VisibilityChangeListener)); + LINK(this,AccessibleSlideSorterView::Implementation,UpdateChildrenCallback)); if (mpWindow != NULL) mpWindow->RemoveEventListener( @@ -969,7 +1001,7 @@ void AccessibleSlideSorterView::Implementation::Notify ( switch (rSdrHint.GetKind()) { case HINT_PAGEORDERCHG: - UpdateChildren(); + RequestUpdateChildren(); break; default: break; @@ -986,7 +1018,7 @@ void AccessibleSlideSorterView::Implementation::Notify ( case sd::ViewShellHint::HINT_COMPLEX_MODEL_CHANGE_END: mbModelChangeLocked = false; - UpdateChildren(); + RequestUpdateChildren(); break; default: break; @@ -1003,7 +1035,7 @@ IMPL_LINK(AccessibleSlideSorterView::Implementation, WindowEventListener, VclWin { case VCLEVENT_WINDOW_MOVE: case VCLEVENT_WINDOW_RESIZE: - UpdateChildren(); + RequestUpdateChildren(); break; case VCLEVENT_WINDOW_GETFOCUS: @@ -1024,6 +1056,18 @@ IMPL_LINK(AccessibleSlideSorterView::Implementation, WindowEventListener, VclWin IMPL_LINK(AccessibleSlideSorterView::Implementation, SelectionChangeListener, void*, EMPTYARG ) { + if (mnSelectionChangeUserEventId == 0) + mnSelectionChangeUserEventId = Application::PostUserEvent( + LINK(this, AccessibleSlideSorterView::Implementation, BroadcastSelectionChange)); + return 1; +} + + + + +IMPL_LINK(AccessibleSlideSorterView::Implementation, BroadcastSelectionChange, void*, EMPTYARG ) +{ + mnSelectionChangeUserEventId = 0; mrAccessibleSlideSorter.FireAccessibleEvent( AccessibleEventId::SELECTION_CHANGED, Any(), @@ -1067,8 +1111,9 @@ IMPL_LINK(AccessibleSlideSorterView::Implementation, FocusChangeListener, void*, -IMPL_LINK(AccessibleSlideSorterView::Implementation, VisibilityChangeListener, void*, EMPTYARG ) +IMPL_LINK(AccessibleSlideSorterView::Implementation, UpdateChildrenCallback, void*, EMPTYARG ) { + mnUpdateChildrenUserEventId = 0; UpdateChildren(); return 1; diff --git a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx index 8e7726da873c..68ae50e091e7 100644 --- a/sd/source/ui/slidesorter/controller/SlsClipboard.cxx +++ b/sd/source/ui/slidesorter/controller/SlsClipboard.cxx @@ -130,7 +130,9 @@ Clipboard::Clipboard (SlideSorter& rSlideSorter) maPagesToRemove(), maPagesToSelect(), mbUpdateSelectionPending(false), - mpUndoContext() + mpUndoContext(), + mpSelectionObserverContext(), + mnDragFinishedUserEventId(0) { } @@ -139,6 +141,8 @@ Clipboard::Clipboard (SlideSorter& rSlideSorter) Clipboard::~Clipboard (void) { + if (mnDragFinishedUserEventId != 0) + Application::RemoveUserEvent(mnDragFinishedUserEventId); } @@ -506,16 +510,36 @@ void Clipboard::StartDrag ( void Clipboard::DragFinished (sal_Int8 nDropAction) { + SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; + if (pDragTransferable != NULL) + pDragTransferable->SetView (NULL); + + if (mnDragFinishedUserEventId == 0) + { + if ( ! Application::PostUserEvent( + mnDragFinishedUserEventId, + LINK(this, Clipboard, ProcessDragFinished), + reinterpret_cast(nDropAction))) + { + mnDragFinishedUserEventId = 0; + } + } +} + + + + +IMPL_LINK(Clipboard, ProcessDragFinished, void*, pUserData) +{ + const sal_Int8 nDropAction (static_cast(reinterpret_cast(pUserData))); + + mnDragFinishedUserEventId = 0; + // Hide the substitution display and insertion indicator. ::rtl::Reference pFunction (mrController.GetCurrentSelectionFunction()); if (pFunction.is()) pFunction->NotifyDragFinished(); - SdTransferable* pDragTransferable = SD_MOD()->pTransferDrag; - - if (pDragTransferable != NULL) - pDragTransferable->SetView (NULL); - PageSelector& rSelector (mrController.GetPageSelector()); if ((nDropAction & DND_ACTION_MOVE) != 0 && ! maPagesToRemove.empty()) @@ -534,6 +558,8 @@ void Clipboard::DragFinished (sal_Int8 nDropAction) } mpUndoContext.reset(); mpSelectionObserverContext.reset(); + + return 1; } diff --git a/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx b/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx index 9a3f8f7fdff5..9b7b1f5ec2d3 100644 --- a/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx +++ b/sd/source/ui/slidesorter/inc/controller/SlsClipboard.hxx @@ -137,6 +137,7 @@ private: ::boost::scoped_ptr mpUndoContext; ::boost::scoped_ptr mpSelectionObserverContext; + ULONG mnDragFinishedUserEventId; void CreateSlideTransferable ( ::Window* pWindow, @@ -219,6 +220,11 @@ private: ::sd::Window* pTargetWindow, USHORT nPage, USHORT nLayer); + + /** Asynchronous part of DragFinished. The argument is the sal_Int8 + nDropAction, disguised as void*. + */ + DECL_LINK(ProcessDragFinished, void*); }; } } } // end of namespace ::sd::slidesorter::controller