/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ /* * 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/.
*/
/** Collects contents of @p xContext in a dummy markup form */
OUString
collectText(const css::uno::Reference<css::accessibility::XAccessibleContext>& xContext);
/** Collects contents of the current document */
OUString collectText() { return collectText(getDocumentAccessibleContext()); }
void documentPostKeyEvent(int nType, int nCharCode, int nKeyCode)
{
vcl::ITiledRenderable* pTiledRenderable
= dynamic_cast<vcl::ITiledRenderable*>(mxDocument.get());
CPPUNIT_ASSERT(pTiledRenderable);
pTiledRenderable->postKeyEvent(nType, nCharCode, nKeyCode);
}
/** * @brief Tries to list all children of an accessible * @param xContext An XAccessibleContext object * @returns The list of all children (but no more than @c AccessibilityTools::MAX_CHILDREN) * * This fetches children of @p xContext. This would ideally just be the same than iterating * over children the regular way up to @c AccessibilityTools::MAX_CHILDREN, but unfortunately * some components (Writer, Impress, ...) do not provide all their children the regular way and * require specifics to include them. * * There is no guarantee on *which* children are returned if there are more than * @c AccessibilityTools::MAX_CHILDREN -- yet they will always be the same in a given context.
*/ virtual std::deque<css::uno::Reference<css::accessibility::XAccessibleContext>>
getAllChildren(const css::uno::Reference<css::accessibility::XAccessibleContext>& xContext);
css::uno::Reference<css::accessibility::XAccessibleContext>
getItemFromName(const css::uno::Reference<css::accessibility::XAccessibleContext>& xMenuCtx,
std::u16string_view name); bool
activateMenuItem(const css::uno::Reference<css::accessibility::XAccessibleAction>& xAction); /* just convenience not to have to query accessibility::XAccessibleAction manually */ bool activateMenuItem(const css::uno::Reference<css::accessibility::XAccessibleContext>& xCtx)
{ return activateMenuItem(css::uno::Reference<css::accessibility::XAccessibleAction>(
xCtx, css::uno::UNO_QUERY_THROW));
}
/* convenience to get a menu item from a list of menu item names. Unlike * getItemFromName(context, name), this requires subsequently found items to implement * XAccessibleAction, as each but the last item will be activated before looking for * the next one, to account for the fact menus might not be fully populated before being
* activated. */ template <typename... Ts>
css::uno::Reference<css::accessibility::XAccessibleContext>
getItemFromName(const css::uno::Reference<css::accessibility::XAccessibleContext>& xMenuCtx,
std::u16string_view name, Ts... names)
{ auto item = getItemFromName(xMenuCtx, name);
CPPUNIT_ASSERT(item.is());
activateMenuItem(item); return getItemFromName(item, names...);
}
/* convenience to activate an item by its name and all its parent menus up to xMenuCtx.
* @see getItemFromName() */ template <typename... Ts> bool
activateMenuItem(const css::uno::Reference<css::accessibility::XAccessibleContext>& xMenuCtx,
Ts... names)
{ auto item = getItemFromName(xMenuCtx, names...);
CPPUNIT_ASSERT(item.is()); return activateMenuItem(item);
}
/* convenience to activate an item by its name and all its parent menus up to the main window
* menu bar */ template <typename... Ts> bool activateMenuItem(Ts... names)
{ auto menuBar = AccessibilityTools::getAccessibleObjectForRole(
getWindowAccessibleContext(), css::accessibility::AccessibleRole::MENU_BAR);
CPPUNIT_ASSERT(menuBar.is()); return activateMenuItem(menuBar, names...);
}
/** * @brief Gets the focused accessible object at @p xAcc level or below * @param xAcc An accessible object * @returns The accessible context of the focused object, or @c nullptr * * Finds the accessible object context at or under @p xAcc that has the focused state (and is * showing). Normally only one such object should exist in a given hierarchy, but in all cases * this function will return the first one found. * * @see AccessibilityTools::getAccessibleObjectForPredicate()
*/ static css::uno::Reference<css::accessibility::XAccessibleContext>
getFocusedObject(const css::uno::Reference<css::accessibility::XAccessibleContext>& xCtx);
/** * @brief Navigates through focusable elements using the Tab keyboard shortcut. * @param xRoot The root element to look for focused elements in. * @param role The accessible role of the element to tab to. * @param name The accessible name of the element to tab to. * @param pEventPosterHelper Pointer to a @c EventPosterHelper instance, or @c nullptr to obtain * it from @p xRoot. * @returns The element tabbed to, or @c nullptr if not found. * * Navigates through focusable elements in the top level containing @p xRoot using the Tab * keyboard key until the focused elements matches @p role and @p name. * * Note that usually @p xRoot should be the toplevel accessible, or at least contain all * focusable elements within that window. It is however *not* a requirement, but only elements * actually inside it will be candidate for a match, and thus if focus goes outside it, it might * lead to not finding the target element. * * If @p pEventPosterHelper is @c nullptr, this function will try to construct one from * @p xRoot. @see EventPosterHelper.
*/ static css::uno::Reference<css::accessibility::XAccessibleContext>
tabTo(const css::uno::Reference<css::accessibility::XAccessible>& xRoot, const sal_Int16 role, const std::u16string_view name, const EventPosterHelperBase* pEventPosterHelper = nullptr);
class DialogWaiter
{ public: virtual ~DialogWaiter() {}
/** * @brief Waits for the associated dialog to close * @param nTimeoutMs Maximum delay to wait the dialog for * @returns @c true if the dialog closed, @c false if timeout was reached * * @throws css::uno::RuntimeException if an unexpected dialog popped up instead of the * expected one. * @throws Any exception that the user callback supplied to awaitDialog() might have thrown.
*/ virtualbool waitEndDialog(sal_uInt64 nTimeoutMs = 3000) = 0;
};
/** * @brief Helper to call user code when a given dialog opens * @param name The title of the dialog window to wait for * @param callback The user code to run when the given dialog opens * @param bAutoClose Whether to automatically cancel the dialog after the user code finished, if * the dialog is still there. You should leave this to @c true unless you * know exactly what you are doing, see below. * @returns A @c DialogWaiter wrapper on which call waitEndDialog() after having triggered the * dialog in some way. * * This function makes it fairly easy and safe to execute code once a dialog pops up: * @code * auto waiter = awaitDialog(u"Special Characters", [this](Dialog &dialog) { * // for example, something like this: * // something(); * // CPPUNIT_ASSERT(dialog.tabTo(...)); * // CPPUNIT_ASSERT(somethingElse); * // dialog.postKeyEventAsync(0, awt::Key::RETURN); * }); * CPPUNIT_ASSERT(activateMenuItem(u"Some menu", u"Some Item Triggering a Dialog...")); * CPPUNIT_ASSERT(waiter->waitEndDialog()); * @endcode * * @note The user code might actually be executed before DialogWaiter::waitEndDialog() is * called. It is actually likely to be called at the time the call that triggers the * dialog happens. However, as letting an exception slip in a event handler is likely to * cause problems, exceptions are forwarded to the DialogWaiter::waitEndDialog() call. * However, note that you cannot rely on something like this: * @code * int foo = 0; * auto waiter = awaitDialog(u"Some Dialog", [&foo](Dialog&) { * CPPUNIT_ASSERT_EQUAL(1, foo); * }); * CPPUNIT_ASSERT(activateMenuItem(u"Some menu", u"Some Item Triggering a Dialog...")); * foo = 1; // here, the callback likely already ran as a result of the * // Scheduler::ProcessEventsToIdle() call that activateMenuItem() did. * CPPUNIT_ASSERT(waiter->waitEndDialog()); * @endcode * * @warning You should almost certainly always leave @p bAutoClose to @c true. If it is set to * @c false, you have to take extreme care: * - The dialog will not be canceled if the user code raises an exception. * - If the dialog is run through Dialog::Execute(), control won't return to the test * body until the dialog is closed. This means that the only ways to execute code * until then is a separate thread or via code dispatched by the main loop. * Thus, you have to make sure you DO close the dialog some way or another yourself * in order for the test code to terminate at some point. * - If the dialog doesn't use Dialog::Execute() but is rather similar to a second * separate window (e.g. non-modal), you might still have to close the dialog before * closing the test document is possible without a CloseVetoException -- which might * badly break the test run.
*/ static std::shared_ptr<DialogWaiter> awaitDialog(const std::u16string_view name,
std::function<void(Dialog&)> callback, bool bAutoClose = true); #endif//defined(MACOSX)
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.