Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Announcements get read :)
  • Loading branch information
yaakovschectman committed Oct 26, 2022
commit 5aa08284a926abf8b3407aa3e20f1961e31c9fb6
151 changes: 151 additions & 0 deletions shell/platform/windows/accessibility_alert.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,157 @@

#include "flutter/shell/platform/windows/accessibility_alert.h"

#include "flutter/shell/platform/windows/accessibility_root_node.h"

namespace flutter {

AccessibilityAlert::AccessibilityAlert() : text_(L""), parent_(nullptr) {}

IFACEMETHODIMP AccessibilityAlert::accHitTest(LONG screen_physical_pixel_x,
LONG screen_physical_pixel_y,
VARIANT* child) {
child->vt = VT_EMPTY;
return S_FALSE;
}

// Performs the object's default action.
IFACEMETHODIMP AccessibilityAlert::accDoDefaultAction(VARIANT var_id) {
return E_FAIL;
}

// Retrieves the specified object's current screen location.
IFACEMETHODIMP AccessibilityAlert::accLocation(LONG* physical_pixel_left,
LONG* physical_pixel_top,
LONG* width,
LONG* height,
VARIANT var_id) {
return E_NOTIMPL;
}

// Traverses to another UI element and retrieves the object.
IFACEMETHODIMP AccessibilityAlert::accNavigate(LONG nav_dir,
VARIANT start,
VARIANT* end) {
end->vt = VT_EMPTY;
return E_NOTIMPL;
}

// Retrieves an IDispatch interface pointer for the specified child.
IFACEMETHODIMP AccessibilityAlert::get_accChild(VARIANT var_child,
IDispatch** disp_child) {
if (V_VT(&var_child) == VT_I4 && V_I4(&var_child) == CHILDID_SELF) {
*disp_child = this;
AddRef();
return S_OK;
}
*disp_child = nullptr;
return E_FAIL;
}

// Retrieves the number of accessible children.
IFACEMETHODIMP AccessibilityAlert::get_accChildCount(LONG* child_count) {
*child_count = 0;
return S_OK;
}

// Retrieves a string that describes the object's default action.
IFACEMETHODIMP AccessibilityAlert::get_accDefaultAction(VARIANT var_id,
BSTR* default_action) {
*default_action = nullptr;
return E_NOTIMPL;
}

// Retrieves the tooltip description.
IFACEMETHODIMP AccessibilityAlert::get_accDescription(VARIANT var_id, BSTR* desc) {
*desc = nullptr;
return E_NOTIMPL;
}

// Retrieves the object that has the keyboard focus.
IFACEMETHODIMP AccessibilityAlert::get_accFocus(VARIANT* focus_child) {
focus_child->vt = VT_EMPTY;
return E_NOTIMPL;
}

// Retrieves the specified object's shortcut.
IFACEMETHODIMP AccessibilityAlert::get_accKeyboardShortcut(VARIANT var_id,
BSTR* access_key) {
*access_key = nullptr;
return E_NOTIMPL;
}

// Retrieves the name of the specified object.
IFACEMETHODIMP AccessibilityAlert::get_accName(VARIANT var_id, BSTR* name) {
*name = SysAllocString(text_.c_str());
return S_OK;
}

// Retrieves the IDispatch interface of the object's parent.
IFACEMETHODIMP AccessibilityAlert::get_accParent(IDispatch** disp_parent) {
//*disp_parent = parent_;
//return S_OK;
*disp_parent = nullptr;
return E_NOTIMPL;
}

// Retrieves information describing the role of the specified object.
IFACEMETHODIMP AccessibilityAlert::get_accRole(VARIANT var_id, VARIANT* role) {
*role = {.vt = VT_I4, .lVal = ROLE_SYSTEM_ALERT};
return S_OK;
}

// Retrieves the current state of the specified object.
IFACEMETHODIMP AccessibilityAlert::get_accState(VARIANT var_id, VARIANT* state) {
*state = {.vt = VT_I4, .lVal = STATE_SYSTEM_DEFAULT};
return S_OK;
}

// Gets the help string for the specified object.
IFACEMETHODIMP AccessibilityAlert::get_accHelp(VARIANT var_id, BSTR* help) {
*help = SysAllocString(L"");
return S_OK;
}

// Retrieve or set the string value associated with the specified object.
// Setting the value is not typically used by screen readers, but it's
// used frequently by automation software.
IFACEMETHODIMP AccessibilityAlert::get_accValue(VARIANT var_id, BSTR* value) {
*value = SysAllocString(text_.c_str());
return S_OK;
}
IFACEMETHODIMP AccessibilityAlert::put_accValue(VARIANT var_id, BSTR new_value) {
return E_NOTIMPL;
}

// IAccessible methods not implemented.
IFACEMETHODIMP AccessibilityAlert::get_accSelection(VARIANT* selected) {
selected->vt = VT_EMPTY;
return E_NOTIMPL;
}
IFACEMETHODIMP AccessibilityAlert::accSelect(LONG flags_sel, VARIANT var_id) {
return E_NOTIMPL;
}
IFACEMETHODIMP AccessibilityAlert::get_accHelpTopic(BSTR* help_file,
VARIANT var_id,
LONG* topic_id) {
if (help_file) {
*help_file = nullptr;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it matter for the return value even if this method returns NotImpl?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation is modeled after the not-implemented method body in ax_platform_node_win.cc

}
if (topic_id) {
*topic_id = 0;
}
return E_NOTIMPL;
}
IFACEMETHODIMP AccessibilityAlert::put_accName(VARIANT var_id, BSTR put_name) {
return E_NOTIMPL;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment indicates the below methods are not part of IAccessible. Currently this is in the // IAccessible methods not implemented. section.

void AccessibilityAlert::SetText(const std::wstring& text) {
text_ = text;
}

void AccessibilityAlert::SetParent(AccessibilityRootNode* parent) {
parent_ = parent;
}

}
15 changes: 12 additions & 3 deletions shell/platform/windows/accessibility_alert.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@

namespace flutter {

class AccessibilityRootNode;

// An IAccessible node representing an alert read to the screen reader.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to mention a bit about how it works? and also mention this node is not interact-able by user

class AccessibilityAlert : public CComObjectRootEx<CComMultiThreadModel>,
public IAccessible {
public IDispatchImpl<IAccessible> {
public:
BEGIN_COM_MAP(AccessibilityAlert)
COM_INTERFACE_ENTRY(IAccessible)
Expand Down Expand Up @@ -94,11 +96,18 @@ class AccessibilityAlert : public CComObjectRootEx<CComMultiThreadModel>,
LONG* topic_id) override;
IFACEMETHODIMP put_accName(VARIANT var_id, BSTR put_name) override;

AccessibilityAlert();
~AccessibilityAlert() = default;

// Sets the text of this alert to the provided message.
void SetText(const std::u16string& text);
void SetText(const std::wstring& text);

void SetParent(AccessibilityRootNode* parent);

private:
std::u16string text_;
std::wstring text_;

AccessibilityRootNode* parent_;

};

Expand Down
56 changes: 42 additions & 14 deletions shell/platform/windows/accessibility_root_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@

#include "flutter/shell/platform/windows/accessibility_root_node.h"

#include "flutter/fml/logging.h"

namespace flutter {

static constexpr LONG kWindowChildId = 1;
static constexpr LONG kAlertChildId = 2;
static constexpr LONG kInvalidChildId = 3;

namespace flutter {
AccessibilityRootNode::AccessibilityRootNode() :
alert_accessible_(nullptr) {}

AccessibilityRootNode::~AccessibilityRootNode() {
if (alert_accessible_) {
Expand Down Expand Up @@ -66,7 +70,7 @@ IFACEMETHODIMP AccessibilityRootNode::accLocation(LONG* physical_pixel_left,
VARIANT var_id) {
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->accLocation(physical_pixel_left, physical_pixel_top, width, height, var_id);
return target->accLocation(physical_pixel_left, physical_pixel_top, width, height, var_id);
}
return S_FALSE;
}
Expand All @@ -76,7 +80,7 @@ IFACEMETHODIMP AccessibilityRootNode::accNavigate(LONG nav_dir,
VARIANT* end) {
IAccessible* target;
if ((target = GetTargetAndChildID(&start))) {
return window_accessible_->accNavigate(nav_dir, start, end);
return target->accNavigate(nav_dir, start, end);
}
return S_FALSE;
}
Expand All @@ -91,10 +95,12 @@ IFACEMETHODIMP AccessibilityRootNode::get_accChild(VARIANT var_child,
*disp_child = this;
} else if (!window_accessible_) {
return E_FAIL;
} else if (child_id == 1) {
} else if (child_id == kWindowChildId) {
*disp_child = window_accessible_;
} else if (child_id == 2 && alert_accessible_) {
} else if (child_id == kAlertChildId && alert_accessible_) {
*disp_child = alert_accessible_;
} else if (child_id < 0) {
return window_accessible_->get_accChild(var_child, disp_child);
} else {
return E_FAIL;
}
Expand All @@ -118,7 +124,7 @@ IFACEMETHODIMP AccessibilityRootNode::get_accDefaultAction(VARIANT var_id,
BSTR* def_action) {
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->get_accDefaultAction(var_id, def_action);
return target->get_accDefaultAction(var_id, def_action);
}
*def_action = nullptr;
return S_FALSE;
Expand All @@ -128,7 +134,7 @@ IFACEMETHODIMP AccessibilityRootNode::get_accDescription(VARIANT var_id,
BSTR* desc) {
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->get_accDescription(var_id, desc);
return target->get_accDescription(var_id, desc);
}
return E_FAIL;
}
Expand All @@ -145,12 +151,17 @@ IFACEMETHODIMP AccessibilityRootNode::get_accKeyboardShortcut(VARIANT var_id,
BSTR* acc_key) {
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->get_accKeyboardShortcut(var_id, acc_key);
return target->get_accKeyboardShortcut(var_id, acc_key);
}
return E_FAIL;
}

IFACEMETHODIMP AccessibilityRootNode::get_accName(VARIANT var_id, BSTR* name_bstr) {
if (V_I4(&var_id) == CHILDID_SELF) {
std::wstring name = L"ROOT_NODE_VIEW";
*name_bstr = SysAllocString(name.c_str());
return S_OK;
}
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->get_accName(var_id, name_bstr);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why hard code to window_accessible_? if this is intended you can get rid of the IAccessible* target i think. Also add some comment explains why

Expand All @@ -165,15 +176,15 @@ IFACEMETHODIMP AccessibilityRootNode::get_accParent(IDispatch** disp_parent) {
IFACEMETHODIMP AccessibilityRootNode::get_accRole(VARIANT var_id, VARIANT* role) {
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->get_accRole(var_id, role);
return target->get_accRole(var_id, role);
}
return E_FAIL;
}

IFACEMETHODIMP AccessibilityRootNode::get_accState(VARIANT var_id, VARIANT* state) {
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->get_accState(var_id, state);
return target->get_accState(var_id, state);
}
return E_FAIL;
}
Expand All @@ -189,15 +200,15 @@ IFACEMETHODIMP AccessibilityRootNode::get_accHelp(VARIANT var_id, BSTR* help) {
IFACEMETHODIMP AccessibilityRootNode::get_accValue(VARIANT var_id, BSTR* value) {
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->get_accValue(var_id, value);
return target->get_accValue(var_id, value);
}
return E_FAIL;
}

IFACEMETHODIMP AccessibilityRootNode::put_accValue(VARIANT var_id, BSTR new_value) {
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->put_accValue(var_id, new_value);
return target->put_accValue(var_id, new_value);
}
return E_FAIL;
}
Expand All @@ -210,7 +221,7 @@ IFACEMETHODIMP AccessibilityRootNode::get_accSelection(VARIANT* selected) {
IFACEMETHODIMP AccessibilityRootNode::accSelect(LONG flagsSelect, VARIANT var_id) {
IAccessible* target;
if ((target = GetTargetAndChildID(&var_id))) {
return window_accessible_->accSelect(flagsSelect, var_id);
return target->accSelect(flagsSelect, var_id);
}
return E_FAIL;
}
Expand All @@ -231,4 +242,21 @@ IFACEMETHODIMP AccessibilityRootNode::put_accName(VARIANT var_id, BSTR put_name)
return E_NOTIMPL;
}

void AccessibilityRootNode::SetWindow(IAccessible* window) {
window_accessible_ = window;
}

AccessibilityAlert* AccessibilityRootNode::GetOrCreateAlert() {
if (!alert_accessible_) {
CComObject<AccessibilityAlert>* instance = nullptr;
HRESULT hr = CComObject<AccessibilityAlert>::CreateInstance(&instance);
if (!SUCCEEDED(hr)) {
FML_LOG(FATAL) << "Failed to create alert accessible";
}
instance->SetParent(this);
alert_accessible_ = instance;
}
return alert_accessible_;
}

}
7 changes: 4 additions & 3 deletions shell/platform/windows/accessibility_root_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ namespace flutter {

// A parent node that wraps the window IAccessible node.
class AccessibilityRootNode : public CComObjectRootEx<CComMultiThreadModel>,
public IAccessible {
public IDispatchImpl<IAccessible> {
public:
static constexpr LONG kAlertChildId = 2;
BEGIN_COM_MAP(AccessibilityRootNode)
COM_INTERFACE_ENTRY(IAccessible)
END_COM_MAP()
Expand Down Expand Up @@ -97,14 +98,14 @@ class AccessibilityRootNode : public CComObjectRootEx<CComMultiThreadModel>,
LONG* topic_id) override;
IFACEMETHODIMP put_accName(VARIANT var_id, BSTR put_name) override;

AccessibilityRootNode() = default;
AccessibilityRootNode();
~AccessibilityRootNode();

void SetWindow(IAccessible* window);

void SetAlert(AccessibilityAlert* alert);

inline AccessibilityAlert* GetAlert() {return alert_accessible_;}
AccessibilityAlert* GetOrCreateAlert();

private:
// Helper method to redirect method calls to the contained window.
Expand Down
1 change: 1 addition & 0 deletions shell/platform/windows/flutter_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ void FlutterWindow::SendInitialAccessibilityFeatures() {
}

AccessibilityRootNode* FlutterWindow::GetAccessibilityRootNode() {
FML_LOG(ERROR) << "Returning accessibility_root_";
return accessibility_root_;
}

Expand Down
Loading