LibreOffice Module vcl (master)  1
uiobject_uno.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 
10 #include <sal/config.h>
11 
12 #include <atomic>
13 #include <condition_variable>
14 #include <memory>
15 #include <mutex>
16 #include "uiobject_uno.hxx"
17 #include <utility>
19 #include <tools/link.hxx>
20 #include <vcl/svapp.hxx>
21 #include <vcl/idle.hxx>
22 #include <vcl/window.hxx>
23 
24 #include <set>
25 
26 class Timer;
27 
28 namespace {
29 
30 struct Notifier {
31  std::condition_variable cv;
32  std::mutex mMutex;
33  bool mReady = false;
34 
35  DECL_LINK( NotifyHdl, Timer*, void );
36 };
37 
38 }
39 
40 UIObjectUnoObj::UIObjectUnoObj(std::unique_ptr<UIObject> pObj):
42  mpObj(std::move(pObj))
43 {
44 }
45 
47 {
48  SolarMutexGuard aGuard;
49  mpObj.reset();
50 }
51 
52 css::uno::Reference<css::ui::test::XUIObject> SAL_CALL UIObjectUnoObj::getChild(const OUString& rID)
53 {
54  if (!mpObj)
55  throw css::uno::RuntimeException();
56 
57  SolarMutexGuard aGuard;
58  std::unique_ptr<UIObject> pObj = mpObj->get_child(rID);
59  return new UIObjectUnoObj(std::move(pObj));
60 }
61 
62 IMPL_LINK_NOARG(Notifier, NotifyHdl, Timer*, void)
63 {
64  std::scoped_lock<std::mutex> lk(mMutex);
65  mReady = true;
66  cv.notify_all();
67 }
68 
69 namespace {
70 
71 class ExecuteWrapper
72 {
73  std::function<void()> mFunc;
74  Link<Timer*, void> mHandler;
75  std::atomic<bool> mbSignal;
76 
77 public:
78 
79  ExecuteWrapper(std::function<void()> func, Link<Timer*, void> handler):
80  mFunc(std::move(func)),
81  mHandler(handler),
82  mbSignal(false)
83  {
84  }
85 
86  void setSignal()
87  {
88  mbSignal = true;
89  }
90 
91  DECL_LINK( ExecuteActionHdl, Timer*, void );
92 };
93 
94 
95 IMPL_LINK_NOARG(ExecuteWrapper, ExecuteActionHdl, Timer*, void)
96 {
97  {
98  Idle aIdle;
99  {
100  mFunc();
101  aIdle.SetDebugName("UI Test Idle Handler2");
103  aIdle.SetInvokeHandler(mHandler);
104  aIdle.Start();
105  }
106 
107  while (!mbSignal) {
109  }
110  }
111  delete this;
112 }
113 
114 }
115 
116 void SAL_CALL UIObjectUnoObj::executeAction(const OUString& rAction, const css::uno::Sequence<css::beans::PropertyValue>& rPropValues)
117 {
118  if (!mpObj)
119  throw css::uno::RuntimeException();
120 
121  auto aIdle = std::make_unique<Idle>();
122  aIdle->SetDebugName("UI Test Idle Handler");
124 
125  std::function<void()> func = [&rAction, &rPropValues, this](){
126 
127  SolarMutexGuard aGuard;
128  StringMap aMap;
129  for (const auto& rPropVal : rPropValues)
130  {
131  OUString aVal;
132  if (!(rPropVal.Value >>= aVal))
133  continue;
134 
135  aMap[rPropVal.Name] = aVal;
136  }
137  mpObj->execute(rAction, aMap);
138  };
139 
140  Notifier notifier;
141  ExecuteWrapper* pWrapper = new ExecuteWrapper(func, LINK(&notifier, Notifier, NotifyHdl));
142  aIdle->SetInvokeHandler(LINK(pWrapper, ExecuteWrapper, ExecuteActionHdl));
143  {
144  SolarMutexGuard aGuard;
145  aIdle->Start();
146  }
147 
148  {
149  std::unique_lock<std::mutex> lk(notifier.mMutex);
150  notifier.cv.wait(lk, [&notifier]{return notifier.mReady;});
151  }
152  pWrapper->setSignal();
153 
154  SolarMutexGuard aGuard;
155  aIdle.reset();
156 }
157 
158 css::uno::Sequence<css::beans::PropertyValue> UIObjectUnoObj::getState()
159 {
160  if (!mpObj)
161  throw css::uno::RuntimeException();
162 
163  SolarMutexGuard aGuard;
164  StringMap aMap = mpObj->get_state();
165  css::uno::Sequence<css::beans::PropertyValue> aProps(aMap.size());
166  sal_Int32 i = 0;
167  for (auto const& elem : aMap)
168  {
169  aProps[i].Name = elem.first;
170  aProps[i].Value <<= elem.second;
171  ++i;
172  }
173 
174  return aProps;
175 }
176 
177 css::uno::Sequence<OUString> UIObjectUnoObj::getChildren()
178 {
179  if (!mpObj)
180  throw css::uno::RuntimeException();
181 
182  std::set<OUString> aChildren;
183 
184  {
185  SolarMutexGuard aGuard;
186  aChildren = mpObj->get_children();
187  }
188 
189  css::uno::Sequence<OUString> aRet(aChildren.size());
190  sal_Int32 i = 0;
191  for (auto const& child : aChildren)
192  {
193  aRet[i] = child;
194  ++i;
195  }
196 
197  return aRet;
198 }
199 
200 OUString SAL_CALL UIObjectUnoObj::getType()
201 {
202  if (!mpObj)
203  throw css::uno::RuntimeException();
204 
205  SolarMutexGuard aGuard;
206  return mpObj->get_type();
207 }
208 
210 {
211  return "org.libreoffice.uitest.UIObject";
212 }
213 
214 sal_Bool UIObjectUnoObj::supportsService(OUString const & ServiceName)
215 {
216  return cppu::supportsService(this, ServiceName);
217 }
218 
219 css::uno::Sequence<OUString> UIObjectUnoObj::getSupportedServiceNames()
220 {
221  return { "com.sun.star.ui.test.UIObject" };
222 }
223 
224 OUString SAL_CALL UIObjectUnoObj::getHierarchy()
225 {
226  if (!mpObj)
227  throw css::uno::RuntimeException();
228 
229  SolarMutexGuard aGuard;
230  return mpObj->dumpHierarchy();
231 }
232 
233 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OUString SAL_CALL getHierarchy() override
css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
css::uno::Reference< css::ui::test::XUIObject > SAL_CALL getChild(const OUString &rID) override
sal_Bool SAL_CALL supportsService(OUString const &ServiceName) override
HashMap_OWString_Interface aMap
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
void SetDebugName(const char *pDebugName)
Definition: task.hxx:82
static bool Reschedule(bool bHandleAllCurrentEvents=false)
Attempt to process current pending event(s)
Definition: svapp.cxx:476
int i
unsigned char sal_Bool
UIObjectUnoObj(std::unique_ptr< UIObject > pObj)
OUString SAL_CALL getType() override
virtual ~UIObjectUnoObj() override
IMPL_LINK_NOARG(Notifier, NotifyHdl, Timer *, void)
void SAL_CALL executeAction(const OUString &rAction, const css::uno::Sequence< css::beans::PropertyValue > &xPropValues) override
std::map< OUString, OUString > StringMap
css::uno::Sequence< OUString > SAL_CALL getChildren() override
std::unique_ptr< UIObject > mpObj
void SetInvokeHandler(const Link< Timer *, void > &rLink)
Definition: timer.hxx:56
These events should run very fast!
virtual void Start(bool bStartTimer=true) override
Schedules the task for execution.
Definition: idle.cxx:34
css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getState() override
Definition: timer.hxx:26
void SetPriority(TaskPriority ePriority)
Definition: scheduler.cxx:597
osl::Mutex m_aMutex
Definition: dtranscomp.cxx:213
Low, very idle cleanup tasks.
OUString SAL_CALL getImplementationName() override
::cppu::WeakComponentImplHelper< css::ui::test::XUIObject, css::lang::XServiceInfo > UIObjectBase
An idle is a timer to be scheduled immediately.
Definition: idle.hxx:34