Atspi wrapper extension 82/157882/8
authorPawel Kurowski <p.kurowski2@samsung.com>
Thu, 26 Oct 2017 15:32:09 +0000 (17:32 +0200)
committerPawel Kurowski <p.kurowski2@samsung.com>
Mon, 30 Oct 2017 11:35:30 +0000 (12:35 +0100)
Text and editable text interfaces allows to get/set text selection, and perform copy, cut, paste on entry.

Change-Id: If64ed2d307c533addd762f939f284507167b335e

src/Atspi.cpp
src/Atspi.hpp
src/ClipboardActivity.cpp
src/SelectActivity.cpp

index 1b15b4f..924189d 100644 (file)
@@ -18,11 +18,19 @@ using namespace DBus;
 #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>
@@ -932,6 +940,105 @@ AtspiValuePtr Atspi::getValueInterface(const AtspiAccessiblePtr &accessibleObj)
        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());
index 55ce0dc..9176245 100644 (file)
@@ -19,7 +19,14 @@ using AtspiSelectionPtr = std::shared_ptr<AtspiSelection>;
 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
@@ -46,6 +53,8 @@ public:
 
        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;
@@ -62,6 +71,14 @@ public:
        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;
index 37f7155..a1caa7c 100644 (file)
@@ -1,6 +1,9 @@
 #include "UIActivity.hpp"
 #include "ActivityFactory.hpp"
 #include "UniversalSwitchLog.hpp"
+#include "Atspi.hpp"
+#include "Singleton.hpp"
+#include "UniversalSwitch.hpp"
 
 #include <memory>
 
@@ -15,30 +18,36 @@ public:
 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;
 };
 
 
@@ -52,11 +61,9 @@ public:
                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();
        }
@@ -72,11 +79,9 @@ public:
                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();
        }
@@ -93,9 +98,9 @@ public:
                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();
        }
index 994be57..41b08c0 100644 (file)
@@ -362,19 +362,20 @@ Optional<telephony_call_state_e>  SelectActivity::getPhoneCallState()
        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;
        }