sd/source/console/PresenterAccessibility.cxx | 1 sd/source/console/PresenterSlideSorter.cxx | 16 +++++ sd/source/console/PresenterSlideSorter.hxx | 1 sd/source/console/PresenterToolBar.cxx | 78 +++++++++++---------------- sd/source/console/PresenterToolBar.hxx | 3 - 5 files changed, 53 insertions(+), 46 deletions(-)
New commits: commit 7b37a38960afe0d990c508d6a3fa51a0bec04776 Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Thu May 15 14:23:06 2025 +0200 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Thu May 15 22:23:30 2025 +0200 sd presenter a11y: Set preview's parent The `mpAccessibleConsole` is the XAccessibleContext for the PresenterAccessible, i.e. the PresenterAccessible object is the XAccessible object for its `mpAccessibleConsole`. PresenterAccessible::UpdateAccessibilityHierarchy sets the `mpAccessiblePreview` as a child of `mpAccessibleConsole`. Therefore, the PresenterAccessible is the parent XAccessible for the preview. Set it accordingly. This fixes an inconsistency in the a11y hierarchy that could be seen as follows with the qt6 VCL plugin: * start an Impress presentation with Presenter Console activated * start Accerciser * navigate to the "Presenter Console" object in Accerciser's tree view of LO a11y. * in Accerciser's IPython console: In [30]: acc.get_child_at_index(0).get_parent() == acc Out[30]: False This means the Presenter Console's a11y child at index 0 (which is the current slide preview) doesn't report it's actual parent as its parent. With this commit in place, this behaves as expected now: In [1]: acc.get_child_at_index(0).get_parent() == acc Out[1]: True Change-Id: Id41da5139214437de44d6b1cf29ad8de1d9d13be Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185364 Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> Tested-by: Jenkins diff --git a/sd/source/console/PresenterAccessibility.cxx b/sd/source/console/PresenterAccessibility.cxx index 39af66d3324f..4adc3be02560 100644 --- a/sd/source/console/PresenterAccessibility.cxx +++ b/sd/source/console/PresenterAccessibility.cxx @@ -190,6 +190,7 @@ void PresenterAccessible::UpdateAccessibilityHierarchy ( mxPreviewBorderWindow); mpAccessibleConsole->AddChild(mpAccessiblePreview); mpAccessiblePreview->SetAccessibleName(rsTitle); + mpAccessiblePreview->SetAccessibleParent(this); } } commit 03dfd09f7e3d009b6f5a0dc32f403352935ccd48 Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Thu May 15 11:27:05 2025 +0200 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Thu May 15 22:23:24 2025 +0200 tdf#76029 sd console: Scroll to new slide as needed When switching to a new slide in Impress, make sure that this new slide is fully visible in the Presenter Console "Slides" mode automatically, by scrolling to adjust the visible area as needed. (Make the slide's row the topmost one that's visible.) This removes the need for the user to manually scroll using the scroll bar after switching slides. Change-Id: I7d2a245e6f4b705a8a2492ccb02bbef490adbe88 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185358 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> diff --git a/sd/source/console/PresenterSlideSorter.cxx b/sd/source/console/PresenterSlideSorter.cxx index 77c5d3cf2786..077a2d3f3b52 100644 --- a/sd/source/console/PresenterSlideSorter.cxx +++ b/sd/source/console/PresenterSlideSorter.cxx @@ -599,6 +599,8 @@ void SAL_CALL PresenterSlideSorter::setCurrentPage (const Reference<drawing::XDr mpPresenterController->GetPaintManager()->Invalidate( mxWindow, maCurrentSlideFrameBoundingBox); + + ScrollSlideIntoView(mnCurrentSlideIndex); } Reference<drawing::XDrawPage> SAL_CALL PresenterSlideSorter::getCurrentPage() @@ -1014,6 +1016,20 @@ void PresenterSlideSorter::GotoSlide (const sal_Int32 nSlideIndex) mxSlideShowController->gotoSlideIndex(nSlideIndex); } +void PresenterSlideSorter::ScrollSlideIntoView(sal_Int32 nSlideIndex) +{ + const double fThumbPos = mpVerticalScrollBar->GetThumbPosition(); + const double fThumbSize = mpVerticalScrollBar->GetThumbSize(); + const double fSlidePos = mpLayout->GetPoint(nSlideIndex, -1, -1).Y; + + const bool bFullyVisible + = (fSlidePos - mpLayout->mnVerticalBorder >= fThumbPos) + && (fSlidePos + mpLayout->maPreviewSize.Height + mpLayout->mnVerticalBorder + <= fThumbPos + fThumbSize); + if (!bFullyVisible) + mpVerticalScrollBar->SetThumbPosition(fSlidePos - mpLayout->mnVerticalBorder, false); +} + bool PresenterSlideSorter::ProvideCanvas() { if ( ! mxCanvas.is()) diff --git a/sd/source/console/PresenterSlideSorter.hxx b/sd/source/console/PresenterSlideSorter.hxx index f1056fbeba6b..ef047a41bdc8 100644 --- a/sd/source/console/PresenterSlideSorter.hxx +++ b/sd/source/console/PresenterSlideSorter.hxx @@ -174,6 +174,7 @@ private: void SetHorizontalOffset (const double nXOffset); void SetVerticalOffset (const double nYOffset); void GotoSlide (const sal_Int32 nSlideIndex); + void ScrollSlideIntoView(sal_Int32 nSlideIndex); bool ProvideCanvas(); /** @throws css::lang::DisposedException when the object has already been commit f63690411df62f373d04d6b78bb93956f5532abf Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Thu May 15 09:27:22 2025 +0200 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Thu May 15 22:23:16 2025 +0200 sd console: Don't subclass std::vector ... without adding any additional functionality. Instead, make PresenterToolBar::ElementContainerPart an alias for std::vector<rtl::Reference<Element>>. Forward-declare Element and make it an inner class of PresenterToolBar, which also fits with the existing //===== PresenterToolBar::Element ============================================= comments. Change-Id: I49c2ef88fb4e4280c4cc21b02ce8a20253947933 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185357 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> diff --git a/sd/source/console/PresenterToolBar.cxx b/sd/source/console/PresenterToolBar.cxx index 10291eead413..77030d2254dc 100644 --- a/sd/source/console/PresenterToolBar.cxx +++ b/sd/source/console/PresenterToolBar.cxx @@ -109,14 +109,12 @@ public: //===== PresenterToolBar::Element ============================================= -namespace { - typedef cppu::WeakComponentImplHelper< css::document::XEventListener, css::frame::XStatusListener > ElementInterfaceBase; -class Element +class PresenterToolBar::Element : private ::cppu::BaseMutex, public ElementInterfaceBase { @@ -182,18 +180,11 @@ private: bool mbIsEnabled; }; -} // end of anonymous namespace - -class PresenterToolBar::ElementContainerPart - : public ::std::vector<rtl::Reference<Element> > -{ -}; - //===== Button ================================================================ namespace { -class Button : public Element +class Button : public PresenterToolBar::Element { public: static ::rtl::Reference<Element> Create ( @@ -227,7 +218,7 @@ private: //===== Label ================================================================= -class Label : public Element +class Label : public PresenterToolBar::Element { public: explicit Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar); @@ -258,7 +249,7 @@ public: virtual void TimeHasChanged (const oslDateTime& rCurrentTime) = 0; protected: explicit TimeLabel(const ::rtl::Reference<PresenterToolBar>& rpToolBar); - using Element::disposing; + using PresenterToolBar::Element::disposing; virtual void SAL_CALL disposing() override; private: class Listener : public PresenterClockTimer::Listener @@ -317,7 +308,7 @@ private: virtual void TimeHasChanged (const oslDateTime& rCurrentTime) override; }; -class VerticalSeparator : public Element +class VerticalSeparator : public PresenterToolBar::Element { public: explicit VerticalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar); @@ -331,7 +322,7 @@ protected: const Reference<rendering::XCanvas>& rxCanvas) override; }; -class HorizontalSeparator : public Element +class HorizontalSeparator : public PresenterToolBar::Element { public: explicit HorizontalSeparator (const ::rtl::Reference<PresenterToolBar>& rpToolBar); @@ -412,7 +403,7 @@ void SAL_CALL PresenterToolBar::disposing() mxWindow = nullptr; } - // Dispose tool bar elements. + // Dispose tool bar PresenterToolBar::Elements. for (const auto& rxPart : maElementContainer) { OSL_ASSERT(rxPart != nullptr); @@ -1115,9 +1106,7 @@ Reference<drawing::XDrawPage> SAL_CALL PresenterToolBarView::getCurrentPage() //===== PresenterToolBar::Element ============================================= -namespace { - -Element::Element ( +PresenterToolBar::Element::Element ( ::rtl::Reference<PresenterToolBar> pToolBar) : ElementInterfaceBase(m_aMutex), mpToolBar(std::move(pToolBar)), @@ -1133,7 +1122,7 @@ Element::Element ( } } -void Element::SetModes ( +void PresenterToolBar::Element::SetModes ( const SharedElementMode& rpNormalMode, const SharedElementMode& rpMouseOverMode, const SharedElementMode& rpSelectedMode, @@ -1148,38 +1137,38 @@ void Element::SetModes ( mpMode = rpNormalMode; } -void Element::disposing() +void PresenterToolBar::Element::disposing() { } -awt::Size const & Element::GetBoundingSize ( +awt::Size const & PresenterToolBar::Element::GetBoundingSize ( const Reference<rendering::XCanvas>& rxCanvas) { maSize = CreateBoundingSize(rxCanvas); return maSize; } -awt::Rectangle Element::GetBoundingBox() const +awt::Rectangle PresenterToolBar::Element::GetBoundingBox() const { return awt::Rectangle(maLocation.X,maLocation.Y, maSize.Width, maSize.Height); } -void Element::CurrentSlideHasChanged() +void PresenterToolBar::Element::CurrentSlideHasChanged() { UpdateState(); } -void Element::SetLocation (const awt::Point& rLocation) +void PresenterToolBar::Element::SetLocation (const awt::Point& rLocation) { maLocation = rLocation; } -void Element::SetSize (const geometry::RealSize2D& rSize) +void PresenterToolBar::Element::SetSize (const geometry::RealSize2D& rSize) { maSize = awt::Size(sal_Int32(0.5+rSize.Width), sal_Int32(0.5+rSize.Height)); } -bool Element::SetState ( +bool PresenterToolBar::Element::SetState ( const bool bIsOver, const bool bIsPressed) { @@ -1232,13 +1221,13 @@ bool Element::SetState ( return bModified; } -void Element::Invalidate (const bool bSynchronous) +void PresenterToolBar::Element::Invalidate (const bool bSynchronous) { OSL_ASSERT(mpToolBar.is()); mpToolBar->InvalidateArea(GetBoundingBox(), bSynchronous); } -bool Element::IsOutside (const awt::Rectangle& rBox) +bool PresenterToolBar::Element::IsOutside (const awt::Rectangle& rBox) { if (rBox.X >= maLocation.X+maSize.Width) return true; @@ -1253,12 +1242,12 @@ bool Element::IsOutside (const awt::Rectangle& rBox) } -bool Element::IsFilling() const +bool PresenterToolBar::Element::IsFilling() const { return false; } -void Element::UpdateState() +void PresenterToolBar::Element::UpdateState() { OSL_ASSERT(mpToolBar); OSL_ASSERT(mpToolBar->GetPresenterController()); @@ -1277,18 +1266,18 @@ void Element::UpdateState() //----- lang::XEventListener -------------------------------------------------- -void SAL_CALL Element::disposing (const css::lang::EventObject&) {} +void SAL_CALL PresenterToolBar::Element::disposing (const css::lang::EventObject&) {} //----- document::XEventListener ---------------------------------------------- -void SAL_CALL Element::notifyEvent (const css::document::EventObject&) +void SAL_CALL PresenterToolBar::Element::notifyEvent (const css::document::EventObject&) { UpdateState(); } //----- frame::XStatusListener ------------------------------------------------ -void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEvent) +void SAL_CALL PresenterToolBar::Element::statusChanged (const css::frame::FeatureStateEvent& rEvent) { bool bIsSelected (mbIsSelected); bool bIsEnabled (rEvent.IsEnabled); @@ -1303,7 +1292,6 @@ void SAL_CALL Element::statusChanged (const css::frame::FeatureStateEvent& rEven } } -} // end of anonymous namespace //===== ElementMode =========================================================== @@ -1371,7 +1359,7 @@ void ElementMode::ReadElementMode ( namespace { -::rtl::Reference<Element> Button::Create ( +::rtl::Reference<PresenterToolBar::Element> Button::Create ( const ::rtl::Reference<PresenterToolBar>& rpToolBar) { ::rtl::Reference<Button> pElement (new Button(rpToolBar)); @@ -1381,7 +1369,7 @@ namespace { Button::Button ( const ::rtl::Reference<PresenterToolBar>& rpToolBar) - : Element(rpToolBar), + : PresenterToolBar::Element(rpToolBar), mbIsListenerRegistered(false) { OSL_ASSERT(mpToolBar); @@ -1406,7 +1394,7 @@ void Button::disposing() mbIsListenerRegistered = false; mpToolBar->GetPresenterController()->GetWindowManager()->RemoveLayoutListener(this); } - Element::disposing(); + PresenterToolBar::Element::disposing(); } void Button::Paint ( @@ -1527,7 +1515,7 @@ PresenterBitmapDescriptor::Mode Button::GetMode() const void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent) { mbIsListenerRegistered = false; - Element::disposing(rEvent); + PresenterToolBar::Element::disposing(rEvent); } } // end of anonymous namespace @@ -1537,7 +1525,7 @@ void SAL_CALL Button::disposing (const css::lang::EventObject& rEvent) namespace { Label::Label (const ::rtl::Reference<PresenterToolBar>& rpToolBar) - : Element(rpToolBar) + : PresenterToolBar::Element(rpToolBar) { } @@ -1585,7 +1573,7 @@ void Label::Paint ( bool Label::SetState (const bool, const bool) { // For labels there is no mouse over effect. - return Element::SetState(false, false); + return PresenterToolBar::Element::SetState(false, false); } } // end of anonymous namespace @@ -1730,7 +1718,7 @@ void TimeLabel::ConnectToTimer() //===== CurrentTimeLabel ====================================================== -::rtl::Reference<Element> CurrentTimeLabel::Create ( +::rtl::Reference<PresenterToolBar::Element> CurrentTimeLabel::Create ( const ::rtl::Reference<PresenterToolBar>& rpToolBar) { ::rtl::Reference<TimeLabel> pElement(new CurrentTimeLabel(rpToolBar)); @@ -1767,7 +1755,7 @@ void CurrentTimeLabel::SetModes ( //===== PresentationTimeLabel ================================================= -::rtl::Reference<Element> PresentationTimeLabel::Create ( +::rtl::Reference<PresenterToolBar::Element> PresentationTimeLabel::Create ( const ::rtl::Reference<PresenterToolBar>& rpToolBar) { ::rtl::Reference<TimeLabel> pElement(new PresentationTimeLabel(rpToolBar)); @@ -1910,7 +1898,7 @@ void PresentationTimeLabel::SetModes ( VerticalSeparator::VerticalSeparator ( const ::rtl::Reference<PresenterToolBar>& rpToolBar) - : Element(rpToolBar) + : PresenterToolBar::Element(rpToolBar) { } @@ -1959,7 +1947,7 @@ bool VerticalSeparator::IsFilling() const HorizontalSeparator::HorizontalSeparator ( const ::rtl::Reference<PresenterToolBar>& rpToolBar) - : Element(rpToolBar) + : PresenterToolBar::Element(rpToolBar) { } diff --git a/sd/source/console/PresenterToolBar.hxx b/sd/source/console/PresenterToolBar.hxx index f95884ee9adc..9cf00e589f63 100644 --- a/sd/source/console/PresenterToolBar.hxx +++ b/sd/source/console/PresenterToolBar.hxx @@ -135,11 +135,12 @@ public: virtual css::uno::Reference<css::drawing::XDrawPage> SAL_CALL getCurrentPage() override; class Context; + class Element; private: css::uno::Reference<css::uno::XComponentContext> mxComponentContext; - class ElementContainerPart; + using ElementContainerPart = std::vector<rtl::Reference<Element>>; typedef std::shared_ptr<ElementContainerPart> SharedElementContainerPart; typedef ::std::vector<SharedElementContainerPart> ElementContainer; ElementContainer maElementContainer;