/* IAccessible */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; int control = accessible->childAt(xLeft, yTop); if (control == -1) { (*pvarID).vt = VT_EMPTY; return S_FALSE; } QAccessibleInterface *acc = 0; if (control) accessible->navigate(Child, control, &acc); if (!acc) { (*pvarID).vt = VT_I4; (*pvarID).lVal = control; return S_OK; } QWindowsAccessible* wacc = new QWindowsAccessible(acc); IDispatch *iface = 0; wacc->QueryInterface(IID_IDispatch, (void**)&iface); if (iface) { (*pvarID).vt = VT_DISPATCH; (*pvarID).pdispVal = iface; return S_OK; } else { delete wacc; } (*pvarID).vt = VT_EMPTY; return S_FALSE; }
HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription) { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (!accessible) return E_FAIL; QString descr; if (varID.lVal) { QAccessibleInterface *child = childPointer(accessible, varID); if (!child || !child->isValid()) return E_FAIL; descr = child->text(QAccessible::Description); } else { descr = accessible->text(QAccessible::Description); } if (descr.size()) { *pszDescription = QStringToBSTR(descr); return S_OK; } *pszDescription = 0; return S_FALSE; }
// moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIANT varID) { Q_UNUSED(flagsSelect); Q_UNUSED(varID); showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; bool res = false; /* ### Check for accessibleTableInterface() or accessibleTextInterface() ### and if there are no ia2 interfaces we should do nothing?? if (flagsSelect & SELFLAG_TAKEFOCUS) res = accessible->doAction(SetFocus, varID.lVal, QVariantList()); if (flagsSelect & SELFLAG_TAKESELECTION) { accessible->doAction(ClearSelection, 0, QVariantList()); res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); } if (flagsSelect & SELFLAG_EXTENDSELECTION) res = accessible->doAction(ExtendSelection, varID.lVal, QVariantList()); if (flagsSelect & SELFLAG_ADDSELECTION) res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); if (flagsSelect & SELFLAG_REMOVESELECTION) res = accessible->doAction(RemoveSelection, varID.lVal, QVariantList()); */ return res ? S_OK : S_FALSE; }
// moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accValue(VARIANT varID, BSTR* pszValue) { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (varID.vt != VT_I4) return E_INVALIDARG; if (!accessible || !accessible->isValid() || varID.lVal) { return E_FAIL; } QString value; if (accessible->valueInterface()) { value = QString::number(accessible->valueInterface()->currentValue().toDouble()); } else { value = accessible->text(QAccessible::Value); } if (!value.isNull()) { *pszValue = QStringToBSTR(value); return S_OK; } *pszValue = 0; accessibleDebug("return S_FALSE"); return S_FALSE; }
// moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; QAccessible::Role role; if (varID.lVal) { QAIPointer child = childPointer(varID); if (!child) return E_FAIL; role = child->role(); } else { role = accessible->role(); } if (role != QAccessible::NoRole) { if (role == QAccessible::LayeredPane) role = QAccessible::Pane; (*pvarRole).vt = VT_I4; (*pvarRole).lVal = role; } else { (*pvarRole).vt = VT_EMPTY; } return S_OK; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIANT varID) { #ifdef DEBUG_SHOW_ATCLIENT_COMMANDS showDebug(__FUNCTION__, accessible); #endif //DEBUG_SHOW_ATCLIENT_COMMANDS if (!accessible->isValid()) return E_FAIL; bool res = false; if (flagsSelect & SELFLAG_TAKEFOCUS) res = accessible->doAction(SetFocus, varID.lVal, QVariantList()); if (flagsSelect & SELFLAG_TAKESELECTION) { accessible->doAction(ClearSelection, 0, QVariantList()); res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); } if (flagsSelect & SELFLAG_EXTENDSELECTION) res = accessible->doAction(ExtendSelection, varID.lVal, QVariantList()); if (flagsSelect & SELFLAG_ADDSELECTION) res = accessible->doAction(AddToSelection, varID.lVal, QVariantList()); if (flagsSelect & SELFLAG_REMOVESELECTION) res = accessible->doAction(RemoveSelection, varID.lVal, QVariantList()); return res ? S_OK : S_FALSE; }
// moz: [important] HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::get_accRole(VARIANT varID, VARIANT *pvarRole) { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (!accessible) return E_FAIL; QAccessible::Role role; if (varID.lVal) { QAccessibleInterface *child = childPointer(accessible, varID); if (!child || !child->isValid()) return E_FAIL; role = child->role(); } else { role = accessible->role(); } if (role != QAccessible::NoRole) { if (role >= QAccessible::LayeredPane) { // This block should hopefully only be entered if the AT client // does not support IAccessible2, since it should prefer IA2::role() then. if (role == QAccessible::LayeredPane) role = QAccessible::Pane; else if (role == QAccessible::WebDocument) role = QAccessible::Document; else role = QAccessible::Client; } (*pvarRole).vt = VT_I4; (*pvarRole).lVal = role; } else { (*pvarRole).vt = VT_EMPTY; } return S_OK; }
/* IAccessible IAccessible::accHitTest documents the value returned in pvarID like this: | *Point location* | *vt member* | *Value member* | +========================================================+=============+=========================+ | Outside of the object's boundaries, and either inside | VT_EMPTY | None. | | or outside of the object's bounding rectangle. | | | +--------------------------------------------------------+-------------+-------------------------+ | Within the object but not within a child element or a | VT_I4 | lVal is CHILDID_SELF | | child object. | | | +--------------------------------------------------------+-------------+-------------------------+ | Within a child element. | VT_I4 | lVal contains | | | | the child ID. | +--------------------------------------------------------+-------------+-------------------------+ | Within a child object. | VT_DISPATCH | pdispVal is set to the | | | | child object's IDispatch| | | | interface pointer | +--------------------------------------------------------+-------------+-------------------------+ */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accHitTest(long xLeft, long yTop, VARIANT *pvarID) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; QAccessibleInterface *child = accessible->childAt(xLeft, yTop); if (child == 0) { // no child found, return this item if it contains the coordinates if (accessible->rect().contains(xLeft, yTop)) { (*pvarID).vt = VT_I4; (*pvarID).lVal = CHILDID_SELF; return S_OK; } } else { QWindowsAccessible* wacc = new QWindowsAccessible(child); IDispatch *iface = 0; wacc->QueryInterface(IID_IDispatch, (void**)&iface); if (iface) { (*pvarID).vt = VT_DISPATCH; (*pvarID).pdispVal = iface; return S_OK; } } // Did not find anything (*pvarID).vt = VT_EMPTY; return S_FALSE; }
// moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accFocus(VARIANT *pvarID) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; QAccessibleInterface *acc = 0; int control = accessible->navigate(QAccessible::FocusChild, 1, &acc); if (control == -1) { (*pvarID).vt = VT_EMPTY; return S_FALSE; } if (!acc || control == 0) { (*pvarID).vt = VT_I4; (*pvarID).lVal = control ? control : CHILDID_SELF; return S_OK; } QWindowsAccessible* wacc = new QWindowsAccessible(acc); IDispatch *iface = 0; wacc->QueryInterface(IID_IDispatch, (void**)&iface); if (iface) { (*pvarID).vt = VT_DISPATCH; (*pvarID).pdispVal = iface; return S_OK; } else { delete wacc; } (*pvarID).vt = VT_EMPTY; return S_FALSE; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChild(VARIANT varChildID, IDispatch** ppdispChild) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; if (varChildID.vt == VT_EMPTY) return E_INVALIDARG; int childIndex = varChildID.lVal; QAccessibleInterface *acc = 0; AccessibleElement elem(childIndex, accessible); if (elem.iface) { RelationFlag rel = elem.entry ? Child : Self; int index = elem.iface->navigate(rel, elem.entry, &acc); if (index == -1) return E_INVALIDARG; } if (acc) { QWindowsAccessible* wacc = new QWindowsAccessible(acc); wacc->QueryInterface(IID_IDispatch, (void**)ppdispChild); return S_OK; } *ppdispChild = 0; return S_FALSE; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::accSelect(long flagsSelect, VARIANT varID) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; bool res = false; AccessibleElement elem(varID.lVal, accessible); QAccessibleInterface *acc = elem.iface; if (acc) { const int entry = elem.entry; if (flagsSelect & SELFLAG_TAKEFOCUS) res = acc->doAction(SetFocus, entry, QVariantList()); if (flagsSelect & SELFLAG_TAKESELECTION) { acc->doAction(ClearSelection, 0, QVariantList()); //### bug, 0 should be entry?? res = acc->doAction(AddToSelection, entry, QVariantList()); } if (flagsSelect & SELFLAG_EXTENDSELECTION) res = acc->doAction(ExtendSelection, entry, QVariantList()); if (flagsSelect & SELFLAG_ADDSELECTION) res = acc->doAction(AddToSelection, entry, QVariantList()); if (flagsSelect & SELFLAG_REMOVESELECTION) res = acc->doAction(RemoveSelection, entry, QVariantList()); } return res ? S_OK : S_FALSE; }
// moz: [important] HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; *pcountChildren = accessible->childCount(); return S_OK; }
/* Properties and methods */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; AccessibleElement elem(varID.lVal, accessible); const bool res = elem.iface ? elem.iface->doAction(DefaultAction, elem.entry, QVariantList()) : false; return res ? S_OK : S_FALSE; }
/* Properties and methods */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) { #ifdef DEBUG_SHOW_ATCLIENT_COMMANDS showDebug(__FUNCTION__, accessible); #endif //DEBUG_SHOW_ATCLIENT_COMMANDS if (!accessible->isValid()) return E_FAIL; return accessible->doAction(DefaultAction, varID.lVal, QVariantList()) ? S_OK : S_FALSE; }
/*! \reimp */ QAccessibleInterface *QAccessibleObject::childAt(int x, int y) const { for (int i = 0; i < childCount(); ++i) { QAccessibleInterface *childIface = child(i); Q_ASSERT(childIface); if (childIface->isValid() && childIface->rect().contains(x,y)) return childIface; } return 0; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIANT *pvarState) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; (*pvarState).vt = VT_I4; AccessibleElement elem(varID.lVal, accessible); (*pvarState).lVal = elem.iface ? elem.iface->state(elem.entry) : State(Normal); return S_OK; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accChildCount(long* pcountChildren) { #ifdef DEBUG_SHOW_ATCLIENT_COMMANDS showDebug(__FUNCTION__, accessible); #endif //DEBUG_SHOW_ATCLIENT_COMMANDS if (!accessible->isValid()) return E_FAIL; *pcountChildren = accessible->childCount(); return S_OK; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accState(VARIANT varID, VARIANT *pvarState) { #ifdef DEBUG_SHOW_ATCLIENT_COMMANDS showDebug(__FUNCTION__, accessible); #endif //DEBUG_SHOW_ATCLIENT_COMMANDS if (!accessible->isValid()) return E_FAIL; (*pvarState).vt = VT_I4; (*pvarState).lVal = accessible->state(varID.lVal); return S_OK; }
static bool populateNode(JNIEnv *env, jobject /*thiz*/, jint objectId, jobject node) { QAccessibleInterface *iface = interfaceFromId(objectId); if (!iface || !iface->isValid()) { __android_log_print(ANDROID_LOG_WARN, m_qtTag, "Accessibility: populateNode for Invalid ID"); return false; } QAccessible::State state = iface->state(); const QStringList actions = QAccessibleBridgeUtils::effectiveActionNames(iface); const bool hasClickableAction = actions.contains(QAccessibleActionInterface::pressAction()) || actions.contains(QAccessibleActionInterface::toggleAction()); const bool hasIncreaseAction = actions.contains(QAccessibleActionInterface::increaseAction()); const bool hasDecreaseAction = actions.contains(QAccessibleActionInterface::decreaseAction()); // try to fill in the text property, this is what the screen reader reads jstring jdesc = descriptionForAccessibleObject_helper(env, iface); if (QAccessibleTextInterface *textIface = iface->textInterface()) { if (m_setTextSelectionMethodID && textIface->selectionCount() > 0) { int startSelection; int endSelection; textIface->selection(0, &startSelection, &endSelection); env->CallVoidMethod(node, m_setTextSelectionMethodID, startSelection, endSelection); } } env->CallVoidMethod(node, m_setEnabledMethodID, !state.disabled); env->CallVoidMethod(node, m_setCheckableMethodID, (bool)state.checkable); env->CallVoidMethod(node, m_setCheckedMethodID, (bool)state.checked); env->CallVoidMethod(node, m_setFocusableMethodID, (bool)state.focusable); env->CallVoidMethod(node, m_setFocusedMethodID, (bool)state.focused); env->CallVoidMethod(node, m_setVisibleToUserMethodID, !state.invisible); env->CallVoidMethod(node, m_setScrollableMethodID, hasIncreaseAction || hasDecreaseAction); env->CallVoidMethod(node, m_setClickableMethodID, hasClickableAction); // Add ACTION_CLICK if (hasClickableAction) env->CallVoidMethod(node, m_addActionMethodID, (int)16); // ACTION_CLICK defined in AccessibilityNodeInfo // Add ACTION_SCROLL_FORWARD if (hasIncreaseAction) env->CallVoidMethod(node, m_addActionMethodID, (int)4096); // ACTION_SCROLL_FORWARD defined in AccessibilityNodeInfo // Add ACTION_SCROLL_BACKWARD if (hasDecreaseAction) env->CallVoidMethod(node, m_addActionMethodID, (int)8192); // ACTION_SCROLL_BACKWARD defined in AccessibilityNodeInfo //CALL_METHOD(node, "setText", "(Ljava/lang/CharSequence;)V", jdesc) env->CallVoidMethod(node, m_setContentDescriptionMethodID, jdesc); return true; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetWindow(HWND *phwnd) { *phwnd = 0; if (!accessible->isValid()) return E_UNEXPECTED; QObject *o = accessible->object(); if (!o || !o->isWidgetType()) return E_FAIL; *phwnd = static_cast<QWidget*>(o)->winId(); return S_OK; }
QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface) { QWindow *window = iface->window(); if (!window) { QAccessibleInterface *acc = iface->parent(); while (acc && acc->isValid() && !window) { window = acc->window(); QAccessibleInterface *par = acc->parent(); acc = par; } } return window; }
static jobject screenRect(JNIEnv *env, jobject /*thiz*/, jint objectId) { QRect rect; QAccessibleInterface *iface = interfaceFromId(objectId); if (iface && iface->isValid()) { rect = iface->rect(); } jclass rectClass = env->FindClass("android/graphics/Rect"); jmethodID ctor = env->GetMethodID(rectClass, "<init>", "(IIII)V"); jobject jrect = env->NewObject(rectClass, ctor, rect.left(), rect.top(), rect.right(), rect.bottom()); return jrect; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDefaultAction(VARIANT varID, BSTR* pszDefaultAction) { Q_UNUSED(varID); showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; *pszDefaultAction = 0; if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { const QString def = actionIface->actionNames().value(0); if (!def.isEmpty()) *pszDefaultAction = QStringToBSTR(def); } return *pszDefaultAction ? S_OK : S_FALSE; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::GetWindow(HWND *phwnd) { *phwnd = 0; if (!accessible->isValid()) return E_UNEXPECTED; QWindow *window = window_helper(accessible); if (!window) return E_FAIL; QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); Q_ASSERT(platform); *phwnd = (HWND)platform->nativeResourceForWindow("handle", window); return S_OK; }
/* Properties and methods */ HRESULT STDMETHODCALLTYPE QWindowsAccessible::accDoDefaultAction(VARIANT varID) { Q_UNUSED(varID); showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; if (QAccessibleActionInterface *actionIface = accessible->actionInterface()) { const QString def = actionIface->actionNames().value(0); if (!def.isEmpty()) { actionIface->doAction(def); return S_OK; } } return S_FALSE; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accDescription(VARIANT varID, BSTR* pszDescription) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; AccessibleElement elem(varID.lVal, accessible); QString descr = elem.text(Description); if (descr.size()) { *pszDescription = QStringToBSTR(descr); return S_OK; } *pszDescription = 0; return S_FALSE; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accHelp(VARIANT varID, BSTR *pszHelp) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; AccessibleElement elem(varID.lVal, accessible); QString help = elem.text(Help); if (help.size()) { *pszHelp = QStringToBSTR(help); return S_OK; } *pszHelp = 0; return S_FALSE; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR *pszKeyboardShortcut) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; AccessibleElement elem(varID.lVal, accessible); QString sc = elem.text(Accelerator); if (sc.size()) { *pszKeyboardShortcut = QStringToBSTR(sc); return S_OK; } *pszKeyboardShortcut = 0; return S_FALSE; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accName(VARIANT varID, BSTR* pszName) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; AccessibleElement elem(varID.lVal, accessible); QString n = elem.text(Name); if (n.size()) { *pszName = QStringToBSTR(n); return S_OK; } *pszName = 0; return S_FALSE; }
HRESULT STDMETHODCALLTYPE QWindowsAccessible::get_accValue(VARIANT varID, BSTR* pszValue) { showDebug(__FUNCTION__, accessible); if (!accessible->isValid()) return E_FAIL; AccessibleElement elem(varID.lVal, accessible); QString value = elem.text(Value); if (!value.isNull()) { *pszValue = QStringToBSTR(value); return S_OK; } *pszValue = 0; return S_FALSE; }