Commit ba8ae9ea authored by Richard Chui's avatar Richard Chui Committed by Chromium LUCI CQ

Capture Mode: a11y chromevox announcements for selecting

CL #1 of 2 for chromevox announcements (second part is for tab
navigation).

Add the following announcements:
-Entering capture mode
-Exiting capture mode
-Selecting the type (image/video)
-Selecting the source (window/region/fullscreen)
-Screenshot captured
-Recording starting
-Recording stopped

Bug: 1140597
Test: manual
Change-Id: I17c8d62de27507dfd4a9711201525fbd76b993cf
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2598056
Commit-Queue: Richard Chui <richui@chromium.org>
Reviewed-by: default avatarAhmed Fakhry <afakhry@chromium.org>
Reviewed-by: default avatarSammie Quon <sammiequon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#843917}
parent 2556cf83
...@@ -3323,6 +3323,51 @@ Here are some things you can try to get started. ...@@ -3323,6 +3323,51 @@ Here are some things you can try to get started.
<message name="IDS_ASH_SCREEN_CAPTURE_SETTING_OFF_STATE" desc="Description for a setting toggle off state."> <message name="IDS_ASH_SCREEN_CAPTURE_SETTING_OFF_STATE" desc="Description for a setting toggle off state.">
off off
</message> </message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_OPEN" desc="Alert spoken by screen readers on entering capture mode.">
Capture Mode, default is <ph name="SOURCE">$1<ex>partial</ex></ph> <ph name="TYPE">$2<ex>screenshot</ex></ph>.
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_SOURCE_FULLSCREEN" desc="Spoken by screen readers for the open alert with the source as full screen.">
full screen
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_SOURCE_PARTIAL" desc="Spoken by screen readers for the open alert with the source as partial.">
partial
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_SOURCE_WINDOW" desc="Spoken by screen readers for the open alert with the source as window.">
window
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_TYPE_SCREENSHOT" desc="Spoken by screen readers for the open alert with the type as screenshot.">
screenshot
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_TYPE_SCREEN_RECORDING" desc="Spoken by screen readers for the open alert with the type as screen recording.">
screen recording
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_CLOSE" desc="Alert spoken by screen readers when exiting capture mode.">
Exit capture mode
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_TYPE_IMAGE" desc="Alert spoken by screen readers on selecting screenshot mode.">
Screenshot mode selected
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_TYPE_VIDEO" desc="Alert spoken by screen readers on selecting screen recording mode.">
Screen recording mode selected
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_SOURCE_FULLSCREEN" desc="Alert spoken by screen readers on selecting full screen as source.">
Selection area set to full screen
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_SOURCE_REGION" desc="Alert spoken by screen readers on selecting partial screen as source.">
Partial screenshot selected
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_SOURCE_WINDOW" desc="Alert spoken by screen readers on selecting window as source.">
Selection area set to window
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_SCREENSHOT_CAPTURED" desc="Alert spoken by screen readers when screenshot captured.">
Screenshot captured
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_RECORDING_STARTING" desc="Alert spoken by screen readers when recording starts.">
Recording starting in 3, 2, 1
</message>
<message name="IDS_ASH_SCREEN_CAPTURE_ALERT_RECORDING_STOPPED" desc="Alert spoken by screen readers when recording stops.">
Screen recording completed
</message>
<!-- Switch Between TABLET/LAPTOP MODE--> <!-- Switch Between TABLET/LAPTOP MODE-->
<message name="IDS_ASH_SWITCH_TO_TABLET_MODE" desc="Alert of switching to tablet mode."> <message name="IDS_ASH_SWITCH_TO_TABLET_MODE" desc="Alert of switching to tablet mode.">
......
b579f2fd0620061f426650f31ae0c917f8dd89d7
\ No newline at end of file
f9f2851b5d3913fafe28fbbadd2c8a1522396ecc
\ No newline at end of file
32627ca6008b88cca148d7289ff2f67503976b83
\ No newline at end of file
80bb8009c74103c155e3fbec35452f391d459a64
\ No newline at end of file
2352bfd8f6fe06a2facebd9591ddc59b0e090f8e
\ No newline at end of file
f95a2a78824a8e773a1d824d2b1dc4960a718065
\ No newline at end of file
f593832fe7ecff335da8e567418d01826fe9d995
\ No newline at end of file
e4c2b9fd39522b27b0db03d35ae28a59e2ed4fc7
\ No newline at end of file
b899ae55a980819614baa38ed42cf1f8aad414d0
\ No newline at end of file
1ca3ac5e681b4bef5320ec2787e0c697f49d0142
\ No newline at end of file
28c64da72bd4769cf94b800981ef13f2fadc4eca
\ No newline at end of file
6fde7de7ebbe279265bd4348ece7ecbbe6762e98
\ No newline at end of file
6d4784959f506b95e1139ff9848c245014d187ff
\ No newline at end of file
28c64da72bd4769cf94b800981ef13f2fadc4eca
\ No newline at end of file
6fde7de7ebbe279265bd4348ece7ecbbe6762e98
\ No newline at end of file
...@@ -747,6 +747,9 @@ void CaptureModeController::TerminateRecordingUiElements() { ...@@ -747,6 +747,9 @@ void CaptureModeController::TerminateRecordingUiElements() {
video_recording_watcher_->window_being_recorded()->GetRootWindow(), video_recording_watcher_->window_being_recorded()->GetRootWindow(),
false); false);
video_recording_watcher_.reset(); video_recording_watcher_.reset();
capture_mode_util::TriggerAccessibilityAlert(
IDS_ASH_SCREEN_CAPTURE_ALERT_RECORDING_STOPPED);
} }
void CaptureModeController::CaptureImage(const CaptureParams& capture_params, void CaptureModeController::CaptureImage(const CaptureParams& capture_params,
...@@ -771,6 +774,9 @@ void CaptureModeController::CaptureImage(const CaptureParams& capture_params, ...@@ -771,6 +774,9 @@ void CaptureModeController::CaptureImage(const CaptureParams& capture_params,
++num_consecutive_screenshots_; ++num_consecutive_screenshots_;
num_consecutive_screenshots_scheduler_.Reset(); num_consecutive_screenshots_scheduler_.Reset();
capture_mode_util::TriggerAccessibilityAlert(
IDS_ASH_SCREEN_CAPTURE_ALERT_SCREENSHOT_CAPTURED);
} }
void CaptureModeController::CaptureVideo(const CaptureParams& capture_params) { void CaptureModeController::CaptureVideo(const CaptureParams& capture_params) {
...@@ -786,6 +792,9 @@ void CaptureModeController::CaptureVideo(const CaptureParams& capture_params) { ...@@ -786,6 +792,9 @@ void CaptureModeController::CaptureVideo(const CaptureParams& capture_params) {
capture_mode_session_->StartCountDown( capture_mode_session_->StartCountDown(
base::BindOnce(&CaptureModeController::OnVideoRecordCountDownFinished, base::BindOnce(&CaptureModeController::OnVideoRecordCountDownFinished,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
capture_mode_util::TriggerAccessibilityAlert(
IDS_ASH_SCREEN_CAPTURE_ALERT_RECORDING_STARTING);
} }
void CaptureModeController::OnImageCaptured( void CaptureModeController::OnImageCaptured(
...@@ -988,6 +997,10 @@ void CaptureModeController::OnVideoRecordCountDownFinished() { ...@@ -988,6 +997,10 @@ void CaptureModeController::OnVideoRecordCountDownFinished() {
if (!IsActive()) if (!IsActive())
return; return;
// Do not trigger an alert when exiting the session, since we end the session
// to start recording.
capture_mode_session_->set_a11y_alert_on_session_exit(false);
const base::Optional<CaptureParams> capture_params = GetCaptureParams(); const base::Optional<CaptureParams> capture_params = GetCaptureParams();
// Stop the capture session now, so the bar doesn't show up in the captured // Stop the capture session now, so the bar doesn't show up in the captured
// video. // video.
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/shell_window_ids.h"
#include "ash/resources/vector_icons/vector_icons.h" #include "ash/resources/vector_icons/vector_icons.h"
#include "ash/shell.h" #include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "ash/style/ash_color_provider.h" #include "ash/style/ash_color_provider.h"
#include "ash/wm/mru_window_tracker.h" #include "ash/wm/mru_window_tracker.h"
#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h"
...@@ -27,6 +28,7 @@ ...@@ -27,6 +28,7 @@
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/base/cursor/cursor_factory.h" #include "ui/base/cursor/cursor_factory.h"
#include "ui/base/cursor/cursor_util.h" #include "ui/base/cursor/cursor_util.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/layer.h" #include "ui/compositor/layer.h"
#include "ui/compositor/layer_type.h" #include "ui/compositor/layer_type.h"
#include "ui/compositor/paint_recorder.h" #include "ui/compositor/paint_recorder.h"
...@@ -285,6 +287,27 @@ void ClipRectToFit(gfx::Rect* out_bounds, const gfx::Rect& rect) { ...@@ -285,6 +287,27 @@ void ClipRectToFit(gfx::Rect* out_bounds, const gfx::Rect& rect) {
std::min(rect.bottom(), out_bounds->bottom())); std::min(rect.bottom(), out_bounds->bottom()));
} }
// Returns the appropriate |message_id| for a chromevox alert.
// |for_toggle_alert| helps differentiate between the session start and when a
// user toggles the source.
int GetMessageIdForCaptureSource(CaptureModeSource source,
bool for_toggle_alert) {
switch (source) {
case CaptureModeSource::kFullscreen:
return for_toggle_alert
? IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_SOURCE_FULLSCREEN
: IDS_ASH_SCREEN_CAPTURE_SOURCE_FULLSCREEN;
case CaptureModeSource::kRegion:
return for_toggle_alert
? IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_SOURCE_REGION
: IDS_ASH_SCREEN_CAPTURE_SOURCE_PARTIAL;
default:
return for_toggle_alert
? IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_SOURCE_WINDOW
: IDS_ASH_SCREEN_CAPTURE_SOURCE_WINDOW;
}
}
} // namespace } // namespace
class CaptureModeSession::CursorSetter { class CaptureModeSession::CursorSetter {
...@@ -460,6 +483,15 @@ CaptureModeSession::CaptureModeSession(CaptureModeController* controller) ...@@ -460,6 +483,15 @@ CaptureModeSession::CaptureModeSession(CaptureModeController* controller)
TabletModeController::Get()->AddObserver(this); TabletModeController::Get()->AddObserver(this);
current_root_->AddObserver(this); current_root_->AddObserver(this);
display::Screen::GetScreen()->AddObserver(this); display::Screen::GetScreen()->AddObserver(this);
capture_mode_util::TriggerAccessibilityAlert(l10n_util::GetStringFUTF8(
IDS_ASH_SCREEN_CAPTURE_ALERT_OPEN,
l10n_util::GetStringUTF16(GetMessageIdForCaptureSource(
controller_->source(), /*for_toggle_alert=*/false)),
l10n_util::GetStringUTF16(
controller_->type() == CaptureModeType::kImage
? IDS_ASH_SCREEN_CAPTURE_TYPE_SCREENSHOT
: IDS_ASH_SCREEN_CAPTURE_TYPE_SCREEN_RECORDING)));
} }
CaptureModeSession::~CaptureModeSession() { CaptureModeSession::~CaptureModeSession() {
...@@ -485,6 +517,11 @@ CaptureModeSession::~CaptureModeSession() { ...@@ -485,6 +517,11 @@ CaptureModeSession::~CaptureModeSession() {
dimensions_label_widget_->CloseNow(); dimensions_label_widget_->CloseNow();
DCHECK(capture_mode_bar_widget_); DCHECK(capture_mode_bar_widget_);
capture_mode_bar_widget_->CloseNow(); capture_mode_bar_widget_->CloseNow();
if (a11y_alert_on_session_exit_) {
capture_mode_util::TriggerAccessibilityAlert(
IDS_ASH_SCREEN_CAPTURE_ALERT_CLOSE);
}
} }
aura::Window* CaptureModeSession::GetSelectedWindow() const { aura::Window* CaptureModeSession::GetSelectedWindow() const {
...@@ -509,6 +546,9 @@ void CaptureModeSession::OnCaptureSourceChanged(CaptureModeSource new_source) { ...@@ -509,6 +546,9 @@ void CaptureModeSession::OnCaptureSourceChanged(CaptureModeSource new_source) {
UpdateCaptureLabelWidget(); UpdateCaptureLabelWidget();
UpdateCursor(display::Screen::GetScreen()->GetCursorScreenPoint(), UpdateCursor(display::Screen::GetScreen()->GetCursorScreenPoint(),
/*is_touch=*/false); /*is_touch=*/false);
capture_mode_util::TriggerAccessibilityAlert(
GetMessageIdForCaptureSource(new_source, /*for_toggle_alert=*/true));
} }
void CaptureModeSession::OnCaptureTypeChanged(CaptureModeType new_type) { void CaptureModeSession::OnCaptureTypeChanged(CaptureModeType new_type) {
...@@ -516,6 +556,11 @@ void CaptureModeSession::OnCaptureTypeChanged(CaptureModeType new_type) { ...@@ -516,6 +556,11 @@ void CaptureModeSession::OnCaptureTypeChanged(CaptureModeType new_type) {
UpdateCaptureLabelWidget(); UpdateCaptureLabelWidget();
UpdateCursor(display::Screen::GetScreen()->GetCursorScreenPoint(), UpdateCursor(display::Screen::GetScreen()->GetCursorScreenPoint(),
/*is_touch=*/false); /*is_touch=*/false);
capture_mode_util::TriggerAccessibilityAlert(
new_type == CaptureModeType::kImage
? IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_TYPE_IMAGE
: IDS_ASH_SCREEN_CAPTURE_ALERT_SELECT_TYPE_VIDEO);
} }
void CaptureModeSession::ReportSessionHistograms() { void CaptureModeSession::ReportSessionHistograms() {
......
...@@ -64,6 +64,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner, ...@@ -64,6 +64,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
aura::Window* current_root() const { return current_root_; } aura::Window* current_root() const { return current_root_; }
bool is_selecting_region() const { return is_selecting_region_; } bool is_selecting_region() const { return is_selecting_region_; }
bool is_drag_in_progress() const { return is_drag_in_progress_; } bool is_drag_in_progress() const { return is_drag_in_progress_; }
void set_a11y_alert_on_session_exit(bool value) {
a11y_alert_on_session_exit_ = value;
}
// Gets the current window selected for |kWindow| capture source. Returns // Gets the current window selected for |kWindow| capture source. Returns
// nullptr if no window is available for selection. // nullptr if no window is available for selection.
...@@ -309,6 +312,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner, ...@@ -309,6 +312,9 @@ class ASH_EXPORT CaptureModeSession : public ui::LayerOwner,
// The window which had input capture prior to entering the session. It may be // The window which had input capture prior to entering the session. It may be
// null if no such window existed. // null if no such window existed.
aura::Window* input_capture_window_ = nullptr; aura::Window* input_capture_window_ = nullptr;
// False only when we end the session to start recording.
bool a11y_alert_on_session_exit_ = true;
}; };
} // namespace ash } // namespace ash
......
...@@ -4,10 +4,13 @@ ...@@ -4,10 +4,13 @@
#include "ash/capture_mode/capture_mode_util.h" #include "ash/capture_mode/capture_mode_util.h"
#include "ash/accessibility/accessibility_controller_impl.h"
#include "ash/capture_mode/stop_recording_button_tray.h" #include "ash/capture_mode/stop_recording_button_tray.h"
#include "ash/root_window_controller.h" #include "ash/root_window_controller.h"
#include "ash/shell.h"
#include "base/check.h" #include "base/check.h"
#include "base/notreached.h" #include "base/notreached.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
...@@ -84,6 +87,16 @@ void SetStopRecordingButtonVisibility(aura::Window* root, bool visible) { ...@@ -84,6 +87,16 @@ void SetStopRecordingButtonVisibility(aura::Window* root, bool visible) {
stop_recording_button->SetVisiblePreferred(visible); stop_recording_button->SetVisiblePreferred(visible);
} }
void TriggerAccessibilityAlert(const std::string& message) {
Shell::Get()
->accessibility_controller()
->TriggerAccessibilityAlertWithMessage(message);
}
void TriggerAccessibilityAlert(int message_id) {
TriggerAccessibilityAlert(l10n_util::GetStringUTF8(message_id));
}
} // namespace capture_mode_util } // namespace capture_mode_util
} // namespace ash } // namespace ash
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
#ifndef ASH_CAPTURE_MODE_CAPTURE_MODE_UTIL_H_ #ifndef ASH_CAPTURE_MODE_CAPTURE_MODE_UTIL_H_
#define ASH_CAPTURE_MODE_CAPTURE_MODE_UTIL_H_ #define ASH_CAPTURE_MODE_CAPTURE_MODE_UTIL_H_
#include <string>
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/capture_mode/capture_mode_types.h" #include "ash/capture_mode/capture_mode_types.h"
...@@ -35,6 +37,10 @@ bool ShouldHideDragAffordance(FineTunePosition position); ...@@ -35,6 +37,10 @@ bool ShouldHideDragAffordance(FineTunePosition position);
// widget of the given |root| window. // widget of the given |root| window.
void SetStopRecordingButtonVisibility(aura::Window* root, bool visible); void SetStopRecordingButtonVisibility(aura::Window* root, bool visible);
// Triggers an accessibility alert to give the user feedback.
void TriggerAccessibilityAlert(const std::string& message);
void TriggerAccessibilityAlert(int message_id);
} // namespace capture_mode_util } // namespace capture_mode_util
} // namespace ash } // namespace ash
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment