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  mxMainWindow(),
477  mxPreviewContentWindow(),
478  mxPreviewBorderWindow(),
479  mxNotesContentWindow(),
480  mxNotesBorderWindow(),
481  mpAccessibleConsole(),
482  mpAccessiblePreview(),
483  mpAccessibleNotes(),
484  mxAccessibleParent()
485 {
486  if (mxMainPane.is())
487  mxMainPane->setAccessible(this);
488 }
489 
491 {
492 }
493 
495 {
497 
498  if ( ! mpPresenterController.is())
499  return pPreviewPane;
500 
501  rtl::Reference<PresenterPaneContainer> pContainer (mpPresenterController->GetPaneContainer());
502  if ( ! pContainer.is())
503  return pPreviewPane;
504 
505  pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msCurrentSlidePreviewPaneURL);
506  Reference<drawing::framework::XPane> xPreviewPane;
507  if (pPreviewPane)
508  xPreviewPane = pPreviewPane->mxPane.get();
509  if ( ! xPreviewPane.is())
510  {
511  pPreviewPane = pContainer->FindPaneURL(PresenterPaneFactory::msSlideSorterPaneURL);
512  }
513  return pPreviewPane;
514 }
515 
517 {
518  if ( ! mpPresenterController.is())
519  return;
520 
521  Reference<drawing::framework::XConfigurationController> xConfigurationController(
522  mpPresenterController->GetConfigurationController());
523  if ( ! xConfigurationController.is())
524  return;
525 
527  mpPresenterController->GetPaneContainer());
528  if ( ! pPaneContainer.is())
529  return;
530 
531  if ( ! mpAccessibleConsole.is())
532  return;
533 
534  // Get the preview pane (standard or notes view) or the slide overview
535  // pane.
537  Reference<drawing::framework::XPane> xPreviewPane;
538  if (pPreviewPane)
539  xPreviewPane = pPreviewPane->mxPane.get();
540 
541  // Get the notes pane.
543  pPaneContainer->FindPaneURL(PresenterPaneFactory::msNotesPaneURL));
544  Reference<drawing::framework::XPane> xNotesPane;
545  if (pNotesPane)
546  xNotesPane = pNotesPane->mxPane.get();
547 
548  // Get the notes view.
549  Reference<drawing::framework::XView> xNotesView;
550  if (pNotesPane)
551  xNotesView = pNotesPane->mxView;
553  dynamic_cast<PresenterNotesView*>(xNotesView.get()));
554 
556  pPreviewPane ? pPreviewPane->mxContentWindow : Reference<awt::XWindow>(),
557  pPreviewPane ? pPreviewPane->mxBorderWindow : Reference<awt::XWindow>(),
558  (pPreviewPane&&pPreviewPane->mxPane.is()) ? pPreviewPane->mxPane->GetTitle() : OUString(),
559  pNotesPane ? pNotesPane->mxContentWindow : Reference<awt::XWindow>(),
560  pNotesPane ? pNotesPane->mxBorderWindow : Reference<awt::XWindow>(),
561  pNotesView.is()
562  ? pNotesView->GetTextView()
563  : std::shared_ptr<PresenterTextView>());
564 }
565 
567  const Reference<awt::XWindow>& rxPreviewContentWindow,
568  const Reference<awt::XWindow>& rxPreviewBorderWindow,
569  const OUString& rsTitle,
570  const Reference<awt::XWindow>& rxNotesContentWindow,
571  const Reference<awt::XWindow>& rxNotesBorderWindow,
572  const std::shared_ptr<PresenterTextView>& rpNotesTextView)
573 {
574  if ( ! mpAccessibleConsole.is())
575  return;
576 
577  if (mxPreviewContentWindow != rxPreviewContentWindow)
578  {
579  if (mpAccessiblePreview.is())
580  {
582  mpAccessiblePreview = nullptr;
583  }
584 
585  mxPreviewContentWindow = rxPreviewContentWindow;
586  mxPreviewBorderWindow = rxPreviewBorderWindow;
587 
588  if (mxPreviewContentWindow.is())
589  {
590  mpAccessiblePreview = AccessiblePreview::Create(
592  lang::Locale(),
596  mpAccessiblePreview->SetAccessibleName(rsTitle);
597  }
598  }
599 
600  if (mxNotesContentWindow == rxNotesContentWindow)
601  return;
602 
603  if (mpAccessibleNotes.is())
604  {
606  mpAccessibleNotes = nullptr;
607  }
608 
609  mxNotesContentWindow = rxNotesContentWindow;
610  mxNotesBorderWindow = rxNotesBorderWindow;
611 
612  if (mxNotesContentWindow.is())
613  {
614  mpAccessibleNotes = AccessibleNotes::Create(
616  lang::Locale(),
619  rpNotesTextView);
620  mpAccessibleConsole->AddChild(mpAccessibleNotes.get());
621  }
622 }
623 
625 {
626  if (mpAccessiblePreview.is())
627  {
629  mpAccessiblePreview->SetAccessibleName(
630  pPreviewPane&&pPreviewPane->mxPane.is()
631  ? pPreviewPane->mxPane->GetTitle()
632  : OUString());
633  }
634 
635  // Play some focus ping-pong to trigger AT tools.
636  //AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
637  AccessibleFocusManager::Instance()->FocusObject(mpAccessiblePreview);
638 }
639 
641 {
643  nullptr,
644  nullptr,
645  OUString(),
646  nullptr,
647  nullptr,
648  std::shared_ptr<PresenterTextView>());
649 
650  if (mxMainWindow.is())
651  {
652  mxMainWindow->removeFocusListener(this);
653 
654  if (mxMainPane.is())
655  mxMainPane->setAccessible(nullptr);
656  }
657 
658  mpAccessiblePreview = nullptr;
659  mpAccessibleNotes = nullptr;
660  mpAccessibleConsole = nullptr;
661 }
662 
663 //----- XAccessible -----------------------------------------------------------
664 
665 Reference<XAccessibleContext> SAL_CALL PresenterAccessible::getAccessibleContext()
666 {
667  if ( ! mpAccessibleConsole.is())
668  {
669  Reference<XPane> xMainPane (mxMainPane, UNO_QUERY);
670  if (xMainPane.is())
671  {
672  mxMainWindow = xMainPane->getWindow();
673  mxMainWindow->addFocusListener(this);
674  }
675  mpAccessibleConsole = AccessibleConsole::Create(
676  mxComponentContext, css::lang::Locale());
677  mpAccessibleConsole->SetWindow(mxMainWindow, nullptr);
678  mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
680  if (mpPresenterController.is())
681  mpPresenterController->SetAccessibilityActiveState(true);
682  }
683  return mpAccessibleConsole->getAccessibleContext();
684 }
685 
686 //----- XFocusListener ----------------------------------------------------
687 
688 void SAL_CALL PresenterAccessible::focusGained (const css::awt::FocusEvent&)
689 {
690  SAL_INFO("sdext.presenter", __func__ << ": PresenterAccessible::focusGained at " << this
691  << " and window " << mxMainWindow.get());
692  AccessibleFocusManager::Instance()->FocusObject(mpAccessibleConsole);
693 }
694 
695 void SAL_CALL PresenterAccessible::focusLost (const css::awt::FocusEvent&)
696 {
697  SAL_INFO("sdext.presenter", __func__ << ": PresenterAccessible::focusLost at " << this);
698  AccessibleFocusManager::Instance()->FocusObject(nullptr);
699 }
700 
701 //----- XEventListener ----------------------------------------------------
702 
703 void SAL_CALL PresenterAccessible::disposing (const css::lang::EventObject& rEvent)
704 {
705  if (rEvent.Source == mxMainWindow)
706  mxMainWindow = nullptr;
707 }
708 
709 //----- XInitialize -----------------------------------------------------------
710 
711 void SAL_CALL PresenterAccessible::initialize (const css::uno::Sequence<css::uno::Any>& rArguments)
712 {
713  if (rArguments.hasElements())
714  {
715  mxAccessibleParent.set(rArguments[0], UNO_QUERY);
716  if (mpAccessibleConsole.is())
717  mpAccessibleConsole->SetAccessibleParent(mxAccessibleParent);
718  }
719 }
720 
721 //===== PresenterAccessible::AccessibleObject =========================================
722 
724  const lang::Locale& rLocale,
725  const sal_Int16 nRole,
726  const OUString& rsName)
727  : PresenterAccessibleObjectInterfaceBase(m_aMutex),
728  msName(rsName),
729  mxContentWindow(),
730  mxBorderWindow(),
731  maLocale(rLocale),
732  mnRole(nRole),
733  mnStateSet(0),
734  mbIsFocused(false),
735  mxParentAccessible(),
736  maChildren(),
737  maListeners()
738 {
739 }
740 
742 {
743  AccessibleFocusManager::Instance()->AddFocusableObject(this);
744 }
745 
747  const Reference<awt::XWindow>& rxContentWindow,
748  const Reference<awt::XWindow>& rxBorderWindow)
749 {
750  Reference<awt::XWindow2> xContentWindow (rxContentWindow, UNO_QUERY);
751 
752  if (mxContentWindow.get() == xContentWindow.get())
753  return;
754 
755  if (mxContentWindow.is())
756  {
757  mxContentWindow->removeWindowListener(this);
758  }
759 
760  mxContentWindow = xContentWindow;
761  mxBorderWindow.set(rxBorderWindow, UNO_QUERY);
762 
763  if (mxContentWindow.is())
764  {
765  mxContentWindow->addWindowListener(this);
766  }
767 
768  UpdateStateSet();
769 }
770 
772  const Reference<XAccessible>& rxAccessibleParent)
773 {
774  mxParentAccessible = rxAccessibleParent;
775 }
776 
778 {
779  AccessibleFocusManager::Instance()->RemoveFocusableObject(this);
780  SetWindow(nullptr, nullptr);
781 }
782 
783 //----- XAccessible -------------------------------------------------------
784 
785 Reference<XAccessibleContext> SAL_CALL
787 {
788  ThrowIfDisposed();
789 
790  return this;
791 }
792 
793 //----- XAccessibleContext ----------------------------------------------
794 
796 {
797  ThrowIfDisposed();
798 
799  const sal_Int32 nChildCount (maChildren.size());
800 
801  return nChildCount;
802 }
803 
804 Reference<XAccessible> SAL_CALL
806 {
807  ThrowIfDisposed();
808 
809  if (nIndex<0 || nIndex>=sal_Int32(maChildren.size()))
810  throw lang::IndexOutOfBoundsException("invalid child index", static_cast<uno::XWeak*>(this));
811 
812  return Reference<XAccessible>(maChildren[nIndex].get());
813 }
814 
815 Reference<XAccessible> SAL_CALL
817 {
818  ThrowIfDisposed();
819 
820  return mxParentAccessible;
821 }
822 
823 sal_Int32 SAL_CALL
825 {
826  ThrowIfDisposed();
827 
828  const Reference<XAccessible> xThis (this);
829  if (mxParentAccessible.is())
830  {
831  const Reference<XAccessibleContext> xContext (mxParentAccessible->getAccessibleContext());
832  for (sal_Int32 nIndex=0,nCount=xContext->getAccessibleChildCount();
833  nIndex<nCount;
834  ++nIndex)
835  {
836  if (xContext->getAccessibleChild(nIndex) == xThis)
837  return nIndex;
838  }
839  }
840 
841  return 0;
842 }
843 
844 sal_Int16 SAL_CALL
846 {
847  ThrowIfDisposed();
848 
849  return mnRole;
850 }
851 
852 OUString SAL_CALL
854 {
855  ThrowIfDisposed();
856 
857  return msName;
858 }
859 
860 OUString SAL_CALL
862 {
863  ThrowIfDisposed();
864 
865  return msName;
866 }
867 
868 Reference<XAccessibleRelationSet> SAL_CALL
870 {
871  ThrowIfDisposed();
872 
873  return nullptr;
874 }
875 
876 Reference<XAccessibleStateSet> SAL_CALL
878 {
879  ThrowIfDisposed();
880 
881  return Reference<XAccessibleStateSet>(new AccessibleStateSet(mnStateSet));
882 }
883 
884 lang::Locale SAL_CALL
886 {
887  ThrowIfDisposed();
888 
889  if (mxParentAccessible.is())
890  {
891  Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
892  if (xParentContext.is())
893  return xParentContext->getLocale();
894  }
895  return maLocale;
896 }
897 
898 //----- XAccessibleComponent ------------------------------------------------
899 
901  const awt::Point& rPoint)
902 {
903  ThrowIfDisposed();
904 
905  if (mxContentWindow.is())
906  {
907  const awt::Rectangle aBox (getBounds());
908  return rPoint.X>=aBox.X
909  && rPoint.Y>=aBox.Y
910  && rPoint.X<aBox.X+aBox.Width
911  && rPoint.Y<aBox.Y+aBox.Height;
912  }
913  else
914  return false;
915 }
916 
917 Reference<XAccessible> SAL_CALL
919 {
920  ThrowIfDisposed();
921 
922  return Reference<XAccessible>();
923 }
924 
926 {
927  ThrowIfDisposed();
928 
929  const awt::Point aLocation (GetRelativeLocation());
930  const awt::Size aSize (GetSize());
931 
932  return awt::Rectangle (aLocation.X, aLocation.Y, aSize.Width, aSize.Height);
933 }
934 
936 {
937  ThrowIfDisposed();
938 
939  const awt::Point aLocation (GetRelativeLocation());
940 
941  return aLocation;
942 }
943 
945 {
946  ThrowIfDisposed();
947 
948  awt::Point aRelativeLocation (GetRelativeLocation());
949  awt::Point aParentLocationOnScreen (GetAbsoluteParentLocation());
950 
951  return awt::Point(
952  aRelativeLocation.X + aParentLocationOnScreen.X,
953  aRelativeLocation.Y + aParentLocationOnScreen.Y);
954 }
955 
957 {
958  ThrowIfDisposed();
959 
960  const awt::Size aSize (GetSize());
961 
962  return aSize;
963 }
964 
966 {
967  ThrowIfDisposed();
968  if (mxBorderWindow.is())
969  mxBorderWindow->setFocus();
970  else if (mxContentWindow.is())
971  mxContentWindow->setFocus();
972 }
973 
975 {
976  ThrowIfDisposed();
977 
978  return 0x00ffffff;
979 }
980 
982 {
983  ThrowIfDisposed();
984 
985  return 0x00000000;
986 }
987 
988 //----- XAccessibleEventBroadcaster -------------------------------------------
989 
991  const Reference<XAccessibleEventListener>& rxListener)
992 {
993  if (!rxListener.is())
994  return;
995 
996  const osl::MutexGuard aGuard(m_aMutex);
997 
998  if (rBHelper.bDisposed || rBHelper.bInDispose)
999  {
1000  uno::Reference<uno::XInterface> xThis (static_cast<XWeak*>(this), UNO_QUERY);
1001  rxListener->disposing (lang::EventObject(xThis));
1002  }
1003  else
1004  {
1005  maListeners.push_back(rxListener);
1006  }
1007 }
1008 
1010  const Reference<XAccessibleEventListener>& rxListener)
1011 {
1012  ThrowIfDisposed();
1013  if (rxListener.is())
1014  {
1015  const osl::MutexGuard aGuard(m_aMutex);
1016 
1017  auto const it(std::remove(maListeners.begin(), maListeners.end(), rxListener));
1018  if (it != maListeners.end())
1019  {
1020  maListeners.erase(it);
1021  }
1022  }
1023 }
1024 
1025 //----- XWindowListener ---------------------------------------------------
1026 
1028  const css::awt::WindowEvent&)
1029 {
1030  FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1031 }
1032 
1034  const css::awt::WindowEvent&)
1035 {
1036  FireAccessibleEvent(AccessibleEventId::BOUNDRECT_CHANGED, Any(), Any());
1037 }
1038 
1040  const css::lang::EventObject&)
1041 {
1042  UpdateStateSet();
1043 }
1044 
1046  const css::lang::EventObject&)
1047 {
1048  UpdateStateSet();
1049 }
1050 
1051 //----- XEventListener --------------------------------------------------------
1052 
1053 void SAL_CALL PresenterAccessible::AccessibleObject::disposing (const css::lang::EventObject& rEvent)
1054 {
1055  if (rEvent.Source == mxContentWindow)
1056  {
1057  mxContentWindow = nullptr;
1058  mxBorderWindow = nullptr;
1059  }
1060  else
1061  {
1062  SetWindow(nullptr, nullptr);
1063  }
1064 }
1065 
1066 //----- private ---------------------------------------------------------------
1067 
1069 {
1070  switch (nType)
1071  {
1072  case AccessibleStateType::ENABLED:
1073  return mxContentWindow.is() && mxContentWindow->isEnabled();
1074 
1075  case AccessibleStateType::FOCUSABLE:
1076  return true;
1077 
1078  case AccessibleStateType::FOCUSED:
1079  return mbIsFocused;
1080 
1081  case AccessibleStateType::SHOWING:
1082  return mxContentWindow.is() && mxContentWindow->isVisible();
1083 
1084  default:
1085  return false;
1086  }
1087 }
1088 
1090 {
1091  UpdateState(AccessibleStateType::FOCUSABLE, true);
1092  UpdateState(AccessibleStateType::VISIBLE, true);
1093  UpdateState(AccessibleStateType::ENABLED, true);
1094  UpdateState(AccessibleStateType::MULTI_LINE, true);
1095  UpdateState(AccessibleStateType::SENSITIVE, true);
1096 
1097  UpdateState(AccessibleStateType::ENABLED, GetWindowState(AccessibleStateType::ENABLED));
1098  UpdateState(AccessibleStateType::FOCUSED, GetWindowState(AccessibleStateType::FOCUSED));
1099  UpdateState(AccessibleStateType::SHOWING, GetWindowState(AccessibleStateType::SHOWING));
1100  // UpdateState(AccessibleStateType::ACTIVE, GetWindowState(AccessibleStateType::ACTIVE));
1101 }
1102 
1104  const sal_Int16 nState,
1105  const bool bValue)
1106 {
1107  const sal_uInt32 nStateMask (AccessibleStateSet::GetStateMask(nState));
1108  if (((mnStateSet & nStateMask)!=0) != bValue)
1109  {
1110  if (bValue)
1111  {
1112  mnStateSet |= nStateMask;
1113  FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(), Any(nState));
1114  }
1115  else
1116  {
1117  mnStateSet &= ~nStateMask;
1118  FireAccessibleEvent(AccessibleEventId::STATE_CHANGED, Any(nState), Any());
1119  }
1120  }
1121 }
1122 
1124  const ::rtl::Reference<AccessibleObject>& rpChild)
1125 {
1126  maChildren.push_back(rpChild);
1127  rpChild->SetAccessibleParent(this);
1128  FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1129 }
1130 
1132  const ::rtl::Reference<AccessibleObject>& rpChild)
1133 {
1134  rpChild->SetAccessibleParent(Reference<XAccessible>());
1135  maChildren.erase(::std::find(maChildren.begin(), maChildren.end(), rpChild));
1136  FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1137 }
1138 
1140 {
1141  if (mbIsFocused != bIsFocused)
1142  {
1143  mbIsFocused = bIsFocused;
1144  UpdateStateSet();
1145  }
1146 }
1147 
1149 {
1150  if (msName != rsName)
1151  {
1152  const OUString sOldName(msName);
1153  msName = rsName;
1154  FireAccessibleEvent(AccessibleEventId::NAME_CHANGED, Any(sOldName), Any(msName));
1155  }
1156 }
1157 
1159  const sal_Int16 nEventId,
1160  const uno::Any& rOldValue,
1161  const uno::Any& rNewValue )
1162 {
1163  AccessibleEventObject aEventObject;
1164 
1165  aEventObject.Source = Reference<XWeak>(this);
1166  aEventObject.EventId = nEventId;
1167  aEventObject.NewValue = rNewValue;
1168  aEventObject.OldValue = rOldValue;
1169 
1170  ::std::vector<Reference<XAccessibleEventListener> > aListenerCopy(maListeners);
1171  for (const auto& rxListener : aListenerCopy)
1172  {
1173  try
1174  {
1175  rxListener->notifyEvent(aEventObject);
1176  }
1177  catch (const lang::DisposedException&)
1178  {
1179  // Listener has been disposed and should have been removed
1180  // already.
1181  removeAccessibleEventListener(rxListener);
1182  }
1183  catch (const Exception&)
1184  {
1185  // Ignore all other exceptions and assume that they are
1186  // caused by a temporary problem.
1187  }
1188  }
1189 }
1190 
1192 {
1193  awt::Point aLocation;
1194  if (mxContentWindow.is())
1195  {
1196  const awt::Rectangle aContentBox (mxContentWindow->getPosSize());
1197  aLocation.X = aContentBox.X;
1198  aLocation.Y = aContentBox.Y;
1199  if (mxBorderWindow.is())
1200  {
1201  const awt::Rectangle aBorderBox (mxBorderWindow->getPosSize());
1202  aLocation.X += aBorderBox.X;
1203  aLocation.Y += aBorderBox.Y;
1204  }
1205  }
1206  return aLocation;
1207 }
1208 
1210 {
1211  if (mxContentWindow.is())
1212  {
1213  const awt::Rectangle aBox (mxContentWindow->getPosSize());
1214  return awt::Size(aBox.Width, aBox.Height);
1215  }
1216  else
1217  return awt::Size();
1218 }
1219 
1221 {
1222  Reference<XAccessibleComponent> xParentComponent;
1223  if (mxParentAccessible.is())
1224  xParentComponent.set( mxParentAccessible->getAccessibleContext(), UNO_QUERY);
1225  if (xParentComponent.is())
1226  return xParentComponent->getLocationOnScreen();
1227  else
1228  return awt::Point();
1229 }
1230 
1232 {
1233  if (rBHelper.bDisposed || rBHelper.bInDispose)
1234  throw lang::DisposedException("object has already been disposed", uno::Reference<uno::XInterface>(const_cast<uno::XWeak*>(static_cast<uno::XWeak const *>(this))));
1235 }
1236 
1237 //===== AccessibleStateSet ====================================================
1238 
1239 AccessibleStateSet::AccessibleStateSet (const sal_Int32 nStateSet)
1240  : AccessibleStateSetInterfaceBase(m_aMutex),
1241  mnStateSet (nStateSet)
1242 {
1243 }
1244 
1245 sal_uInt32 AccessibleStateSet::GetStateMask (const sal_Int16 nState)
1246 {
1247  if (nState<0 || nState>=sal_Int16(sizeof(sal_uInt32)*8))
1248  {
1249  throw RuntimeException("AccessibleStateSet::GetStateMask: invalid state");
1250  }
1251 
1252  return 1<<nState;
1253 }
1254 
1255 //----- XAccessibleStateSet ---------------------------------------------------
1256 
1257 sal_Bool SAL_CALL AccessibleStateSet::isEmpty()
1258 {
1259  return mnStateSet==0;
1260 }
1261 
1262 sal_Bool SAL_CALL AccessibleStateSet::contains (sal_Int16 nState)
1263 {
1264  return (mnStateSet & GetStateMask(nState)) != 0;
1265 }
1266 
1267 sal_Bool SAL_CALL AccessibleStateSet::containsAll (const css::uno::Sequence<sal_Int16>& rStateSet)
1268 {
1269  return std::none_of(rStateSet.begin(), rStateSet.end(),
1270  [this](const sal_Int16 nState) { return (mnStateSet & GetStateMask(nState)) == 0; });
1271 }
1272 
1273 css::uno::Sequence<sal_Int16> SAL_CALL AccessibleStateSet::getStates()
1274 {
1275  ::std::vector<sal_Int16> aStates;
1276  aStates.reserve(sizeof(mnStateSet)*8);
1277  for (sal_uInt16 nIndex=0; nIndex<sizeof(mnStateSet)*8; ++nIndex)
1278  if ((mnStateSet & GetStateMask(nIndex)) != 0)
1279  aStates.push_back(nIndex);
1280  return Sequence<sal_Int16>(aStates.data(), aStates.size());
1281 }
1282 
1283 //===== AccessibleRelationSet =================================================
1284 
1285 AccessibleRelationSet::AccessibleRelationSet()
1286  : AccessibleRelationSetInterfaceBase(m_aMutex),
1287  maRelations()
1288 {
1289 }
1290 
1291 void AccessibleRelationSet::AddRelation (
1292  const sal_Int16 nRelationType,
1293  const Reference<XInterface>& rxObject)
1294 {
1295  maRelations.emplace_back();
1296  maRelations.back().RelationType = nRelationType;
1297  maRelations.back().TargetSet.realloc(1);
1298  maRelations.back().TargetSet[0] = rxObject;
1299 }
1300 
1301 //----- XAccessibleRelationSet ------------------------------------------------
1302 
1303 sal_Int32 SAL_CALL AccessibleRelationSet::getRelationCount()
1304 {
1305  return maRelations.size();
1306 }
1307 
1308 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelation (sal_Int32 nIndex)
1309 {
1310  if (nIndex<0 && o3tl::make_unsigned(nIndex)>=maRelations.size())
1311  return AccessibleRelation();
1312  else
1313  return maRelations[nIndex];
1314 }
1315 
1316 sal_Bool SAL_CALL AccessibleRelationSet::containsRelation (sal_Int16 nRelationType)
1317 {
1318  return std::any_of(maRelations.begin(), maRelations.end(),
1319  [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1320 }
1321 
1322 AccessibleRelation SAL_CALL AccessibleRelationSet::getRelationByType (sal_Int16 nRelationType)
1323 {
1324  auto iRelation = std::find_if(maRelations.begin(), maRelations.end(),
1325  [nRelationType](const AccessibleRelation& rRelation) { return rRelation.RelationType == nRelationType; });
1326  if (iRelation != maRelations.end())
1327  return *iRelation;
1328  return AccessibleRelation();
1329 }
1330 
1331 //===== PresenterAccessible::AccessibleParagraph ==============================
1332 
1334  const lang::Locale& rLocale,
1335  const OUString& rsName,
1336  const SharedPresenterTextParagraph& rpParagraph,
1337  const sal_Int32 nParagraphIndex)
1338  : PresenterAccessibleParagraphInterfaceBase(rLocale, AccessibleRole::PARAGRAPH, rsName),
1339  mpParagraph(rpParagraph),
1340  mnParagraphIndex(nParagraphIndex)
1341 {
1342 }
1343 
1344 //----- XAccessibleContext ----------------------------------------------------
1345 
1346 Reference<XAccessibleRelationSet> SAL_CALL
1348 {
1349  ThrowIfDisposed();
1350 
1351  rtl::Reference<AccessibleRelationSet> pSet (new AccessibleRelationSet);
1352 
1353  if (mxParentAccessible.is())
1354  {
1355  Reference<XAccessibleContext> xParentContext (mxParentAccessible->getAccessibleContext());
1356  if (xParentContext.is())
1357  {
1358  if (mnParagraphIndex>0)
1359  pSet->AddRelation(
1360  AccessibleRelationType::CONTENT_FLOWS_FROM,
1361  xParentContext->getAccessibleChild(mnParagraphIndex-1));
1362 
1363  if (mnParagraphIndex<xParentContext->getAccessibleChildCount()-1)
1364  pSet->AddRelation(
1365  AccessibleRelationType::CONTENT_FLOWS_TO,
1366  xParentContext->getAccessibleChild(mnParagraphIndex+1));
1367  }
1368  }
1369 
1370  return Reference<XAccessibleRelationSet>(pSet.get());
1371 }
1372 
1373 //----- XAccessibleText -------------------------------------------------------
1374 
1376 {
1377  ThrowIfDisposed();
1378 
1379  sal_Int32 nPosition (-1);
1380  if (mpParagraph)
1381  nPosition = mpParagraph->GetCaretPosition();
1382 
1383  return nPosition;
1384 }
1385 
1387 {
1388  ThrowIfDisposed();
1389 
1390  if (mpParagraph)
1391  {
1392  mpParagraph->SetCaretPosition(nIndex);
1393  return true;
1394  }
1395  else
1396  return false;
1397 }
1398 
1400 {
1401  ThrowIfDisposed();
1402 
1403  if (!mpParagraph)
1404  throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1405  return mpParagraph->GetCharacter(nIndex);
1406 }
1407 
1408 Sequence<css::beans::PropertyValue> SAL_CALL
1410  ::sal_Int32 nIndex,
1411  const css::uno::Sequence<OUString>& rRequestedAttributes)
1412 {
1413  ThrowIfDisposed();
1414 
1415 #if OSL_DEBUG_LEVEL > 0
1416  SAL_INFO( "sdext.presenter", __func__ << " at " << this << ", " << nIndex << " returns empty set" );
1417  for (sal_Int32 nAttributeIndex(0), nAttributeCount(rRequestedAttributes.getLength());
1418  nAttributeIndex < nAttributeCount;
1419  ++nAttributeIndex)
1420  {
1421  SAL_INFO( "sdext.presenter",
1422  " requested attribute " << nAttributeIndex << " is " << rRequestedAttributes[nAttributeIndex] );
1423  }
1424 #else
1425  (void)nIndex;
1426  (void)rRequestedAttributes;
1427 #endif
1428 
1429  // Character properties are not supported.
1430  return Sequence<css::beans::PropertyValue>();
1431 }
1432 
1434  sal_Int32 nIndex)
1435 {
1436  ThrowIfDisposed();
1437 
1438  awt::Rectangle aCharacterBox;
1439  if (nIndex < 0)
1440  {
1441  throw lang::IndexOutOfBoundsException("invalid text index", static_cast<uno::XWeak*>(this));
1442  }
1443  else if (mpParagraph)
1444  {
1445  aCharacterBox = mpParagraph->GetCharacterBounds(nIndex, false);
1446  // Convert coordinates relative to the window origin into absolute
1447  // screen coordinates.
1448  const awt::Point aWindowLocationOnScreen (getLocationOnScreen());
1449  aCharacterBox.X += aWindowLocationOnScreen.X;
1450  aCharacterBox.Y += aWindowLocationOnScreen.Y;
1451  }
1452  else
1453  {
1454  throw lang::IndexOutOfBoundsException("no text support in current mode", static_cast<uno::XWeak*>(this));
1455  }
1456 
1457  return aCharacterBox;
1458 }
1459 
1461 {
1462  ThrowIfDisposed();
1463 
1464  sal_Int32 nCount (0);
1465  if (mpParagraph)
1466  nCount = mpParagraph->GetCharacterCount();
1467 
1468  return nCount;
1469 }
1470 
1472  const css::awt::Point& )
1473 {
1474  ThrowIfDisposed();
1475  return -1;
1476 }
1477 
1479 {
1480  ThrowIfDisposed();
1481 
1482  return getTextRange(getSelectionStart(), getSelectionEnd());
1483 }
1484 
1486 {
1487  ThrowIfDisposed();
1488 
1489  return getCaretPosition();
1490 }
1491 
1493 {
1494  ThrowIfDisposed();
1495 
1496  return getCaretPosition();
1497 }
1498 
1500  sal_Int32 nStartIndex,
1501  sal_Int32)
1502 {
1503  ThrowIfDisposed();
1504 
1505  return setCaretPosition(nStartIndex);
1506 }
1507 
1509 {
1510  ThrowIfDisposed();
1511 
1512  OUString sText;
1513  if (mpParagraph)
1514  sText = mpParagraph->GetText();
1515 
1516  return sText;
1517 }
1518 
1520  sal_Int32 nLocalStartIndex,
1521  sal_Int32 nLocalEndIndex)
1522 {
1523  ThrowIfDisposed();
1524 
1525  OUString sText;
1526  if (mpParagraph)
1527  {
1528  const TextSegment aSegment (
1529  mpParagraph->CreateTextSegment(nLocalStartIndex, nLocalEndIndex));
1530  sText = aSegment.SegmentText;
1531  }
1532 
1533  return sText;
1534 }
1535 
1537  sal_Int32 nLocalCharacterIndex,
1538  sal_Int16 nTextType)
1539 {
1540  ThrowIfDisposed();
1541 
1542  TextSegment aSegment;
1543  if (mpParagraph)
1544  aSegment = mpParagraph->GetTextSegment(0, nLocalCharacterIndex, nTextType);
1545 
1546  return aSegment;
1547 }
1548 
1550  sal_Int32 nLocalCharacterIndex,
1551  sal_Int16 nTextType)
1552 {
1553  ThrowIfDisposed();
1554 
1555  TextSegment aSegment;
1556  if (mpParagraph)
1557  aSegment = mpParagraph->GetTextSegment(-1, nLocalCharacterIndex, nTextType);
1558 
1559  return aSegment;
1560 }
1561 
1563  sal_Int32 nLocalCharacterIndex,
1564  sal_Int16 nTextType)
1565 {
1566  ThrowIfDisposed();
1567 
1568  TextSegment aSegment;
1569  if (mpParagraph)
1570  aSegment = mpParagraph->GetTextSegment(+1, nLocalCharacterIndex, nTextType);
1571 
1572  return aSegment;
1573 }
1574 
1576  sal_Int32,
1577  sal_Int32)
1578 {
1579  ThrowIfDisposed();
1580 
1581  // Return false because copying to clipboard is not supported.
1582  // It IS supported in the notes view. There is no need to duplicate
1583  // this here.
1584  return false;
1585 }
1586 
1588  sal_Int32,
1589  sal_Int32,
1590  AccessibleScrollType)
1591 {
1592  return false;
1593 }
1594 
1595 //----- protected -------------------------------------------------------------
1596 
1598 {
1599  awt::Point aLocation (AccessibleObject::GetRelativeLocation());
1600  if (mpParagraph)
1601  {
1602  const awt::Point aParagraphLocation (mpParagraph->GetRelativeLocation());
1603  aLocation.X += aParagraphLocation.X;
1604  aLocation.Y += aParagraphLocation.Y;
1605  }
1606 
1607  return aLocation;
1608 }
1609 
1611 {
1612  if (mpParagraph)
1613  return mpParagraph->GetSize();
1614  else
1615  return AccessibleObject::GetSize();
1616 }
1617 
1619 {
1620  if (mxParentAccessible.is())
1621  {
1622  Reference<XAccessibleContext> xParentContext =
1623  mxParentAccessible->getAccessibleContext();
1624  if (xParentContext.is())
1625  {
1626  Reference<XAccessibleComponent> xGrandParentComponent(
1627  xParentContext->getAccessibleParent(), UNO_QUERY);
1628  if (xGrandParentComponent.is())
1629  return xGrandParentComponent->getLocationOnScreen();
1630  }
1631  }
1632 
1633  return awt::Point();
1634 }
1635 
1637 {
1638  switch (nType)
1639  {
1640  case AccessibleStateType::EDITABLE:
1641  return bool(mpParagraph);
1642 
1643  case AccessibleStateType::ACTIVE:
1644  return true;
1645 
1646  default:
1647  return AccessibleObject::GetWindowState(nType);
1648  }
1649 }
1650 
1651 //===== AccessibleNotes =======================================================
1652 
1653 AccessibleNotes::AccessibleNotes (
1654  const css::lang::Locale& rLocale,
1655  const OUString& rsName)
1656  : AccessibleObject(rLocale,AccessibleRole::PANEL,rsName),
1657  mpTextView()
1658 {
1659 }
1660 
1662  const css::uno::Reference<css::uno::XComponentContext>& rxContext,
1663  const lang::Locale& rLocale,
1664  const Reference<awt::XWindow>& rxContentWindow,
1665  const Reference<awt::XWindow>& rxBorderWindow,
1666  const std::shared_ptr<PresenterTextView>& rpTextView)
1667 {
1668  OUString sName ("Presenter Notes Text");
1669  {
1670  PresenterConfigurationAccess aConfiguration (
1671  rxContext,
1672  "/org.openoffice.Office.PresenterScreen/",
1674  aConfiguration.GetConfigurationNode("Presenter/Accessibility/Notes/String")
1675  >>= sName;
1676  }
1677 
1679  new AccessibleNotes(
1680  rLocale,
1681  sName));
1682  pObject->LateInitialization();
1683  pObject->SetTextView(rpTextView);
1684  pObject->UpdateStateSet();
1685  pObject->SetWindow(rxContentWindow, rxBorderWindow);
1686 
1688 }
1689 
1690 void AccessibleNotes::SetTextView (
1691  const std::shared_ptr<PresenterTextView>& rpTextView)
1692 {
1693  ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> > aChildren;
1694 
1695  // Release any listeners to the current text view.
1696  if (mpTextView)
1697  {
1698  mpTextView->GetCaret()->SetCaretMotionBroadcaster(
1699  ::std::function<void (sal_Int32,sal_Int32,sal_Int32,sal_Int32)>());
1700  mpTextView->SetTextChangeBroadcaster(
1701  ::std::function<void ()>());
1702  }
1703 
1704  mpTextView = rpTextView;
1705 
1706  if (!mpTextView)
1707  return;
1708 
1709  // Create a new set of children, one for each paragraph.
1710  const sal_Int32 nParagraphCount (mpTextView->GetParagraphCount());
1711  for (sal_Int32 nIndex=0; nIndex<nParagraphCount; ++nIndex)
1712  {
1714  new PresenterAccessible::AccessibleParagraph(
1715  css::lang::Locale(),
1716  "Paragraph"+OUString::number(nIndex),
1717  rpTextView->GetParagraph(nIndex),
1718  nIndex));
1719  pParagraph->LateInitialization();
1720  pParagraph->SetWindow(mxContentWindow, mxBorderWindow);
1721  pParagraph->SetAccessibleParent(this);
1722  aChildren.emplace_back(pParagraph.get());
1723  }
1724  maChildren.swap(aChildren);
1725  FireAccessibleEvent(AccessibleEventId::INVALIDATE_ALL_CHILDREN, Any(), Any());
1726 
1727  // Dispose the old children. (This will remove them from the focus
1728  // manager).
1729  for (const auto& rxChild : aChildren)
1730  {
1731  Reference<lang::XComponent> xComponent (static_cast<XWeak*>(rxChild.get()), UNO_QUERY);
1732  if (xComponent.is())
1733  xComponent->dispose();
1734  }
1735 
1736  // This class acts as a controller of who broadcasts caret motion
1737  // events and handles text changes. Register the corresponding
1738  // listeners here.
1739  mpTextView->GetCaret()->SetCaretMotionBroadcaster(
1740  [this](sal_Int32 a, sal_Int32 b, sal_Int32 c, sal_Int32 d)
1741  { return this->NotifyCaretChange(a, b, c, d); });
1742  mpTextView->SetTextChangeBroadcaster(
1743  [this]() { return SetTextView(mpTextView); });
1744 }
1745 
1746 void AccessibleNotes::SetWindow (
1747  const css::uno::Reference<css::awt::XWindow>& rxContentWindow,
1748  const css::uno::Reference<css::awt::XWindow>& rxBorderWindow)
1749 {
1750  AccessibleObject::SetWindow(rxContentWindow, rxBorderWindow);
1751 
1752  // Set the windows at the children as well, so that every paragraph can
1753  // setup its geometry.
1754  for (auto& rxChild : maChildren)
1755  {
1756  rxChild->SetWindow(rxContentWindow, rxBorderWindow);
1757  }
1758 }
1759 
1760 void AccessibleNotes::NotifyCaretChange (
1761  const sal_Int32 nOldParagraphIndex,
1762  const sal_Int32 nOldCharacterIndex,
1763  const sal_Int32 nNewParagraphIndex,
1764  const sal_Int32 nNewCharacterIndex)
1765 {
1766  AccessibleFocusManager::Instance()->FocusObject(
1767  nNewParagraphIndex >= 0
1768  ? maChildren[nNewParagraphIndex]
1769  : this);
1770 
1771  if (nOldParagraphIndex != nNewParagraphIndex)
1772  {
1773  // Moved caret from one paragraph to another (or showed or
1774  // hid the caret). Move focus from one accessible
1775  // paragraph to another.
1776  if (nOldParagraphIndex >= 0)
1777  {
1778  maChildren[nOldParagraphIndex]->FireAccessibleEvent(
1779  AccessibleEventId::CARET_CHANGED,
1780  Any(nOldCharacterIndex),
1781  Any(sal_Int32(-1)));
1782  }
1783  if (nNewParagraphIndex >= 0)
1784  {
1785  maChildren[nNewParagraphIndex]->FireAccessibleEvent(
1786  AccessibleEventId::CARET_CHANGED,
1787  Any(sal_Int32(-1)),
1788  Any(nNewCharacterIndex));
1789  }
1790  }
1791  else if (nNewParagraphIndex >= 0)
1792  {
1793  // Caret moved inside one paragraph.
1794  maChildren[nNewParagraphIndex]->FireAccessibleEvent(
1795  AccessibleEventId::CARET_CHANGED,
1796  Any(nOldCharacterIndex),
1797  Any(nNewCharacterIndex));
1798  }
1799 }
1800 
1801 
1802 //===== AccessibleFocusManager ================================================
1803 
1804 std::shared_ptr<AccessibleFocusManager> AccessibleFocusManager::mpInstance;
1805 
1806 std::shared_ptr<AccessibleFocusManager> const & AccessibleFocusManager::Instance()
1807 {
1808  if ( ! mpInstance)
1809  {
1810  mpInstance.reset(new AccessibleFocusManager());
1811  }
1812  return mpInstance;
1813 }
1814 
1815 AccessibleFocusManager::AccessibleFocusManager()
1816 {
1817 }
1818 
1819 AccessibleFocusManager::~AccessibleFocusManager()
1820 {
1821  // copy member to stack, then drop it - otherwise will get use-after-free
1822  // from AccessibleObject::disposing(), it will call ~Reference *twice*
1823  auto const temp(std::move(maFocusableObjects));
1824  (void) temp;
1825  m_isInDtor = true;
1826 }
1827 
1828 void AccessibleFocusManager::AddFocusableObject (
1829  const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1830 {
1831  OSL_ASSERT(rpObject.is());
1832  OSL_ASSERT(::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject)==maFocusableObjects.end());
1833 
1834  maFocusableObjects.push_back(rpObject);
1835 }
1836 
1837 void AccessibleFocusManager::RemoveFocusableObject (
1838  const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1839 {
1840  ::std::vector<rtl::Reference<PresenterAccessible::AccessibleObject> >::iterator iObject (
1841  ::std::find(maFocusableObjects.begin(),maFocusableObjects.end(), rpObject));
1842 
1843  if (iObject != maFocusableObjects.end())
1844  maFocusableObjects.erase(iObject);
1845  else
1846  {
1847  OSL_ASSERT(m_isInDtor); // in dtor, was removed already
1848  }
1849 }
1850 
1851 void AccessibleFocusManager::FocusObject (
1852  const ::rtl::Reference<PresenterAccessible::AccessibleObject>& rpObject)
1853 {
1854  // Remove the focus of any of the other focusable objects.
1855  for (auto& rxObject : maFocusableObjects)
1856  {
1857  if (rxObject!=rpObject)
1858  rxObject->SetIsFocused(false);
1859  }
1860 
1861  if (rpObject.is())
1862  rpObject->SetIsFocused(true);
1863 }
1864 
1865 } // end of namespace ::sd::presenter
1866 
1867 /* 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
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)
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
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