/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include #include #include #include #include #include #include "uiobject_uno.hxx" #include #include #include #include #include #include #include #include class Timer; namespace { struct Notifier { std::condition_variable cv; std::mutex mMutex; bool mReady = false; DECL_LINK( NotifyHdl, Timer*, void ); }; } UIObjectUnoObj::UIObjectUnoObj(std::unique_ptr pObj): UIObjectBase(m_aMutex), mpObj(std::move(pObj)) { } UIObjectUnoObj::~UIObjectUnoObj() { SolarMutexGuard aGuard; mpObj.reset(); } css::uno::Reference SAL_CALL UIObjectUnoObj::getChild(const OUString& rID) { if (!mpObj) throw css::uno::RuntimeException(); SolarMutexGuard aGuard; std::unique_ptr pObj = mpObj->get_child(rID); return new UIObjectUnoObj(std::move(pObj)); } IMPL_LINK_NOARG(Notifier, NotifyHdl, Timer*, void) { std::scoped_lock lk(mMutex); mReady = true; cv.notify_all(); } namespace { class ExecuteWrapper { std::function mFunc; Link mHandler; std::atomic mbSignal; public: ExecuteWrapper(std::function func, Link handler): mFunc(std::move(func)), mHandler(handler), mbSignal(false) { } void setSignal() { mbSignal = true; } DECL_LINK( ExecuteActionHdl, Timer*, void ); }; IMPL_LINK_NOARG(ExecuteWrapper, ExecuteActionHdl, Timer*, void) { { Idle aIdle("UI Test Idle Handler2"); { mFunc(); aIdle.SetPriority(TaskPriority::LOWEST); aIdle.SetInvokeHandler(mHandler); aIdle.Start(); } while (!mbSignal) { Application::Reschedule(); } } delete this; } } void SAL_CALL UIObjectUnoObj::executeAction(const OUString& rAction, const css::uno::Sequence& rPropValues) { if (!mpObj) throw css::uno::RuntimeException(); auto aIdle = std::make_unique("UI Test Idle Handler"); aIdle->SetPriority(TaskPriority::HIGHEST); std::function func = [&rAction, &rPropValues, this](){ SolarMutexGuard aGuard; StringMap aMap; for (const auto& rPropVal : rPropValues) { OUString aVal; if (!(rPropVal.Value >>= aVal)) continue; aMap[rPropVal.Name] = aVal; } mpObj->execute(rAction, aMap); }; Notifier notifier; ExecuteWrapper* pWrapper = new ExecuteWrapper(std::move(func), LINK(¬ifier, Notifier, NotifyHdl)); aIdle->SetInvokeHandler(LINK(pWrapper, ExecuteWrapper, ExecuteActionHdl)); { SolarMutexGuard aGuard; aIdle->Start(); } { std::unique_lock lk(notifier.mMutex); notifier.cv.wait(lk, [¬ifier]{return notifier.mReady;}); } pWrapper->setSignal(); SolarMutexGuard aGuard; aIdle.reset(); } css::uno::Sequence UIObjectUnoObj::getState() { if (!mpObj) throw css::uno::RuntimeException(); SolarMutexGuard aGuard; StringMap aMap = mpObj->get_state(); css::uno::Sequence aProps(aMap.size()); std::transform(aMap.begin(), aMap.end(), aProps.getArray(), [](auto const& elem) { return comphelper::makePropertyValue(elem.first, elem.second); }); return aProps; } css::uno::Sequence UIObjectUnoObj::getChildren() { if (!mpObj) throw css::uno::RuntimeException(); std::set aChildren; { SolarMutexGuard aGuard; aChildren = mpObj->get_children(); } css::uno::Sequence aRet(aChildren.size()); std::copy(aChildren.begin(), aChildren.end(), aRet.getArray()); return aRet; } OUString SAL_CALL UIObjectUnoObj::getType() { if (!mpObj) throw css::uno::RuntimeException(); SolarMutexGuard aGuard; return mpObj->get_type(); } OUString SAL_CALL UIObjectUnoObj::getImplementationName() { return "org.libreoffice.uitest.UIObject"; } sal_Bool UIObjectUnoObj::supportsService(OUString const & ServiceName) { return cppu::supportsService(this, ServiceName); } css::uno::Sequence UIObjectUnoObj::getSupportedServiceNames() { return { "com.sun.star.ui.test.UIObject" }; } OUString SAL_CALL UIObjectUnoObj::getHierarchy() { if (!mpObj) throw css::uno::RuntimeException(); SolarMutexGuard aGuard; return mpObj->dumpHierarchy(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */