Text and editable text interfaces allows to get/set text selection, and perform copy, cut, paste on entry.
Change-Id: If64ed2d307c533addd762f939f284507167b335e
#define EXIT_IF_NULLPTR(obj) \
do { \
if (!obj) { \
- DEBUG("nullptr passed as critical argument"); \
+ ERROR("nullptr passed as critical argument"); \
return {}; \
} \
} while (0)
+#define RETURN_ON_NULLPTR(obj) \
+ do { \
+ if (!obj) { \
+ DEBUG("nullptr passed as critical argument"); \
+ return; \
+ } \
+ } while (0)
+
namespace
{
template<class ReturnType, class GetValueFunctionType, class InterfaceType>
return {valueInterface, g_object_unref};
}
+AtspiTextPtr Atspi::getTextInterface(const AtspiAccessiblePtr &accessibleObj) const
+{
+ EXIT_IF_NULLPTR(accessibleObj);
+ auto textInterface = atspi_accessible_get_text_iface(accessibleObj.get());
+ if (!textInterface)
+ DEBUG("Object %p do not has text interface", accessibleObj.get());
+ return {textInterface, g_object_unref};
+}
+
+AtspiEditableTextPtr Atspi::getEditableTextInterface(const AtspiAccessiblePtr &accessibleObj) const
+{
+ EXIT_IF_NULLPTR(accessibleObj);
+ auto editableTextInterface = atspi_accessible_get_editable_text_iface(accessibleObj.get());
+ if (!editableTextInterface)
+ DEBUG("Object %p do not has editable text interface", accessibleObj.get());
+ return {editableTextInterface, g_object_unref};
+}
+
+Optional<TextRange> Atspi::getTextSelection(const AtspiTextPtr &textInterface, int selectionNum) const
+{
+ EXIT_IF_NULLPTR(textInterface);
+ GError *error = nullptr;
+ auto range = std::unique_ptr<AtspiRange, void(*)(void *)>(atspi_text_get_selection(textInterface.get(), selectionNum, &error), g_free);
+ PRINT_ERROR_AND_FREE(error);
+ Optional<TextRange> ret;
+ if (range && range->start_offset >= 0 && range->end_offset >= 0)
+ ret = TextRange {static_cast<size_t>(range->start_offset), static_cast<size_t>(range->end_offset)};
+ return ret;
+}
+
+void Atspi::setTextSelection(const AtspiTextPtr &textInterface, TextRange range, int selectionNum) const
+{
+ RETURN_ON_NULLPTR(textInterface);
+ if (range.start > range.end) {
+ ERROR("Incorrect range - start: %d, end: %d", range.start, range.end);
+ return;
+ }
+ GError *error = nullptr;
+ if (!atspi_text_set_selection(textInterface.get(), selectionNum, range.start, range.end, &error))
+ ERROR("atspi_text_set_selection failed");
+ PRINT_ERROR_AND_FREE(error);
+}
+
+Optional<size_t> Atspi::getTextCaretOffset(const AtspiTextPtr &textInterface) const
+{
+ EXIT_IF_NULLPTR(textInterface);
+ GError *error = nullptr;
+ auto offset = atspi_text_get_caret_offset(textInterface.get(), &error);
+ Optional<size_t> ret;
+ if (!error && offset >= 0)
+ ret = static_cast<size_t>(offset);
+ PRINT_ERROR_AND_FREE(error);
+ return ret;
+}
+
+Optional<size_t> Atspi::countTextCharacters(const AtspiTextPtr &textInterface) const
+{
+ EXIT_IF_NULLPTR(textInterface);
+ GError *error = nullptr;
+ auto count = atspi_text_get_character_count(textInterface.get(), &error);
+ Optional<size_t> ret;
+ if (!error && count >= 0)
+ ret = static_cast<size_t>(count);
+ PRINT_ERROR_AND_FREE(error);
+ return ret;
+}
+
+void Atspi::copyEditableText(const AtspiEditableTextPtr &editableTextInterface, TextRange range) const
+{
+ RETURN_ON_NULLPTR(editableTextInterface);
+ if (range.start > range.end) {
+ ERROR("Incorrect range - start: %d, end: %d", range.start, range.end);
+ return;
+ }
+ GError *error = nullptr;
+ atspi_editable_text_copy_text(editableTextInterface.get(), range.start, range.end, &error);
+ PRINT_ERROR_AND_FREE(error);
+}
+
+void Atspi::cutEditableText(const AtspiEditableTextPtr &editableTextInterface, TextRange range) const
+{
+ RETURN_ON_NULLPTR(editableTextInterface);
+ if (range.start > range.end) {
+ ERROR("Incorrect range - start: %d, end: %d", range.start, range.end);
+ return;
+ }
+ GError *error = nullptr;
+ atspi_editable_text_cut_text(editableTextInterface.get(), range.start, range.end, &error);
+ PRINT_ERROR_AND_FREE(error);
+}
+
+void Atspi::pasteEditableText(const AtspiEditableTextPtr &editableTextInterface, size_t offset) const
+{
+ RETURN_ON_NULLPTR(editableTextInterface);
+ GError *error = nullptr;
+ atspi_editable_text_paste_text(editableTextInterface.get(), offset, &error);
+ PRINT_ERROR_AND_FREE(error);
+}
+
Optional<double> Atspi::getCurrentValue(const AtspiValuePtr &valueInterface) const
{
return getValueTemplateFunction<double>(atspi_value_get_current_value, valueInterface.get());
using AtspiCollectionPtr = std::shared_ptr<AtspiCollection>;
using AtspiComponentPtr = std::shared_ptr<AtspiComponent>;
using AtspiValuePtr = std::shared_ptr<AtspiValue>;
+using AtspiTextPtr = std::shared_ptr<AtspiText>;
using AtspiEditableTextPtr = std::shared_ptr<AtspiEditableText>;
+
+struct TextRange {
+ size_t start;
+ size_t end;
+};
+
template <typename ... T> using AsyncCallback = typename std::function<void(DBus::ValueOrError<T...>)>;
class Atspi
AtspiCollectionPtr getCollectionInterface(const AtspiAccessiblePtr &accessibleObj) const;
AtspiValuePtr getValueInterface(const AtspiAccessiblePtr &accessibleObj) const;
+ AtspiTextPtr getTextInterface(const AtspiAccessiblePtr &accessibleObj) const;
+ AtspiEditableTextPtr getEditableTextInterface(const AtspiAccessiblePtr &accessibleObj) const;
Optional<double> getCurrentValue(const AtspiValuePtr &valueInterface) const;
bool setCurrentValue(const AtspiValuePtr &valueInterface, double newValue) const;
Optional<double> getMinimumIncrement(const AtspiValuePtr &valueInterface) const;
Optional<std::string> getName(const AtspiAccessiblePtr &accessibleObj) const;
Optional<StateSet> getStateSet(const AtspiAccessiblePtr &accessibleObj) const;
+ Optional<TextRange> getTextSelection(const AtspiTextPtr &textInterface, int selectionNum = 0) const;
+ void setTextSelection(const AtspiTextPtr &textInterface, TextRange range, int selectionNum = 0) const;
+ Optional<size_t> getTextCaretOffset(const AtspiTextPtr &textInterface) const;
+ Optional<size_t> countTextCharacters(const AtspiTextPtr &textInterface) const;
+ void copyEditableText(const AtspiEditableTextPtr &editableTextInterface, TextRange) const;
+ void cutEditableText(const AtspiEditableTextPtr &editableTextInterface, TextRange) const;
+ void pasteEditableText(const AtspiEditableTextPtr &editableTextInterface, size_t offset) const;
+
AtspiAccessiblePtr getParent(const AtspiAccessiblePtr &accessibleObj) const;
Optional<size_t> getIndexInParent(const AtspiAccessiblePtr &accessibleObj) const;
AtspiSelectionPtr getSelectionInterface(const AtspiAccessiblePtr &accessibleObj) const;
#include "UIActivity.hpp"
#include "ActivityFactory.hpp"
#include "UniversalSwitchLog.hpp"
+#include "Atspi.hpp"
+#include "Singleton.hpp"
+#include "UniversalSwitch.hpp"
#include <memory>
protected:
bool getAtspiInterfaces()
{
- if (!uiElement || !uiElement->getObject()) {
+ if (!uiElement) {
ERROR("Process invoked with incorrect UIElement");
markAsCompleted();
return false;
}
- atspiText.reset(atspi_accessible_get_text_iface(uiElement->getObject().get()), g_object_unref);
- if (!atspiText) {
- ERROR("Get text iface failed");
+ atspi = Singleton<UniversalSwitch>::instance().getAtspi();
+ if (!atspi) {
markAsCompleted();
return false;
}
- atspiEditableText.reset(atspi_accessible_get_editable_text_iface(uiElement->getObject().get()), g_object_unref);
+ atspiText = atspi->getTextInterface(uiElement->getObject());
if (!atspiText) {
- ERROR("Get text iface failed");
markAsCompleted();
return false;
}
+
+ atspiEditableText = atspi->getEditableTextInterface(uiElement->getObject());
+ if (!atspiEditableText) {
+ markAsCompleted();
+ return false;
+ }
+
return true;
}
- std::shared_ptr<AtspiText> atspiText;
- std::shared_ptr<AtspiEditableText> atspiEditableText;
+ std::shared_ptr<Atspi> atspi;
+ AtspiTextPtr atspiText;
+ AtspiEditableTextPtr atspiEditableText;
};
if (!getAtspiInterfaces())
return;
- auto range = atspi_text_get_selection(atspiText.get(), 0, nullptr);
- if (!range)
- DEBUG("atspi_text_get_selection failed");
- else if (!atspi_editable_text_copy_text(atspiEditableText.get(), range->start_offset, range->end_offset, nullptr))
- DEBUG("atspi_editable_text_copy_text failed");
+ auto range = atspi->getTextSelection(atspiText);
+ if (range)
+ atspi->copyEditableText(atspiEditableText, *range);
markAsCompleted();
}
if (!getAtspiInterfaces())
return;
- auto range = atspi_text_get_selection(atspiText.get(), 0, nullptr);
- if (!range)
- DEBUG("atspi_text_get_selection failed");
- else if (!atspi_editable_text_cut_text(atspiEditableText.get(), range->start_offset, range->end_offset, nullptr))
- DEBUG("atspi_editable_text_cut_text failed");
+ auto range = atspi->getTextSelection(atspiText);
+ if (range)
+ atspi->cutEditableText(atspiEditableText, *range);
markAsCompleted();
}
if (!getAtspiInterfaces())
return;
- auto caretOffset = atspi_text_get_caret_offset(atspiText.get(), nullptr);
- if (!atspi_editable_text_paste_text(atspiEditableText.get(), caretOffset, nullptr))
- DEBUG("atspi_editable_text_paste_text failed");
+ auto caretOffset = atspi->getTextCaretOffset(atspiText);
+ if (caretOffset)
+ atspi->pasteEditableText(atspiEditableText, *caretOffset);
markAsCompleted();
}
return TELEPHONY_CALL_STATE_IDLE;
}
-bool SelectActivity::isRealUIElementSlider() //TODO: Use Atspi wrapper functions when available
+bool SelectActivity::isRealUIElementSlider()
{
- if (!realUiElementIsSlider)
- realUiElementIsSlider = realUiElement->getObject() &&
- atspi_accessible_get_role(realUiElement->getObject().get(), nullptr) == ATSPI_ROLE_SLIDER;
+ if (!realUiElementIsSlider) {
+ auto role = Singleton<UniversalSwitch>::instance().getAtspi()->getRole(realUiElement->getObject());
+ realUiElementIsSlider = role && *role == ATSPI_ROLE_SLIDER;
+ }
+
return *realUiElementIsSlider;
}
-bool SelectActivity::hasRealUIElementEditableTextIface() //TODO: Use Atspi wrapper functions when available
+bool SelectActivity::hasRealUIElementEditableTextIface()
{
if (!realUiElementHasEditableText) {
- auto editableTextIface = realUiElement->getObject() &&
- std::unique_ptr<AtspiEditableText, void(*)(gpointer)> (atspi_accessible_get_editable_text_iface(realUiElement->getObject().get()), g_object_unref);
+ auto editableTextIface = Singleton<UniversalSwitch>::instance().getAtspi()->getEditableTextInterface(realUiElement->getObject());
realUiElementHasEditableText = editableTextIface ? true : false;
}