Browse Source

Windows Accessibility: Improved support for read-only text interfaces and fixed issue causing text past 1000 characters to not be read out by Narrator

v6.1.6
ed 4 years ago
parent
commit
963fd79e6a
4 changed files with 58 additions and 23 deletions
  1. +6
    -9
      modules/juce_gui_basics/native/accessibility/juce_win32_AccessibilityElement.cpp
  2. +3
    -2
      modules/juce_gui_basics/native/accessibility/juce_win32_UIAHelpers.h
  3. +49
    -6
      modules/juce_gui_basics/native/accessibility/juce_win32_UIATextProvider.h
  4. +0
    -6
      modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h

+ 6
- 9
modules/juce_gui_basics/native/accessibility/juce_win32_AccessibilityElement.cpp View File

@@ -158,16 +158,18 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetPatternProvider (PATTERNID pId, IUn
case UIA_TextPatternId:
case UIA_TextPattern2Id:
{
if (accessibilityHandler.getTextInterface() != nullptr)
if (accessibilityHandler.getTextInterface() != nullptr
|| isReadOnlyText (accessibilityHandler))
{
return new UIATextProvider (this);
}
break;
}
case UIA_ValuePatternId:
{
if (accessibilityHandler.getValueInterface() != nullptr
|| isEditableText (accessibilityHandler)
|| nameIsAccessibilityValue (role))
|| isEditableText (accessibilityHandler))
{
return new UIAValueProvider (this);
}
@@ -539,12 +541,7 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetFocus (IRawElementProviderFragment*
//==============================================================================
String AccessibilityNativeHandle::getElementName() const
{
const auto role = accessibilityHandler.getRole();
if (nameIsAccessibilityValue (role))
return {};
if (role == AccessibilityRole::tooltip)
if (accessibilityHandler.getRole() == AccessibilityRole::tooltip)
return accessibilityHandler.getDescription();
auto name = accessibilityHandler.getTitle();


+ 3
- 2
modules/juce_gui_basics/native/accessibility/juce_win32_UIAHelpers.h View File

@@ -106,9 +106,10 @@ inline bool isEditableText (const AccessibilityHandler& handler)
&& handler.getTextInterface() != nullptr;
}
inline bool nameIsAccessibilityValue (AccessibilityRole role)
inline bool isReadOnlyText (const AccessibilityHandler& handler)
{
return role == AccessibilityRole::staticText;
return handler.getRole() == AccessibilityRole::staticText
&& handler.getValueInterface() != nullptr;
}
} // namespace juce

+ 49
- 6
modules/juce_gui_basics/native/accessibility/juce_win32_UIATextProvider.h View File

@@ -34,6 +34,10 @@ public:
explicit UIATextProvider (AccessibilityNativeHandle* nativeHandle)
: UIAProviderBase (nativeHandle)
{
const auto& handler = getHandler();
if (isReadOnlyText (handler))
readOnlyTextInterface = std::make_unique<ReadOnlyTextInterface> (handler.getValueInterface()->getCurrentValueAsString());
}
//==============================================================================
@@ -63,7 +67,9 @@ public:
{
return withCheckedComArgs (pRetVal, *this, [&]
{
*pRetVal = SupportedTextSelection_Single;
*pRetVal = (readOnlyTextInterface != nullptr ? SupportedTextSelection_None
: SupportedTextSelection_Single);
return S_OK;
});
}
@@ -163,6 +169,15 @@ public:
});
}
//==============================================================================
AccessibilityTextInterface* getTextInterface() const
{
if (readOnlyTextInterface != nullptr)
return readOnlyTextInterface.get();
return getHandler().getTextInterface();
}
private:
//==============================================================================
template <typename Value, typename Callback>
@@ -170,7 +185,7 @@ private:
{
return withCheckedComArgs (pRetVal, *this, [&]() -> HRESULT
{
if (auto* textInterface = getHandler().getTextInterface())
if (auto* textInterface = getTextInterface())
return callback (*textInterface);
return UIA_E_NOTSUPPORTED;
@@ -243,7 +258,7 @@ private:
if (! isElementValid())
return UIA_E_ELEMENTNOTAVAILABLE;
if (auto* textInterface = getHandler().getTextInterface())
if (auto* textInterface = owner->getTextInterface())
{
auto numCharacters = textInterface->getTotalNumCharacters();
@@ -468,7 +483,7 @@ private:
if (! isElementValid())
return UIA_E_ELEMENTNOTAVAILABLE;
if (auto* textInterface = getHandler().getTextInterface())
if (auto* textInterface = owner->getTextInterface())
{
auto otherRange = static_cast<UIATextRangeProvider*> (targetRange)->getSelectionRange();
auto targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start ? otherRange.getStart()
@@ -552,7 +567,7 @@ private:
if (! isElementValid())
return UIA_E_ELEMENTNOTAVAILABLE;
if (auto* textInterface = getHandler().getTextInterface())
if (auto* textInterface = owner->getTextInterface())
{
textInterface->setSelection ({});
return S_OK;
@@ -574,7 +589,7 @@ private:
if (! isElementValid())
return UIA_E_ELEMENTNOTAVAILABLE;
if (auto* textInterface = getHandler().getTextInterface())
if (auto* textInterface = owner->getTextInterface())
{
textInterface->setSelection ({});
textInterface->setSelection (selectionRange);
@@ -635,6 +650,34 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIATextRangeProvider)
};
//==============================================================================
class ReadOnlyTextInterface : public AccessibilityTextInterface
{
public:
explicit ReadOnlyTextInterface (const String& t)
: text (t)
{
}
bool isDisplayingProtectedText() const override { return false; }
int getTotalNumCharacters() const { return text.length(); }
Range<int> getSelection() const override { return selection; }
void setSelection (Range<int> s) override { selection = s; }
int getTextInsertionOffset() const override { return 0; }
String getText (Range<int> range) const override { return text.substring (range.getStart(), range.getEnd()); }
void setText (const String&) override {}
RectangleList<int> getTextBounds (Range<int>) const override { return {}; }
int getOffsetAtPoint (Point<int>) const override { return 0; }
private:
const String text;
Range<int> selection;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ReadOnlyTextInterface)
};
std::unique_ptr<ReadOnlyTextInterface> readOnlyTextInterface;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (UIATextProvider)
};


+ 0
- 6
modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h View File

@@ -44,9 +44,6 @@ public:
const auto& handler = getHandler();
if (nameIsAccessibilityValue (handler.getRole()))
return UIA_E_NOTSUPPORTED;
const auto sendValuePropertyChangeMessage = [&]()
{
VARIANT newValue;
@@ -112,9 +109,6 @@ private:
{
const auto& handler = getHandler();
if (nameIsAccessibilityValue (handler.getRole()))
return handler.getTitle();
if (isEditableText (handler))
if (auto* textInterface = getHandler().getTextInterface())
return textInterface->getText ({ 0, textInterface->getTotalNumCharacters() });


Loading…
Cancel
Save