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/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 <o3tl/safeint.hxx>
43 #include <sal/log.hxx>
44 
45 #include <algorithm>
46 
47 using namespace ::com::sun::star;
48 using namespace ::com::sun::star::accessibility;
49 using namespace ::com::sun::star::uno;
50 using namespace ::com::sun::star::drawing::framework;
51 
52 //===== PresenterAccessibleObject =============================================
53 
54 namespace sdext::presenter {
55 
56 namespace {
57  typedef ::cppu::WeakComponentImplHelper <
58  css::accessibility::XAccessible,
59  css::accessibility::XAccessibleContext,
60  css::accessibility::XAccessibleComponent,
61  css::accessibility::XAccessibleEventBroadcaster,
62  css::awt::XWindowListener
63  > PresenterAccessibleObjectInterfaceBase;
64 }
65 
67  : public ::cppu::BaseMutex,
68  public PresenterAccessibleObjectInterfaceBase
69 {
70 public:
72  const css::lang::Locale& rLocale,
73  const sal_Int16 nRole,
74  const OUString& rsName);
75  void LateInitialization();
76 
77  virtual void SetWindow (
78  const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
79  const css::uno::Reference<css::awt::XWindow>& rxBorderWindow);
80  void SetAccessibleParent (const css::uno::Reference<css::accessibility::XAccessible>& rxAccessibleParent);
81 
82  virtual void SAL_CALL disposing() override;
83 
84  void AddChild (const ::rtl::Reference<AccessibleObject>& rpChild);
85  void RemoveChild (const ::rtl::Reference<AccessibleObject>& rpChild);
86 
87  void SetIsFocused (const bool bIsFocused);
88  void SetAccessibleName (const OUString& rsName);
89 
90  void FireAccessibleEvent (
91  const sal_Int16 nEventId,
92  const css::uno::Any& rOldValue,
93  const css::uno::Any& rNewValue);
94 
95  void UpdateStateSet();
96 
97  //----- XAccessible -------------------------------------------------------
98 
99  virtual css::uno::Reference<css::accessibility::XAccessibleContext> SAL_CALL
100  getAccessibleContext() override;
101 
102  //----- XAccessibleContext ----------------------------------------------
103 
104  virtual sal_Int32 SAL_CALL getAccessibleChildCount() override;
105 
106  virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL
107  getAccessibleChild (sal_Int32 nIndex) override;
108 
109  virtual css::uno::Reference< css::accessibility::XAccessible> SAL_CALL getAccessibleParent() override;
110 
111  virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override;
112 
113  virtual sal_Int16 SAL_CALL getAccessibleRole() override;
114 
115  virtual OUString SAL_CALL getAccessibleDescription() override;
116 
117  virtual OUString SAL_CALL getAccessibleName() override;
118 
119  virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet> SAL_CALL
120  getAccessibleRelationSet() override;
121 
122  virtual css::uno::Reference<css::accessibility::XAccessibleStateSet> SAL_CALL
123  getAccessibleStateSet() override;
124 
125  virtual css::lang::Locale SAL_CALL getLocale() override;
126 
127  //----- XAccessibleComponent --------------------------------------------
128 
129  virtual sal_Bool SAL_CALL containsPoint (
130  const css::awt::Point& aPoint) override;
131 
132  virtual css::uno::Reference<css::accessibility::XAccessible> SAL_CALL
134  const css::awt::Point& aPoint) override;
135 
136  virtual css::awt::Rectangle SAL_CALL getBounds() override;
137 
138  virtual css::awt::Point SAL_CALL getLocation() override;
139 
140  virtual css::awt::Point SAL_CALL getLocationOnScreen() override;
141 
142  virtual css::awt::Size SAL_CALL getSize() override;
143 
144  virtual void SAL_CALL grabFocus() override;
145 
146  virtual sal_Int32 SAL_CALL getForeground() override;
147 
148  virtual sal_Int32 SAL_CALL getBackground() override;
149 
150  //----- XAccessibleEventBroadcaster --------------------------------------
151 
152  virtual void SAL_CALL addAccessibleEventListener (
153  const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rxListener) override;
154 
155  virtual void SAL_CALL removeAccessibleEventListener (
156  const css::uno::Reference<css::accessibility::XAccessibleEventListener>& rxListener) override;
157 
158  //----- XWindowListener ---------------------------------------------------
159 
160  virtual void SAL_CALL windowResized (const css::awt::WindowEvent& rEvent) override;
161 
162  virtual void SAL_CALL windowMoved (const css::awt::WindowEvent& rEvent) override;
163 
164  virtual void SAL_CALL windowShown (const css::lang::EventObject& rEvent) override;
165 
166  virtual void SAL_CALL windowHidden (const css::lang::EventObject& rEvent) override;
167 
168  //----- XEventListener ----------------------------------------------------
169 
170  virtual void SAL_CALL disposing (const css::lang::EventObject& rEvent) override;
171 
172 protected:
173  OUString msName;
174  css::uno::Reference<css::awt::XWindow2> mxContentWindow;
175  css::uno::Reference<css::awt::XWindow2> mxBorderWindow;
176  const css::lang::Locale maLocale;
177  const sal_Int16 mnRole;
178  sal_uInt32 mnStateSet;
180  css::uno::Reference<css::accessibility::XAccessible> mxParentAccessible;
181  ::std::vector<rtl::Reference<AccessibleObject> > maChildren;
182  ::std::vector<Reference<XAccessibleEventListener> > maListeners;
183 
184  virtual awt::Point GetRelativeLocation();
185  virtual awt::Size GetSize();
186  virtual awt::Point GetAbsoluteParentLocation();
187 
188  virtual bool GetWindowState (const sal_Int16 nType) const;
189 
190  void UpdateState (const sal_Int16 aState, const bool bValue);
191 
193  void ThrowIfDisposed() const;
194 };
195 
196 //===== AccessibleStateSet ====================================================
197 
198 namespace {
199 typedef ::cppu::WeakComponentImplHelper <
200  css::accessibility::XAccessibleStateSet
201  > AccessibleStateSetInterfaceBase;
202 
203 class AccessibleStateSet
204  : public ::cppu::BaseMutex,
205  public AccessibleStateSetInterfaceBase
206 {
207 public:
208  explicit AccessibleStateSet (const sal_Int32 nStateSet);
209 
210  static sal_uInt32 GetStateMask (const sal_Int16 nType);
211 
212  //----- XAccessibleStateSet -----------------------------------------------
213 
214  virtual sal_Bool SAL_CALL isEmpty() override;
215 
216  virtual sal_Bool SAL_CALL contains (sal_Int16 nState) override;
217 
218  virtual sal_Bool SAL_CALL containsAll (const css::uno::Sequence<sal_Int16>& rStateSet) override;
219 
220  virtual css::uno::Sequence<sal_Int16> SAL_CALL getStates() override;
221 
222 private:
223  const sal_Int32 mnStateSet;
224 };
225 
226 //===== AccessibleRelationSet =================================================
227 
228 typedef ::cppu::WeakComponentImplHelper <
229  css::accessibility::XAccessibleRelationSet
230  > AccessibleRelationSetInterfaceBase;
231 
232 class AccessibleRelationSet
233  : public ::cppu::BaseMutex,
234  public AccessibleRelationSetInterfaceBase
235 {
236 public:
237  AccessibleRelationSet();
238 
239  void AddRelation (
240  const sal_Int16 nRelationType,
241  const Reference<XInterface>& rxObject);
242 
243  //----- XAccessibleRelationSet --------------------------------------------
244 
245  virtual sal_Int32 SAL_CALL getRelationCount() override;
246 
247  virtual AccessibleRelation SAL_CALL getRelation (sal_Int32 nIndex) override;
248 
249  virtual sal_Bool SAL_CALL containsRelation (sal_Int16 nRelationType) override;
250 
251  virtual AccessibleRelation SAL_CALL getRelationByType (sal_Int16 nRelationType) override;
252 
253 private:
254  ::std::vector<AccessibleRelation> maRelations;
255 };
256 
257 //===== PresenterAccessibleParagraph ==========================================
258 
259 typedef ::cppu::ImplInheritanceHelper <
260  PresenterAccessible::AccessibleObject,
261  css::accessibility::XAccessibleText
262  > PresenterAccessibleParagraphInterfaceBase;
263 }
264 
266  : public PresenterAccessibleParagraphInterfaceBase
267 {
268 public:
270  const css::lang::Locale& rLocale,
271  const OUString& rsName,
272  const SharedPresenterTextParagraph& rpParagraph,
273  const sal_Int32 nParagraphIndex);
274 
275  //----- XAccessibleContext ------------------------------------------------
276 
277  virtual css::uno::Reference<css::accessibility::XAccessibleRelationSet> SAL_CALL
278  getAccessibleRelationSet() override;
279 
280  //----- XAccessibleText ---------------------------------------------------
281 
282  virtual sal_Int32 SAL_CALL getCaretPosition() override;
283 
284  virtual sal_Bool SAL_CALL setCaretPosition (sal_Int32 nIndex) override;
285 
286  virtual sal_Unicode SAL_CALL getCharacter (sal_Int32 nIndex) override;
287 
288  virtual css::uno::Sequence<css::beans::PropertyValue> SAL_CALL
290  ::sal_Int32 nIndex,
291  const css::uno::Sequence<OUString>& rRequestedAttributes) override;
292 
293  virtual css::awt::Rectangle SAL_CALL getCharacterBounds (sal_Int32 nIndex) override;
294 
295  virtual sal_Int32 SAL_CALL getCharacterCount() override;
296 
297  virtual sal_Int32 SAL_CALL getIndexAtPoint (const css::awt::Point& rPoint) override;
298 
299  virtual OUString SAL_CALL getSelectedText() override;
300 
301  virtual sal_Int32 SAL_CALL getSelectionStart() override;
302 
303  virtual sal_Int32 SAL_CALL getSelectionEnd() override;
304 
305  virtual sal_Bool SAL_CALL setSelection (sal_Int32 nStartIndex, sal_Int32 nEndIndex) override;
306 
307  virtual OUString SAL_CALL getText() override;
308 
309  virtual OUString SAL_CALL getTextRange (
310  sal_Int32 nStartIndex,
311  sal_Int32 nEndIndex) override;
312 
313  virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex (
314  sal_Int32 nIndex,
315  sal_Int16 nTextType) override;
316 
317  virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex (
318  sal_Int32 nIndex,
319  sal_Int16 nTextType) override;
320 
321  virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex (
322  sal_Int32 nIndex,
323  sal_Int16 nTextType) override;
324 
325  virtual sal_Bool SAL_CALL copyText (sal_Int32 nStartIndex, sal_Int32 nEndIndex) override;
326 
327 protected:
328  virtual awt::Point GetRelativeLocation() override;
329  virtual awt::Size GetSize() override;
330  virtual awt::Point GetAbsoluteParentLocation() override;
331  virtual bool GetWindowState (const sal_Int16 nType) const override;
332 
333 private:
335  const sal_Int32 mnParagraphIndex;
336 };
337 
338 //===== AccessibleConsole =====================================================
339 
340 namespace {
341 
342 class AccessibleConsole
343 {
344 public:
346  const css::uno::Reference<css::uno::XComponentContext>& rxContext,
347  const lang::Locale& rLocale)
348  {
349  OUString sName ("Presenter Console");
350  PresenterConfigurationAccess aConfiguration (
351  rxContext,
352  "/org.openoffice.Office.PresenterScreen/",
354  aConfiguration.GetConfigurationNode("Presenter/Accessibility/Console/String")
355  >>= sName;
356 
359  rLocale, AccessibleRole::PANEL, sName));
360  pObject->LateInitialization();
361  pObject->UpdateStateSet();
362 
363  return pObject;
364  }
365 };
366 
367 //===== AccessiblePreview =====================================================
368 
369 class AccessiblePreview
370 {
371 public:
373  const Reference<css::uno::XComponentContext>& rxContext,
374  const lang::Locale& rLocale,
375  const Reference<awt::XWindow>& rxContentWindow,
376  const Reference<awt::XWindow>& rxBorderWindow)
377  {
378  OUString sName ("Presenter Notes Window");
379  {
380  PresenterConfigurationAccess aConfiguration (
381  rxContext,
382  "/org.openoffice.Office.PresenterScreen/",
384  aConfiguration.GetConfigurationNode("Presenter/Accessibility/Preview/String")
385  >>= sName;
386  }
387 
389  new PresenterAccessible::AccessibleObject(
390  rLocale,
391  AccessibleRole::LABEL,
392  sName));
393  pObject->LateInitialization();
394  pObject->UpdateStateSet();
395  pObject->SetWindow(rxContentWindow, rxBorderWindow);
396 
397  return pObject;
398  }
399 };
400 
401 //===== AccessibleNotes =======================================================
402 
403 class AccessibleNotes : public PresenterAccessible::AccessibleObject
404 {
405 public:
406  AccessibleNotes (
407  const css::lang::Locale& rLocale,
408  const OUString& rsName);
409 
411  const css::uno::Reference<css::uno::XComponentContext>& rxContext,
412  const lang::Locale& rLocale,
413  const Reference<awt::XWindow>& rxContentWindow,
414  const Reference<awt::XWindow>& rxBorderWindow,
415  const std::shared_ptr<PresenterTextView>& rpTextView);
416 
417  void SetTextView (const std::shared_ptr<PresenterTextView>& rpTextView);
418 
419  virtual void SetWindow (
420  const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
421  const css::uno::Reference<css::awt::XWindow>& rxBorderWindow) override;
422 
423 private:
424  std::shared_ptr<PresenterTextView> mpTextView;
425 
426  void NotifyCaretChange (
427  const sal_Int32 nOldParagraphIndex,
428  const sal_Int32 nOldCharacterIndex,
429  const sal_Int32 nNewParagraphIndex,
430  const sal_Int32 nNewCharacterIndex);
431 };
432 
433 //===== AccessibleFocusManager ================================================
434 
438 class AccessibleFocusManager
439 {
440 public:
441  static std::shared_ptr<AccessibleFocusManager> const & Instance();
442 
443  void AddFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
444  void RemoveFocusableObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
445 
446  void FocusObject (const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject);
447 
448 private:
449  static std::shared_ptr<AccessibleFocusManager> mpInstance;
450  ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > maFocusableObjects;
451 
452  AccessibleFocusManager();
453 };
454 
455 }
456 
457 //===== PresenterAccessible ===================================================
458 
460  const css::uno::Reference<css::uno::XComponentContext>& rxContext,
461  const ::rtl::Reference<PresenterController>& rpPresenterController,
462  const Reference<drawing::framework::XPane>& rxMainPane)
464  mxComponentContext(rxContext),
465  mpPresenterController(rpPresenterController),
466  mxMainPane(rxMainPane, UNO_QUERY),
467  mxMainWindow(),
468  mxPreviewContentWindow(),
469  mxPreviewBorderWindow(),
470  mxNotesContentWindow(),
471  mxNotesBorderWindow(),
472  mpAccessibleConsole(),
473  mpAccessiblePreview(),
474  mpAccessibleNotes(),
475  mxAccessibleParent()
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  {
593  if (mpAccessibleNotes.is())
594  {
596  mpAccessibleNotes = nullptr;
597  }
598 
599  mxNotesContentWindow = rxNotesContentWindow;
600  mxNotesBorderWindow = rxNotesBorderWindow;
601 
602  if (mxNotesContentWindow.is())
603  {
604  mpAccessibleNotes = AccessibleNotes::Create(
606  lang::Locale(),
609  rpNotesTextView);
610  mpAccessibleConsole->AddChild(mpAccessibleNotes.get());
611  }
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", OSL_THIS_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", OSL_THIS_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  mxContentWindow(),
721  mxBorderWindow(),
722  maLocale(rLocale),
723  mnRole(nRole),
724  mnStateSet(0),
725  mbIsFocused(false),
726  mxParentAccessible(),
727  maChildren(),
728  maListeners()
729 {
730 }
731 
733 {
734  AccessibleFocusManager::Instance()->AddFocusableObject(this);
735 }
736 
738  const Reference<awt::XWindow>& rxContentWindow,
739  const Reference<awt::XWindow>& rxBorderWindow)
740 {
741  Reference<awt::XWindow2> xContentWindow (rxContentWindow, UNO_QUERY);
742 
743  if (mxContentWindow.get() != xContentWindow.get())
744  {
745  if (mxContentWindow.is())
746  {
747  mxContentWindow->removeWindowListener(this);
748  }
749 
750  mxContentWindow = xContentWindow;
751  mxBorderWindow.set(rxBorderWindow, UNO_QUERY);
752 
753  if (mxContentWindow.is())
754  {
755  mxContentWindow->addWindowListener(this);
756  }
757 
758  UpdateStateSet();
759  }
760 }
761 
763  const Reference<XAccessible>& rxAccessibleParent)
764 {
765  mxParentAccessible = rxAccessibleParent;
766 }
767 
769 {
770  AccessibleFocusManager::Instance()->RemoveFocusableObject(this);
771  SetWindow(nullptr, nullptr);
772 }
773 
774 //----- XAccessible -------------------------------------------------------
775 
776 Reference<XAccessibleContext> SAL_CALL
778 {
779  ThrowIfDisposed();
780 
781  return this;
782 }
783 
784 //----- XAccessibleContext ----------------------------------------------
785 
787 {
788  ThrowIfDisposed();
789 
790  const sal_Int32 nChildCount (maChildren.size());
791 
792  return nChildCount;
793 }
794 
795 Reference<XAccessible> SAL_CALL
797 {
798  ThrowIfDisposed();
799 
800  if (nIndex<0 || nIndex>=sal_Int32(maChildren.size()))
801  throw lang::IndexOutOfBoundsException("invalid child index", static_cast<uno::XWeak*>(this));
802 
803  return Reference<XAccessible>(maChildren[nIndex].get());
804 }
805 
806 Reference<XAccessible> SAL_CALL
808 {
809  ThrowIfDisposed();
810 
811  return mxParentAccessible;
812 }
813 
814 sal_Int32 SAL_CALL
816 {
817  ThrowIfDisposed();
818 
819  const Reference<XAccessible> xThis (this);
820  if (mxParentAccessible.is())
821  {
822  const Reference<XAccessibleContext> xContext (mxParentAccessible->getAccessibleContext());
823  for (sal_Int32 nIndex=0,nCount=xContext->getAccessibleChildCount();
824  nIndex<nCount;
825  ++nIndex)
826  {
827  if (xContext->getAccessibleChild(nIndex) == xThis)
828  return nIndex;
829  }
830  }
831 
832  return 0;
833 }
834 
835 sal_Int16 SAL_CALL
837 {
838  ThrowIfDisposed();
839 
840  return mnRole;
841 }
842 
843 OUString SAL_CALL
845 {
846  ThrowIfDisposed();
847 
848  return msName;
849 }
850 
851 OUString SAL_CALL
853 {
854  ThrowIfDisposed();
855 
856  return msName;
857 }
858 
859 Reference<XAccessibleRelationSet> SAL_CALL
861 {
862  ThrowIfDisposed();
863 
864  return nullptr;
865 }
866 
867 Reference<XAccessibleStateSet> SAL_CALL
869 {
870  ThrowIfDisposed();
871 
872  return Reference<XAccessibleStateSet>(new AccessibleStateSet(mnStateSet));
873 }
874 
875 lang::Locale SAL_CALL
877 {
878  ThrowIfDisposed();
879 
880  if (mxParentAccessible.is())
881  {
882  Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
883  if (xParentContext.is())
884  return xParentContext->getLocale();
885  }
886  return maLocale;
887 }
888 
889 //----- XAccessibleComponent ------------------------------------------------
890 
892  const awt::Point& rPoint)
893 {
894  ThrowIfDisposed();
895 
896  if (mxContentWindow.is())
897  {
898  const awt::Rectangle aBox (getBounds());
899  return rPoint.X>=aBox.X
900  && rPoint.Y>=aBox.Y
901  && rPoint.X<aBox.X+aBox.Width
902  && rPoint.Y<aBox.Y+aBox.Height;
903  }
904  else
905  return false;
906 }
907 
908 Reference<XAccessible> SAL_CALL
910 {
911  ThrowIfDisposed();
912 
913  return Reference<XAccessible>();
914 }
915 
917 {
918  ThrowIfDisposed();
919 
920  const awt::Point aLocation (GetRelativeLocation());
921  const awt::Size aSize (GetSize());
922 
923  return awt::Rectangle (aLocation.X, aLocation.Y, aSize.Width, aSize.Height);
924 }
925 
927 {
928  ThrowIfDisposed();
929 
930  const awt::Point aLocation (GetRelativeLocation());
931 
932  return aLocation;
933 }
934 
936 {
937  ThrowIfDisposed();
938 
939  awt::Point aRelativeLocation (GetRelativeLocation());
940  awt::Point aParentLocationOnScreen (GetAbsoluteParentLocation());
941 
942  return awt::Point(
943  aRelativeLocation.X + aParentLocationOnScreen.X,
944  aRelativeLocation.Y + aParentLocationOnScreen.Y);
945 }
946 
948 {
949  ThrowIfDisposed();
950 
951  const awt::Size aSize (GetSize());
952 
953  return aSize;
954 }
955 
957 {
958  ThrowIfDisposed();
959  if (mxBorderWindow.is())
960  mxBorderWindow->setFocus();
961  else if (mxContentWindow.is())
962  mxContentWindow->setFocus();
963 }
964 
966 {
967  ThrowIfDisposed();
968 
969  return 0x00ffffff;
970 }
971 
973 {
974  ThrowIfDisposed();
975 
976  return 0x00000000;
977 }
978 
979 //----- XAccessibleEventBroadcaster -------------------------------------------
980 
982  const Reference<XAccessibleEventListener>& rxListener)
983 {
984  if (rxListener.is())
985  {
986  const osl::MutexGuard aGuard(m_aMutex);
987 
988  if (rBHelper.bDisposed || rBHelper.bInDispose)
989  {
990  uno::Reference<uno::XInterface> xThis (static_cast<XWeak*>(this), UNO_QUERY);
991  rxListener->disposing (lang::EventObject(xThis));
992  }
993  else
994  {
995  maListeners.push_back(rxListener);
996  }
997  }
998 }
999 
1001  const Reference<XAccessibleEventListener>& rxListener)
1002 {
1003  ThrowIfDisposed();
1004  if (rxListener.is())
1005  {
1006  const osl::MutexGuard aGuard(m_aMutex);
1007 
1008  auto const it(std::remove(maListeners.begin(), maListeners.end(), rxListener));
1009  if (it != maListeners.end())
1010  {
1011  maListeners.erase(it);
1012  }
1013  }
1014 }
1015 
1016 //----- XWindowListener ---------------------------------------------------
1017 
1019  const css::awt::WindowEvent&)
1020 {
1021  FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1022 }
1023 
1025  const css::awt::WindowEvent&)
1026 {
1027  FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1028 }
1029 
1031  const css::lang::EventObject&)
1032 {
1033  UpdateStateSet();
1034 }
1035 
1037  const css::lang::EventObject&)
1038 {
1039  UpdateStateSet();
1040 }
1041 
1042 //----- XEventListener --------------------------------------------------------
1043 
1044 void SAL_CALL PresenterAccessible::AccessibleObject::disposing (const css::lang::EventObject& rEvent)
1045 {
1046  if (rEvent.Source == mxContentWindow)
1047  {
1048  mxContentWindow = nullptr;
1049  mxBorderWindow = nullptr;
1050  }
1051  else
1052  {
1053  SetWindow(nullptr, nullptr);
1054  }
1055 }
1056 
1057 //----- private ---------------------------------------------------------------
1058 
1060 {
1061  switch (nType)
1062  {
1063  case AccessibleStateType::ENABLED:
1064  return mxContentWindow.is() && mxContentWindow->isEnabled();
1065 
1066  case AccessibleStateType::FOCUSABLE:
1067  return true;
1068 
1069  case AccessibleStateType::FOCUSED:
1070  return mbIsFocused;
1071 
1072  case AccessibleStateType::SHOWING:
1073  return mxContentWindow.is() && mxContentWindow->isVisible();
1074 
1075  default:
1076  return false;
1077  }
1078 }
1079 
1081 {
1082  UpdateState(AccessibleStateType::FOCUSABLE, true);
1083  UpdateState(AccessibleStateType::VISIBLE, true);
1084  UpdateState(AccessibleStateType::ENABLED, true);
1085  UpdateState(AccessibleStateType::MULTI_LINE, true);
1086  UpdateState(AccessibleStateType::SENSITIVE, true);
1087 
1088  UpdateState(AccessibleStateType::ENABLED, GetWindowState(AccessibleStateType::ENABLED));
1089  UpdateState(AccessibleStateType::FOCUSED, GetWindowState(AccessibleStateType::FOCUSED));
1090  UpdateState(AccessibleStateType::SHOWING, GetWindowState(AccessibleStateType::SHOWING));
1091  // UpdateState(AccessibleStateType::ACTIVE, GetWindowState(AccessibleStateType::ACTIVE));
1092 }
1093 
1095  const sal_Int16 nState,
1096  const bool bValue)
1097 {
1098  const sal_uInt32 nStateMask (AccessibleStateSet::GetStateMask(nState));
1099  if (((mnStateSet & nStateMask)!=0) != bValue)
1100  {
1101  if (bValue)
1102  {
1103  mnStateSet |= nStateMask;
1104  FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(), Any(nState));
1105  }
1106  else
1107  {
1108  mnStateSet &= ~nStateMask;
1109  FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(nState), Any());
1110  }
1111  }
1112 }
1113 
1115  const ::rtl::Reference<AccessibleObject>& rpChild)
1116 {
1117  maChildren.push_back(rpChild);
1118  rpChild->SetAccessibleParent(this);
1119  FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1120 }
1121 
1123  const ::rtl::Reference<AccessibleObject>& rpChild)
1124 {
1125  rpChild->SetAccessibleParent(Reference<XAccessible>());
1126  maChildren.erase(::std::find(maChildren.begin(), maChildren.end(), rpChild));
1127  FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1128 }
1129 
1131 {
1132  if (mbIsFocused != bIsFocused)
1133  {
1134  mbIsFocused = bIsFocused;
1135  UpdateStateSet();
1136  }
1137 }
1138 
1140 {
1141  if (msName != rsName)
1142  {
1143  const OUString sOldName(msName);
1144  msName = rsName;
1145  FireAccessibleEvent(AccessibleEventId::NAME_CHANGED, Any(sOldName), Any(msName));
1146  }
1147 }
1148 
1150  const sal_Int16 nEventId,
1151  const uno::Any& rOldValue,
1152  const uno::Any& rNewValue )
1153 {
1154  AccessibleEventObject aEventObject;
1155 
1156  aEventObject.Source = Reference<XWeak>(this);
1157  aEventObject.EventId = nEventId;
1158  aEventObject.NewValue = rNewValue;
1159  aEventObject.OldValue = rOldValue;
1160 
1161  ::std::vector<Reference<XAccessibleEventListener> > aListenerCopy(maListeners);
1162  for (const auto& rxListener : aListenerCopy)
1163  {
1164  try
1165  {
1166  rxListener->notifyEvent(aEventObject);
1167  }
1168  catch (const lang::DisposedException&)
1169  {
1170  // Listener has been disposed and should have been removed
1171  // already.
1172  removeAccessibleEventListener(rxListener);
1173  }
1174  catch (const Exception&)
1175  {
1176  // Ignore all other exceptions and assume that they are
1177  // caused by a temporary problem.
1178  }
1179  }
1180 }
1181 
1183 {
1184  awt::Point aLocation;
1185  if (mxContentWindow.is())
1186  {
1187  const awt::Rectangle aContentBox (mxContentWindow->getPosSize());
1188  aLocation.X = aContentBox.X;
1189  aLocation.Y = aContentBox.Y;
1190  if (mxBorderWindow.is())
1191  {
1192  const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize());
1193  aLocation.X += aBorderBox.X;
1194  aLocation.Y += aBorderBox.Y;
1195  }
1196  }
1197  return aLocation;
1198 }
1199 
1201 {
1202  if (mxContentWindow.is())
1203  {
1204  const awt::Rectangle aBox (mxContentWindow->getPosSize());
1205  return awt::Size(aBox.Width, aBox.Height);
1206  }
1207  else
1208  return awt::Size();
1209 }
1210 
1212 {
1213  Reference<XAccessibleComponent> xParentComponent;
1214  if (mxParentAccessible.is())
1215  xParentComponent.set( mxParentAccessible->getAccessibleContext(), UNO_QUERY);
1216  if (xParentComponent.is())
1217  return xParentComponent->getLocationOnScreen();
1218  else
1219  return awt::Point();
1220 }
1221 
1223 {
1224  if (rBHelper.bDisposed || rBHelper.bInDispose)
1225  throw lang::DisposedException("object has already been disposed", uno::Reference<uno::XInterface>(const_cast<uno::XWeak*>(static_cast<uno::XWeak const *>(this))));
1226 }
1227 
1228 //===== AccessibleStateSet ====================================================
1229 
1230 AccessibleStateSet::AccessibleStateSet (const sal_Int32 nStateSet)
1231  : AccessibleStateSetInterfaceBase(m_aMutex),
1232  mnStateSet (nStateSet)
1233 {
1234 }
1235 
1236 sal_uInt32 AccessibleStateSet::GetStateMask (const sal_Int16 nState)
1237 {
1238  if (nState<0 || nState>=sal_Int16(sizeof(sal_uInt32)*8))
1239  {
1240  throw RuntimeException("AccessibleStateSet::GetStateMask: invalid state");
1241  }
1242 
1243  return 1<<nState;
1244 }
1245 
1246 //----- XAccessibleStateSet ---------------------------------------------------
1247 
1248 sal_Bool SAL_CALL AccessibleStateSet::isEmpty()
1249 {
1250  return mnStateSet==0;
1251 }
1252 
1253 sal_Bool SAL_CALL AccessibleStateSet::contains (sal_Int16 nState)
1254 {
1255  return (mnStateSet & GetStateMask(nState)) != 0;
1256 }
1257 
1258 sal_Bool SAL_CALL AccessibleStateSet::containsAll (const css::uno::Sequence<sal_Int16>& rStateSet)
1259 {
1260  return std::none_of(rStateSet.begin(), rStateSet.end(),
1261  [this](const sal_Int16 nState) { return (mnStateSet & GetStateMask(nState)) == 0; });
1262 }
1263 
1264 css::uno::Sequence<sal_Int16> SAL_CALL AccessibleStateSet::getStates()
1265 {
1266  ::std::vector<sal_Int16> aStates;
1267  aStates.reserve(sizeof(mnStateSet)*8);
1268  for (sal_uInt16 nIndex=0; nIndex<sizeof(mnStateSet)*8; ++nIndex)
1269  if ((mnStateSet & GetStateMask(nIndex)) != 0)
1270  aStates.push_back(nIndex);
1271  return Sequence<sal_Int16>(aStates.data(), aStates.size());
1272 }
1273 
1274 //===== AccessibleRelationSet =================================================
1275 
1276 AccessibleRelationSet::AccessibleRelationSet()
1277  : AccessibleRelationSetInterfaceBase(m_aMutex),
1278  maRelations()
1279 {
1280 }
1281 
1282 void AccessibleRelationSet::AddRelation (
1283  const sal_Int16 nRelationType,
1284  const Reference<XInterface>& rxObject)
1285 {
1286  maRelations.emplace_back();
1287  maRelations.back().RelationType = nRelationType;
1288  maRelations.back().TargetSet.realloc(1);
1289  maRelations.back().TargetSet[0] = rxObject;
1290 }
1291 
1292 //----- XAccessibleRelationSet ------------------------------------------------
1293 
1294 sal_Int32 SAL_CALL AccessibleRelationSet::getRelationCount()
1295 {
1296  return maRelations.size();
1297 }
1298 
1299 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelation (sal_Int32 nIndex)
1300 {
1301  if (nIndex<0 && o3tl::make_unsigned(nIndex)>=maRelations.size())
1302  return AccessibleRelation();
1303  else
1304  return maRelations[nIndex];
1305 }
1306 
1307 sal_Bool SAL_CALL AccessibleRelationSet::containsRelation (sal_Int16 nRelationType)
1308 {
1309  return std::any_of(maRelations.begin(), maRelations.end(),
1310  [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1311 }
1312 
1313 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelationByType (sal_Int16 nRelationType)
1314 {
1315  auto iRelation = std::find_if(maRelations.begin(), maRelations.end(),
1316  [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1317  if (iRelation != maRelations.end())
1318  return *iRelation;
1319  return AccessibleRelation();
1320 }
1321 
1322 //===== PresenterAccessible::AccessibleParagraph ==============================
1323 
1325  const lang::Locale& rLocale,
1326  const OUString& rsName,
1327  const SharedPresenterTextParagraph& rpParagraph,
1328  const sal_Int32 nParagraphIndex)
1329  : PresenterAccessibleParagraphInterfaceBase(rLocale, AccessibleRole::PARAGRAPH, rsName),
1330  mpParagraph(rpParagraph),
1331  mnParagraphIndex(nParagraphIndex)
1332 {
1333 }
1334 
1335 //----- XAccessibleContext ----------------------------------------------------
1336 
1337 Reference<XAccessibleRelationSet> SAL_CALL
1339 {
1340  ThrowIfDisposed();
1341 
1342  rtl::Reference<AccessibleRelationSet> pSet (new AccessibleRelationSet);
1343 
1344  if (mxParentAccessible.is())
1345  {
1346  Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
1347  if (xParentContext.is())
1348  {
1349  if (mnParagraphIndex>0)
1350  pSet->AddRelation(
1351  AccessibleRelationType::CONTENT_FLOWS_FROM,
1352  xParentContext->getAccessibleChild(mnParagraphIndex-1));
1353 
1354  if (mnParagraphIndex<xParentContext->getAccessibleChildCount()-1)
1355  pSet->AddRelation(
1356  AccessibleRelationType::CONTENT_FLOWS_TO,
1357  xParentContext->getAccessibleChild(mnParagraphIndex+1));
1358  }
1359  }
1360 
1361  return Reference<XAccessibleRelationSet>(pSet.get());
1362 }
1363 
1364 //----- XAccessibleText -------------------------------------------------------
1365 
1367 {
1368  ThrowIfDisposed();
1369 
1370  sal_Int32 nPosition (-1);
1371  if (mpParagraph)
1372  nPosition = mpParagraph->GetCaretPosition();
1373 
1374  return nPosition;
1375 }
1376 
1378 {
1379  ThrowIfDisposed();
1380 
1381  if (mpParagraph)
1382  {
1383  mpParagraph->SetCaretPosition(nIndex);
1384  return true;
1385  }
1386  else
1387  return false;
1388 }
1389 
1391 {
1392  ThrowIfDisposed();
1393 
1394  if (!mpParagraph)
1395  throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1396  return mpParagraph->GetCharacter(nIndex);
1397 }
1398 
1399 Sequence<css::beans::PropertyValue> SAL_CALL
1401  ::sal_Int32 nIndex,
1402  const css::uno::Sequence<OUString>& rRequestedAttributes)
1403 {
1404  ThrowIfDisposed();
1405 
1406 #if OSL_DEBUG_LEVEL > 0
1407  SAL_INFO( "sdext.presenter", OSL_THIS_FUNC << " at " << this << ", " << nIndex << " returns empty set" );
1408  for (sal_Int32 nAttributeIndex(0), nAttributeCount(rRequestedAttributes.getLength());
1409  nAttributeIndex < nAttributeCount;
1410  ++nAttributeIndex)
1411  {
1412  SAL_INFO( "sdext.presenter",
1413  " requested attribute " << nAttributeIndex << " is " << rRequestedAttributes[nAttributeIndex] );
1414  }
1415 #else
1416  (void)nIndex;
1417  (void)rRequestedAttributes;
1418 #endif
1419 
1420  // Character properties are not supported.
1421  return Sequence<css::beans::PropertyValue>();
1422 }
1423 
1425  sal_Int32 nIndex)
1426 {
1427  ThrowIfDisposed();
1428 
1429  awt::Rectangle aCharacterBox;
1430  if (nIndex < 0)
1431  {
1432  throw lang::IndexOutOfBoundsException("invalid text index", static_cast<uno::XWeak*>(this));
1433  }
1434  else if (mpParagraph)
1435  {
1436  aCharacterBox = mpParagraph->GetCharacterBounds(nIndex, false);
1437  // Convert coordinates relative to the window origin into absolute
1438  // screen coordinates.
1439  const awt::Point aWindowLocationOnScreen (getLocationOnScreen());
1440  aCharacterBox.X += aWindowLocationOnScreen.X;
1441  aCharacterBox.Y += aWindowLocationOnScreen.Y;
1442  }
1443  else
1444  {
1445  throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1446  }
1447 
1448  return aCharacterBox;
1449 }
1450 
1452 {
1453  ThrowIfDisposed();
1454 
1455  sal_Int32 nCount (0);
1456  if (mpParagraph)
1457  nCount = mpParagraph->GetCharacterCount();
1458 
1459  return nCount;
1460 }
1461 
1463  const css::awt::Point& )
1464 {
1465  ThrowIfDisposed();
1466  return -1;
1467 }
1468 
1470 {
1471  ThrowIfDisposed();
1472 
1473  return getTextRange(getSelectionStart(), getSelectionEnd());
1474 }
1475 
1477 {
1478  ThrowIfDisposed();
1479 
1480  return getCaretPosition();
1481 }
1482 
1484 {
1485  ThrowIfDisposed();
1486 
1487  return getCaretPosition();
1488 }
1489 
1491  sal_Int32 nStartIndex,
1492  sal_Int32)
1493 {
1494  ThrowIfDisposed();
1495 
1496  return setCaretPosition(nStartIndex);
1497 }
1498 
1500 {
1501  ThrowIfDisposed();
1502 
1503  OUString sText;
1504  if (mpParagraph)
1505  sText = mpParagraph->GetText();
1506 
1507  return sText;
1508 }
1509 
1511  sal_Int32 nLocalStartIndex,
1512  sal_Int32 nLocalEndIndex)
1513 {
1514  ThrowIfDisposed();
1515 
1516  OUString sText;
1517  if (mpParagraph)
1518  {
1519  const TextSegment aSegment (
1520  mpParagraph->CreateTextSegment(nLocalStartIndex, nLocalEndIndex));
1521  sText = aSegment.SegmentText;
1522  }
1523 
1524  return sText;
1525 }
1526 
1528  sal_Int32 nLocalCharacterIndex,
1529  sal_Int16 nTextType)
1530 {
1531  ThrowIfDisposed();
1532 
1533  TextSegment aSegment;
1534  if (mpParagraph)
1535  aSegment = mpParagraph->GetTextSegment(0, nLocalCharacterIndex, nTextType);
1536 
1537  return aSegment;
1538 }
1539 
1541  sal_Int32 nLocalCharacterIndex,
1542  sal_Int16 nTextType)
1543 {
1544  ThrowIfDisposed();
1545 
1546  TextSegment aSegment;
1547  if (mpParagraph)
1548  aSegment = mpParagraph->GetTextSegment(-1, nLocalCharacterIndex, nTextType);
1549 
1550  return aSegment;
1551 }
1552 
1554  sal_Int32 nLocalCharacterIndex,
1555  sal_Int16 nTextType)
1556 {
1557  ThrowIfDisposed();
1558 
1559  TextSegment aSegment;
1560  if (mpParagraph)
1561  aSegment = mpParagraph->GetTextSegment(+1, nLocalCharacterIndex, nTextType);
1562 
1563  return aSegment;
1564 }
1565 
1567  sal_Int32,
1568  sal_Int32)
1569 {
1570  ThrowIfDisposed();
1571 
1572  // Return false because copying to clipboard is not supported.
1573  // It IS supported in the notes view. There is no need to duplicate
1574  // this here.
1575  return false;
1576 }
1577 
1578 //----- protected -------------------------------------------------------------
1579 
1581 {
1582  awt::Point aLocation (AccessibleObject::GetRelativeLocation());
1583  if (mpParagraph)
1584  {
1585  const awt::Point aParagraphLocation (mpParagraph->GetRelativeLocation());
1586  aLocation.X += aParagraphLocation.X;
1587  aLocation.Y += aParagraphLocation.Y;
1588  }
1589 
1590  return aLocation;
1591 }
1592 
1594 {
1595  if (mpParagraph)
1596  return mpParagraph->GetSize();
1597  else
1598  return AccessibleObject::GetSize();
1599 }
1600 
1602 {
1603  if (mxParentAccessible.is())
1604  {
1605  Reference<XAccessibleContext> xParentContext =
1606  mxParentAccessible->getAccessibleContext();
1607  if (xParentContext.is())
1608  {
1609  Reference<XAccessibleComponent> xGrandParentComponent(
1610  xParentContext->getAccessibleParent(), UNO_QUERY);
1611  if (xGrandParentComponent.is())
1612  return xGrandParentComponent->getLocationOnScreen();
1613  }
1614  }
1615 
1616  return awt::Point();
1617 }
1618 
1620 {
1621  switch (nType)
1622  {
1623  case AccessibleStateType::EDITABLE:
1624  return mpParagraph.get()!=nullptr;
1625 
1626  case AccessibleStateType::ACTIVE:
1627  return true;
1628 
1629  default:
1630  return AccessibleObject::GetWindowState(nType);
1631  }
1632 }
1633 
1634 //===== AccessibleNotes =======================================================
1635 
1636 AccessibleNotes::AccessibleNotes (
1637  const css::lang::Locale& rLocale,
1638  const OUString& rsName)
1639  : AccessibleObject(rLocale,AccessibleRole::PANEL,rsName),
1640  mpTextView()
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 
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  {
1691  // Create a new set of children, one for each paragraph.
1692  const sal_Int32 nParagraphCount (mpTextView->GetParagraphCount());
1693  for (sal_Int32 nIndex=0; nIndex<nParagraphCount; ++nIndex)
1694  {
1696  new PresenterAccessible::AccessibleParagraph(
1697  css::lang::Locale(),
1698  "Paragraph"+OUString::number(nIndex),
1699  rpTextView->GetParagraph(nIndex),
1700  nIndex));
1701  pParagraph->LateInitialization();
1702  pParagraph->SetWindow(mxContentWindow, mxBorderWindow);
1703  pParagraph->SetAccessibleParent(this);
1704  aChildren.emplace_back(pParagraph.get());
1705  }
1706  maChildren.swap(aChildren);
1707  FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1708 
1709  // Dispose the old children. (This will remove them from the focus
1710  // manager).
1711  for (const auto& rxChild : aChildren)
1712  {
1713  Reference<lang::XComponent> xComponent (static_cast<XWeak*>(rxChild.get()), UNO_QUERY);
1714  if (xComponent.is())
1715  xComponent->dispose();
1716  }
1717 
1718  // This class acts as a controller of who broadcasts caret motion
1719  // events and handles text changes. Register the corresponding
1720  // listeners here.
1721  mpTextView->GetCaret()->SetCaretMotionBroadcaster(
1722  [this](sal_Int32 a, sal_Int32 b, sal_Int32 c, sal_Int32 d)
1723  { return this->NotifyCaretChange(a, b, c, d); });
1724  mpTextView->SetTextChangeBroadcaster(
1725  [this]() { return SetTextView(mpTextView); });
1726  }
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  : maFocusableObjects()
1800 {
1801 }
1802 
1803 void AccessibleFocusManager::AddFocusableObject (
1804  const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1805 {
1806  OSL_ASSERT(rpObject.is());
1807  OSL_ASSERT(::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject)==maFocusableObjects.end());
1808 
1809  maFocusableObjects.push_back(rpObject);
1810 }
1811 
1812 void AccessibleFocusManager::RemoveFocusableObject (
1813  const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1814 {
1815  ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> >::iterator iObject (
1816  ::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject));
1817 
1818  if (iObject != maFocusableObjects.end())
1819  maFocusableObjects.erase(iObject);
1820  else
1821  {
1822  OSL_ASSERT(iObject!=maFocusableObjects.end());
1823  }
1824 }
1825 
1826 void AccessibleFocusManager::FocusObject (
1827  const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1828 {
1829  // Remove the focus of any of the other focusable objects.
1830  for (auto& rxObject : maFocusableObjects)
1831  {
1832  if (rxObject!=rpObject)
1833  rxObject->SetIsFocused(false);
1834  }
1835 
1836  if (rpObject.is())
1837  rpObject->SetIsFocused(true);
1838 }
1839 
1840 } // end of namespace ::sd::presenter
1841 
1842 /* 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
::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
osl::Mutex m_aMutex
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)
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
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
css::uno::Reference< css::lang::XComponent > xComponent
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
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 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
::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