vcl: allow for overriding the default PDF rendering resolution
[LibreOffice.git] / sdext / source / presenter / PresenterAccessibility.cxx
blob14c3c81ede7f2e2dcae40261324717a768569f1f
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/AccessibleStateType.hpp>
32 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
33 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
34 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
35 #include <com/sun/star/accessibility/XAccessibleText.hpp>
36 #include <com/sun/star/awt/XWindow2.hpp>
37 #include <com/sun/star/drawing/framework/XPane.hpp>
38 #include <com/sun/star/drawing/framework/XView.hpp>
39 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
40 #include <cppuhelper/compbase.hxx>
41 #include <cppuhelper/implbase.hxx>
42 #include <sal/log.hxx>
44 #include <algorithm>
46 using namespace ::com::sun::star;
47 using namespace ::com::sun::star::accessibility;
48 using namespace ::com::sun::star::uno;
49 using namespace ::com::sun::star::drawing::framework;
51 //===== PresenterAccessibleObject =============================================
53 namespace sdext { namespace presenter {
55 namespace {
56 typedef ::cppu::WeakComponentImplHelper <
57 css::accessibility::XAccessible,
58 css::accessibility::XAccessibleContext,
59 css::accessibility::XAccessibleComponent,
60 css::accessibility::XAccessibleEventBroadcaster,
61 css::awt::XWindowListener
62 > PresenterAccessibleObjectInterfaceBase;
65 class PresenterAccessible::AccessibleObject
66 : public ::cppu::BaseMutex,
67 public PresenterAccessibleObjectInterfaceBase
69 public:
70 AccessibleObject (
71 const css::lang::Locale& rLocale,
72 const sal_Int16 nRole,
73 const OUString& rsName);
74 void LateInitialization();
76 virtual void SetWindow (
77 const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
78 const css::uno::Reference<css::awt::XWindow>& rxBorderWindow);
79 void SetAccessibleParent (const css::uno::Reference<css::accessibility::XAccessible>& rxAccessibleParent);
81 virtual void SAL_CALL disposing() override;
83 void AddChild (const ::rtl::Reference<AccessibleObject>& rpChild);
84 void RemoveChild (const ::rtl::Reference<AccessibleObject>& rpChild);
86 void SetIsFocused (const bool bIsFocused);
87 void SetAccessibleName (const OUString& rsName);
89 void FireAccessibleEvent (
90 const sal_Int16 nEventId,
91 const css::uno::Any& rOldValue,
92 const css::uno::Any& rNewValue);
94 void UpdateStateSet();
96 //----- XAccessible -------------------------------------------------------
98 virtual css::uno::Reference<css::accessibility::XAccessibleContext> SAL_CALL
99 getAccessibleContext() override;
101 //----- XAccessibleContext ----------------------------------------------
103 virtual sal_Int32 SAL_CALL getAccessibleChildCount() override;
105 virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL
106 getAccessibleChild (sal_Int32 nIndex) override;
108 virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL getAccessibleParent() override;
110 virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override;
112 virtual sal_Int16 SAL_CALL getAccessibleRole() override;
114 virtual OUString SAL_CALL getAccessibleDescription() override;
116 virtual OUString SAL_CALL getAccessibleName() override;
118 virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet> SAL_CALL
119 getAccessibleRelationSet() override;
121 virtual css::uno::Reference<css::accessibility::XAccessibleStateSet> SAL_CALL
122 getAccessibleStateSet() override;
124 virtual css::lang::Locale SAL_CALL getLocale() override;
126 //----- XAccessibleComponent --------------------------------------------
128 virtual sal_Bool SAL_CALL containsPoint (
129 const css::awt::Point& aPoint) override;
131 virtual css::uno::Reference<css::accessibility::XAccessible> SAL_CALL
132 getAccessibleAtPoint (
133 const css::awt::Point& aPoint) override;
135 virtual css::awt::Rectangle SAL_CALL getBounds() override;
137 virtual css::awt::Point SAL_CALL getLocation() override;
139 virtual css::awt::Point SAL_CALL getLocationOnScreen() override;
141 virtual css::awt::Size SAL_CALL getSize() override;
143 virtual void SAL_CALL grabFocus() override;
145 virtual sal_Int32 SAL_CALL getForeground() override;
147 virtual sal_Int32 SAL_CALL getBackground() override;
149 //----- XAccessibleEventBroadcaster --------------------------------------
151 virtual void SAL_CALL addAccessibleEventListener (
152 const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rxListener) override;
154 virtual void SAL_CALL removeAccessibleEventListener (
155 const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rxListener) override;
157 //----- XWindowListener ---------------------------------------------------
159 virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) override;
161 virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) override;
163 virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) override;
165 virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) override;
167 //----- XEventListener ----------------------------------------------------
169 virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override;
171 protected:
172 OUString msName;
173 css::uno::Reference<css::awt::XWindow2> mxContentWindow;
174 css::uno::Reference<css::awt::XWindow2> mxBorderWindow;
175 const css::lang::Locale maLocale;
176 const sal_Int16 mnRole;
177 sal_uInt32 mnStateSet;
178 bool mbIsFocused;
179 css::uno::Reference<css::accessibility::XAccessible> mxParentAccessible;
180 ::std::vector<rtl::Reference<AccessibleObject> > maChildren;
181 ::std::vector<Reference<XAccessibleEventListener> > maListeners;
183 virtual awt::Point GetRelativeLocation();
184 virtual awt::Size GetSize();
185 virtual awt::Point GetAbsoluteParentLocation();
187 virtual bool GetWindowState (const sal_Int16 nType) const;
189 void UpdateState (const sal_Int16 aState, const bool bValue);
191 /// @throws css::lang::DisposedException
192 void ThrowIfDisposed() const;
195 //===== AccessibleStateSet ====================================================
197 namespace {
198 typedef ::cppu::WeakComponentImplHelper <
199 css::accessibility::XAccessibleStateSet
200 > AccessibleStateSetInterfaceBase;
203 class AccessibleStateSet
204 : public ::cppu::BaseMutex,
205 public AccessibleStateSetInterfaceBase
207 public:
208 explicit AccessibleStateSet (const sal_Int32 nStateSet);
210 static sal_uInt32 GetStateMask (const sal_Int16 nType);
212 //----- XAccessibleStateSet -----------------------------------------------
214 virtual sal_Bool SAL_CALL isEmpty() override;
216 virtual sal_Bool SAL_CALL contains (sal_Int16 nState) override;
218 virtual sal_Bool SAL_CALL containsAll (const css::uno::Sequence<sal_Int16>& rStateSet) override;
220 virtual css::uno::Sequence<sal_Int16> SAL_CALL getStates() override;
222 private:
223 const sal_Int32 mnStateSet;
226 //===== AccessibleRelationSet =================================================
228 namespace {
229 typedef ::cppu::WeakComponentImplHelper <
230 css::accessibility::XAccessibleRelationSet
231 > AccessibleRelationSetInterfaceBase;
234 class AccessibleRelationSet
235 : public ::cppu::BaseMutex,
236 public AccessibleRelationSetInterfaceBase
238 public:
239 AccessibleRelationSet();
241 void AddRelation (
242 const sal_Int16 nRelationType,
243 const Reference<XInterface>& rxObject);
245 //----- XAccessibleRelationSet --------------------------------------------
247 virtual sal_Int32 SAL_CALL getRelationCount() override;
249 virtual AccessibleRelation SAL_CALL getRelation (sal_Int32 nIndex) override;
251 virtual sal_Bool SAL_CALL containsRelation (sal_Int16 nRelationType) override;
253 virtual AccessibleRelation SAL_CALL getRelationByType (sal_Int16 nRelationType) override;
255 private:
256 ::std::vector<AccessibleRelation> maRelations;
259 //===== PresenterAccessibleParagraph ==========================================
261 namespace {
262 typedef ::cppu::ImplInheritanceHelper <
263 PresenterAccessible::AccessibleObject,
264 css::accessibility::XAccessibleText
265 > PresenterAccessibleParagraphInterfaceBase;
268 class PresenterAccessible::AccessibleParagraph
269 : public PresenterAccessibleParagraphInterfaceBase
271 public:
272 AccessibleParagraph (
273 const css::lang::Locale& rLocale,
274 const OUString& rsName,
275 const SharedPresenterTextParagraph& rpParagraph,
276 const sal_Int32 nParagraphIndex);
278 //----- XAccessibleContext ------------------------------------------------
280 virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet> SAL_CALL
281 getAccessibleRelationSet() override;
283 //----- XAccessibleText ---------------------------------------------------
285 virtual sal_Int32 SAL_CALL getCaretPosition() override;
287 virtual sal_Bool SAL_CALL setCaretPosition (sal_Int32 nIndex) override;
289 virtual sal_Unicode SAL_CALL getCharacter (sal_Int32 nIndex) override;
291 virtual css::uno::Sequence<css::beans::PropertyValue> SAL_CALL
292 getCharacterAttributes (
293 ::sal_Int32 nIndex,
294 const css::uno::Sequence<OUString>& rRequestedAttributes) override;
296 virtual css::awt::Rectangle SAL_CALL getCharacterBounds (sal_Int32 nIndex) override;
298 virtual sal_Int32 SAL_CALL getCharacterCount() override;
300 virtual sal_Int32 SAL_CALL getIndexAtPoint (const css::awt::Point& rPoint) override;
302 virtual OUString SAL_CALL getSelectedText() override;
304 virtual sal_Int32 SAL_CALL getSelectionStart() override;
306 virtual sal_Int32 SAL_CALL getSelectionEnd() override;
308 virtual sal_Bool SAL_CALL setSelection (sal_Int32 nStartIndex, sal_Int32 nEndIndex) override;
310 virtual OUString SAL_CALL getText() override;
312 virtual OUString SAL_CALL getTextRange (
313 sal_Int32 nStartIndex,
314 sal_Int32 nEndIndex) override;
316 virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex (
317 sal_Int32 nIndex,
318 sal_Int16 nTextType) override;
320 virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex (
321 sal_Int32 nIndex,
322 sal_Int16 nTextType) override;
324 virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex (
325 sal_Int32 nIndex,
326 sal_Int16 nTextType) override;
328 virtual sal_Bool SAL_CALL copyText (sal_Int32 nStartIndex, sal_Int32 nEndIndex) override;
330 protected:
331 virtual awt::Point GetRelativeLocation() override;
332 virtual awt::Size GetSize() override;
333 virtual awt::Point GetAbsoluteParentLocation() override;
334 virtual bool GetWindowState (const sal_Int16 nType) const override;
336 private:
337 SharedPresenterTextParagraph mpParagraph;
338 const sal_Int32 mnParagraphIndex;
341 //===== AccessibleConsole =====================================================
343 class AccessibleConsole
345 public:
346 static rtl::Reference<PresenterAccessible::AccessibleObject> Create (
347 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
348 const lang::Locale& rLocale)
350 OUString sName ("Presenter Console");
351 PresenterConfigurationAccess aConfiguration (
352 rxContext,
353 "/org.openoffice.Office.PresenterScreen/",
354 PresenterConfigurationAccess::READ_ONLY);
355 aConfiguration.GetConfigurationNode("Presenter/Accessibility/Console/String")
356 >>= sName;
358 rtl::Reference<PresenterAccessible::AccessibleObject> pObject (
359 new PresenterAccessible::AccessibleObject(
360 rLocale, AccessibleRole::PANEL, sName));
361 pObject->LateInitialization();
362 pObject->UpdateStateSet();
364 return pObject;
368 //===== AccessiblePreview =====================================================
370 class AccessiblePreview
372 public:
373 static rtl::Reference<PresenterAccessible::AccessibleObject> Create (
374 const Reference<css::uno::XComponentContext>& rxContext,
375 const lang::Locale& rLocale,
376 const Reference<awt::XWindow>& rxContentWindow,
377 const Reference<awt::XWindow>& rxBorderWindow)
379 OUString sName ("Presenter Notes Window");
381 PresenterConfigurationAccess aConfiguration (
382 rxContext,
383 "/org.openoffice.Office.PresenterScreen/",
384 PresenterConfigurationAccess::READ_ONLY);
385 aConfiguration.GetConfigurationNode("Presenter/Accessibility/Preview/String")
386 >>= sName;
389 rtl::Reference<PresenterAccessible::AccessibleObject> pObject (
390 new PresenterAccessible::AccessibleObject(
391 rLocale,
392 AccessibleRole::LABEL,
393 sName));
394 pObject->LateInitialization();
395 pObject->UpdateStateSet();
396 pObject->SetWindow(rxContentWindow, rxBorderWindow);
398 return pObject;
402 //===== AccessibleNotes =======================================================
404 class AccessibleNotes : public PresenterAccessible::AccessibleObject
406 public:
407 AccessibleNotes (
408 const css::lang::Locale& rLocale,
409 const OUString& rsName);
411 static rtl::Reference<PresenterAccessible::AccessibleObject> Create (
412 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
413 const lang::Locale& rLocale,
414 const Reference<awt::XWindow>& rxContentWindow,
415 const Reference<awt::XWindow>& rxBorderWindow,
416 const std::shared_ptr<PresenterTextView>& rpTextView);
418 void SetTextView (const std::shared_ptr<PresenterTextView>& rpTextView);
420 virtual void SetWindow (
421 const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
422 const css::uno::Reference<css::awt::XWindow>& rxBorderWindow) override;
424 private:
425 std::shared_ptr<PresenterTextView> mpTextView;
427 void NotifyCaretChange (
428 const sal_Int32 nOldParagraphIndex,
429 const sal_Int32 nOldCharacterIndex,
430 const sal_Int32 nNewParagraphIndex,
431 const sal_Int32 nNewCharacterIndex);
434 //===== AccessibleFocusManager ================================================
436 /** A singleton class that makes sure that only one accessibility object in
437 the PresenterConsole hierarchy has the focus.
439 class AccessibleFocusManager
441 public:
442 static std::shared_ptr<AccessibleFocusManager> const & Instance();
444 void AddFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
445 void RemoveFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
447 void FocusObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
449 private:
450 static std::shared_ptr<AccessibleFocusManager> mpInstance;
451 ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > maFocusableObjects;
453 AccessibleFocusManager();
456 //===== PresenterAccessible ===================================================
458 PresenterAccessible::PresenterAccessible (
459 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
460 const ::rtl::Reference<PresenterController>& rpPresenterController,
461 const Reference<drawing::framework::XPane>& rxMainPane)
462 : PresenterAccessibleInterfaceBase(m_aMutex),
463 mxComponentContext(rxContext),
464 mpPresenterController(rpPresenterController),
465 mxMainPane(rxMainPane, UNO_QUERY),
466 mxMainWindow(),
467 mxPreviewContentWindow(),
468 mxPreviewBorderWindow(),
469 mxNotesContentWindow(),
470 mxNotesBorderWindow(),
471 mpAccessibleConsole(),
472 mpAccessiblePreview(),
473 mpAccessibleNotes(),
474 mxAccessibleParent()
476 if (mxMainPane.is())
477 mxMainPane->setAccessible(this);
480 PresenterAccessible::~PresenterAccessible()
484 PresenterPaneContainer::SharedPaneDescriptor PresenterAccessible::GetPreviewPane() const
486 PresenterPaneContainer::SharedPaneDescriptor pPreviewPane;
488 if ( ! mpPresenterController.is())
489 return pPreviewPane;
491 rtl::Reference<PresenterPaneContainer> pContainer (mpPresenterController->GetPaneContainer());
492 if ( ! pContainer.is())
493 return pPreviewPane;
495 pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL);
496 Reference<drawing::framework::XPane> xPreviewPane;
497 if (pPreviewPane)
498 xPreviewPane = pPreviewPane->mxPane.get();
499 if ( ! xPreviewPane.is())
501 pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msSlideSorterPaneURL);
503 return pPreviewPane;
506 void PresenterAccessible::UpdateAccessibilityHierarchy()
508 if ( ! mpPresenterController.is())
509 return;
511 Reference<drawing::framework::XConfigurationController> xConfigurationController(
512 mpPresenterController->GetConfigurationController());
513 if ( ! xConfigurationController.is())
514 return;
516 rtl::Reference<PresenterPaneContainer> pPaneContainer (
517 mpPresenterController->GetPaneContainer());
518 if ( ! pPaneContainer.is())
519 return;
521 if ( ! mpAccessibleConsole.is())
522 return;
524 // Get the preview pane (standard or notes view) or the slide overview
525 // pane.
526 PresenterPaneContainer::SharedPaneDescriptor pPreviewPane(GetPreviewPane());
527 Reference<drawing::framework::XPane> xPreviewPane;
528 if (pPreviewPane)
529 xPreviewPane = pPreviewPane->mxPane.get();
531 // Get the notes pane.
532 PresenterPaneContainer::SharedPaneDescriptor pNotesPane(
533 pPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL));
534 Reference<drawing::framework::XPane> xNotesPane;
535 if (pNotesPane)
536 xNotesPane = pNotesPane->mxPane.get();
538 // Get the notes view.
539 Reference<drawing::framework::XView> xNotesView;
540 if (pNotesPane)
541 xNotesView = pNotesPane->mxView;
542 rtl::Reference<PresenterNotesView> pNotesView (
543 dynamic_cast<PresenterNotesView*>(xNotesView.get()));
545 UpdateAccessibilityHierarchy(
546 pPreviewPane ? pPreviewPane->mxContentWindow : Reference<awt::XWindow>(),
547 pPreviewPane ? pPreviewPane->mxBorderWindow : Reference<awt::XWindow>(),
548 (pPreviewPane&&pPreviewPane->mxPane.is()) ? pPreviewPane->mxPane->GetTitle() : OUString(),
549 pNotesPane ? pNotesPane->mxContentWindow : Reference<awt::XWindow>(),
550 pNotesPane ? pNotesPane->mxBorderWindow : Reference<awt::XWindow>(),
551 pNotesView.is()
552 ? pNotesView->GetTextView()
553 : std::shared_ptr<PresenterTextView>());
556 void PresenterAccessible::UpdateAccessibilityHierarchy (
557 const Reference<awt::XWindow>& rxPreviewContentWindow,
558 const Reference<awt::XWindow>& rxPreviewBorderWindow,
559 const OUString& rsTitle,
560 const Reference<awt::XWindow>& rxNotesContentWindow,
561 const Reference<awt::XWindow>& rxNotesBorderWindow,
562 const std::shared_ptr<PresenterTextView>& rpNotesTextView)
564 if ( ! mpAccessibleConsole.is())
565 return;
567 if (mxPreviewContentWindow != rxPreviewContentWindow)
569 if (mpAccessiblePreview.is())
571 mpAccessibleConsole->RemoveChild(mpAccessiblePreview);
572 mpAccessiblePreview = nullptr;
575 mxPreviewContentWindow = rxPreviewContentWindow;
576 mxPreviewBorderWindow = rxPreviewBorderWindow;
578 if (mxPreviewContentWindow.is())
580 mpAccessiblePreview = AccessiblePreview::Create(
581 mxComponentContext,
582 lang::Locale(),
583 mxPreviewContentWindow,
584 mxPreviewBorderWindow);
585 mpAccessibleConsole->AddChild(mpAccessiblePreview);
586 mpAccessiblePreview->SetAccessibleName(rsTitle);
590 if (mxNotesContentWindow != rxNotesContentWindow)
592 if (mpAccessibleNotes.is())
594 mpAccessibleConsole->RemoveChild(mpAccessibleNotes);
595 mpAccessibleNotes = nullptr;
598 mxNotesContentWindow = rxNotesContentWindow;
599 mxNotesBorderWindow = rxNotesBorderWindow;
601 if (mxNotesContentWindow.is())
603 mpAccessibleNotes = AccessibleNotes::Create(
604 mxComponentContext,
605 lang::Locale(),
606 mxNotesContentWindow,
607 mxNotesBorderWindow,
608 rpNotesTextView);
609 mpAccessibleConsole->AddChild(mpAccessibleNotes.get());
614 void PresenterAccessible::NotifyCurrentSlideChange ()
616 if (mpAccessiblePreview.is())
618 PresenterPaneContainer::SharedPaneDescriptor pPreviewPane (GetPreviewPane());
619 mpAccessiblePreview->SetAccessibleName(
620 pPreviewPane&&pPreviewPane->mxPane.is()
621 ? pPreviewPane->mxPane->GetTitle()
622 : OUString());
625 // Play some focus ping-pong to trigger AT tools.
626 //AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
627 AccessibleFocusManager::Instance()->FocusObject(mpAccessiblePreview);
630 void SAL_CALL PresenterAccessible::disposing()
632 UpdateAccessibilityHierarchy(
633 nullptr,
634 nullptr,
635 OUString(),
636 nullptr,
637 nullptr,
638 std::shared_ptr<PresenterTextView>());
640 if (mxMainWindow.is())
642 mxMainWindow->removeFocusListener(this);
644 if (mxMainPane.is())
645 mxMainPane->setAccessible(nullptr);
648 mpAccessiblePreview = nullptr;
649 mpAccessibleNotes = nullptr;
650 mpAccessibleConsole = nullptr;
653 //----- XAccessible -----------------------------------------------------------
655 Reference<XAccessibleContext> SAL_CALL PresenterAccessible::getAccessibleContext()
657 if ( ! mpAccessibleConsole.is())
659 Reference<XPane> xMainPane (mxMainPane, UNO_QUERY);
660 if (xMainPane.is())
662 mxMainWindow = xMainPane->getWindow();
663 mxMainWindow->addFocusListener(this);
665 mpAccessibleConsole = AccessibleConsole::Create(
666 mxComponentContext, css::lang::Locale());
667 mpAccessibleConsole->SetWindow(mxMainWindow, nullptr);
668 mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
669 UpdateAccessibilityHierarchy();
670 if (mpPresenterController.is())
671 mpPresenterController->SetAccessibilityActiveState(true);
673 return mpAccessibleConsole->getAccessibleContext();
676 //----- XFocusListener ----------------------------------------------------
678 void SAL_CALL PresenterAccessible::focusGained (const css::awt::FocusEvent&)
680 SAL_INFO("sdext.presenter", OSL_THIS_FUNC << ": PresenterAccessible::focusGained at " << this
681 << " and window " << mxMainWindow.get());
682 AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
685 void SAL_CALL PresenterAccessible::focusLost (const css::awt::FocusEvent&)
687 SAL_INFO("sdext.presenter", OSL_THIS_FUNC << ": PresenterAccessible::focusLost at " << this);
688 AccessibleFocusManager::Instance()->FocusObject(nullptr);
691 //----- XEventListener ----------------------------------------------------
693 void SAL_CALL PresenterAccessible::disposing (const css::lang::EventObject& rEvent)
695 if (rEvent.Source == mxMainWindow)
696 mxMainWindow = nullptr;
699 //----- XInitialize -----------------------------------------------------------
701 void SAL_CALL PresenterAccessible::initialize (const css::uno::Sequence<css::uno::Any>& rArguments)
703 if (rArguments.hasElements())
705 mxAccessibleParent.set(rArguments[0], UNO_QUERY);
706 if (mpAccessibleConsole.is())
707 mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
711 //===== PresenterAccessible::AccessibleObject =========================================
713 PresenterAccessible::AccessibleObject::AccessibleObject (
714 const lang::Locale& rLocale,
715 const sal_Int16 nRole,
716 const OUString& rsName)
717 : PresenterAccessibleObjectInterfaceBase(m_aMutex),
718 msName(rsName),
719 mxContentWindow(),
720 mxBorderWindow(),
721 maLocale(rLocale),
722 mnRole(nRole),
723 mnStateSet(0),
724 mbIsFocused(false),
725 mxParentAccessible(),
726 maChildren(),
727 maListeners()
731 void PresenterAccessible::AccessibleObject::LateInitialization()
733 AccessibleFocusManager::Instance()->AddFocusableObject(this);
736 void PresenterAccessible::AccessibleObject::SetWindow (
737 const Reference<awt::XWindow>& rxContentWindow,
738 const Reference<awt::XWindow>& rxBorderWindow)
740 Reference<awt::XWindow2> xContentWindow (rxContentWindow, UNO_QUERY);
742 if (mxContentWindow.get() != xContentWindow.get())
744 if (mxContentWindow.is())
746 mxContentWindow->removeWindowListener(this);
749 mxContentWindow = xContentWindow;
750 mxBorderWindow.set(rxBorderWindow, UNO_QUERY);
752 if (mxContentWindow.is())
754 mxContentWindow->addWindowListener(this);
757 UpdateStateSet();
761 void PresenterAccessible::AccessibleObject::SetAccessibleParent (
762 const Reference<XAccessible>& rxAccessibleParent)
764 mxParentAccessible = rxAccessibleParent;
767 void SAL_CALL PresenterAccessible::AccessibleObject::disposing()
769 AccessibleFocusManager::Instance()->RemoveFocusableObject(this);
770 SetWindow(nullptr, nullptr);
773 //----- XAccessible -------------------------------------------------------
775 Reference<XAccessibleContext> SAL_CALL
776 PresenterAccessible::AccessibleObject::getAccessibleContext()
778 ThrowIfDisposed();
780 return this;
783 //----- XAccessibleContext ----------------------------------------------
785 sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getAccessibleChildCount()
787 ThrowIfDisposed();
789 const sal_Int32 nChildCount (maChildren.size());
791 return nChildCount;
794 Reference<XAccessible> SAL_CALL
795 PresenterAccessible::AccessibleObject::getAccessibleChild (sal_Int32 nIndex)
797 ThrowIfDisposed();
799 if (nIndex<0 || nIndex>=sal_Int32(maChildren.size()))
800 throw lang::IndexOutOfBoundsException("invalid child index", static_cast<uno::XWeak*>(this));
802 return Reference<XAccessible>(maChildren[nIndex].get());
805 Reference<XAccessible> SAL_CALL
806 PresenterAccessible::AccessibleObject::getAccessibleParent()
808 ThrowIfDisposed();
810 return mxParentAccessible;
813 sal_Int32 SAL_CALL
814 PresenterAccessible::AccessibleObject::getAccessibleIndexInParent()
816 ThrowIfDisposed();
818 const Reference<XAccessible> xThis (this);
819 if (mxParentAccessible.is())
821 const Reference<XAccessibleContext> xContext (mxParentAccessible->getAccessibleContext());
822 for (sal_Int32 nIndex=0,nCount=xContext->getAccessibleChildCount();
823 nIndex<nCount;
824 ++nIndex)
826 if (xContext->getAccessibleChild(nIndex) == xThis)
827 return nIndex;
831 return 0;
834 sal_Int16 SAL_CALL
835 PresenterAccessible::AccessibleObject::getAccessibleRole()
837 ThrowIfDisposed();
839 return mnRole;
842 OUString SAL_CALL
843 PresenterAccessible::AccessibleObject::getAccessibleDescription()
845 ThrowIfDisposed();
847 return msName;
850 OUString SAL_CALL
851 PresenterAccessible::AccessibleObject::getAccessibleName()
853 ThrowIfDisposed();
855 return msName;
858 Reference<XAccessibleRelationSet> SAL_CALL
859 PresenterAccessible::AccessibleObject::getAccessibleRelationSet()
861 ThrowIfDisposed();
863 return nullptr;
866 Reference<XAccessibleStateSet> SAL_CALL
867 PresenterAccessible::AccessibleObject::getAccessibleStateSet()
869 ThrowIfDisposed();
871 return Reference<XAccessibleStateSet>(new AccessibleStateSet(mnStateSet));
874 lang::Locale SAL_CALL
875 PresenterAccessible::AccessibleObject::getLocale()
877 ThrowIfDisposed();
879 if (mxParentAccessible.is())
881 Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
882 if (xParentContext.is())
883 return xParentContext->getLocale();
885 return maLocale;
888 //----- XAccessibleComponent ------------------------------------------------
890 sal_Bool SAL_CALL PresenterAccessible::AccessibleObject::containsPoint (
891 const awt::Point& rPoint)
893 ThrowIfDisposed();
895 if (mxContentWindow.is())
897 const awt::Rectangle aBox (getBounds());
898 return rPoint.X>=aBox.X
899 && rPoint.Y>=aBox.Y
900 && rPoint.X<aBox.X+aBox.Width
901 && rPoint.Y<aBox.Y+aBox.Height;
903 else
904 return false;
907 Reference<XAccessible> SAL_CALL
908 PresenterAccessible::AccessibleObject::getAccessibleAtPoint (const awt::Point&)
910 ThrowIfDisposed();
912 return Reference<XAccessible>();
915 awt::Rectangle SAL_CALL PresenterAccessible::AccessibleObject::getBounds()
917 ThrowIfDisposed();
919 const awt::Point aLocation (GetRelativeLocation());
920 const awt::Size aSize (GetSize());
922 return awt::Rectangle (aLocation.X, aLocation.Y, aSize.Width, aSize.Height);
925 awt::Point SAL_CALL PresenterAccessible::AccessibleObject::getLocation()
927 ThrowIfDisposed();
929 const awt::Point aLocation (GetRelativeLocation());
931 return aLocation;
934 awt::Point SAL_CALL PresenterAccessible::AccessibleObject::getLocationOnScreen()
936 ThrowIfDisposed();
938 awt::Point aRelativeLocation (GetRelativeLocation());
939 awt::Point aParentLocationOnScreen (GetAbsoluteParentLocation());
941 return awt::Point(
942 aRelativeLocation.X + aParentLocationOnScreen.X,
943 aRelativeLocation.Y + aParentLocationOnScreen.Y);
946 awt::Size SAL_CALL PresenterAccessible::AccessibleObject::getSize()
948 ThrowIfDisposed();
950 const awt::Size aSize (GetSize());
952 return aSize;
955 void SAL_CALL PresenterAccessible::AccessibleObject::grabFocus()
957 ThrowIfDisposed();
958 if (mxBorderWindow.is())
959 mxBorderWindow->setFocus();
960 else if (mxContentWindow.is())
961 mxContentWindow->setFocus();
964 sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getForeground()
966 ThrowIfDisposed();
968 return 0x00ffffff;
971 sal_Int32 SAL_CALL PresenterAccessible::AccessibleObject::getBackground()
973 ThrowIfDisposed();
975 return 0x00000000;
978 //----- XAccessibleEventBroadcaster -------------------------------------------
980 void SAL_CALL PresenterAccessible::AccessibleObject::addAccessibleEventListener (
981 const Reference<XAccessibleEventListener>& rxListener)
983 if (rxListener.is())
985 const osl::MutexGuard aGuard(m_aMutex);
987 if (rBHelper.bDisposed || rBHelper.bInDispose)
989 uno::Reference<uno::XInterface> xThis (static_cast<XWeak*>(this), UNO_QUERY);
990 rxListener->disposing (lang::EventObject(xThis));
992 else
994 maListeners.push_back(rxListener);
999 void SAL_CALL PresenterAccessible::AccessibleObject::removeAccessibleEventListener (
1000 const Reference<XAccessibleEventListener>& rxListener)
1002 ThrowIfDisposed();
1003 if (rxListener.is())
1005 const osl::MutexGuard aGuard(m_aMutex);
1007 auto const it(std::remove(maListeners.begin(), maListeners.end(), rxListener));
1008 if (it != maListeners.end())
1010 maListeners.erase(it);
1015 //----- XWindowListener ---------------------------------------------------
1017 void SAL_CALL PresenterAccessible::AccessibleObject::windowResized (
1018 const css::awt::WindowEvent&)
1020 FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1023 void SAL_CALL PresenterAccessible::AccessibleObject::windowMoved (
1024 const css::awt::WindowEvent&)
1026 FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1029 void SAL_CALL PresenterAccessible::AccessibleObject::windowShown (
1030 const css::lang::EventObject&)
1032 UpdateStateSet();
1035 void SAL_CALL PresenterAccessible::AccessibleObject::windowHidden (
1036 const css::lang::EventObject&)
1038 UpdateStateSet();
1041 //----- XEventListener --------------------------------------------------------
1043 void SAL_CALL PresenterAccessible::AccessibleObject::disposing (const css::lang::EventObject& rEvent)
1045 if (rEvent.Source == mxContentWindow)
1047 mxContentWindow = nullptr;
1048 mxBorderWindow = nullptr;
1050 else
1052 SetWindow(nullptr, nullptr);
1056 //----- private ---------------------------------------------------------------
1058 bool PresenterAccessible::AccessibleObject::GetWindowState (const sal_Int16 nType) const
1060 switch (nType)
1062 case AccessibleStateType::ENABLED:
1063 return mxContentWindow.is() && mxContentWindow->isEnabled();
1065 case AccessibleStateType::FOCUSABLE:
1066 return true;
1068 case AccessibleStateType::FOCUSED:
1069 return mbIsFocused;
1071 case AccessibleStateType::SHOWING:
1072 return mxContentWindow.is() && mxContentWindow->isVisible();
1074 default:
1075 return false;
1079 void PresenterAccessible::AccessibleObject::UpdateStateSet()
1081 UpdateState(AccessibleStateType::FOCUSABLE, true);
1082 UpdateState(AccessibleStateType::VISIBLE, true);
1083 UpdateState(AccessibleStateType::ENABLED, true);
1084 UpdateState(AccessibleStateType::MULTI_LINE, true);
1085 UpdateState(AccessibleStateType::SENSITIVE, true);
1087 UpdateState(AccessibleStateType::ENABLED, GetWindowState(AccessibleStateType::ENABLED));
1088 UpdateState(AccessibleStateType::FOCUSED, GetWindowState(AccessibleStateType::FOCUSED));
1089 UpdateState(AccessibleStateType::SHOWING, GetWindowState(AccessibleStateType::SHOWING));
1090 // UpdateState(AccessibleStateType::ACTIVE, GetWindowState(AccessibleStateType::ACTIVE));
1093 void PresenterAccessible::AccessibleObject::UpdateState(
1094 const sal_Int16 nState,
1095 const bool bValue)
1097 const sal_uInt32 nStateMask (AccessibleStateSet::GetStateMask(nState));
1098 if (((mnStateSet & nStateMask)!=0) != bValue)
1100 if (bValue)
1102 mnStateSet |= nStateMask;
1103 FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(), Any(nState));
1105 else
1107 mnStateSet &= ~nStateMask;
1108 FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(nState), Any());
1113 void PresenterAccessible::AccessibleObject::AddChild (
1114 const ::rtl::Reference<AccessibleObject>& rpChild)
1116 maChildren.push_back(rpChild);
1117 rpChild->SetAccessibleParent(this);
1118 FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1121 void PresenterAccessible::AccessibleObject::RemoveChild (
1122 const ::rtl::Reference<AccessibleObject>& rpChild)
1124 rpChild->SetAccessibleParent(Reference<XAccessible>());
1125 maChildren.erase(::std::find(maChildren.begin(), maChildren.end(), rpChild));
1126 FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1129 void PresenterAccessible::AccessibleObject::SetIsFocused (const bool bIsFocused)
1131 if (mbIsFocused != bIsFocused)
1133 mbIsFocused = bIsFocused;
1134 UpdateStateSet();
1138 void PresenterAccessible::AccessibleObject::SetAccessibleName (const OUString& rsName)
1140 if (msName != rsName)
1142 const OUString sOldName(msName);
1143 msName = rsName;
1144 FireAccessibleEvent(AccessibleEventId::NAME_CHANGED, Any(sOldName), Any(msName));
1148 void PresenterAccessible::AccessibleObject::FireAccessibleEvent (
1149 const sal_Int16 nEventId,
1150 const uno::Any& rOldValue,
1151 const uno::Any& rNewValue )
1153 AccessibleEventObject aEventObject;
1155 aEventObject.Source = Reference<XWeak>(this);
1156 aEventObject.EventId = nEventId;
1157 aEventObject.NewValue = rNewValue;
1158 aEventObject.OldValue = rOldValue;
1160 ::std::vector<Reference<XAccessibleEventListener> > aListenerCopy(maListeners);
1161 for (const auto& rxListener : aListenerCopy)
1165 rxListener->notifyEvent(aEventObject);
1167 catch (const lang::DisposedException&)
1169 // Listener has been disposed and should have been removed
1170 // already.
1171 removeAccessibleEventListener(rxListener);
1173 catch (const Exception&)
1175 // Ignore all other exceptions and assume that they are
1176 // caused by a temporary problem.
1181 awt::Point PresenterAccessible::AccessibleObject::GetRelativeLocation()
1183 awt::Point aLocation;
1184 if (mxContentWindow.is())
1186 const awt::Rectangle aContentBox (mxContentWindow->getPosSize());
1187 aLocation.X = aContentBox.X;
1188 aLocation.Y = aContentBox.Y;
1189 if (mxBorderWindow.is())
1191 const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize());
1192 aLocation.X += aBorderBox.X;
1193 aLocation.Y += aBorderBox.Y;
1196 return aLocation;
1199 awt::Size PresenterAccessible::AccessibleObject::GetSize()
1201 if (mxContentWindow.is())
1203 const awt::Rectangle aBox (mxContentWindow->getPosSize());
1204 return awt::Size(aBox.Width, aBox.Height);
1206 else
1207 return awt::Size();
1210 awt::Point PresenterAccessible::AccessibleObject::GetAbsoluteParentLocation()
1212 Reference<XAccessibleComponent> xParentComponent;
1213 if (mxParentAccessible.is())
1214 xParentComponent.set( mxParentAccessible->getAccessibleContext(), UNO_QUERY);
1215 if (xParentComponent.is())
1216 return xParentComponent->getLocationOnScreen();
1217 else
1218 return awt::Point();
1221 void PresenterAccessible::AccessibleObject::ThrowIfDisposed() const
1223 if (rBHelper.bDisposed || rBHelper.bInDispose)
1224 throw lang::DisposedException("object has already been disposed", uno::Reference<uno::XInterface>(const_cast<uno::XWeak*>(static_cast<uno::XWeak const *>(this))));
1227 //===== AccessibleStateSet ====================================================
1229 AccessibleStateSet::AccessibleStateSet (const sal_Int32 nStateSet)
1230 : AccessibleStateSetInterfaceBase(m_aMutex),
1231 mnStateSet (nStateSet)
1235 sal_uInt32 AccessibleStateSet::GetStateMask (const sal_Int16 nState)
1237 if (nState<0 || nState>=sal_Int16(sizeof(sal_uInt32)*8))
1239 throw RuntimeException("AccessibleStateSet::GetStateMask: invalid state");
1242 return 1<<nState;
1245 //----- XAccessibleStateSet ---------------------------------------------------
1247 sal_Bool SAL_CALL AccessibleStateSet::isEmpty()
1249 return mnStateSet==0;
1252 sal_Bool SAL_CALL AccessibleStateSet::contains (sal_Int16 nState)
1254 return (mnStateSet & GetStateMask(nState)) != 0;
1257 sal_Bool SAL_CALL AccessibleStateSet::containsAll (const css::uno::Sequence<sal_Int16>& rStateSet)
1259 return std::none_of(rStateSet.begin(), rStateSet.end(),
1260 [this](const sal_Int16 nState) { return (mnStateSet & GetStateMask(nState)) == 0; });
1263 css::uno::Sequence<sal_Int16> SAL_CALL AccessibleStateSet::getStates()
1265 ::std::vector<sal_Int16> aStates;
1266 aStates.reserve(sizeof(mnStateSet)*8);
1267 for (sal_uInt16 nIndex=0; nIndex<sizeof(mnStateSet)*8; ++nIndex)
1268 if ((mnStateSet & GetStateMask(nIndex)) != 0)
1269 aStates.push_back(nIndex);
1270 return Sequence<sal_Int16>(aStates.data(), aStates.size());
1273 //===== AccessibleRelationSet =================================================
1275 AccessibleRelationSet::AccessibleRelationSet()
1276 : AccessibleRelationSetInterfaceBase(m_aMutex),
1277 maRelations()
1281 void AccessibleRelationSet::AddRelation (
1282 const sal_Int16 nRelationType,
1283 const Reference<XInterface>& rxObject)
1285 maRelations.emplace_back();
1286 maRelations.back().RelationType = nRelationType;
1287 maRelations.back().TargetSet.realloc(1);
1288 maRelations.back().TargetSet[0] = rxObject;
1291 //----- XAccessibleRelationSet ------------------------------------------------
1293 sal_Int32 SAL_CALL AccessibleRelationSet::getRelationCount()
1295 return maRelations.size();
1298 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelation (sal_Int32 nIndex)
1300 if (nIndex<0 && sal_uInt32(nIndex)>=maRelations.size())
1301 return AccessibleRelation();
1302 else
1303 return maRelations[nIndex];
1306 sal_Bool SAL_CALL AccessibleRelationSet::containsRelation (sal_Int16 nRelationType)
1308 return std::any_of(maRelations.begin(), maRelations.end(),
1309 [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1312 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelationByType (sal_Int16 nRelationType)
1314 auto iRelation = std::find_if(maRelations.begin(), maRelations.end(),
1315 [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1316 if (iRelation != maRelations.end())
1317 return *iRelation;
1318 return AccessibleRelation();
1321 //===== PresenterAccessible::AccessibleParagraph ==============================
1323 PresenterAccessible::AccessibleParagraph::AccessibleParagraph (
1324 const lang::Locale& rLocale,
1325 const OUString& rsName,
1326 const SharedPresenterTextParagraph& rpParagraph,
1327 const sal_Int32 nParagraphIndex)
1328 : PresenterAccessibleParagraphInterfaceBase(rLocale, AccessibleRole::PARAGRAPH, rsName),
1329 mpParagraph(rpParagraph),
1330 mnParagraphIndex(nParagraphIndex)
1334 //----- XAccessibleContext ----------------------------------------------------
1336 Reference<XAccessibleRelationSet> SAL_CALL
1337 PresenterAccessible::AccessibleParagraph::getAccessibleRelationSet()
1339 ThrowIfDisposed();
1341 rtl::Reference<AccessibleRelationSet> pSet (new AccessibleRelationSet);
1343 if (mxParentAccessible.is())
1345 Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
1346 if (xParentContext.is())
1348 if (mnParagraphIndex>0)
1349 pSet->AddRelation(
1350 AccessibleRelationType::CONTENT_FLOWS_FROM,
1351 xParentContext->getAccessibleChild(mnParagraphIndex-1));
1353 if (mnParagraphIndex<xParentContext->getAccessibleChildCount()-1)
1354 pSet->AddRelation(
1355 AccessibleRelationType::CONTENT_FLOWS_TO,
1356 xParentContext->getAccessibleChild(mnParagraphIndex+1));
1360 return Reference<XAccessibleRelationSet>(pSet.get());
1363 //----- XAccessibleText -------------------------------------------------------
1365 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCaretPosition()
1367 ThrowIfDisposed();
1369 sal_Int32 nPosition (-1);
1370 if (mpParagraph)
1371 nPosition = mpParagraph->GetCaretPosition();
1373 return nPosition;
1376 sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::setCaretPosition (sal_Int32 nIndex)
1378 ThrowIfDisposed();
1380 if (mpParagraph)
1382 mpParagraph->SetCaretPosition(nIndex);
1383 return true;
1385 else
1386 return false;
1389 sal_Unicode SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacter (sal_Int32 nIndex)
1391 ThrowIfDisposed();
1393 if (!mpParagraph)
1394 throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1395 return mpParagraph->GetCharacter(nIndex);
1398 Sequence<css::beans::PropertyValue> SAL_CALL
1399 PresenterAccessible::AccessibleParagraph::getCharacterAttributes (
1400 ::sal_Int32 nIndex,
1401 const css::uno::Sequence<OUString>& rRequestedAttributes)
1403 ThrowIfDisposed();
1405 #if OSL_DEBUG_LEVEL > 0
1406 SAL_INFO( "sdext.presenter", OSL_THIS_FUNC << " at " << this << ", " << nIndex << " returns empty set" );
1407 for (sal_Int32 nAttributeIndex(0), nAttributeCount(rRequestedAttributes.getLength());
1408 nAttributeIndex < nAttributeCount;
1409 ++nAttributeIndex)
1411 SAL_INFO( "sdext.presenter",
1412 " requested attribute " << nAttributeIndex << " is " << rRequestedAttributes[nAttributeIndex] );
1414 #else
1415 (void)nIndex;
1416 (void)rRequestedAttributes;
1417 #endif
1419 // Character properties are not supported.
1420 return Sequence<css::beans::PropertyValue>();
1423 awt::Rectangle SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterBounds (
1424 sal_Int32 nIndex)
1426 ThrowIfDisposed();
1428 awt::Rectangle aCharacterBox;
1429 if (nIndex < 0)
1431 throw lang::IndexOutOfBoundsException("invalid text index", static_cast<uno::XWeak*>(this));
1433 else if (mpParagraph)
1435 aCharacterBox = mpParagraph->GetCharacterBounds(nIndex, false);
1436 // Convert coordinates relative to the window origin into absolute
1437 // screen coordinates.
1438 const awt::Point aWindowLocationOnScreen (getLocationOnScreen());
1439 aCharacterBox.X += aWindowLocationOnScreen.X;
1440 aCharacterBox.Y += aWindowLocationOnScreen.Y;
1442 else
1444 throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1447 return aCharacterBox;
1450 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getCharacterCount()
1452 ThrowIfDisposed();
1454 sal_Int32 nCount (0);
1455 if (mpParagraph)
1456 nCount = mpParagraph->GetCharacterCount();
1458 return nCount;
1461 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getIndexAtPoint (
1462 const css::awt::Point& )
1464 ThrowIfDisposed();
1465 return -1;
1468 OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectedText()
1470 ThrowIfDisposed();
1472 return getTextRange(getSelectionStart(), getSelectionEnd());
1475 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionStart()
1477 ThrowIfDisposed();
1479 return getCaretPosition();
1482 sal_Int32 SAL_CALL PresenterAccessible::AccessibleParagraph::getSelectionEnd()
1484 ThrowIfDisposed();
1486 return getCaretPosition();
1489 sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::setSelection (
1490 sal_Int32 nStartIndex,
1491 sal_Int32)
1493 ThrowIfDisposed();
1495 return setCaretPosition(nStartIndex);
1498 OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getText()
1500 ThrowIfDisposed();
1502 OUString sText;
1503 if (mpParagraph)
1504 sText = mpParagraph->GetText();
1506 return sText;
1509 OUString SAL_CALL PresenterAccessible::AccessibleParagraph::getTextRange (
1510 sal_Int32 nLocalStartIndex,
1511 sal_Int32 nLocalEndIndex)
1513 ThrowIfDisposed();
1515 OUString sText;
1516 if (mpParagraph)
1518 const TextSegment aSegment (
1519 mpParagraph->CreateTextSegment(nLocalStartIndex, nLocalEndIndex));
1520 sText = aSegment.SegmentText;
1523 return sText;
1526 TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextAtIndex (
1527 sal_Int32 nLocalCharacterIndex,
1528 sal_Int16 nTextType)
1530 ThrowIfDisposed();
1532 TextSegment aSegment;
1533 if (mpParagraph)
1534 aSegment = mpParagraph->GetTextSegment(0, nLocalCharacterIndex, nTextType);
1536 return aSegment;
1539 TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextBeforeIndex (
1540 sal_Int32 nLocalCharacterIndex,
1541 sal_Int16 nTextType)
1543 ThrowIfDisposed();
1545 TextSegment aSegment;
1546 if (mpParagraph)
1547 aSegment = mpParagraph->GetTextSegment(-1, nLocalCharacterIndex, nTextType);
1549 return aSegment;
1552 TextSegment SAL_CALL PresenterAccessible::AccessibleParagraph::getTextBehindIndex (
1553 sal_Int32 nLocalCharacterIndex,
1554 sal_Int16 nTextType)
1556 ThrowIfDisposed();
1558 TextSegment aSegment;
1559 if (mpParagraph)
1560 aSegment = mpParagraph->GetTextSegment(+1, nLocalCharacterIndex, nTextType);
1562 return aSegment;
1565 sal_Bool SAL_CALL PresenterAccessible::AccessibleParagraph::copyText (
1566 sal_Int32,
1567 sal_Int32)
1569 ThrowIfDisposed();
1571 // Return false because copying to clipboard is not supported.
1572 // It IS supported in the notes view. There is no need to duplicate
1573 // this here.
1574 return false;
1577 //----- protected -------------------------------------------------------------
1579 awt::Point PresenterAccessible::AccessibleParagraph::GetRelativeLocation()
1581 awt::Point aLocation (AccessibleObject::GetRelativeLocation());
1582 if (mpParagraph)
1584 const awt::Point aParagraphLocation (mpParagraph->GetRelativeLocation());
1585 aLocation.X += aParagraphLocation.X;
1586 aLocation.Y += aParagraphLocation.Y;
1589 return aLocation;
1592 awt::Size PresenterAccessible::AccessibleParagraph::GetSize()
1594 if (mpParagraph)
1595 return mpParagraph->GetSize();
1596 else
1597 return AccessibleObject::GetSize();
1600 awt::Point PresenterAccessible::AccessibleParagraph::GetAbsoluteParentLocation()
1602 if (mxParentAccessible.is())
1604 Reference<XAccessibleContext> xParentContext =
1605 mxParentAccessible->getAccessibleContext();
1606 if (xParentContext.is())
1608 Reference<XAccessibleComponent> xGrandParentComponent(
1609 xParentContext->getAccessibleParent(), UNO_QUERY);
1610 if (xGrandParentComponent.is())
1611 return xGrandParentComponent->getLocationOnScreen();
1615 return awt::Point();
1618 bool PresenterAccessible::AccessibleParagraph::GetWindowState (const sal_Int16 nType) const
1620 switch (nType)
1622 case AccessibleStateType::EDITABLE:
1623 return mpParagraph.get()!=nullptr;
1625 case AccessibleStateType::ACTIVE:
1626 return true;
1628 default:
1629 return AccessibleObject::GetWindowState(nType);
1633 //===== AccessibleNotes =======================================================
1635 AccessibleNotes::AccessibleNotes (
1636 const css::lang::Locale& rLocale,
1637 const OUString& rsName)
1638 : AccessibleObject(rLocale,AccessibleRole::PANEL,rsName),
1639 mpTextView()
1643 rtl::Reference<PresenterAccessible::AccessibleObject> AccessibleNotes::Create (
1644 const css::uno::Reference<css::uno::XComponentContext>& rxContext,
1645 const lang::Locale& rLocale,
1646 const Reference<awt::XWindow>& rxContentWindow,
1647 const Reference<awt::XWindow>& rxBorderWindow,
1648 const std::shared_ptr<PresenterTextView>& rpTextView)
1650 OUString sName ("Presenter Notes Text");
1652 PresenterConfigurationAccess aConfiguration (
1653 rxContext,
1654 "/org.openoffice.Office.PresenterScreen/",
1655 PresenterConfigurationAccess::READ_ONLY);
1656 aConfiguration.GetConfigurationNode("Presenter/Accessibility/Notes/String")
1657 >>= sName;
1660 rtl::Reference<AccessibleNotes> pObject (
1661 new AccessibleNotes(
1662 rLocale,
1663 sName));
1664 pObject->LateInitialization();
1665 pObject->SetTextView(rpTextView);
1666 pObject->UpdateStateSet();
1667 pObject->SetWindow(rxContentWindow, rxBorderWindow);
1669 return rtl::Reference<PresenterAccessible::AccessibleObject>(pObject.get());
1672 void AccessibleNotes::SetTextView (
1673 const std::shared_ptr<PresenterTextView>& rpTextView)
1675 ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > aChildren;
1677 // Release any listeners to the current text view.
1678 if (mpTextView)
1680 mpTextView->GetCaret()->SetCaretMotionBroadcaster(
1681 ::std::function<void (sal_Int32,sal_Int32,sal_Int32,sal_Int32)>());
1682 mpTextView->SetTextChangeBroadcaster(
1683 ::std::function<void ()>());
1686 mpTextView = rpTextView;
1688 if (mpTextView)
1690 // Create a new set of children, one for each paragraph.
1691 const sal_Int32 nParagraphCount (mpTextView->GetParagraphCount());
1692 for (sal_Int32 nIndex=0; nIndex<nParagraphCount; ++nIndex)
1694 rtl::Reference<PresenterAccessible::AccessibleParagraph> pParagraph (
1695 new PresenterAccessible::AccessibleParagraph(
1696 css::lang::Locale(),
1697 "Paragraph"+OUString::number(nIndex),
1698 rpTextView->GetParagraph(nIndex),
1699 nIndex));
1700 pParagraph->LateInitialization();
1701 pParagraph->SetWindow(mxContentWindow, mxBorderWindow);
1702 pParagraph->SetAccessibleParent(this);
1703 aChildren.emplace_back(pParagraph.get());
1705 maChildren.swap(aChildren);
1706 FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1708 // Dispose the old children. (This will remove them from the focus
1709 // manager).
1710 for (const auto& rxChild : aChildren)
1712 Reference<lang::XComponent> xComponent (static_cast<XWeak*>(rxChild.get()), UNO_QUERY);
1713 if (xComponent.is())
1714 xComponent->dispose();
1717 // This class acts as a controller of who broadcasts caret motion
1718 // events and handles text changes. Register the corresponding
1719 // listeners here.
1720 mpTextView->GetCaret()->SetCaretMotionBroadcaster(
1721 [this](sal_Int32 a, sal_Int32 b, sal_Int32 c, sal_Int32 d)
1722 { return this->NotifyCaretChange(a, b, c, d); });
1723 mpTextView->SetTextChangeBroadcaster(
1724 [this]() { return SetTextView(mpTextView); });
1728 void AccessibleNotes::SetWindow (
1729 const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
1730 const css::uno::Reference<css::awt::XWindow>& rxBorderWindow)
1732 AccessibleObject::SetWindow(rxContentWindow, rxBorderWindow);
1734 // Set the windows at the children as well, so that every paragraph can
1735 // setup its geometry.
1736 for (auto& rxChild : maChildren)
1738 rxChild->SetWindow(rxContentWindow, rxBorderWindow);
1742 void AccessibleNotes::NotifyCaretChange (
1743 const sal_Int32 nOldParagraphIndex,
1744 const sal_Int32 nOldCharacterIndex,
1745 const sal_Int32 nNewParagraphIndex,
1746 const sal_Int32 nNewCharacterIndex)
1748 AccessibleFocusManager::Instance()->FocusObject(
1749 nNewParagraphIndex >= 0
1750 ? maChildren[nNewParagraphIndex]
1751 : this);
1753 if (nOldParagraphIndex != nNewParagraphIndex)
1755 // Moved caret from one paragraph to another (or showed or
1756 // hid the caret). Move focus from one accessible
1757 // paragraph to another.
1758 if (nOldParagraphIndex >= 0)
1760 maChildren[nOldParagraphIndex]->FireAccessibleEvent(
1761 AccessibleEventId::CARET_CHANGED,
1762 Any(nOldCharacterIndex),
1763 Any(sal_Int32(-1)));
1765 if (nNewParagraphIndex >= 0)
1767 maChildren[nNewParagraphIndex]->FireAccessibleEvent(
1768 AccessibleEventId::CARET_CHANGED,
1769 Any(sal_Int32(-1)),
1770 Any(nNewCharacterIndex));
1773 else if (nNewParagraphIndex >= 0)
1775 // Caret moved inside one paragraph.
1776 maChildren[nNewParagraphIndex]->FireAccessibleEvent(
1777 AccessibleEventId::CARET_CHANGED,
1778 Any(nOldCharacterIndex),
1779 Any(nNewCharacterIndex));
1784 //===== AccessibleFocusManager ================================================
1786 std::shared_ptr<AccessibleFocusManager> AccessibleFocusManager::mpInstance;
1788 std::shared_ptr<AccessibleFocusManager> const & AccessibleFocusManager::Instance()
1790 if ( ! mpInstance)
1792 mpInstance.reset(new AccessibleFocusManager());
1794 return mpInstance;
1797 AccessibleFocusManager::AccessibleFocusManager()
1798 : maFocusableObjects()
1802 void AccessibleFocusManager::AddFocusableObject (
1803 const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1805 OSL_ASSERT(rpObject.is());
1806 OSL_ASSERT(::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject)==maFocusableObjects.end());
1808 maFocusableObjects.push_back(rpObject);
1811 void AccessibleFocusManager::RemoveFocusableObject (
1812 const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1814 ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> >::iterator iObject (
1815 ::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject));
1817 if (iObject != maFocusableObjects.end())
1818 maFocusableObjects.erase(iObject);
1819 else
1821 OSL_ASSERT(iObject!=maFocusableObjects.end());
1825 void AccessibleFocusManager::FocusObject (
1826 const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1828 // Remove the focus of any of the other focusable objects.
1829 for (auto& rxObject : maFocusableObjects)
1831 if (rxObject!=rpObject)
1832 rxObject->SetIsFocused(false);
1835 if (rpObject.is())
1836 rpObject->SetIsFocused(true);
1839 } } // end of namespace ::sd::presenter
1841 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */