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