-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement IValueProvider #12263
base: main
Are you sure you want to change the base?
Implement IValueProvider #12263
Changes from 2 commits
fe357d7
d22a18c
3e0df00
11fb0a5
8a2b5ee
4178883
af06e6e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"type": "prerelease", | ||
"comment": "value provider changes", | ||
"packageName": "react-native-windows", | ||
"email": "yajurgrover24@gmail.com", | ||
"dependentChangeType": "patch" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -137,6 +137,7 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE | |
if (props == nullptr) | ||
return UIA_E_ELEMENTNOTAVAILABLE; | ||
auto accessibilityRole = props->accessibilityRole; | ||
auto accessibilityValue = props->accessibilityValue; | ||
// Invoke control pattern is used to support controls that do not maintain state | ||
// when activated but rather initiate or perform a single, unambiguous action. | ||
if (patternId == UIA_InvokePatternId && | ||
|
@@ -147,6 +148,11 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE | |
AddRef(); | ||
} | ||
|
||
if (patternId == UIA_ValuePatternId && accessibilityValue.text.has_value()) { | ||
*pRetVal = static_cast<IValueProvider *>(this); | ||
AddRef(); | ||
} | ||
|
||
return S_OK; | ||
} | ||
|
||
|
@@ -327,4 +333,62 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Invoke() { | |
return S_OK; | ||
} | ||
|
||
} // namespace winrt::Microsoft::ReactNative::implementation | ||
std::string convertLPCWSTRToString(LPCWSTR val) { | ||
int strLength = WideCharToMultiByte(CP_UTF8, 0, val, -1, nullptr, 0, nullptr, nullptr); | ||
std::string str(strLength, 0); | ||
WideCharToMultiByte(CP_UTF8, 0, val, -1, &str[0], strLength, nullptr, nullptr); | ||
return str; | ||
} | ||
|
||
BSTR StringToBSTR(const std::string &str) { | ||
// Calculate the required BSTR size in bytes | ||
int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0); | ||
if (len == 0) { | ||
return nullptr; // Conversion error | ||
} | ||
|
||
// Allocate memory for the BSTR | ||
BSTR bstr = SysAllocStringLen(nullptr, len - 1); // len includes the null terminator | ||
|
||
// Convert the std::string to BSTR | ||
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, bstr, len); | ||
|
||
return bstr; | ||
} | ||
|
||
HRESULT __stdcall CompositionDynamicAutomationProvider::SetValue(LPCWSTR val) { | ||
auto strongView = m_view.view(); | ||
|
||
if (!strongView) | ||
return UIA_E_ELEMENTNOTAVAILABLE; | ||
|
||
auto props = std::static_pointer_cast<const facebook::react::ViewProps>(strongView->props()); | ||
std::string value = convertLPCWSTRToString(val); | ||
auto baseView = std::static_pointer_cast<::Microsoft::ReactNative::CompositionBaseComponentView>(strongView); | ||
if (baseView == nullptr) | ||
return UIA_E_ELEMENTNOTAVAILABLE; | ||
winrt::IInspectable uiaProvider = baseView->EnsureUiaProvider(); | ||
UpdateUiaProperty(uiaProvider, UIA_ValueValuePropertyId, *props->accessibilityValue.text, value); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. setValue should go to the ComponentView, which would decide if it needs to update its state based on the new value. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could you clarify what you mean by going to ComponentView? I tried adding an Also. not sure if this is expected behaviour, but SetValue() never seemed to be getting called when updating accessibilityValue (breakpoint in the function was never hit). My guess was that the accessibilityValue example in accesible.tsx doesn't call SetValue() to update the property. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The call to SetValue on the AutomationProvider would only occur if the accessibility tool wants to manipulate the value. This would happen say through voice control or if you select the value pattern actions button in insights and set the value from there. That value set should then go to the component view to actually modify its value. Separately, whenever the component view updates its value it needs to notify the automation peer that its value has been changed. That should happen through a call to UpdateUiaProperty, which would notify the automation provider of the new value, and then the automation provider should call UiaRaiseAutomationEvent which will notify say insights that the value has changed, at which point it can decide if it needs the updates value, and it would call back into the automation peer's getvalue. |
||
|
||
return S_OK; | ||
} | ||
|
||
HRESULT __stdcall CompositionDynamicAutomationProvider::get_Value(BSTR* pRetVal) { | ||
if (pRetVal == nullptr) | ||
return E_POINTER; | ||
auto strongView = m_view.view(); | ||
|
||
if (!strongView) | ||
return UIA_E_ELEMENTNOTAVAILABLE; | ||
|
||
auto props = std::static_pointer_cast<const facebook::react::ViewProps>(strongView->props()); | ||
*pRetVal = StringToBSTR(*props->accessibilityValue.text); | ||
|
||
return S_OK; | ||
} | ||
|
||
HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsReadOnly(BOOL* pRetVal) { | ||
return S_OK; | ||
} | ||
|
||
} // namespace winrt::Microsoft::ReactNative::implementation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can probably use wint::to_string in place of this.