Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Announce alerts through SemanticsService on Windows #37173

Merged
merged 3 commits into from
Nov 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
4 changes: 4 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -3067,9 +3067,13 @@ FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_texture_regi
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_value.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/fl_view.h
FILE: ../../../flutter/shell/platform/linux/public/flutter_linux/flutter_linux.h
FILE: ../../../flutter/shell/platform/windows/accessibility_alert.cc
FILE: ../../../flutter/shell/platform/windows/accessibility_alert.h
FILE: ../../../flutter/shell/platform/windows/accessibility_bridge_delegate_windows.cc
FILE: ../../../flutter/shell/platform/windows/accessibility_bridge_delegate_windows.h
FILE: ../../../flutter/shell/platform/windows/accessibility_bridge_delegate_windows_unittests.cc
FILE: ../../../flutter/shell/platform/windows/accessibility_root_node.cc
FILE: ../../../flutter/shell/platform/windows/accessibility_root_node.h
FILE: ../../../flutter/shell/platform/windows/angle_surface_manager.cc
FILE: ../../../flutter/shell/platform/windows/angle_surface_manager.h
FILE: ../../../flutter/shell/platform/windows/client_wrapper/dart_project_unittests.cc
Expand Down
4 changes: 4 additions & 0 deletions shell/platform/windows/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ source_set("flutter_windows_headers") {
source_set("flutter_windows_source") {
# Common Windows sources.
sources = [
"accessibility_alert.cc",
"accessibility_alert.h",
"accessibility_bridge_delegate_windows.cc",
"accessibility_bridge_delegate_windows.h",
"accessibility_root_node.cc",
"accessibility_root_node.h",
"angle_surface_manager.cc",
"angle_surface_manager.h",
"cursor_handler.cc",
Expand Down
187 changes: 187 additions & 0 deletions shell/platform/windows/accessibility_alert.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#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) {}

// IAccessible methods.

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 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 the tooltip description.
IFACEMETHODIMP AccessibilityAlert::get_accDescription(VARIANT var_id,
BSTR* desc) {
*desc = SysAllocString(text_.c_str());
return S_OK;
}

// 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_;
if (*disp_parent) {
(*disp_parent)->AddRef();
return S_OK;
}
return S_FALSE;
}

// 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;
}

// 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::put_accValue(VARIANT var_id,
BSTR new_value) {
return E_NOTIMPL;
}

IFACEMETHODIMP AccessibilityAlert::get_accFocus(VARIANT* focus_child) {
focus_child->vt = VT_EMPTY;
return E_NOTIMPL;
}

IFACEMETHODIMP AccessibilityAlert::get_accHelpTopic(BSTR* help_file,
VARIANT var_id,
LONG* topic_id) {
if (help_file) {
*help_file = nullptr;
}
if (topic_id) {
*topic_id = 0;
}
return E_NOTIMPL;
}

IFACEMETHODIMP AccessibilityAlert::put_accName(VARIANT var_id, BSTR put_name) {
return E_NOTIMPL;
}

IFACEMETHODIMP AccessibilityAlert::get_accKeyboardShortcut(VARIANT var_id,
BSTR* access_key) {
*access_key = nullptr;
return E_NOTIMPL;
}

IFACEMETHODIMP AccessibilityAlert::accLocation(LONG* physical_pixel_left,
LONG* physical_pixel_top,
LONG* width,
LONG* height,
VARIANT var_id) {
return E_NOTIMPL;
}

IFACEMETHODIMP AccessibilityAlert::accNavigate(LONG nav_dir,
VARIANT start,
VARIANT* end) {
end->vt = VT_EMPTY;
return E_NOTIMPL;
}

IFACEMETHODIMP AccessibilityAlert::get_accDefaultAction(VARIANT var_id,
BSTR* default_action) {
*default_action = nullptr;
return E_NOTIMPL;
}

// End of IAccessible methods.

//
// IServiceProvider implementation.
//

IFACEMETHODIMP AccessibilityAlert::QueryService(REFGUID guidService,
REFIID riid,
void** object) {
if (!object) {
return E_INVALIDARG;
}

if (guidService == IID_IAccessible) {
return QueryInterface(riid, object);
}

*object = nullptr;
return E_FAIL;
}

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

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

} // namespace flutter
123 changes: 123 additions & 0 deletions shell/platform/windows/accessibility_alert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_ACCESSIBILITY_ALERT_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_ACCESSIBILITY_ALERT_H_

#include <atlbase.h>
#include <atlcom.h>
#include <oleacc.h>

#include <string>

namespace flutter {

class AccessibilityRootNode;

// An IAccessible node representing an alert read to the screen reader.
// When an announcement is requested by the framework, an instance of
// this class, if none exists already, is created and made a child of
// the root AccessibilityRootNode node, and is therefore also a sibling
// of the window's root node.
// This node is not interactable to the user.
class __declspec(uuid("778c1bd8-383f-4d49-b6be-8937e12b6a32"))
AccessibilityAlert : public CComObjectRootEx<CComMultiThreadModel>,
public IDispatchImpl<IAccessible>,
public IServiceProvider {
public:
BEGIN_COM_MAP(AccessibilityAlert)
COM_INTERFACE_ENTRY(AccessibilityAlert)
COM_INTERFACE_ENTRY(IAccessible)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(IServiceProvider)
END_COM_MAP()
//
// IAccessible methods.
//

// Retrieves the child element or child object at a given point on the screen.
IFACEMETHODIMP accHitTest(LONG screen_physical_pixel_x,
LONG screen_physical_pixel_y,
VARIANT* child) override;

// Retrieves an IDispatch interface pointer for the specified child.
IFACEMETHODIMP get_accChild(VARIANT var_child,
IDispatch** disp_child) override;

// Retrieves the number of accessible children.
IFACEMETHODIMP get_accChildCount(LONG* child_count) override;

// Retrieves a string that describes the object's default action.
IFACEMETHODIMP get_accDefaultAction(VARIANT var_id,
BSTR* default_action) override;

// Retrieves the tooltip description.
IFACEMETHODIMP get_accDescription(VARIANT var_id, BSTR* desc) override;

// Retrieves the name of the specified object.
IFACEMETHODIMP get_accName(VARIANT var_id, BSTR* name) override;

// Retrieves the IDispatch interface of the object's parent.
IFACEMETHODIMP get_accParent(IDispatch** disp_parent) override;

// Retrieves information describing the role of the specified object.
IFACEMETHODIMP get_accRole(VARIANT var_id, VARIANT* role) override;

// Retrieves the current state of the specified object.
IFACEMETHODIMP get_accState(VARIANT var_id, VARIANT* state) override;

// Gets the help string for the specified object.
IFACEMETHODIMP get_accHelp(VARIANT var_id, BSTR* help) override;

// Retrieve the string value associated with the specified object.
IFACEMETHODIMP get_accValue(VARIANT var_id, BSTR* value) override;

// IAccessible methods not implemented.
IFACEMETHODIMP accLocation(LONG* physical_pixel_left,
LONG* physical_pixel_top,
LONG* width,
LONG* height,
VARIANT var_id) override;
IFACEMETHODIMP accNavigate(LONG nav_dir,
VARIANT start,
VARIANT* end) override;
IFACEMETHODIMP accDoDefaultAction(VARIANT var_id) override;
IFACEMETHODIMP get_accFocus(VARIANT* focus_child) override;
IFACEMETHODIMP get_accKeyboardShortcut(VARIANT var_id,
BSTR* access_key) override;
IFACEMETHODIMP get_accSelection(VARIANT* selected) override;
IFACEMETHODIMP accSelect(LONG flags_sel, VARIANT var_id) override;
IFACEMETHODIMP get_accHelpTopic(BSTR* help_file,
VARIANT var_id,
LONG* topic_id) override;
IFACEMETHODIMP put_accName(VARIANT var_id, BSTR put_name) override;
IFACEMETHODIMP put_accValue(VARIANT var_id, BSTR new_value) override;

// End of IAccessible methods.

//
// IServiceProvider method.
//

IFACEMETHODIMP QueryService(REFGUID guidService,
REFIID riid,
void** object) override;

AccessibilityAlert();
~AccessibilityAlert() = default;

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

void SetParent(AccessibilityRootNode* parent);

private:
std::wstring text_;

AccessibilityRootNode* parent_;
};

} // namespace flutter

#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_ACCESSIBILITY_ALERT_H_
Loading