LibreOffice Module sdext (master)  1
PresenterAccessibility.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
21 #include "PresenterTextView.hxx"
23 #include "PresenterNotesView.hxx"
24 #include "PresenterPaneBase.hxx"
26 #include "PresenterPaneFactory.hxx"
27 
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>
45 
46 #include <algorithm>
47 
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;
52 
53 //===== PresenterAccessibleObject =============================================
54 
55 namespace sdext::presenter {
56 
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;
65 }
66 
68  : public ::cppu::BaseMutex,
69  public PresenterAccessibleObjectInterfaceBase
70 {
71 public:
73  const css::lang::Locale& rLocale,
74  const sal_Int16 nRole,
75  const OUString& rsName);
76  void LateInitialization();
77 
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);
82 
83  virtual void SAL_CALL disposing() override;
84 
85  void AddChild (const ::rtl::Reference<AccessibleObject>& rpChild);
86  void RemoveChild (const ::rtl::Reference<AccessibleObject>& rpChild);
87 
88  void SetIsFocused (const bool bIsFocused);
89  void SetAccessibleName (const OUString& rsName);
90 
91  void FireAccessibleEvent (
92  const sal_Int16 nEventId,
93  const css::uno::Any& rOldValue,
94  const css::uno::Any& rNewValue);
95 
96  void UpdateStateSet();
97 
98  //----- XAccessible -------------------------------------------------------
99 
100  virtual css::uno::Reference<css::accessibility::XAccessibleContext> SAL_CALL
101  getAccessibleContext() override;
102 
103  //----- XAccessibleContext ----------------------------------------------
104 
105  virtual sal_Int32 SAL_CALL getAccessibleChildCount() override;
106 
107  virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL
108  getAccessibleChild (sal_Int32 nIndex) override;
109 
110  virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL getAccessibleParent() override;
111 
112  virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override;
113 
114  virtual sal_Int16 SAL_CALL getAccessibleRole() override;
115 
116  virtual OUString SAL_CALL getAccessibleDescription() override;
117 
118  virtual OUString SAL_CALL getAccessibleName() override;
119 
120  virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet> SAL_CALL
121  getAccessibleRelationSet() override;
122 
123  virtual css::uno::Reference<css::accessibility::XAccessibleStateSet> SAL_CALL
124  getAccessibleStateSet() override;
125 
126  virtual css::lang::Locale SAL_CALL getLocale() override;
127 
128  //----- XAccessibleComponent --------------------------------------------
129 
130  virtual sal_Bool SAL_CALL containsPoint (
131  const css::awt::Point& aPoint) override;
132 
133  virtual css::uno::Reference<css::accessibility::XAccessible> SAL_CALL
135  const css::awt::Point& aPoint) override;
136 
137  virtual css::awt::Rectangle SAL_CALL getBounds() override;
138 
139  virtual css::awt::Point SAL_CALL getLocation() override;
140 
141  virtual css::awt::Point SAL_CALL getLocationOnScreen() override;
142 
143  virtual css::awt::Size SAL_CALL getSize() override;
144 
145  virtual void SAL_CALL grabFocus() override;
146 
147  virtual sal_Int32 SAL_CALL getForeground() override;
148 
149  virtual sal_Int32 SAL_CALL getBackground() override;
150 
151  //----- XAccessibleEventBroadcaster --------------------------------------
152 
153  virtual void SAL_CALL addAccessibleEventListener (
154  const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rxListener) override;
155 
156  virtual void SAL_CALL removeAccessibleEventListener (
157  const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rxListener) override;
158 
159  //----- XWindowListener ---------------------------------------------------
160 
161  virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) override;
162 
163  virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) override;
164 
165  virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) override;
166 
167  virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) override;
168 
169  //----- XEventListener ----------------------------------------------------
170 
171  virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override;
172 
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;
181  css::uno::Reference<css::accessibility::XAccessible> mxParentAccessible;
182  ::std::vector<rtl::Reference<AccessibleObject> > maChildren;
183  ::std::vector<Reference<XAccessibleEventListener> > maListeners;
184 
185  virtual awt::Point GetRelativeLocation();
186  virtual awt::Size GetSize();
187  virtual awt::Point GetAbsoluteParentLocation();
188 
189  virtual bool GetWindowState (const sal_Int16 nType) const;
190 
191  void UpdateState (const sal_Int16 aState, const bool bValue);
192 
194  void ThrowIfDisposed() const;
195 };
196 
197 //===== AccessibleStateSet ====================================================
198 
199 namespace {
200 typedef ::cppu::WeakComponentImplHelper <
201  css::accessibility::XAccessibleStateSet
202  > AccessibleStateSetInterfaceBase;
203 
204 class AccessibleStateSet
205  : public ::cppu::BaseMutex,
206  public AccessibleStateSetInterfaceBase
207 {
208 public:
209  explicit AccessibleStateSet (const sal_Int32 nStateSet);
210 
211  static sal_uInt32 GetStateMask (const sal_Int16 nType);
212 
213  //----- XAccessibleStateSet -----------------------------------------------
214 
215  virtual sal_Bool SAL_CALL isEmpty() override;
216 
217  virtual sal_Bool SAL_CALL contains (sal_Int16 nState) override;
218 
219  virtual sal_Bool SAL_CALL containsAll (const css::uno::Sequence<sal_Int16>& rStateSet) override;
220 
221  virtual css::uno::Sequence<sal_Int16> SAL_CALL getStates() override;
222 
223 private:
224  const sal_Int32 mnStateSet;
225 };
226 
227 //===== AccessibleRelationSet =================================================
228 
229 typedef ::cppu::WeakComponentImplHelper <
230  css::accessibility::XAccessibleRelationSet
231  > AccessibleRelationSetInterfaceBase;
232 
233 class AccessibleRelationSet
234  : public ::cppu::BaseMutex,
235  public AccessibleRelationSetInterfaceBase
236 {
237 public:
238  AccessibleRelationSet();
239 
240  void AddRelation (
241  const sal_Int16 nRelationType,
242  const Reference<XInterface>& rxObject);
243 
244  //----- XAccessibleRelationSet --------------------------------------------
245 
246  virtual sal_Int32 SAL_CALL getRelationCount() override;
247 
248  virtual AccessibleRelation SAL_CALL getRelation (sal_Int32 nIndex) override;
249 
250  virtual sal_Bool SAL_CALL containsRelation (sal_Int16 nRelationType) override;
251 
252  virtual AccessibleRelation SAL_CALL getRelationByType (sal_Int16 nRelationType) override;
253 
254 private:
255  ::std::vector<AccessibleRelation> maRelations;
256 };
257 
258 //===== PresenterAccessibleParagraph ==========================================
259 
260 typedef ::cppu::ImplInheritanceHelper <
261  PresenterAccessible::AccessibleObject,
262  css::accessibility::XAccessibleText
263  > PresenterAccessibleParagraphInterfaceBase;
264 }
265 
267  : public PresenterAccessibleParagraphInterfaceBase
268 {
269 public:
271  const css::lang::Locale& rLocale,
272  const OUString& rsName,
273  const SharedPresenterTextParagraph& rpParagraph,
274  const sal_Int32 nParagraphIndex);
275 
276  //----- XAccessibleContext ------------------------------------------------
277 
278  virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet> SAL_CALL
279  getAccessibleRelationSet() override;
280 
281  //----- XAccessibleText ---------------------------------------------------
282 
283  virtual sal_Int32 SAL_CALL getCaretPosition() override;
284 
285  virtual sal_Bool SAL_CALL setCaretPosition (sal_Int32 nIndex) override;
286 
287  virtual sal_Unicode SAL_CALL getCharacter (sal_Int32 nIndex) override;
288 
289  virtual css::uno::Sequence<css::beans::PropertyValue> SAL_CALL
291  ::sal_Int32 nIndex,
292  const css::uno::Sequence<OUString>& rRequestedAttributes) override;
293 
294  virtual css::awt::Rectangle SAL_CALL getCharacterBounds (sal_Int32 nIndex) override;
295 
296  virtual sal_Int32 SAL_CALL getCharacterCount() override;
297 
298  virtual sal_Int32 SAL_CALL getIndexAtPoint (const css::awt::Point& rPoint) override;
299 
300  virtual OUString SAL_CALL getSelectedText() override;
301 
302  virtual sal_Int32 SAL_CALL getSelectionStart() override;
303 
304  virtual sal_Int32 SAL_CALL getSelectionEnd() override;
305 
306  virtual sal_Bool SAL_CALL setSelection (sal_Int32 nStartIndex, sal_Int32 nEndIndex) override;
307 
308  virtual OUString SAL_CALL getText() override;
309 
310  virtual OUString SAL_CALL getTextRange (
311  sal_Int32 nStartIndex,
312  sal_Int32 nEndIndex) override;
313 
314  virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex (
315  sal_Int32 nIndex,
316  sal_Int16 nTextType) override;
317 
318  virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex (
319  sal_Int32 nIndex,
320  sal_Int16 nTextType) override;
321 
322  virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex (
323  sal_Int32 nIndex,
324  sal_Int16 nTextType) override;
325 
326  virtual sal_Bool SAL_CALL copyText (sal_Int32 nStartIndex, sal_Int32 nEndIndex) override;
327 
328  virtual sal_Bool SAL_CALL scrollSubstringTo(
329  sal_Int32 nStartIndex,
330  sal_Int32 nEndIndex,
331  css::accessibility::AccessibleScrollType aScrollType) override;
332 
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;
338 
339 private:
341  const sal_Int32 mnParagraphIndex;
342 };
343 
344 //===== AccessibleConsole =====================================================
345 
346 namespace {
347 
348 class AccessibleConsole
349 {
350 public:
352  const css::uno::Reference<css::uno::XComponentContext>& rxContext,
353  const lang::Locale& rLocale)
354  {
355  OUString sName ("Presenter Console");
356  PresenterConfigurationAccess aConfiguration (
357  rxContext,
358  "/org.openoffice.Office.PresenterScreen/",
360  aConfiguration.GetConfigurationNode("Presenter/Accessibility/Console/String")
361  >>= sName;
362 
365  rLocale, AccessibleRole::PANEL, sName));
366  pObject->LateInitialization();
367  pObject->UpdateStateSet();
368 
369  return pObject;
370  }
371 };
372 
373 //===== AccessiblePreview =====================================================
374 
375 class AccessiblePreview
376 {
377 public:
379  const Reference<css::uno::XComponentContext>& rxContext,
380  const lang::Locale& rLocale,
381  const Reference<awt::XWindow>& rxContentWindow,
382  const Reference<awt::XWindow>& rxBorderWindow)
383  {
384  OUString sName ("Presenter Notes Window");
385  {
386  PresenterConfigurationAccess aConfiguration (
387  rxContext,
388  "/org.openoffice.Office.PresenterScreen/",
390  aConfiguration.GetConfigurationNode("Presenter/Accessibility/Preview/String")
391  >>= sName;
392  }
393 
395  new PresenterAccessible::AccessibleObject(
396  rLocale,
397  AccessibleRole::LABEL,
398  sName));
399  pObject->LateInitialization();
400  pObject->UpdateStateSet();
401  pObject->SetWindow(rxContentWindow, rxBorderWindow);
402 
403  return pObject;
404  }
405 };
406 
407 //===== AccessibleNotes =======================================================
408 
409 class AccessibleNotes : public PresenterAccessible::AccessibleObject
410 {
411 public:
412  AccessibleNotes (
413  const css::lang::Locale& rLocale,
414  const OUString& rsName);
415 
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);
422 
423  void SetTextView (const std::shared_ptr<PresenterTextView>& rpTextView);
424 
425  virtual void SetWindow (
426  const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
427  const css::uno::Reference<css::awt::XWindow>& rxBorderWindow) override;
428 
429 private:
430  std::shared_ptr<PresenterTextView> mpTextView;
431 
432  void NotifyCaretChange (
433  const sal_Int32 nOldParagraphIndex,
434  const sal_Int32 nOldCharacterIndex,
435  const sal_Int32 nNewParagraphIndex,
436  const sal_Int32 nNewCharacterIndex);
437 };
438 
439 //===== AccessibleFocusManager ================================================
440 
444 class AccessibleFocusManager
445 {
446 public:
447  static std::shared_ptr<AccessibleFocusManager> const & Instance();
448 
449  void AddFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
450  void RemoveFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
451 
452  void FocusObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
453 
454  ~AccessibleFocusManager();
455 
456 private:
457  static std::shared_ptr<AccessibleFocusManager> mpInstance;
458  ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > maFocusableObjects;
459  bool m_isInDtor = false;
460 
461  AccessibleFocusManager();
462 };
463 
464 }
465 
466 //===== PresenterAccessible ===================================================
467 
469  const css::uno::Reference<css::uno::XComponentContext>& rxContext,
470  const ::rtl::Reference<PresenterController>& rpPresenterController,
471  const Reference<drawing::framework::XPane>& rxMainPane)
473  mxComponentContext(rxContext),
474  mpPresenterController(rpPresenterController),
475  mxMainPane(rxMainPane, UNO_QUERY)
476 {
477  if (mxMainPane.is())
478  mxMainPane->setAccessible(this);
479 }
480 
482 {
483 }
484 
486 {
488 
489  if ( ! mpPresenterController.is())
490  return pPreviewPane;
491 
492  rtl::Reference<PresenterPaneContainer> pContainer (mpPresenterController->GetPaneContainer());
493  if ( ! pContainer.is())
494  return pPreviewPane;
495 
496  pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL);
497  Reference<drawing::framework::XPane> xPreviewPane;
498  if (pPreviewPane)
499  xPreviewPane = pPreviewPane->mxPane.get();
500  if ( ! xPreviewPane.is())
501  {
502  pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msSlideSorterPaneURL);
503  }
504  return pPreviewPane;
505 }
506 
508 {
509  if ( ! mpPresenterController.is())
510  return;
511 
512  Reference<drawing::framework::XConfigurationController> xConfigurationController(
513  mpPresenterController->GetConfigurationController());
514  if ( ! xConfigurationController.is())
515  return;
516 
518  mpPresenterController->GetPaneContainer());
519  if ( ! pPaneContainer.is())
520  return;
521 
522  if ( ! mpAccessibleConsole.is())
523  return;
524 
525  // Get the preview pane (standard or notes view) or the slide overview
526  // pane.
528  Reference<drawing::framework::XPane> xPreviewPane;
529  if (pPreviewPane)
530  xPreviewPane = pPreviewPane->mxPane.get();
531 
532  // Get the notes pane.
534  pPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL));
535  Reference<drawing::framework::XPane> xNotesPane;
536  if (pNotesPane)
537  xNotesPane = pNotesPane->mxPane.get();
538 
539  // Get the notes view.
540  Reference<drawing::framework::XView> xNotesView;
541  if (pNotesPane)
542  xNotesView = pNotesPane->mxView;
544  dynamic_cast<PresenterNotesView*>(xNotesView.get()));
545 
547  pPreviewPane ? pPreviewPane->mxContentWindow : Reference<awt::XWindow>(),
548  pPreviewPane ? pPreviewPane->mxBorderWindow : Reference<awt::XWindow>(),
549  (pPreviewPane&&pPreviewPane->mxPane.is()) ? pPreviewPane->mxPane->GetTitle() : OUString(),
550  pNotesPane ? pNotesPane->mxContentWindow : Reference<awt::XWindow>(),
551  pNotesPane ? pNotesPane->mxBorderWindow : Reference<awt::XWindow>(),
552  pNotesView.is()
553  ? pNotesView->GetTextView()
554  : std::shared_ptr<PresenterTextView>());
555 }
556 
558  const Reference<awt::XWindow>& rxPreviewContentWindow,
559  const Reference<awt::XWindow>& rxPreviewBorderWindow,
560  const OUString& rsTitle,
561  const Reference<awt::XWindow>& rxNotesContentWindow,
562  const Reference<awt::XWindow>& rxNotesBorderWindow,
563  const std::shared_ptr<PresenterTextView>& rpNotesTextView)
564 {
565  if ( ! mpAccessibleConsole.is())
566  return;
567 
568  if (mxPreviewContentWindow != rxPreviewContentWindow)
569  {
570  if (mpAccessiblePreview.is())
571  {
573  mpAccessiblePreview = nullptr;
574  }
575 
576  mxPreviewContentWindow = rxPreviewContentWindow;
577  mxPreviewBorderWindow = rxPreviewBorderWindow;
578 
579  if (mxPreviewContentWindow.is())
580  {
581  mpAccessiblePreview = AccessiblePreview::Create(
583  lang::Locale(),
587  mpAccessiblePreview->SetAccessibleName(rsTitle);
588  }
589  }
590 
591  if (mxNotesContentWindow == rxNotesContentWindow)
592  return;
593 
594  if (mpAccessibleNotes.is())
595  {
597  mpAccessibleNotes = nullptr;
598  }
599 
600  mxNotesContentWindow = rxNotesContentWindow;
601  mxNotesBorderWindow = rxNotesBorderWindow;
602 
603  if (mxNotesContentWindow.is())
604  {
605  mpAccessibleNotes = AccessibleNotes::Create(
607  lang::Locale(),
610  rpNotesTextView);
612  }
613 }
614 
616 {
617  if (mpAccessiblePreview.is())
618  {
620  mpAccessiblePreview->SetAccessibleName(
621  pPreviewPane&&pPreviewPane->mxPane.is()
622  ? pPreviewPane->mxPane->GetTitle()
623  : OUString());
624  }
625 
626  // Play some focus ping-pong to trigger AT tools.
627  //AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
628  AccessibleFocusManager::Instance()->FocusObject(mpAccessiblePreview);
629 }
630 
632 {
634  nullptr,
635  nullptr,
636  OUString(),
637  nullptr,
638  nullptr,
639  std::shared_ptr<PresenterTextView>());
640 
641  if (mxMainWindow.is())
642  {
643  mxMainWindow->removeFocusListener(this);
644 
645  if (mxMainPane.is())
646  mxMainPane->setAccessible(nullptr);
647  }
648 
649  mpAccessiblePreview = nullptr;
650  mpAccessibleNotes = nullptr;
651  mpAccessibleConsole = nullptr;
652 }
653 
654 //----- XAccessible -----------------------------------------------------------
655 
656 Reference<XAccessibleContext> SAL_CALL PresenterAccessible::getAccessibleContext()
657 {
658  if ( ! mpAccessibleConsole.is())
659  {
660  Reference<XPane> xMainPane (mxMainPane, UNO_QUERY);
661  if (xMainPane.is())
662  {
663  mxMainWindow = xMainPane->getWindow();
664  mxMainWindow->addFocusListener(this);
665  }
666  mpAccessibleConsole = AccessibleConsole::Create(
667  mxComponentContext, css::lang::Locale());
668  mpAccessibleConsole->SetWindow(mxMainWindow, nullptr);
669  mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
671  if (mpPresenterController.is())
672  mpPresenterController->SetAccessibilityActiveState(true);
673  }
674  return mpAccessibleConsole->getAccessibleContext();
675 }
676 
677 //----- XFocusListener ----------------------------------------------------
678 
679 void SAL_CALL PresenterAccessible::focusGained (const css::awt::FocusEvent&)
680 {
681  SAL_INFO("sdext.presenter", __func__ << ": PresenterAccessible::focusGained at " << this
682  << " and window " << mxMainWindow.get());
683  AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
684 }
685 
686 void SAL_CALL PresenterAccessible::focusLost (const css::awt::FocusEvent&)
687 {
688  SAL_INFO("sdext.presenter", __func__ << ": PresenterAccessible::focusLost at " << this);
689  AccessibleFocusManager::Instance()->FocusObject(nullptr);
690 }
691 
692 //----- XEventListener ----------------------------------------------------
693 
694 void SAL_CALL PresenterAccessible::disposing (const css::lang::EventObject& rEvent)
695 {
696  if (rEvent.Source == mxMainWindow)
697  mxMainWindow = nullptr;
698 }
699 
700 //----- XInitialize -----------------------------------------------------------
701 
702 void SAL_CALL PresenterAccessible::initialize (const css::uno::Sequence<css::uno::Any>& rArguments)
703 {
704  if (rArguments.hasElements())
705  {
706  mxAccessibleParent.set(rArguments[0], UNO_QUERY);
707  if (mpAccessibleConsole.is())
708  mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
709  }
710 }
711 
712 //===== PresenterAccessible::AccessibleObject =========================================
713 
715  const lang::Locale& rLocale,
716  const sal_Int16 nRole,
717  const OUString& rsName)
718  : PresenterAccessibleObjectInterfaceBase(m_aMutex),
719  msName(rsName),
720  maLocale(rLocale),
721  mnRole(nRole),
722  mnStateSet(0),
723  mbIsFocused(false)
724 {
725 }
726 
728 {
729  AccessibleFocusManager::Instance()->AddFocusableObject(this);
730 }
731 
733  const Reference<awt::XWindow>& rxContentWindow,
734  const Reference<awt::XWindow>& rxBorderWindow)
735 {
736  Reference<awt::XWindow2> xContentWindow (rxContentWindow, UNO_QUERY);
737 
738  if (mxContentWindow.get() == xContentWindow.get())
739  return;
740 
741  if (mxContentWindow.is())
742  {
743  mxContentWindow->removeWindowListener(this);
744  }
745 
746  mxContentWindow = xContentWindow;
747  mxBorderWindow.set(rxBorderWindow, UNO_QUERY);
748 
749  if (mxContentWindow.is())
750  {
751  mxContentWindow->addWindowListener(this);
752  }
753 
754  UpdateStateSet();
755 }
756 
758  const Reference<XAccessible>& rxAccessibleParent)
759 {
760  mxParentAccessible = rxAccessibleParent;
761 }
762 
764 {
765  AccessibleFocusManager::Instance()->RemoveFocusableObject(this);
766  SetWindow(nullptr, nullptr);
767 }
768 
769 //----- XAccessible -------------------------------------------------------
770 
771 Reference<XAccessibleContext> SAL_CALL
773 {
774  ThrowIfDisposed();
775 
776  return this;
777 }
778 
779 //----- XAccessibleContext ----------------------------------------------
780 
782 {
783  ThrowIfDisposed();
784 
785  const sal_Int32 nChildCount (maChildren.size());
786 
787  return nChildCount;
788 }
789 
790 Reference<XAccessible> SAL_CALL
792 {
793  ThrowIfDisposed();
794 
795  if (nIndex<0 || nIndex>=sal_Int32(maChildren.size()))
796  throw lang::IndexOutOfBoundsException("invalid child index", static_cast<uno::XWeak*>(this));
797 
798  return maChildren[nIndex];
799 }
800 
801 Reference<XAccessible> SAL_CALL
803 {
804  ThrowIfDisposed();
805 
806  return mxParentAccessible;
807 }
808 
809 sal_Int32 SAL_CALL
811 {
812  ThrowIfDisposed();
813 
814  const Reference<XAccessible> xThis (this);
815  if (mxParentAccessible.is())
816  {
817  const Reference<XAccessibleContext> xContext (mxParentAccessible->getAccessibleContext());
818  for (sal_Int32 nIndex=0,nCount=xContext->getAccessibleChildCount();
819  nIndex<nCount;
820  ++nIndex)
821  {
822  if (xContext->getAccessibleChild(nIndex) == xThis)
823  return nIndex;
824  }
825  }
826 
827  return 0;
828 }
829 
830 sal_Int16 SAL_CALL
832 {
833  ThrowIfDisposed();
834 
835  return mnRole;
836 }
837 
838 OUString SAL_CALL
840 {
841  ThrowIfDisposed();
842 
843  return msName;
844 }
845 
846 OUString SAL_CALL
848 {
849  ThrowIfDisposed();
850 
851  return msName;
852 }
853 
854 Reference<XAccessibleRelationSet> SAL_CALL
856 {
857  ThrowIfDisposed();
858 
859  return nullptr;
860 }
861 
862 Reference<XAccessibleStateSet> SAL_CALL
864 {
865  ThrowIfDisposed();
866 
867  return Reference<XAccessibleStateSet>(new AccessibleStateSet(mnStateSet));
868 }
869 
870 lang::Locale SAL_CALL
872 {
873  ThrowIfDisposed();
874 
875  if (mxParentAccessible.is())
876  {
877  Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
878  if (xParentContext.is())
879  return xParentContext->getLocale();
880  }
881  return maLocale;
882 }
883 
884 //----- XAccessibleComponent ------------------------------------------------
885 
887  const awt::Point& rPoint)
888 {
889  ThrowIfDisposed();
890 
891  if (mxContentWindow.is())
892  {
893  const awt::Rectangle aBox (getBounds());
894  return rPoint.X>=aBox.X
895  && rPoint.Y>=aBox.Y
896  && rPoint.X<aBox.X+aBox.Width
897  && rPoint.Y<aBox.Y+aBox.Height;
898  }
899  else
900  return false;
901 }
902 
903 Reference<XAccessible> SAL_CALL
905 {
906  ThrowIfDisposed();
907 
908  return Reference<XAccessible>();
909 }
910 
912 {
913  ThrowIfDisposed();
914 
915  const awt::Point aLocation (GetRelativeLocation());
916  const awt::Size aSize (GetSize());
917 
918  return awt::Rectangle (aLocation.X, aLocation.Y, aSize.Width, aSize.Height);
919 }
920 
922 {
923  ThrowIfDisposed();
924 
925  const awt::Point aLocation (GetRelativeLocation());
926 
927  return aLocation;
928 }
929 
931 {
932  ThrowIfDisposed();
933 
934  awt::Point aRelativeLocation (GetRelativeLocation());
935  awt::Point aParentLocationOnScreen (GetAbsoluteParentLocation());
936 
937  return awt::Point(
938  aRelativeLocation.X + aParentLocationOnScreen.X,
939  aRelativeLocation.Y + aParentLocationOnScreen.Y);
940 }
941 
943 {
944  ThrowIfDisposed();
945 
946  const awt::Size aSize (GetSize());
947 
948  return aSize;
949 }
950 
952 {
953  ThrowIfDisposed();
954  if (mxBorderWindow.is())
955  mxBorderWindow->setFocus();
956  else if (mxContentWindow.is())
957  mxContentWindow->setFocus();
958 }
959 
961 {
962  ThrowIfDisposed();
963 
964  return 0x00ffffff;
965 }
966 
968 {
969  ThrowIfDisposed();
970 
971  return 0x00000000;
972 }
973 
974 //----- XAccessibleEventBroadcaster -------------------------------------------
975 
977  const Reference<XAccessibleEventListener>& rxListener)
978 {
979  if (!rxListener.is())
980  return;
981 
982  const osl::MutexGuard aGuard(m_aMutex);
983 
984  if (rBHelper.bDisposed || rBHelper.bInDispose)
985  {
986  uno::Reference<uno::XInterface> xThis (static_cast<XWeak*>(this), UNO_QUERY);
987  rxListener->disposing (lang::EventObject(xThis));
988  }
989  else
990  {
991  maListeners.push_back(rxListener);
992  }
993 }
994 
996  const Reference<XAccessibleEventListener>& rxListener)
997 {
998  ThrowIfDisposed();
999  if (rxListener.is())
1000  {
1001  const osl::MutexGuard aGuard(m_aMutex);
1002 
1003  auto const it(std::remove(maListeners.begin(), maListeners.end(), rxListener));
1004  if (it != maListeners.end())
1005  {
1006  maListeners.erase(it);
1007  }
1008  }
1009 }
1010 
1011 //----- XWindowListener ---------------------------------------------------
1012 
1014  const css::awt::WindowEvent&)
1015 {
1016  FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1017 }
1018 
1020  const css::awt::WindowEvent&)
1021 {
1022  FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1023 }
1024 
1026  const css::lang::EventObject&)
1027 {
1028  UpdateStateSet();
1029 }
1030 
1032  const css::lang::EventObject&)
1033 {
1034  UpdateStateSet();
1035 }
1036 
1037 //----- XEventListener --------------------------------------------------------
1038 
1039 void SAL_CALL PresenterAccessible::AccessibleObject::disposing (const css::lang::EventObject& rEvent)
1040 {
1041  if (rEvent.Source == mxContentWindow)
1042  {
1043  mxContentWindow = nullptr;
1044  mxBorderWindow = nullptr;
1045  }
1046  else
1047  {
1048  SetWindow(nullptr, nullptr);
1049  }
1050 }
1051 
1052 //----- private ---------------------------------------------------------------
1053 
1055 {
1056  switch (nType)
1057  {
1058  case AccessibleStateType::ENABLED:
1059  return mxContentWindow.is() && mxContentWindow->isEnabled();
1060 
1061  case AccessibleStateType::FOCUSABLE:
1062  return true;
1063 
1064  case AccessibleStateType::FOCUSED:
1065  return mbIsFocused;
1066 
1067  case AccessibleStateType::SHOWING:
1068  return mxContentWindow.is() && mxContentWindow->isVisible();
1069 
1070  default:
1071  return false;
1072  }
1073 }
1074 
1076 {
1077  UpdateState(AccessibleStateType::FOCUSABLE, true);
1078  UpdateState(AccessibleStateType::VISIBLE, true);
1079  UpdateState(AccessibleStateType::ENABLED, true);
1080  UpdateState(AccessibleStateType::MULTI_LINE, true);
1081  UpdateState(AccessibleStateType::SENSITIVE, true);
1082 
1083  UpdateState(AccessibleStateType::ENABLED, GetWindowState(AccessibleStateType::ENABLED));
1084  UpdateState(AccessibleStateType::FOCUSED, GetWindowState(AccessibleStateType::FOCUSED));
1085  UpdateState(AccessibleStateType::SHOWING, GetWindowState(AccessibleStateType::SHOWING));
1086  // UpdateState(AccessibleStateType::ACTIVE, GetWindowState(AccessibleStateType::ACTIVE));
1087 }
1088 
1090  const sal_Int16 nState,
1091  const bool bValue)
1092 {
1093  const sal_uInt32 nStateMask (AccessibleStateSet::GetStateMask(nState));
1094  if (((mnStateSet & nStateMask) != 0) == bValue)
1095  return;
1096  if (bValue)
1097  {
1098  mnStateSet |= nStateMask;
1099  FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(), Any(nState));
1100  }
1101  else
1102  {
1103  mnStateSet &= ~nStateMask;
1104  FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(nState), Any());
1105  }
1106 }
1107 
1109  const ::rtl::Reference<AccessibleObject>& rpChild)
1110 {
1111  maChildren.push_back(rpChild);
1112  rpChild->SetAccessibleParent(this);
1113  FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1114 }
1115 
1117  const ::rtl::Reference<AccessibleObject>& rpChild)
1118 {
1119  rpChild->SetAccessibleParent(Reference<XAccessible>());
1120  maChildren.erase(::std::find(maChildren.begin(), maChildren.end(), rpChild));
1121  FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1122 }
1123 
1125 {
1126  if (mbIsFocused != bIsFocused)
1127  {
1128  mbIsFocused = bIsFocused;
1129  UpdateStateSet();
1130  }
1131 }
1132 
1134 {
1135  if (msName != rsName)
1136  {
1137  const OUString sOldName(msName);
1138  msName = rsName;
1139  FireAccessibleEvent(AccessibleEventId::NAME_CHANGED, Any(sOldName), Any(msName));
1140  }
1141 }
1142 
1144  const sal_Int16 nEventId,
1145  const uno::Any& rOldValue,
1146  const uno::Any& rNewValue )
1147 {
1148  AccessibleEventObject aEventObject;
1149 
1150  aEventObject.Source = Reference<XWeak>(this);
1151  aEventObject.EventId = nEventId;
1152  aEventObject.NewValue = rNewValue;
1153  aEventObject.OldValue = rOldValue;
1154 
1155  ::std::vector<Reference<XAccessibleEventListener> > aListenerCopy(maListeners);
1156  for (const auto& rxListener : aListenerCopy)
1157  {
1158  try
1159  {
1160  rxListener->notifyEvent(aEventObject);
1161  }
1162  catch (const lang::DisposedException&)
1163  {
1164  // Listener has been disposed and should have been removed
1165  // already.
1166  removeAccessibleEventListener(rxListener);
1167  }
1168  catch (const Exception&)
1169  {
1170  // Ignore all other exceptions and assume that they are
1171  // caused by a temporary problem.
1172  }
1173  }
1174 }
1175 
1177 {
1178  awt::Point aLocation;
1179  if (mxContentWindow.is())
1180  {
1181  const awt::Rectangle aContentBox (mxContentWindow->getPosSize());
1182  aLocation.X = aContentBox.X;
1183  aLocation.Y = aContentBox.Y;
1184  if (mxBorderWindow.is())
1185  {
1186  const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize());
1187  aLocation.X += aBorderBox.X;
1188  aLocation.Y += aBorderBox.Y;
1189  }
1190  }
1191  return aLocation;
1192 }
1193 
1195 {
1196  if (mxContentWindow.is())
1197  {
1198  const awt::Rectangle aBox (mxContentWindow->getPosSize());
1199  return awt::Size(aBox.Width, aBox.Height);
1200  }
1201  else
1202  return awt::Size();
1203 }
1204 
1206 {
1207  Reference<XAccessibleComponent> xParentComponent;
1208  if (mxParentAccessible.is())
1209  xParentComponent.set( mxParentAccessible->getAccessibleContext(), UNO_QUERY);
1210  if (xParentComponent.is())
1211  return xParentComponent->getLocationOnScreen();
1212  else
1213  return awt::Point();
1214 }
1215 
1217 {
1218  if (rBHelper.bDisposed || rBHelper.bInDispose)
1219  throw lang::DisposedException("object has already been disposed", uno::Reference<uno::XInterface>(const_cast<uno::XWeak*>(static_cast<uno::XWeak const *>(this))));
1220 }
1221 
1222 //===== AccessibleStateSet ====================================================
1223 
1224 AccessibleStateSet::AccessibleStateSet (const sal_Int32 nStateSet)
1225  : AccessibleStateSetInterfaceBase(m_aMutex),
1226  mnStateSet (nStateSet)
1227 {
1228 }
1229 
1230 sal_uInt32 AccessibleStateSet::GetStateMask (const sal_Int16 nState)
1231 {
1232  if (nState<0 || nState>=sal_Int16(sizeof(sal_uInt32)*8))
1233  {
1234  throw RuntimeException("AccessibleStateSet::GetStateMask: invalid state");
1235  }
1236 
1237  return 1<<nState;
1238 }
1239 
1240 //----- XAccessibleStateSet ---------------------------------------------------
1241 
1242 sal_Bool SAL_CALL AccessibleStateSet::isEmpty()
1243 {
1244  return mnStateSet==0;
1245 }
1246 
1247 sal_Bool SAL_CALL AccessibleStateSet::contains (sal_Int16 nState)
1248 {
1249  return (mnStateSet & GetStateMask(nState)) != 0;
1250 }
1251 
1252 sal_Bool SAL_CALL AccessibleStateSet::containsAll (const css::uno::Sequence<sal_Int16>& rStateSet)
1253 {
1254  return std::none_of(rStateSet.begin(), rStateSet.end(),
1255  [this](const sal_Int16 nState) { return (mnStateSet & GetStateMask(nState)) == 0; });
1256 }
1257 
1258 css::uno::Sequence<sal_Int16> SAL_CALL AccessibleStateSet::getStates()
1259 {
1260  ::std::vector<sal_Int16> aStates;
1261  aStates.reserve(sizeof(mnStateSet)*8);
1262  for (sal_uInt16 nIndex=0; nIndex<sizeof(mnStateSet)*8; ++nIndex)
1263  if ((mnStateSet & GetStateMask(nIndex)) != 0)
1264  aStates.push_back(nIndex);
1265  return Sequence<sal_Int16>(aStates.data(), aStates.size());
1266 }
1267 
1268 //===== AccessibleRelationSet =================================================
1269 
1270 AccessibleRelationSet::AccessibleRelationSet()
1271  : AccessibleRelationSetInterfaceBase(m_aMutex)
1272 {
1273 }
1274 
1275 void AccessibleRelationSet::AddRelation (
1276  const sal_Int16 nRelationType,
1277  const Reference<XInterface>& rxObject)
1278 {
1279  maRelations.emplace_back();
1280  maRelations.back().RelationType = nRelationType;
1281  maRelations.back().TargetSet.realloc(1);
1282  maRelations.back().TargetSet[0] = rxObject;
1283 }
1284 
1285 //----- XAccessibleRelationSet ------------------------------------------------
1286 
1287 sal_Int32 SAL_CALL AccessibleRelationSet::getRelationCount()
1288 {
1289  return maRelations.size();
1290 }
1291 
1292 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelation (sal_Int32 nIndex)
1293 {
1294  if (nIndex<0 && o3tl::make_unsigned(nIndex)>=maRelations.size())
1295  return AccessibleRelation();
1296  else
1297  return maRelations[nIndex];
1298 }
1299 
1300 sal_Bool SAL_CALL AccessibleRelationSet::containsRelation (sal_Int16 nRelationType)
1301 {
1302  return std::any_of(maRelations.begin(), maRelations.end(),
1303  [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1304 }
1305 
1306 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelationByType (sal_Int16 nRelationType)
1307 {
1308  auto iRelation = std::find_if(maRelations.begin(), maRelations.end(),
1309  [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1310  if (iRelation != maRelations.end())
1311  return *iRelation;
1312  return AccessibleRelation();
1313 }
1314 
1315 //===== PresenterAccessible::AccessibleParagraph ==============================
1316 
1318  const lang::Locale& rLocale,
1319  const OUString& rsName,
1320  const SharedPresenterTextParagraph& rpParagraph,
1321  const sal_Int32 nParagraphIndex)
1322  : PresenterAccessibleParagraphInterfaceBase(rLocale, AccessibleRole::PARAGRAPH, rsName),
1323  mpParagraph(rpParagraph),
1324  mnParagraphIndex(nParagraphIndex)
1325 {
1326 }
1327 
1328 //----- XAccessibleContext ----------------------------------------------------
1329 
1330 Reference<XAccessibleRelationSet> SAL_CALL
1332 {
1333  ThrowIfDisposed();
1334 
1335  rtl::Reference<AccessibleRelationSet> pSet (new AccessibleRelationSet);
1336 
1337  if (mxParentAccessible.is())
1338  {
1339  Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
1340  if (xParentContext.is())
1341  {
1342  if (mnParagraphIndex>0)
1343  pSet->AddRelation(
1344  AccessibleRelationType::CONTENT_FLOWS_FROM,
1345  xParentContext->getAccessibleChild(mnParagraphIndex-1));
1346 
1347  if (mnParagraphIndex<xParentContext->getAccessibleChildCount()-1)
1348  pSet->AddRelation(
1349  AccessibleRelationType::CONTENT_FLOWS_TO,
1350  xParentContext->getAccessibleChild(mnParagraphIndex+1));
1351  }
1352  }
1353 
1354  return pSet;
1355 }
1356 
1357 //----- XAccessibleText -------------------------------------------------------
1358 
1360 {
1361  ThrowIfDisposed();
1362 
1363  sal_Int32 nPosition (-1);
1364  if (mpParagraph)
1365  nPosition = mpParagraph->GetCaretPosition();
1366 
1367  return nPosition;
1368 }
1369 
1371 {
1372  ThrowIfDisposed();
1373 
1374  if (mpParagraph)
1375  {
1376  mpParagraph->SetCaretPosition(nIndex);
1377  return true;
1378  }
1379  else
1380  return false;
1381 }
1382 
1384 {
1385  ThrowIfDisposed();
1386 
1387  if (!mpParagraph)
1388  throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1389  return mpParagraph->GetCharacter(nIndex);
1390 }
1391 
1392 Sequence<css::beans::PropertyValue> SAL_CALL
1394  ::sal_Int32 nIndex,
1395  const css::uno::Sequence<OUString>& rRequestedAttributes)
1396 {
1397  ThrowIfDisposed();
1398 
1399 #if OSL_DEBUG_LEVEL > 0
1400  SAL_INFO( "sdext.presenter", __func__ << " at " << this << ", " << nIndex << " returns empty set" );
1401  for (sal_Int32 nAttributeIndex(0), nAttributeCount(rRequestedAttributes.getLength());
1402  nAttributeIndex < nAttributeCount;
1403  ++nAttributeIndex)
1404  {
1405  SAL_INFO( "sdext.presenter",
1406  " requested attribute " << nAttributeIndex << " is " << rRequestedAttributes[nAttributeIndex] );
1407  }
1408 #else
1409  (void)nIndex;
1410  (void)rRequestedAttributes;
1411 #endif
1412 
1413  // Character properties are not supported.
1414  return Sequence<css::beans::PropertyValue>();
1415 }
1416 
1418  sal_Int32 nIndex)
1419 {
1420  ThrowIfDisposed();
1421 
1422  awt::Rectangle aCharacterBox;
1423  if (nIndex < 0)
1424  {
1425  throw lang::IndexOutOfBoundsException("invalid text index", static_cast<uno::XWeak*>(this));
1426  }
1427  else if (mpParagraph)
1428  {
1429  aCharacterBox = mpParagraph->GetCharacterBounds(nIndex, false);
1430  // Convert coordinates relative to the window origin into absolute
1431  // screen coordinates.
1432  const awt::Point aWindowLocationOnScreen (getLocationOnScreen());
1433  aCharacterBox.X += aWindowLocationOnScreen.X;
1434  aCharacterBox.Y += aWindowLocationOnScreen.Y;
1435  }
1436  else
1437  {
1438  throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1439  }
1440 
1441  return aCharacterBox;
1442 }
1443 
1445 {
1446  ThrowIfDisposed();
1447 
1448  sal_Int32 nCount (0);
1449  if (mpParagraph)
1450  nCount = mpParagraph->GetCharacterCount();
1451 
1452  return nCount;
1453 }
1454 
1456  const css::awt::Point& )
1457 {
1458  ThrowIfDisposed();
1459  return -1;
1460 }
1461 
1463 {
1464  ThrowIfDisposed();
1465 
1466  return getTextRange(getSelectionStart(), getSelectionEnd());
1467 }
1468 
1470 {
1471  ThrowIfDisposed();
1472 
1473  return getCaretPosition();
1474 }
1475 
1477 {
1478  ThrowIfDisposed();
1479 
1480  return getCaretPosition();
1481 }
1482 
1484  sal_Int32 nStartIndex,
1485  sal_Int32)
1486 {
1487  ThrowIfDisposed();
1488 
1489  return setCaretPosition(nStartIndex);
1490 }
1491 
1493 {
1494  ThrowIfDisposed();
1495 
1496  OUString sText;
1497  if (mpParagraph)
1498  sText = mpParagraph->GetText();
1499 
1500  return sText;
1501 }
1502 
1504  sal_Int32 nLocalStartIndex,
1505  sal_Int32 nLocalEndIndex)
1506 {
1507  ThrowIfDisposed();
1508 
1509  OUString sText;
1510  if (mpParagraph)
1511  {
1512  const TextSegment aSegment (
1513  mpParagraph->CreateTextSegment(nLocalStartIndex, nLocalEndIndex));
1514  sText = aSegment.SegmentText;
1515  }
1516 
1517  return sText;
1518 }
1519 
1521  sal_Int32 nLocalCharacterIndex,
1522  sal_Int16 nTextType)
1523 {
1524  ThrowIfDisposed();
1525 
1526  TextSegment aSegment;
1527  if (mpParagraph)
1528  aSegment = mpParagraph->GetTextSegment(0, nLocalCharacterIndex, nTextType);
1529 
1530  return aSegment;
1531 }
1532 
1534  sal_Int32 nLocalCharacterIndex,
1535  sal_Int16 nTextType)
1536 {
1537  ThrowIfDisposed();
1538 
1539  TextSegment aSegment;
1540  if (mpParagraph)
1541  aSegment = mpParagraph->GetTextSegment(-1, nLocalCharacterIndex, nTextType);
1542 
1543  return aSegment;
1544 }
1545 
1547  sal_Int32 nLocalCharacterIndex,
1548  sal_Int16 nTextType)
1549 {
1550  ThrowIfDisposed();
1551 
1552  TextSegment aSegment;
1553  if (mpParagraph)
1554  aSegment = mpParagraph->GetTextSegment(+1, nLocalCharacterIndex, nTextType);
1555 
1556  return aSegment;
1557 }
1558 
1560  sal_Int32,
1561  sal_Int32)
1562 {
1563  ThrowIfDisposed();
1564 
1565  // Return false because copying to clipboard is not supported.
1566  // It IS supported in the notes view. There is no need to duplicate
1567  // this here.
1568  return false;
1569 }
1570 
1572  sal_Int32,
1573  sal_Int32,
1574  AccessibleScrollType)
1575 {
1576  return false;
1577 }
1578 
1579 //----- protected -------------------------------------------------------------
1580 
1582 {
1583  awt::Point aLocation (AccessibleObject::GetRelativeLocation());
1584  if (mpParagraph)
1585  {
1586  const awt::Point aParagraphLocation (mpParagraph->GetRelativeLocation());
1587  aLocation.X += aParagraphLocation.X;
1588  aLocation.Y += aParagraphLocation.Y;
1589  }
1590 
1591  return aLocation;
1592 }
1593 
1595 {
1596  if (mpParagraph)
1597  return mpParagraph->GetSize();
1598  else
1599  return AccessibleObject::GetSize();
1600 }
1601 
1603 {
1604  if (mxParentAccessible.is())
1605  {
1606  Reference<XAccessibleContext> xParentContext =
1607  mxParentAccessible->getAccessibleContext();
1608  if (xParentContext.is())
1609  {
1610  Reference<XAccessibleComponent> xGrandParentComponent(
1611  xParentContext->getAccessibleParent(), UNO_QUERY);
1612  if (xGrandParentComponent.is())
1613  return xGrandParentComponent->getLocationOnScreen();
1614  }
1615  }
1616 
1617  return awt::Point();
1618 }
1619 
1621 {
1622  switch (nType)
1623  {
1624  case AccessibleStateType::EDITABLE:
1625  return bool(mpParagraph);
1626 
1627  case AccessibleStateType::ACTIVE:
1628  return true;
1629 
1630  default:
1631  return AccessibleObject::GetWindowState(nType);
1632  }
1633 }
1634 
1635 //===== AccessibleNotes =======================================================
1636 
1637 AccessibleNotes::AccessibleNotes (
1638  const css::lang::Locale& rLocale,
1639  const OUString& rsName)
1640  : AccessibleObject(rLocale,AccessibleRole::PANEL,rsName)
1641 {
1642 }
1643 
1645  const css::uno::Reference<css::uno::XComponentContext>& rxContext,
1646  const lang::Locale& rLocale,
1647  const Reference<awt::XWindow>& rxContentWindow,
1648  const Reference<awt::XWindow>& rxBorderWindow,
1649  const std::shared_ptr<PresenterTextView>& rpTextView)
1650 {
1651  OUString sName ("Presenter Notes Text");
1652  {
1653  PresenterConfigurationAccess aConfiguration (
1654  rxContext,
1655  "/org.openoffice.Office.PresenterScreen/",
1657  aConfiguration.GetConfigurationNode("Presenter/Accessibility/Notes/String")
1658  >>= sName;
1659  }
1660 
1662  new AccessibleNotes(
1663  rLocale,
1664  sName));
1665  pObject->LateInitialization();
1666  pObject->SetTextView(rpTextView);
1667  pObject->UpdateStateSet();
1668  pObject->SetWindow(rxContentWindow, rxBorderWindow);
1669 
1670  return pObject;
1671 }
1672 
1673 void AccessibleNotes::SetTextView (
1674  const std::shared_ptr<PresenterTextView>& rpTextView)
1675 {
1676  ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > aChildren;
1677 
1678  // Release any listeners to the current text view.
1679  if (mpTextView)
1680  {
1681  mpTextView->GetCaret()->SetCaretMotionBroadcaster(
1682  ::std::function<void (sal_Int32,sal_Int32,sal_Int32,sal_Int32)>());
1683  mpTextView->SetTextChangeBroadcaster(
1684  ::std::function<void ()>());
1685  }
1686 
1687  mpTextView = rpTextView;
1688 
1689  if (!mpTextView)
1690  return;
1691 
1692  // Create a new set of children, one for each paragraph.
1693  const sal_Int32 nParagraphCount (mpTextView->GetParagraphCount());
1694  for (sal_Int32 nIndex=0; nIndex<nParagraphCount; ++nIndex)
1695  {
1697  new PresenterAccessible::AccessibleParagraph(
1698  css::lang::Locale(),
1699  "Paragraph"+OUString::number(nIndex),
1700  rpTextView->GetParagraph(nIndex),
1701  nIndex));
1702  pParagraph->LateInitialization();
1703  pParagraph->SetWindow(mxContentWindow, mxBorderWindow);
1704  pParagraph->SetAccessibleParent(this);
1705  aChildren.emplace_back(pParagraph.get());
1706  }
1707  maChildren.swap(aChildren);
1708  FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1709 
1710  // Dispose the old children. (This will remove them from the focus
1711  // manager).
1712  for (const auto& rxChild : aChildren)
1713  {
1714  Reference<lang::XComponent> xComponent = rxChild;
1715  if (xComponent.is())
1716  xComponent->dispose();
1717  }
1718 
1719  // This class acts as a controller of who broadcasts caret motion
1720  // events and handles text changes. Register the corresponding
1721  // listeners here.
1722  mpTextView->GetCaret()->SetCaretMotionBroadcaster(
1723  [this](sal_Int32 a, sal_Int32 b, sal_Int32 c, sal_Int32 d)
1724  { return this->NotifyCaretChange(a, b, c, d); });
1725  mpTextView->SetTextChangeBroadcaster(
1726  [this]() { return SetTextView(mpTextView); });
1727 }
1728 
1729 void AccessibleNotes::SetWindow (
1730  const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
1731  const css::uno::Reference<css::awt::XWindow>& rxBorderWindow)
1732 {
1733  AccessibleObject::SetWindow(rxContentWindow, rxBorderWindow);
1734 
1735  // Set the windows at the children as well, so that every paragraph can
1736  // setup its geometry.
1737  for (auto& rxChild : maChildren)
1738  {
1739  rxChild->SetWindow(rxContentWindow, rxBorderWindow);
1740  }
1741 }
1742 
1743 void AccessibleNotes::NotifyCaretChange (
1744  const sal_Int32 nOldParagraphIndex,
1745  const sal_Int32 nOldCharacterIndex,
1746  const sal_Int32 nNewParagraphIndex,
1747  const sal_Int32 nNewCharacterIndex)
1748 {
1749  AccessibleFocusManager::Instance()->FocusObject(
1750  nNewParagraphIndex >= 0
1751  ? maChildren[nNewParagraphIndex]
1752  : this);
1753 
1754  if (nOldParagraphIndex != nNewParagraphIndex)
1755  {
1756  // Moved caret from one paragraph to another (or showed or
1757  // hid the caret). Move focus from one accessible
1758  // paragraph to another.
1759  if (nOldParagraphIndex >= 0)
1760  {
1761  maChildren[nOldParagraphIndex]->FireAccessibleEvent(
1762  AccessibleEventId::CARET_CHANGED,
1763  Any(nOldCharacterIndex),
1764  Any(sal_Int32(-1)));
1765  }
1766  if (nNewParagraphIndex >= 0)
1767  {
1768  maChildren[nNewParagraphIndex]->FireAccessibleEvent(
1769  AccessibleEventId::CARET_CHANGED,
1770  Any(sal_Int32(-1)),
1771  Any(nNewCharacterIndex));
1772  }
1773  }
1774  else if (nNewParagraphIndex >= 0)
1775  {
1776  // Caret moved inside one paragraph.
1777  maChildren[nNewParagraphIndex]->FireAccessibleEvent(
1778  AccessibleEventId::CARET_CHANGED,
1779  Any(nOldCharacterIndex),
1780  Any(nNewCharacterIndex));
1781  }
1782 }
1783 
1784 
1785 //===== AccessibleFocusManager ================================================
1786 
1787 std::shared_ptr<AccessibleFocusManager> AccessibleFocusManager::mpInstance;
1788 
1789 std::shared_ptr<AccessibleFocusManager> const & AccessibleFocusManager::Instance()
1790 {
1791  if ( ! mpInstance)
1792  {
1793  mpInstance.reset(new AccessibleFocusManager());
1794  }
1795  return mpInstance;
1796 }
1797 
1798 AccessibleFocusManager::AccessibleFocusManager()
1799 {
1800 }
1801 
1802 AccessibleFocusManager::~AccessibleFocusManager()
1803 {
1804  // copy member to stack, then drop it - otherwise will get use-after-free
1805  // from AccessibleObject::disposing(), it will call ~Reference *twice*
1806  auto const temp(std::move(maFocusableObjects));
1807  (void) temp;
1808  m_isInDtor = true;
1809 }
1810 
1811 void AccessibleFocusManager::AddFocusableObject (
1812  const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1813 {
1814  OSL_ASSERT(rpObject.is());
1815  OSL_ASSERT(::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject)==maFocusableObjects.end());
1816 
1817  maFocusableObjects.push_back(rpObject);
1818 }
1819 
1820 void AccessibleFocusManager::RemoveFocusableObject (
1821  const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1822 {
1823  ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> >::iterator iObject (
1824  ::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject));
1825 
1826  if (iObject != maFocusableObjects.end())
1827  maFocusableObjects.erase(iObject);
1828  else
1829  {
1830  OSL_ASSERT(m_isInDtor); // in dtor, was removed already
1831  }
1832 }
1833 
1834 void AccessibleFocusManager::FocusObject (
1835  const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1836 {
1837  // Remove the focus of any of the other focusable objects.
1838  for (auto& rxObject : maFocusableObjects)
1839  {
1840  if (rxObject!=rpObject)
1841  rxObject->SetIsFocused(false);
1842  }
1843 
1844  if (rpObject.is())
1845  rpObject->SetIsFocused(true);
1846 }
1847 
1848 } // end of namespace ::sd::presenter
1849 
1850 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual void SAL_CALL windowMoved(const css::awt::WindowEvent &rEvent) override
css::uno::Reference< css::awt::XWindow > mxMainWindow
std::vector< Reference< XAnimationNode > > maChildren
static constexpr OUStringLiteral msCurrentSlidePreviewPaneURL
::std::vector< rtl::Reference< PresenterAccessible::AccessibleObject > > maFocusableObjects
static std::shared_ptr< AccessibleFocusManager > mpInstance
virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex(sal_Int32 nIndex, sal_Int16 nTextType) override
sal_Int32 nIndex
css::uno::Reference< css::awt::XWindow > mxPreviewContentWindow
virtual void SAL_CALL windowHidden(const css::lang::EventObject &rEvent) override
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex(sal_Int32 nIndex, sal_Int16 nTextType) override
::rtl::Reference< AccessibleObject > mpAccessibleConsole
css::uno::Reference< css::awt::XWindow > mxPreviewBorderWindow
void Create(SwFormatVertOrient &rItem, SvStream &rStrm, sal_uInt16 nVersionAbusedAsSize)
bool m_isInDtor
void UpdateState(const sal_Int16 aState, const bool bValue)
OUString msName
mutable::osl::Mutex m_aMutex
virtual bool GetWindowState(const sal_Int16 nType) const override
::cppu::WeakComponentImplHelper< css::accessibility::XAccessible, css::lang::XInitialization, css::awt::XFocusListener > PresenterAccessibleInterfaceBase
virtual sal_Bool SAL_CALL setSelection(sal_Int32 nStartIndex, sal_Int32 nEndIndex) override
EmbeddedObjectRef * pObject
virtual OUString SAL_CALL getTextRange(sal_Int32 nStartIndex, sal_Int32 nEndIndex) override
css::uno::Reference< css::accessibility::XAccessible > mxParentAccessible
PresenterPaneContainer::SharedPaneDescriptor GetPreviewPane() const
virtual css::awt::Point SAL_CALL getLocation() override
::rtl::Reference< AccessibleObject > mpAccessibleNotes
sal_uInt16 sal_Unicode
void RemoveChild(const ::rtl::Reference< AccessibleObject > &rpChild)
This class gives access to the configuration.
virtual sal_Unicode SAL_CALL getCharacter(sal_Int32 nIndex) override
virtual void SAL_CALL initialize(const css::uno::Sequence< css::uno::Any > &rArguments) override
virtual void SAL_CALL disposing() override
::rtl::Reference< PresenterController > mpPresenterController
virtual bool GetWindowState(const sal_Int16 nType) const
int nCount
std::mutex m_aMutex
virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getCharacterAttributes(::sal_Int32 nIndex, const css::uno::Sequence< OUString > &rRequestedAttributes) override
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override
const sal_Int32 mnStateSet
virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext() override
void FireAccessibleEvent(const sal_Int16 nEventId, const css::uno::Any &rOldValue, const css::uno::Any &rNewValue)
const char * sName
virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex(sal_Int32 nIndex, sal_Int16 nTextType) override
virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override
virtual sal_Bool SAL_CALL setCaretPosition(sal_Int32 nIndex) override
css::uno::Reference< css::uno::XComponentContext > mxComponentContext
sal_Int16 mnParagraphIndex
virtual css::awt::Rectangle SAL_CALL getCharacterBounds(sal_Int32 nIndex) override
static constexpr OUStringLiteral msNotesPaneURL
virtual void SAL_CALL focusGained(const css::awt::FocusEvent &rEvent) override
AccessibleParagraph(const css::lang::Locale &rLocale, const OUString &rsName, const SharedPresenterTextParagraph &rpParagraph, const sal_Int32 nParagraphIndex)
std::shared_ptr< PresenterTextView > mpTextView
css::uno::Reference< css::drawing::framework::XPane2 > mxMainPane
::rtl::Reference< AccessibleObject > mpAccessiblePreview
void AddChild(const ::rtl::Reference< AccessibleObject > &rpChild)
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
css::uno::Reference< css::awt::XWindow > mxNotesBorderWindow
css::uno::Any GetConfigurationNode(const OUString &rsPathToNode)
Return a configuration node below the root of the called object.
unsigned char sal_Bool
css::uno::Reference< css::awt::XWindow2 > mxContentWindow
virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override
virtual sal_Bool SAL_CALL scrollSubstringTo(sal_Int32 nStartIndex, sal_Int32 nEndIndex, css::accessibility::AccessibleScrollType aScrollType) override
virtual void SAL_CALL removeAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &rxListener) override
::std::vector< Reference< XAccessibleEventListener > > maListeners
PresenterAccessible(const css::uno::Reference< css::uno::XComponentContext > &rxContext, const ::rtl::Reference< PresenterController > &rpPresenterController, const css::uno::Reference< css::drawing::framework::XPane > &rxMainPane)
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint(const css::awt::Point &aPoint) override
const css::uno::Reference< css::uno::XComponentContext > mxComponentContext
virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() override
virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override
virtual void SetWindow(const css::uno::Reference< css::awt::XWindow > &rxContentWindow, const css::uno::Reference< css::awt::XWindow > &rxBorderWindow)
rtl::Reference< PresenterController > mpPresenterController
AccessibleObject(const css::lang::Locale &rLocale, const sal_Int16 nRole, const OUString &rsName)
#define SAL_INFO(area, stream)
std::shared_ptr< PaneDescriptor > SharedPaneDescriptor
virtual void SAL_CALL addAccessibleEventListener(const css::uno::Reference< css::accessibility::XAccessibleEventListener > &rxListener) override
virtual sal_Bool SAL_CALL copyText(sal_Int32 nStartIndex, sal_Int32 nEndIndex) override
virtual void SAL_CALL windowResized(const css::awt::WindowEvent &rEvent) override
QPRO_FUNC_TYPE nType
css::uno::Reference< css::awt::XWindow2 > mxBorderWindow
css::uno::Reference< css::accessibility::XAccessible > mxAccessibleParent
virtual css::awt::Rectangle SAL_CALL getBounds() override
static constexpr OUStringLiteral msSlideSorterPaneURL
::std::vector< AccessibleRelation > maRelations
UpdateState
virtual void SAL_CALL windowShown(const css::lang::EventObject &rEvent) override
virtual sal_Bool SAL_CALL containsPoint(const css::awt::Point &aPoint) override
void SetAccessibleParent(const css::uno::Reference< css::accessibility::XAccessible > &rxAccessibleParent)
::std::vector< rtl::Reference< AccessibleObject > > maChildren
css::uno::Reference< css::awt::XWindow > mxNotesContentWindow
virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild(sal_Int32 nIndex) override
virtual css::lang::Locale SAL_CALL getLocale() override
std::shared_ptr< PresenterTextParagraph > SharedPresenterTextParagraph
virtual sal_Int32 SAL_CALL getIndexAtPoint(const css::awt::Point &rPoint) override
virtual void SAL_CALL focusLost(const css::awt::FocusEvent &rEvent) override
virtual css::awt::Point SAL_CALL getLocationOnScreen() override
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo