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