nss: upgrade to release 3.73
[LibreOffice.git] / sdext / source / presenter / PresenterAccessibility.cxx
blob936c75df35f78ca256fa21afb57ca7e1241b94d5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "PresenterAccessibility.hxx"
21 #include "PresenterTextView.hxx"
22 #include "PresenterConfigurationAccess.hxx"
23 #include "PresenterNotesView.hxx"
24 #include "PresenterPaneBase.hxx"
25 #include "PresenterPaneContainer.hxx"
26 #include "PresenterPaneFactory.hxx"
28 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
29 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
30 #include <com/sun/star/accessibility/AccessibleRole.hpp>
31 #include <com/sun/star/accessibility/AccessibleScrollType.hpp>
32 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
33 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
34 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
35 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
36 #include <com/sun/star/accessibility/XAccessibleText.hpp>
37 #include <com/sun/star/awt/XWindow2.hpp>
38 #include <com/sun/star/drawing/framework/XPane.hpp>
39 #include <com/sun/star/drawing/framework/XView.hpp>
40 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
41 #include <cppuhelper/compbase.hxx>
42 #include <cppuhelper/implbase.hxx>
43 #include <o3tl/safeint.hxx>
44 #include <sal/log.hxx>
46 #include <algorithm>
48 using namespace ::com::sun::star;
49 using namespace ::com::sun::star::accessibility;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::drawing::framework;
53 //===== PresenterAccessibleObject =============================================
55 namespace sdext::presenter {
57 namespace {
58 typedef ::cppu::WeakComponentImplHelper <
59 css::accessibility::XAccessible,
60 css::accessibility::XAccessibleContext,
61 css::accessibility::XAccessibleComponent,
62 css::accessibility::XAccessibleEventBroadcaster,
63 css::awt::XWindowListener
64 > PresenterAccessibleObjectInterfaceBase;
67 class PresenterAccessible::AccessibleObject
68 : public ::cppu::BaseMutex,
69 public PresenterAccessibleObjectInterfaceBase
71 public:
72 AccessibleObject (
73 const css::lang::Locale& rLocale,
74 const sal_Int16 nRole,
75 const OUString& rsName);
76 void LateInitialization();
78 virtual void SetWindow (
79 const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
80 const css::uno::Reference<css::awt::XWindow>& rxBorderWindow);
81 void SetAccessibleParent (const css::uno::Reference<css::accessibility::XAccessible>& rxAccessibleParent);
83 virtual void SAL_CALL disposing() override;
85 void AddChild (const ::rtl::Reference<AccessibleObject>& rpChild);
86 void RemoveChild (const ::rtl::Reference<AccessibleObject>& rpChild);
88 void SetIsFocused (const bool bIsFocused);
89 void SetAccessibleName (const OUString& rsName);
91 void FireAccessibleEvent (
92 const sal_Int16 nEventId,
93 const css::uno::Any& rOldValue,
94 const css::uno::Any& rNewValue);
96 void UpdateStateSet();
98 //----- XAccessible -------------------------------------------------------
100 virtual css::uno::Reference<css::accessibility::XAccessibleContext> SAL_CALL
101 getAccessibleContext() override;
103 //----- XAccessibleContext ----------------------------------------------
105 virtual sal_Int32 SAL_CALL getAccessibleChildCount() override;
107 virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL
108 getAccessibleChild (sal_Int32 nIndex) override;
110 virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL getAccessibleParent() override;
112 virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override;
114 virtual sal_Int16 SAL_CALL getAccessibleRole() override;
116 virtual OUString SAL_CALL getAccessibleDescription() override;
118 virtual OUString SAL_CALL getAccessibleName() override;
120 virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet> SAL_CALL
121 getAccessibleRelationSet() override;
123 virtual css::uno::Reference<css::accessibility::XAccessibleStateSet> SAL_CALL
124 getAccessibleStateSet() override;
126 virtual css::lang::Locale SAL_CALL getLocale() override;
128 //----- XAccessibleComponent --------------------------------------------
130 virtual sal_Bool SAL_CALL containsPoint (
131 const css::awt::Point& aPoint) override;
133 virtual css::uno::Reference<css::accessibility::XAccessible> SAL_CALL
134 getAccessibleAtPoint (
135 const css::awt::Point& aPoint) override;
137 virtual css::awt::Rectangle SAL_CALL getBounds() override;
139 virtual css::awt::Point SAL_CALL getLocation() override;
141 virtual css::awt::Point SAL_CALL getLocationOnScreen() override;
143 virtual css::awt::Size SAL_CALL getSize() override;
145 virtual void SAL_CALL grabFocus() override;
147 virtual sal_Int32 SAL_CALL getForeground() override;
149 virtual sal_Int32 SAL_CALL getBackground() override;
151 //----- XAccessibleEventBroadcaster --------------------------------------
153 virtual void SAL_CALL addAccessibleEventListener (
154 const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rxListener) override;
156 virtual void SAL_CALL removeAccessibleEventListener (
157 const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rxListener) override;
159 //----- XWindowListener ---------------------------------------------------
161 virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) override;
163 virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) override;
165 virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) override;
167 virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) override;
169 //----- XEventListener ----------------------------------------------------
171 virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override;
173 protected:
174 OUString msName;
175 css::uno::Reference<css::awt::XWindow2> mxContentWindow;
176 css::uno::Reference<css::awt::XWindow2> mxBorderWindow;
177 const css::lang::Locale maLocale;
178 const sal_Int16 mnRole;
179 sal_uInt32 mnStateSet;
180 bool mbIsFocused;
181 css::uno::Reference<css::accessibility::XAccessible> mxParentAccessible;
182 ::std::vector<rtl::Reference<AccessibleObject> > maChildren;
183 ::std::vector<Reference<XAccessibleEventListener> > maListeners;
185 virtual awt::Point GetRelativeLocation();
186 virtual awt::Size GetSize();
187 virtual awt::Point GetAbsoluteParentLocation();
189 virtual bool GetWindowState (const sal_Int16 nType) const;
191 void UpdateState (const sal_Int16 aState, const bool bValue);
193 /// @throws css::lang::DisposedException
194 void ThrowIfDisposed() const;
197 //===== AccessibleStateSet ====================================================
199 namespace {
200 typedef ::cppu::WeakComponentImplHelper <
201 css::accessibility::XAccessibleStateSet
202 > AccessibleStateSetInterfaceBase;
204 class AccessibleStateSet
205 : public ::cppu::BaseMutex,
206 public AccessibleStateSetInterfaceBase
208 public:
209 explicit AccessibleStateSet (const sal_Int32 nStateSet);
211 static sal_uInt32 GetStateMask (const sal_Int16 nType);
213 //----- XAccessibleStateSet -----------------------------------------------
215 virtual sal_Bool SAL_CALL isEmpty() override;
217 virtual sal_Bool SAL_CALL contains (sal_Int16 nState) override;
219 virtual sal_Bool SAL_CALL containsAll (const css::uno::Sequence<sal_Int16>& rStateSet) override;
221 virtual css::uno::Sequence<sal_Int16> SAL_CALL getStates() override;
223 private:
224 const sal_Int32 mnStateSet;
227 //===== AccessibleRelationSet =================================================
229 typedef ::cppu::WeakComponentImplHelper <
230 css::accessibility::XAccessibleRelationSet
231 > AccessibleRelationSetInterfaceBase;
233 class AccessibleRelationSet
234 : public ::cppu::BaseMutex,
235 public AccessibleRelationSetInterfaceBase
237 public:
238 AccessibleRelationSet();
240 void AddRelation (
241 const sal_Int16 nRelationType,
242 const Reference<XInterface>& rxObject);
244 //----- XAccessibleRelationSet --------------------------------------------
246 virtual sal_Int32 SAL_CALL getRelationCount() override;
248 virtual AccessibleRelation SAL_CALL getRelation (sal_Int32 nIndex) override;
250 virtual sal_Bool SAL_CALL containsRelation (sal_Int16 nRelationType) override;
252 virtual AccessibleRelation SAL_CALL getRelationByType (sal_Int16 nRelationType) override;
254 private:
255 ::std::vector<AccessibleRelation> maRelations;
258 //===== PresenterAccessibleParagraph ==========================================
260 typedef ::cppu::ImplInheritanceHelper <
261 PresenterAccessible::AccessibleObject,
262 css::accessibility::XAccessibleText
263 > PresenterAccessibleParagraphInterfaceBase;
266 class PresenterAccessible::AccessibleParagraph
267 : public PresenterAccessibleParagraphInterfaceBase
269 public:
270 AccessibleParagraph (
271 const css::lang::Locale& rLocale,
272 const OUString& rsName,
273 const SharedPresenterTextParagraph& rpParagraph,
274 const sal_Int32 nParagraphIndex);
276 //----- XAccessibleContext ------------------------------------------------
278 virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet> SAL_CALL
279 getAccessibleRelationSet() override;
281 //----- XAccessibleText ---------------------------------------------------
283 virtual sal_Int32 SAL_CALL getCaretPosition() override;
285 virtual sal_Bool SAL_CALL setCaretPosition (sal_Int32 nIndex) override;
287 virtual sal_Unicode SAL_CALL getCharacter (sal_Int32 nIndex) override;
289 virtual css::uno::Sequence<css::beans::PropertyValue> SAL_CALL
290 getCharacterAttributes (
291 ::sal_Int32 nIndex,
292 const css::uno::Sequence<OUString>& rRequestedAttributes) override;
294 virtual css::awt::Rectangle SAL_CALL getCharacterBounds (sal_Int32 nIndex) override;
296 virtual sal_Int32 SAL_CALL getCharacterCount() override;
298 virtual sal_Int32 SAL_CALL getIndexAtPoint (const css::awt::Point& rPoint) override;
300 virtual OUString SAL_CALL getSelectedText() override;
302 virtual sal_Int32 SAL_CALL getSelectionStart() override;
304 virtual sal_Int32 SAL_CALL getSelectionEnd() override;
306 virtual sal_Bool SAL_CALL setSelection (sal_Int32 nStartIndex, sal_Int32 nEndIndex) override;
308 virtual OUString SAL_CALL getText() override;
310 virtual OUString SAL_CALL getTextRange (
311 sal_Int32 nStartIndex,
312 sal_Int32 nEndIndex) override;
314 virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex (
315 sal_Int32 nIndex,
316 sal_Int16 nTextType) override;
318 virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex (
319 sal_Int32 nIndex,
320 sal_Int16 nTextType) override;
322 virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex (
323 sal_Int32 nIndex,
324 sal_Int16 nTextType) override;
326 virtual sal_Bool SAL_CALL copyText (sal_Int32 nStartIndex, sal_Int32 nEndIndex) override;
328 virtual sal_Bool SAL_CALL scrollSubstringTo(
329 sal_Int32 nStartIndex,
330 sal_Int32 nEndIndex,
331 css::accessibility::AccessibleScrollType aScrollType) override;
333 protected:
334 virtual awt::Point GetRelativeLocation() override;
335 virtual awt::Size GetSize() override;
336 virtual awt::Point GetAbsoluteParentLocation() override;
337 virtual bool GetWindowState (const sal_Int16 nType) const override;
339 private:
340 SharedPresenterTextParagraph mpParagraph;
341 const sal_Int32 mnParagraphIndex;
344 //===== AccessibleConsole =====================================================
346 namespace {
348 class AccessibleConsole
350 public:
351 static rtl::Reference<PresenterAccessible::AccessibleObject> Create (
352 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
353 const lang::Locale& rLocale)
355 OUString sName ("Presenter Console");
356 PresenterConfigurationAccess aConfiguration (
357 rxContext,
358 "/org.openoffice.Office.PresenterScreen/",
359 PresenterConfigurationAccess::READ_ONLY);
360 aConfiguration.GetConfigurationNode("Presenter/Accessibility/Console/String")
361 >>= sName;
363 rtl::Reference<PresenterAccessible::AccessibleObject> pObject (
364 new PresenterAccessible::AccessibleObject(
365 rLocale, AccessibleRole::PANEL, sName));
366 pObject->LateInitialization();
367 pObject->UpdateStateSet();
369 return pObject;
373 //===== AccessiblePreview =====================================================
375 class AccessiblePreview
377 public:
378 static rtl::Reference<PresenterAccessible::AccessibleObject> Create (
379 const Reference<css::uno::XComponentContext>& rxContext,
380 const lang::Locale& rLocale,
381 const Reference<awt::XWindow>& rxContentWindow,
382 const Reference<awt::XWindow>& rxBorderWindow)
384 OUString sName ("Presenter Notes Window");
386 PresenterConfigurationAccess aConfiguration (
387 rxContext,
388 "/org.openoffice.Office.PresenterScreen/",
389 PresenterConfigurationAccess::READ_ONLY);
390 aConfiguration.GetConfigurationNode("Presenter/Accessibility/Preview/String")
391 >>= sName;
394 rtl::Reference<PresenterAccessible::AccessibleObject> pObject (
395 new PresenterAccessible::AccessibleObject(
396 rLocale,
397 AccessibleRole::LABEL,
398 sName));
399 pObject->LateInitialization();
400 pObject->UpdateStateSet();
401 pObject->SetWindow(rxContentWindow, rxBorderWindow);
403 return pObject;
407 //===== AccessibleNotes =======================================================
409 class AccessibleNotes : public PresenterAccessible::AccessibleObject
411 public:
412 AccessibleNotes (
413 const css::lang::Locale& rLocale,
414 const OUString& rsName);
416 static rtl::Reference<PresenterAccessible::AccessibleObject> Create (
417 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
418 const lang::Locale& rLocale,
419 const Reference<awt::XWindow>& rxContentWindow,
420 const Reference<awt::XWindow>& rxBorderWindow,
421 const std::shared_ptr<PresenterTextView>& rpTextView);
423 void SetTextView (const std::shared_ptr<PresenterTextView>& rpTextView);
425 virtual void SetWindow (
426 const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
427 const css::uno::Reference<css::awt::XWindow>& rxBorderWindow) override;
429 private:
430 std::shared_ptr<PresenterTextView> mpTextView;
432 void NotifyCaretChange (
433 const sal_Int32 nOldParagraphIndex,
434 const sal_Int32 nOldCharacterIndex,
435 const sal_Int32 nNewParagraphIndex,
436 const sal_Int32 nNewCharacterIndex);
439 //===== AccessibleFocusManager ================================================
441 /** A singleton class that makes sure that only one accessibility object in
442 the PresenterConsole hierarchy has the focus.
444 class AccessibleFocusManager
446 public:
447 static std::shared_ptr<AccessibleFocusManager> const & Instance();
449 void AddFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
450 void RemoveFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
452 void FocusObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
454 ~AccessibleFocusManager();
456 private:
457 static std::shared_ptr<AccessibleFocusManager> mpInstance;
458 ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > maFocusableObjects;
459 bool m_isInDtor = false;
461 AccessibleFocusManager();
466 //===== PresenterAccessible ===================================================
468 PresenterAccessible::PresenterAccessible (
469 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
470 const ::rtl::Reference<PresenterController>& rpPresenterController,
471 const Reference<drawing::framework::XPane>& rxMainPane)
472 : PresenterAccessibleInterfaceBase(m_aMutex),
473 mxComponentContext(rxContext),
474 mpPresenterController(rpPresenterController),
475 mxMainPane(rxMainPane, UNO_QUERY),
476 mxMainWindow(),
477 mxPreviewContentWindow(),
478 mxPreviewBorderWindow(),
479 mxNotesContentWindow(),
480 mxNotesBorderWindow(),
481 mpAccessibleConsole(),
482 mpAccessiblePreview(),
483 mpAccessibleNotes(),
484 mxAccessibleParent()
486 if (mxMainPane.is())
487 mxMainPane->setAccessible(this);
490 PresenterAccessible::~PresenterAccessible()
494 PresenterPaneContainer::SharedPaneDescriptor PresenterAccessible::GetPreviewPane() const
496 PresenterPaneContainer::SharedPaneDescriptor pPreviewPane;
498 if ( ! mpPresenterController.is())
499 return pPreviewPane;
501 rtl::Reference<PresenterPaneContainer> pContainer (mpPresenterController->GetPaneContainer());
502 if ( ! pContainer.is())
503 return pPreviewPane;
505 pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL);
506 Reference<drawing::framework::XPane> xPreviewPane;
507 if (pPreviewPane)
508 xPreviewPane = pPreviewPane->mxPane.get();
509 if ( ! xPreviewPane.is())
511 pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msSlideSorterPaneURL);
513 return pPreviewPane;
516 void PresenterAccessible::UpdateAccessibilityHierarchy()
518 if ( ! mpPresenterController.is())
519 return;
521 Reference<drawing::framework::XConfigurationController> xConfigurationController(
522 mpPresenterController->GetConfigurationController());
523 if ( ! xConfigurationController.is())
524 return;
526 rtl::Reference<PresenterPaneContainer> pPaneContainer (
527 mpPresenterController->GetPaneContainer());
528 if ( ! pPaneContainer.is())
529 return;
531 if ( ! mpAccessibleConsole.is())
532 return;
534 // Get the preview pane (standard or notes view) or the slide overview
535 // pane.
536 PresenterPaneContainer::SharedPaneDescriptor pPreviewPane(GetPreviewPane());
537 Reference<drawing::framework::XPane> xPreviewPane;
538 if (pPreviewPane)
539 xPreviewPane = pPreviewPane->mxPane.get();
541 // Get the notes pane.
542 PresenterPaneContainer::SharedPaneDescriptor pNotesPane(
543 pPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL));
544 Reference<drawing::framework::XPane> xNotesPane;
545 if (pNotesPane)
546 xNotesPane = pNotesPane->mxPane.get();
548 // Get the notes view.
549 Reference<drawing::framework::XView> xNotesView;
550 if (pNotesPane)
551 xNotesView = pNotesPane->mxView;
552 rtl::Reference<PresenterNotesView> pNotesView (
553 dynamic_cast<PresenterNotesView*>(xNotesView.get()));
555 UpdateAccessibilityHierarchy(
556 pPreviewPane ? pPreviewPane->mxContentWindow : Reference<awt::XWindow>(),
557 pPreviewPane ? pPreviewPane->mxBorderWindow : Reference<awt::XWindow>(),
558 (pPreviewPane&&pPreviewPane->mxPane.is()) ? pPreviewPane->mxPane->GetTitle() : OUString(),
559 pNotesPane ? pNotesPane->mxContentWindow : Reference<awt::XWindow>(),
560 pNotesPane ? pNotesPane->mxBorderWindow : Reference<awt::XWindow>(),
561 pNotesView.is()
562 ? pNotesView->GetTextView()
563 : std::shared_ptr<PresenterTextView>());
566 void PresenterAccessible::UpdateAccessibilityHierarchy (
567 const Reference<awt::XWindow>& rxPreviewContentWindow,
568 const Reference<awt::XWindow>& rxPreviewBorderWindow,
569 const OUString& rsTitle,
570 const Reference<awt::XWindow>& rxNotesContentWindow,
571 const Reference<awt::XWindow>& rxNotesBorderWindow,
572 const std::shared_ptr<PresenterTextView>& rpNotesTextView)
574 if ( ! mpAccessibleConsole.is())
575 return;
577 if (mxPreviewContentWindow != rxPreviewContentWindow)
579 if (mpAccessiblePreview.is())
581 mpAccessibleConsole->RemoveChild(mpAccessiblePreview);
582 mpAccessiblePreview = nullptr;
585 mxPreviewContentWindow = rxPreviewContentWindow;
586 mxPreviewBorderWindow = rxPreviewBorderWindow;
588 if (mxPreviewContentWindow.is())
590 mpAccessiblePreview = AccessiblePreview::Create(
591 mxComponentContext,
592 lang::Locale(),
593 mxPreviewContentWindow,
594 mxPreviewBorderWindow);
595 mpAccessibleConsole->AddChild(mpAccessiblePreview);
596 mpAccessiblePreview->SetAccessibleName(rsTitle);
600 if (mxNotesContentWindow == rxNotesContentWindow)
601 return;
603 if (mpAccessibleNotes.is())
605 mpAccessibleConsole->RemoveChild(mpAccessibleNotes);
606 mpAccessibleNotes = nullptr;
609 mxNotesContentWindow = rxNotesContentWindow;
610 mxNotesBorderWindow = rxNotesBorderWindow;
612 if (mxNotesContentWindow.is())
614 mpAccessibleNotes = AccessibleNotes::Create(
615 mxComponentContext,
616 lang::Locale(),
617 mxNotesContentWindow,
618 mxNotesBorderWindow,
619 rpNotesTextView);
620 mpAccessibleConsole->AddChild(mpAccessibleNotes.get());
624 void PresenterAccessible::NotifyCurrentSlideChange ()
626 if (mpAccessiblePreview.is())
628 PresenterPaneContainer::SharedPaneDescriptor pPreviewPane (GetPreviewPane());
629 mpAccessiblePreview->SetAccessibleName(
630 pPreviewPane&&pPreviewPane->mxPane.is()
631 ? pPreviewPane->mxPane->GetTitle()
632 : OUString());
635 // Play some focus ping-pong to trigger AT tools.
636 //AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
637 AccessibleFocusManager::Instance()->FocusObject(mpAccessiblePreview);
640 void SAL_CALL PresenterAccessible::disposing()
642 UpdateAccessibilityHierarchy(
643 nullptr,
644 nullptr,
645 OUString(),
646 nullptr,
647 nullptr,
648 std::shared_ptr<PresenterTextView>());
650 if (mxMainWindow.is())
652 mxMainWindow->removeFocusListener(this);
654 if (mxMainPane.is())
655 mxMainPane->setAccessible(nullptr);
658 mpAccessiblePreview = nullptr;
659 mpAccessibleNotes = nullptr;
660 mpAccessibleConsole = nullptr;
663 //----- XAccessible -----------------------------------------------------------
665 Reference<XAccessibleContext> SAL_CALL PresenterAccessible::getAccessibleContext()
667 if ( ! mpAccessibleConsole.is())
669 Reference<XPane> xMainPane (mxMainPane, UNO_QUERY);
670 if (xMainPane.is())
672 mxMainWindow = xMainPane->getWindow();
673 mxMainWindow->addFocusListener(this);
675 mpAccessibleConsole = AccessibleConsole::Create(
676 mxComponentContext, css::lang::Locale());
677 mpAccessibleConsole->SetWindow(mxMainWindow, nullptr);
678 mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
679 UpdateAccessibilityHierarchy();
680 if (mpPresenterController.is())
681 mpPresenterController->SetAccessibilityActiveState(true);
683 return mpAccessibleConsole->getAccessibleContext();
686 //----- XFocusListener ----------------------------------------------------
688 void SAL_CALL PresenterAccessible::focusGained (const css::awt::FocusEvent&)
690 SAL_INFO("sdext.presenter", __func__ << ": PresenterAccessible::focusGained at " << this
691 << " and window " << mxMainWindow.get());
692 AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
695 void SAL_CALL PresenterAccessible::focusLost (const css::awt::FocusEvent&)
697 SAL_INFO("sdext.presenter", __func__ << ": PresenterAccessible::focusLost at " << this);
698 AccessibleFocusManager::Instance()->FocusObject(nullptr);
701 //----- XEventListener ----------------------------------------------------
703 void SAL_CALL PresenterAccessible::disposing (const css::lang::EventObject& rEvent)
705 if (rEvent.Source == mxMainWindow)
706 mxMainWindow = nullptr;
709 //----- XInitialize -----------------------------------------------------------
711 void SAL_CALL PresenterAccessible::initialize (const css::uno::Sequence<css::uno::Any>& rArguments)
713 if (rArguments.hasElements())
715 mxAccessibleParent.set(rArguments[0], UNO_QUERY);
716 if (mpAccessibleConsole.is())
717 mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
721 //===== PresenterAccessible::AccessibleObject =========================================
723 PresenterAccessible::AccessibleObject::AccessibleObject (
724 const lang::Locale& rLocale,
725 const sal_Int16 nRole,
726 const OUString& rsName)
727 : PresenterAccessibleObjectInterfaceBase(m_aMutex),
728 msName(rsName),
729 mxContentWindow(),
730 mxBorderWindow(),
731 maLocale(rLocale),
732 mnRole(nRole),
733 mnStateSet(0),
734 mbIsFocused(false),
735 mxParentAccessible(),
736 maChildren(),
737 maListeners()
741 void PresenterAccessible::AccessibleObject::LateInitialization()
743 AccessibleFocusManager::Instance()->AddFocusableObject(this);
746 void PresenterAccessible::AccessibleObject::SetWindow (
747 const Reference<awt::XWindow>& rxContentWindow,
748 const Reference<awt::XWindow>& rxBorderWindow)
750 Reference<awt::XWindow2> xContentWindow (rxContentWindow, UNO_QUERY);
752 if (mxContentWindow.get() == xContentWindow.get())
753 return;
755 if (mxContentWindow.is())
757 mxContentWindow->removeWindowListener(this);
760 mxContentWindow = xContentWindow;
761 mxBorderWindow.set(rxBorderWindow, UNO_QUERY);
763 if (mxContentWindow.is())
765 mxContentWindow->addWindowListener(this);
768 UpdateStateSet();
771 void PresenterAccessible::AccessibleObject::SetAccessibleParent (
772 const Reference<XAccessible>& rxAccessibleParent)
774 mxParentAccessible = rxAccessibleParent;
777 void SAL_CALL PresenterAccessible::AccessibleObject::disposing()
779 AccessibleFocusManager::Instance()->RemoveFocusableObject(this);
780 SetWindow(nullptr, nullptr);
783 //----- XAccessible -------------------------------------------------------
785 Reference<XAccessibleContext> SAL_CALL
786 PresenterAccessible::AccessibleObject::getAccessibleContext()
788 ThrowIfDisposed();
790 return this;
793 //----- XAccessibleContext ----------------------------------------------
795 sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleChildCount()
797 ThrowIfDisposed();
799 const sal_Int32 nChildCount (maChildren.size());
801 return nChildCount;
804 Reference<XAccessible> SAL_CALL
805 PresenterAccessible::AccessibleObject::getAccessibleChild (sal_Int32 nIndex)
807 ThrowIfDisposed();
809 if (nIndex<0 || nIndex>=sal_Int32(maChildren.size()))
810 throw lang::IndexOutOfBoundsException("invalid child index", static_cast<uno::XWeak*>(this));
812 return Reference<XAccessible>(maChildren[nIndex].get());
815 Reference<XAccessible> SAL_CALL
816 PresenterAccessible::AccessibleObject::getAccessibleParent()
818 ThrowIfDisposed();
820 return mxParentAccessible;
823 sal_Int32 SAL_CALL
824 PresenterAccessible::AccessibleObject::getAccessibleIndexInParent()
826 ThrowIfDisposed();
828 const Reference<XAccessible> xThis (this);
829 if (mxParentAccessible.is())
831 const Reference<XAccessibleContext> xContext (mxParentAccessible->getAccessibleContext());
832 for (sal_Int32 nIndex=0,nCount=xContext->getAccessibleChildCount();
833 nIndex<nCount;
834 ++nIndex)
836 if (xContext->getAccessibleChild(nIndex) == xThis)
837 return nIndex;
841 return 0;
844 sal_Int16 SAL_CALL
845 PresenterAccessible::AccessibleObject::getAccessibleRole()
847 ThrowIfDisposed();
849 return mnRole;
852 OUString SAL_CALL
853 PresenterAccessible::AccessibleObject::getAccessibleDescription()
855 ThrowIfDisposed();
857 return msName;
860 OUString SAL_CALL
861 PresenterAccessible::AccessibleObject::getAccessibleName()
863 ThrowIfDisposed();
865 return msName;
868 Reference<XAccessibleRelationSet> SAL_CALL
869 PresenterAccessible::AccessibleObject::getAccessibleRelationSet()
871 ThrowIfDisposed();
873 return nullptr;
876 Reference<XAccessibleStateSet> SAL_CALL
877 PresenterAccessible::AccessibleObject::getAccessibleStateSet()
879 ThrowIfDisposed();
881 return Reference<XAccessibleStateSet>(new AccessibleStateSet(mnStateSet));
884 lang::Locale SAL_CALL
885 PresenterAccessible::AccessibleObject::getLocale()
887 ThrowIfDisposed();
889 if (mxParentAccessible.is())
891 Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
892 if (xParentContext.is())
893 return xParentContext->getLocale();
895 return maLocale;
898 //----- XAccessibleComponent ------------------------------------------------
900 sal_Bool SAL_CALL PresenterAccessible::AccessibleObject::containsPoint (
901 const awt::Point& rPoint)
903 ThrowIfDisposed();
905 if (mxContentWindow.is())
907 const awt::Rectangle aBox (getBounds());
908 return rPoint.X>=aBox.X
909 && rPoint.Y>=aBox.Y
910 && rPoint.X<aBox.X+aBox.Width
911 && rPoint.Y<aBox.Y+aBox.Height;
913 else
914 return false;
917 Reference<XAccessible> SAL_CALL
918 PresenterAccessible::AccessibleObject::getAccessibleAtPoint (const awt::Point&)
920 ThrowIfDisposed();
922 return Reference<XAccessible>();
925 awt::Rectangle SAL_CALL PresenterAccessible::AccessibleObject::getBounds()
927 ThrowIfDisposed();
929 const awt::Point aLocation (GetRelativeLocation());
930 const awt::Size aSize (GetSize());
932 return awt::Rectangle (aLocation.X, aLocation.Y, aSize.Width, aSize.Height);
935 awt::Point SAL_CALL PresenterAccessible::AccessibleObject::getLocation()
937 ThrowIfDisposed();
939 const awt::Point aLocation (GetRelativeLocation());
941 return aLocation;
944 awt::Point SAL_CALL PresenterAccessible::AccessibleObject::getLocationOnScreen()
946 ThrowIfDisposed();
948 awt::Point aRelativeLocation (GetRelativeLocation());
949 awt::Point aParentLocationOnScreen (GetAbsoluteParentLocation());
951 return awt::Point(
952 aRelativeLocation.X + aParentLocationOnScreen.X,
953 aRelativeLocation.Y + aParentLocationOnScreen.Y);
956 awt::Size SAL_CALL PresenterAccessible::AccessibleObject::getSize()
958 ThrowIfDisposed();
960 const awt::Size aSize (GetSize());
962 return aSize;
965 void SAL_CALL PresenterAccessible::AccessibleObject::grabFocus()
967 ThrowIfDisposed();
968 if (mxBorderWindow.is())
969 mxBorderWindow->setFocus();
970 else if (mxContentWindow.is())
971 mxContentWindow->setFocus();
974 sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getForeground()
976 ThrowIfDisposed();
978 return 0x00ffffff;
981 sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getBackground()
983 ThrowIfDisposed();
985 return 0x00000000;
988 //----- XAccessibleEventBroadcaster -------------------------------------------
990 void SAL_CALL PresenterAccessible::AccessibleObject::addAccessibleEventListener (
991 const Reference<XAccessibleEventListener>& rxListener)
993 if (!rxListener.is())
994 return;
996 const osl::MutexGuard aGuard(m_aMutex);
998 if (rBHelper.bDisposed || rBHelper.bInDispose)
1000 uno::Reference<uno::XInterface> xThis (static_cast<XWeak*>(this), UNO_QUERY);
1001 rxListener->disposing (lang::EventObject(xThis));
1003 else
1005 maListeners.push_back(rxListener);
1009 void SAL_CALL PresenterAccessible::AccessibleObject::removeAccessibleEventListener (
1010 const Reference<XAccessibleEventListener>& rxListener)
1012 ThrowIfDisposed();
1013 if (rxListener.is())
1015 const osl::MutexGuard aGuard(m_aMutex);
1017 auto const it(std::remove(maListeners.begin(), maListeners.end(), rxListener));
1018 if (it != maListeners.end())
1020 maListeners.erase(it);
1025 //----- XWindowListener ---------------------------------------------------
1027 void SAL_CALL PresenterAccessible::AccessibleObject::windowResized (
1028 const css::awt::WindowEvent&)
1030 FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1033 void SAL_CALL PresenterAccessible::AccessibleObject::windowMoved (
1034 const css::awt::WindowEvent&)
1036 FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1039 void SAL_CALL PresenterAccessible::AccessibleObject::windowShown (
1040 const css::lang::EventObject&)
1042 UpdateStateSet();
1045 void SAL_CALL PresenterAccessible::AccessibleObject::windowHidden (
1046 const css::lang::EventObject&)
1048 UpdateStateSet();
1051 //----- XEventListener --------------------------------------------------------
1053 void SAL_CALL PresenterAccessible::AccessibleObject::disposing (const css::lang::EventObject& rEvent)
1055 if (rEvent.Source == mxContentWindow)
1057 mxContentWindow = nullptr;
1058 mxBorderWindow = nullptr;
1060 else
1062 SetWindow(nullptr, nullptr);
1066 //----- private ---------------------------------------------------------------
1068 bool PresenterAccessible::AccessibleObject::GetWindowState (const sal_Int16 nType) const
1070 switch (nType)
1072 case AccessibleStateType::ENABLED:
1073 return mxContentWindow.is() && mxContentWindow->isEnabled();
1075 case AccessibleStateType::FOCUSABLE:
1076 return true;
1078 case AccessibleStateType::FOCUSED:
1079 return mbIsFocused;
1081 case AccessibleStateType::SHOWING:
1082 return mxContentWindow.is() && mxContentWindow->isVisible();
1084 default:
1085 return false;
1089 void PresenterAccessible::AccessibleObject::UpdateStateSet()
1091 UpdateState(AccessibleStateType::FOCUSABLE, true);
1092 UpdateState(AccessibleStateType::VISIBLE, true);
1093 UpdateState(AccessibleStateType::ENABLED, true);
1094 UpdateState(AccessibleStateType::MULTI_LINE, true);
1095 UpdateState(AccessibleStateType::SENSITIVE, true);
1097 UpdateState(AccessibleStateType::ENABLED, GetWindowState(AccessibleStateType::ENABLED));
1098 UpdateState(AccessibleStateType::FOCUSED, GetWindowState(AccessibleStateType::FOCUSED));
1099 UpdateState(AccessibleStateType::SHOWING, GetWindowState(AccessibleStateType::SHOWING));
1100 // UpdateState(AccessibleStateType::ACTIVE, GetWindowState(AccessibleStateType::ACTIVE));
1103 void PresenterAccessible::AccessibleObject::UpdateState(
1104 const sal_Int16 nState,
1105 const bool bValue)
1107 const sal_uInt32 nStateMask (AccessibleStateSet::GetStateMask(nState));
1108 if (((mnStateSet & nStateMask)!=0) != bValue)
1110 if (bValue)
1112 mnStateSet |= nStateMask;
1113 FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(), Any(nState));
1115 else
1117 mnStateSet &= ~nStateMask;
1118 FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(nState), Any());
1123 void PresenterAccessible::AccessibleObject::AddChild (
1124 const ::rtl::Reference<AccessibleObject>& rpChild)
1126 maChildren.push_back(rpChild);
1127 rpChild->SetAccessibleParent(this);
1128 FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1131 void PresenterAccessible::AccessibleObject::RemoveChild (
1132 const ::rtl::Reference<AccessibleObject>& rpChild)
1134 rpChild->SetAccessibleParent(Reference<XAccessible>());
1135 maChildren.erase(::std::find(maChildren.begin(), maChildren.end(), rpChild));
1136 FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1139 void PresenterAccessible::AccessibleObject::SetIsFocused (const bool bIsFocused)
1141 if (mbIsFocused != bIsFocused)
1143 mbIsFocused = bIsFocused;
1144 UpdateStateSet();
1148 void PresenterAccessible::AccessibleObject::SetAccessibleName (const OUString& rsName)
1150 if (msName != rsName)
1152 const OUString sOldName(msName);
1153 msName = rsName;
1154 FireAccessibleEvent(AccessibleEventId::NAME_CHANGED, Any(sOldName), Any(msName));
1158 void PresenterAccessible::AccessibleObject::FireAccessibleEvent (
1159 const sal_Int16 nEventId,
1160 const uno::Any& rOldValue,
1161 const uno::Any& rNewValue )
1163 AccessibleEventObject aEventObject;
1165 aEventObject.Source = Reference<XWeak>(this);
1166 aEventObject.EventId = nEventId;
1167 aEventObject.NewValue = rNewValue;
1168 aEventObject.OldValue = rOldValue;
1170 ::std::vector<Reference<XAccessibleEventListener> > aListenerCopy(maListeners);
1171 for (const auto& rxListener : aListenerCopy)
1175 rxListener->notifyEvent(aEventObject);
1177 catch (const lang::DisposedException&)
1179 // Listener has been disposed and should have been removed
1180 // already.
1181 removeAccessibleEventListener(rxListener);
1183 catch (const Exception&)
1185 // Ignore all other exceptions and assume that they are
1186 // caused by a temporary problem.
1191 awt::Point PresenterAccessible::AccessibleObject::GetRelativeLocation()
1193 awt::Point aLocation;
1194 if (mxContentWindow.is())
1196 const awt::Rectangle aContentBox (mxContentWindow->getPosSize());
1197 aLocation.X = aContentBox.X;
1198 aLocation.Y = aContentBox.Y;
1199 if (mxBorderWindow.is())
1201 const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize());
1202 aLocation.X += aBorderBox.X;
1203 aLocation.Y += aBorderBox.Y;
1206 return aLocation;
1209 awt::Size PresenterAccessible::AccessibleObject::GetSize()
1211 if (mxContentWindow.is())
1213 const awt::Rectangle aBox (mxContentWindow->getPosSize());
1214 return awt::Size(aBox.Width, aBox.Height);
1216 else
1217 return awt::Size();
1220 awt::Point PresenterAccessible::AccessibleObject::GetAbsoluteParentLocation()
1222 Reference<XAccessibleComponent> xParentComponent;
1223 if (mxParentAccessible.is())
1224 xParentComponent.set( mxParentAccessible->getAccessibleContext(), UNO_QUERY);
1225 if (xParentComponent.is())
1226 return xParentComponent->getLocationOnScreen();
1227 else
1228 return awt::Point();
1231 void PresenterAccessible::AccessibleObject::ThrowIfDisposed() const
1233 if (rBHelper.bDisposed || rBHelper.bInDispose)
1234 throw lang::DisposedException("object has already been disposed", uno::Reference<uno::XInterface>(const_cast<uno::XWeak*>(static_cast<uno::XWeak const *>(this))));
1237 //===== AccessibleStateSet ====================================================
1239 AccessibleStateSet::AccessibleStateSet (const sal_Int32 nStateSet)
1240 : AccessibleStateSetInterfaceBase(m_aMutex),
1241 mnStateSet (nStateSet)
1245 sal_uInt32 AccessibleStateSet::GetStateMask (const sal_Int16 nState)
1247 if (nState<0 || nState>=sal_Int16(sizeof(sal_uInt32)*8))
1249 throw RuntimeException("AccessibleStateSet::GetStateMask: invalid state");
1252 return 1<<nState;
1255 //----- XAccessibleStateSet ---------------------------------------------------
1257 sal_Bool SAL_CALL AccessibleStateSet::isEmpty()
1259 return mnStateSet==0;
1262 sal_Bool SAL_CALL AccessibleStateSet::contains (sal_Int16 nState)
1264 return (mnStateSet & GetStateMask(nState)) != 0;
1267 sal_Bool SAL_CALL AccessibleStateSet::containsAll (const css::uno::Sequence<sal_Int16>& rStateSet)
1269 return std::none_of(rStateSet.begin(), rStateSet.end(),
1270 [this](const sal_Int16 nState) { return (mnStateSet & GetStateMask(nState)) == 0; });
1273 css::uno::Sequence<sal_Int16> SAL_CALL AccessibleStateSet::getStates()
1275 ::std::vector<sal_Int16> aStates;
1276 aStates.reserve(sizeof(mnStateSet)*8);
1277 for (sal_uInt16 nIndex=0; nIndex<sizeof(mnStateSet)*8; ++nIndex)
1278 if ((mnStateSet & GetStateMask(nIndex)) != 0)
1279 aStates.push_back(nIndex);
1280 return Sequence<sal_Int16>(aStates.data(), aStates.size());
1283 //===== AccessibleRelationSet =================================================
1285 AccessibleRelationSet::AccessibleRelationSet()
1286 : AccessibleRelationSetInterfaceBase(m_aMutex),
1287 maRelations()
1291 void AccessibleRelationSet::AddRelation (
1292 const sal_Int16 nRelationType,
1293 const Reference<XInterface>& rxObject)
1295 maRelations.emplace_back();
1296 maRelations.back().RelationType = nRelationType;
1297 maRelations.back().TargetSet.realloc(1);
1298 maRelations.back().TargetSet[0] = rxObject;
1301 //----- XAccessibleRelationSet ------------------------------------------------
1303 sal_Int32 SAL_CALL AccessibleRelationSet::getRelationCount()
1305 return maRelations.size();
1308 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelation (sal_Int32 nIndex)
1310 if (nIndex<0 && o3tl::make_unsigned(nIndex)>=maRelations.size())
1311 return AccessibleRelation();
1312 else
1313 return maRelations[nIndex];
1316 sal_Bool SAL_CALL AccessibleRelationSet::containsRelation (sal_Int16 nRelationType)
1318 return std::any_of(maRelations.begin(), maRelations.end(),
1319 [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1322 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelationByType (sal_Int16 nRelationType)
1324 auto iRelation = std::find_if(maRelations.begin(), maRelations.end(),
1325 [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1326 if (iRelation != maRelations.end())
1327 return *iRelation;
1328 return AccessibleRelation();
1331 //===== PresenterAccessible::AccessibleParagraph ==============================
1333 PresenterAccessible::AccessibleParagraph::AccessibleParagraph (
1334 const lang::Locale& rLocale,
1335 const OUString& rsName,
1336 const SharedPresenterTextParagraph& rpParagraph,
1337 const sal_Int32 nParagraphIndex)
1338 : PresenterAccessibleParagraphInterfaceBase(rLocale, AccessibleRole::PARAGRAPH, rsName),
1339 mpParagraph(rpParagraph),
1340 mnParagraphIndex(nParagraphIndex)
1344 //----- XAccessibleContext ----------------------------------------------------
1346 Reference<XAccessibleRelationSet> SAL_CALL
1347 PresenterAccessible::AccessibleParagraph::getAccessibleRelationSet()
1349 ThrowIfDisposed();
1351 rtl::Reference<AccessibleRelationSet> pSet (new AccessibleRelationSet);
1353 if (mxParentAccessible.is())
1355 Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
1356 if (xParentContext.is())
1358 if (mnParagraphIndex>0)
1359 pSet->AddRelation(
1360 AccessibleRelationType::CONTENT_FLOWS_FROM,
1361 xParentContext->getAccessibleChild(mnParagraphIndex-1));
1363 if (mnParagraphIndex<xParentContext->getAccessibleChildCount()-1)
1364 pSet->AddRelation(
1365 AccessibleRelationType::CONTENT_FLOWS_TO,
1366 xParentContext->getAccessibleChild(mnParagraphIndex+1));
1370 return Reference<XAccessibleRelationSet>(pSet.get());
1373 //----- XAccessibleText -------------------------------------------------------
1375 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCaretPosition()
1377 ThrowIfDisposed();
1379 sal_Int32 nPosition (-1);
1380 if (mpParagraph)
1381 nPosition = mpParagraph->GetCaretPosition();
1383 return nPosition;
1386 sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::setCaretPosition (sal_Int32 nIndex)
1388 ThrowIfDisposed();
1390 if (mpParagraph)
1392 mpParagraph->SetCaretPosition(nIndex);
1393 return true;
1395 else
1396 return false;
1399 sal_Unicode SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacter (sal_Int32 nIndex)
1401 ThrowIfDisposed();
1403 if (!mpParagraph)
1404 throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1405 return mpParagraph->GetCharacter(nIndex);
1408 Sequence<css::beans::PropertyValue> SAL_CALL
1409 PresenterAccessible::AccessibleParagraph::getCharacterAttributes (
1410 ::sal_Int32 nIndex,
1411 const css::uno::Sequence<OUString>& rRequestedAttributes)
1413 ThrowIfDisposed();
1415 #if OSL_DEBUG_LEVEL > 0
1416 SAL_INFO( "sdext.presenter", __func__ << " at " << this << ", " << nIndex << " returns empty set" );
1417 for (sal_Int32 nAttributeIndex(0), nAttributeCount(rRequestedAttributes.getLength());
1418 nAttributeIndex < nAttributeCount;
1419 ++nAttributeIndex)
1421 SAL_INFO( "sdext.presenter",
1422 " requested attribute " << nAttributeIndex << " is " << rRequestedAttributes[nAttributeIndex] );
1424 #else
1425 (void)nIndex;
1426 (void)rRequestedAttributes;
1427 #endif
1429 // Character properties are not supported.
1430 return Sequence<css::beans::PropertyValue>();
1433 awt::Rectangle SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterBounds (
1434 sal_Int32 nIndex)
1436 ThrowIfDisposed();
1438 awt::Rectangle aCharacterBox;
1439 if (nIndex < 0)
1441 throw lang::IndexOutOfBoundsException("invalid text index", static_cast<uno::XWeak*>(this));
1443 else if (mpParagraph)
1445 aCharacterBox = mpParagraph->GetCharacterBounds(nIndex, false);
1446 // Convert coordinates relative to the window origin into absolute
1447 // screen coordinates.
1448 const awt::Point aWindowLocationOnScreen (getLocationOnScreen());
1449 aCharacterBox.X += aWindowLocationOnScreen.X;
1450 aCharacterBox.Y += aWindowLocationOnScreen.Y;
1452 else
1454 throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1457 return aCharacterBox;
1460 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterCount()
1462 ThrowIfDisposed();
1464 sal_Int32 nCount (0);
1465 if (mpParagraph)
1466 nCount = mpParagraph->GetCharacterCount();
1468 return nCount;
1471 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getIndexAtPoint (
1472 const css::awt::Point& )
1474 ThrowIfDisposed();
1475 return -1;
1478 OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectedText()
1480 ThrowIfDisposed();
1482 return getTextRange(getSelectionStart(), getSelectionEnd());
1485 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionStart()
1487 ThrowIfDisposed();
1489 return getCaretPosition();
1492 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionEnd()
1494 ThrowIfDisposed();
1496 return getCaretPosition();
1499 sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::setSelection (
1500 sal_Int32 nStartIndex,
1501 sal_Int32)
1503 ThrowIfDisposed();
1505 return setCaretPosition(nStartIndex);
1508 OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getText()
1510 ThrowIfDisposed();
1512 OUString sText;
1513 if (mpParagraph)
1514 sText = mpParagraph->GetText();
1516 return sText;
1519 OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getTextRange (
1520 sal_Int32 nLocalStartIndex,
1521 sal_Int32 nLocalEndIndex)
1523 ThrowIfDisposed();
1525 OUString sText;
1526 if (mpParagraph)
1528 const TextSegment aSegment (
1529 mpParagraph->CreateTextSegment(nLocalStartIndex, nLocalEndIndex));
1530 sText = aSegment.SegmentText;
1533 return sText;
1536 TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextAtIndex (
1537 sal_Int32 nLocalCharacterIndex,
1538 sal_Int16 nTextType)
1540 ThrowIfDisposed();
1542 TextSegment aSegment;
1543 if (mpParagraph)
1544 aSegment = mpParagraph->GetTextSegment(0, nLocalCharacterIndex, nTextType);
1546 return aSegment;
1549 TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextBeforeIndex (
1550 sal_Int32 nLocalCharacterIndex,
1551 sal_Int16 nTextType)
1553 ThrowIfDisposed();
1555 TextSegment aSegment;
1556 if (mpParagraph)
1557 aSegment = mpParagraph->GetTextSegment(-1, nLocalCharacterIndex, nTextType);
1559 return aSegment;
1562 TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextBehindIndex (
1563 sal_Int32 nLocalCharacterIndex,
1564 sal_Int16 nTextType)
1566 ThrowIfDisposed();
1568 TextSegment aSegment;
1569 if (mpParagraph)
1570 aSegment = mpParagraph->GetTextSegment(+1, nLocalCharacterIndex, nTextType);
1572 return aSegment;
1575 sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::copyText (
1576 sal_Int32,
1577 sal_Int32)
1579 ThrowIfDisposed();
1581 // Return false because copying to clipboard is not supported.
1582 // It IS supported in the notes view. There is no need to duplicate
1583 // this here.
1584 return false;
1587 sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::scrollSubstringTo(
1588 sal_Int32,
1589 sal_Int32,
1590 AccessibleScrollType)
1592 return false;
1595 //----- protected -------------------------------------------------------------
1597 awt::Point PresenterAccessible::AccessibleParagraph::GetRelativeLocation()
1599 awt::Point aLocation (AccessibleObject::GetRelativeLocation());
1600 if (mpParagraph)
1602 const awt::Point aParagraphLocation (mpParagraph->GetRelativeLocation());
1603 aLocation.X += aParagraphLocation.X;
1604 aLocation.Y += aParagraphLocation.Y;
1607 return aLocation;
1610 awt::Size PresenterAccessible::AccessibleParagraph::GetSize()
1612 if (mpParagraph)
1613 return mpParagraph->GetSize();
1614 else
1615 return AccessibleObject::GetSize();
1618 awt::Point PresenterAccessible::AccessibleParagraph::GetAbsoluteParentLocation()
1620 if (mxParentAccessible.is())
1622 Reference<XAccessibleContext> xParentContext =
1623 mxParentAccessible->getAccessibleContext();
1624 if (xParentContext.is())
1626 Reference<XAccessibleComponent> xGrandParentComponent(
1627 xParentContext->getAccessibleParent(), UNO_QUERY);
1628 if (xGrandParentComponent.is())
1629 return xGrandParentComponent->getLocationOnScreen();
1633 return awt::Point();
1636 bool PresenterAccessible::AccessibleParagraph::GetWindowState (const sal_Int16 nType) const
1638 switch (nType)
1640 case AccessibleStateType::EDITABLE:
1641 return bool(mpParagraph);
1643 case AccessibleStateType::ACTIVE:
1644 return true;
1646 default:
1647 return AccessibleObject::GetWindowState(nType);
1651 //===== AccessibleNotes =======================================================
1653 AccessibleNotes::AccessibleNotes (
1654 const css::lang::Locale& rLocale,
1655 const OUString& rsName)
1656 : AccessibleObject(rLocale,AccessibleRole::PANEL,rsName),
1657 mpTextView()
1661 rtl::Reference<PresenterAccessible::AccessibleObject> AccessibleNotes::Create (
1662 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
1663 const lang::Locale& rLocale,
1664 const Reference<awt::XWindow>& rxContentWindow,
1665 const Reference<awt::XWindow>& rxBorderWindow,
1666 const std::shared_ptr<PresenterTextView>& rpTextView)
1668 OUString sName ("Presenter Notes Text");
1670 PresenterConfigurationAccess aConfiguration (
1671 rxContext,
1672 "/org.openoffice.Office.PresenterScreen/",
1673 PresenterConfigurationAccess::READ_ONLY);
1674 aConfiguration.GetConfigurationNode("Presenter/Accessibility/Notes/String")
1675 >>= sName;
1678 rtl::Reference<AccessibleNotes> pObject (
1679 new AccessibleNotes(
1680 rLocale,
1681 sName));
1682 pObject->LateInitialization();
1683 pObject->SetTextView(rpTextView);
1684 pObject->UpdateStateSet();
1685 pObject->SetWindow(rxContentWindow, rxBorderWindow);
1687 return rtl::Reference<PresenterAccessible::AccessibleObject>(pObject.get());
1690 void AccessibleNotes::SetTextView (
1691 const std::shared_ptr<PresenterTextView>& rpTextView)
1693 ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > aChildren;
1695 // Release any listeners to the current text view.
1696 if (mpTextView)
1698 mpTextView->GetCaret()->SetCaretMotionBroadcaster(
1699 ::std::function<void (sal_Int32,sal_Int32,sal_Int32,sal_Int32)>());
1700 mpTextView->SetTextChangeBroadcaster(
1701 ::std::function<void ()>());
1704 mpTextView = rpTextView;
1706 if (!mpTextView)
1707 return;
1709 // Create a new set of children, one for each paragraph.
1710 const sal_Int32 nParagraphCount (mpTextView->GetParagraphCount());
1711 for (sal_Int32 nIndex=0; nIndex<nParagraphCount; ++nIndex)
1713 rtl::Reference<PresenterAccessible::AccessibleParagraph> pParagraph (
1714 new PresenterAccessible::AccessibleParagraph(
1715 css::lang::Locale(),
1716 "Paragraph"+OUString::number(nIndex),
1717 rpTextView->GetParagraph(nIndex),
1718 nIndex));
1719 pParagraph->LateInitialization();
1720 pParagraph->SetWindow(mxContentWindow, mxBorderWindow);
1721 pParagraph->SetAccessibleParent(this);
1722 aChildren.emplace_back(pParagraph.get());
1724 maChildren.swap(aChildren);
1725 FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1727 // Dispose the old children. (This will remove them from the focus
1728 // manager).
1729 for (const auto& rxChild : aChildren)
1731 Reference<lang::XComponent> xComponent (static_cast<XWeak*>(rxChild.get()), UNO_QUERY);
1732 if (xComponent.is())
1733 xComponent->dispose();
1736 // This class acts as a controller of who broadcasts caret motion
1737 // events and handles text changes. Register the corresponding
1738 // listeners here.
1739 mpTextView->GetCaret()->SetCaretMotionBroadcaster(
1740 [this](sal_Int32 a, sal_Int32 b, sal_Int32 c, sal_Int32 d)
1741 { return this->NotifyCaretChange(a, b, c, d); });
1742 mpTextView->SetTextChangeBroadcaster(
1743 [this]() { return SetTextView(mpTextView); });
1746 void AccessibleNotes::SetWindow (
1747 const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
1748 const css::uno::Reference<css::awt::XWindow>& rxBorderWindow)
1750 AccessibleObject::SetWindow(rxContentWindow, rxBorderWindow);
1752 // Set the windows at the children as well, so that every paragraph can
1753 // setup its geometry.
1754 for (auto& rxChild : maChildren)
1756 rxChild->SetWindow(rxContentWindow, rxBorderWindow);
1760 void AccessibleNotes::NotifyCaretChange (
1761 const sal_Int32 nOldParagraphIndex,
1762 const sal_Int32 nOldCharacterIndex,
1763 const sal_Int32 nNewParagraphIndex,
1764 const sal_Int32 nNewCharacterIndex)
1766 AccessibleFocusManager::Instance()->FocusObject(
1767 nNewParagraphIndex >= 0
1768 ? maChildren[nNewParagraphIndex]
1769 : this);
1771 if (nOldParagraphIndex != nNewParagraphIndex)
1773 // Moved caret from one paragraph to another (or showed or
1774 // hid the caret). Move focus from one accessible
1775 // paragraph to another.
1776 if (nOldParagraphIndex >= 0)
1778 maChildren[nOldParagraphIndex]->FireAccessibleEvent(
1779 AccessibleEventId::CARET_CHANGED,
1780 Any(nOldCharacterIndex),
1781 Any(sal_Int32(-1)));
1783 if (nNewParagraphIndex >= 0)
1785 maChildren[nNewParagraphIndex]->FireAccessibleEvent(
1786 AccessibleEventId::CARET_CHANGED,
1787 Any(sal_Int32(-1)),
1788 Any(nNewCharacterIndex));
1791 else if (nNewParagraphIndex >= 0)
1793 // Caret moved inside one paragraph.
1794 maChildren[nNewParagraphIndex]->FireAccessibleEvent(
1795 AccessibleEventId::CARET_CHANGED,
1796 Any(nOldCharacterIndex),
1797 Any(nNewCharacterIndex));
1802 //===== AccessibleFocusManager ================================================
1804 std::shared_ptr<AccessibleFocusManager> AccessibleFocusManager::mpInstance;
1806 std::shared_ptr<AccessibleFocusManager> const & AccessibleFocusManager::Instance()
1808 if ( ! mpInstance)
1810 mpInstance.reset(new AccessibleFocusManager());
1812 return mpInstance;
1815 AccessibleFocusManager::AccessibleFocusManager()
1819 AccessibleFocusManager::~AccessibleFocusManager()
1821 // copy member to stack, then drop it - otherwise will get use-after-free
1822 // from AccessibleObject::disposing(), it will call ~Reference *twice*
1823 auto const temp(std::move(maFocusableObjects));
1824 (void) temp;
1825 m_isInDtor = true;
1828 void AccessibleFocusManager::AddFocusableObject (
1829 const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1831 OSL_ASSERT(rpObject.is());
1832 OSL_ASSERT(::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject)==maFocusableObjects.end());
1834 maFocusableObjects.push_back(rpObject);
1837 void AccessibleFocusManager::RemoveFocusableObject (
1838 const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1840 ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> >::iterator iObject (
1841 ::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject));
1843 if (iObject != maFocusableObjects.end())
1844 maFocusableObjects.erase(iObject);
1845 else
1847 OSL_ASSERT(m_isInDtor); // in dtor, was removed already
1851 void AccessibleFocusManager::FocusObject (
1852 const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1854 // Remove the focus of any of the other focusable objects.
1855 for (auto& rxObject : maFocusableObjects)
1857 if (rxObject!=rpObject)
1858 rxObject->SetIsFocused(false);
1861 if (rpObject.is())
1862 rpObject->SetIsFocused(true);
1865 } // end of namespace ::sd::presenter
1867 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */