summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorabodenha@chromium.org <abodenha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-22 19:37:21 +0000
committerabodenha@chromium.org <abodenha@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-11-22 19:37:21 +0000
commitc69ed2f46fc00694dd2e939241ef7b1a4831cdb2 (patch)
treef03d3266fdfff57abc246dc928c2ddfbca950bb4
parentd225048e30b2b4783c2f98d5aba27fa6df54fc0f (diff)
downloadchromium_src-c69ed2f46fc00694dd2e939241ef7b1a4831cdb2.zip
chromium_src-c69ed2f46fc00694dd2e939241ef7b1a4831cdb2.tar.gz
chromium_src-c69ed2f46fc00694dd2e939241ef7b1a4831cdb2.tar.bz2
Add an accessibility alert for incorrect use of some accelerators.
Some accelerators don't make sense if no windows exist on the desktop. ChromeVox users can end up in this state and not know it. If a window-needing accelerator is issued and there is no window we fire off an accessibiliy event to let the user know there is no window. This CL: Extends Ash's AcceleratorController to intercept these accelerators. Adds the concept of triggering an alert to AccessibilityDelegate. Adds handling in Chrome's AccessibilityDelegate to generate an alert. BUG=217571 TEST=All automated tests pass. Activate ChromeVox and hit ctrl-m with no window open on Chrome OS. You should get an alert telling you to open a window. Review URL: https://codereview.chromium.org/77453013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@236812 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ash/accelerators/accelerator_controller.cc9
-rw-r--r--ash/accelerators/accelerator_controller.h2
-rw-r--r--ash/accelerators/accelerator_controller_unittest.cc31
-rw-r--r--ash/accelerators/accelerator_table.cc17
-rw-r--r--ash/accelerators/accelerator_table.h4
-rw-r--r--ash/accessibility_delegate.h11
-rw-r--r--ash/default_accessibility_delegate.cc12
-rw-r--r--ash/default_accessibility_delegate.h4
-rw-r--r--chrome/app/generated_resources.grd5
-rw-r--r--chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc25
-rw-r--r--chrome/browser/ui/ash/chrome_shell_delegate_views.cc9
11 files changed, 127 insertions, 2 deletions
diff --git a/ash/accelerators/accelerator_controller.cc b/ash/accelerators/accelerator_controller.cc
index f761acb..2e8d4b7 100644
--- a/ash/accelerators/accelerator_controller.cc
+++ b/ash/accelerators/accelerator_controller.cc
@@ -44,6 +44,7 @@
#include "ash/system/web_notification/web_notification_tray.h"
#include "ash/touch/touch_hud_debug.h"
#include "ash/volume_control_delegate.h"
+#include "ash/wm/mru_window_tracker.h"
#include "ash/wm/overview/window_selector_controller.h"
#include "ash/wm/partial_screenshot_view.h"
#include "ash/wm/power_button_controller.h"
@@ -436,6 +437,8 @@ void AcceleratorController::Init() {
nonrepeatable_actions_.insert(kNonrepeatableActions[i]);
for (size_t i = 0; i < kActionsAllowedInAppModeLength; ++i)
actions_allowed_in_app_mode_.insert(kActionsAllowedInAppMode[i]);
+ for (size_t i = 0; i < kActionsNeedingWindowLength; ++i)
+ actions_needing_window_.insert(kActionsNeedingWindow[i]);
RegisterAccelerators(kAcceleratorData, kAcceleratorDataLength);
@@ -524,6 +527,12 @@ bool AcceleratorController::PerformAction(int action,
actions_allowed_in_app_mode_.end()) {
return false;
}
+ if (MruWindowTracker::BuildWindowList(false).empty() &&
+ actions_needing_window_.find(action) != actions_needing_window_.end()) {
+ Shell::GetInstance()->accessibility_delegate()->TriggerAccessibilityAlert(
+ A11Y_ALERT_WINDOW_NEEDED);
+ return true;
+ }
const ui::KeyboardCode key_code = accelerator.key_code();
// PerformAction() is performed from gesture controllers and passes
diff --git a/ash/accelerators/accelerator_controller.h b/ash/accelerators/accelerator_controller.h
index cacba0e..5689a41 100644
--- a/ash/accelerators/accelerator_controller.h
+++ b/ash/accelerators/accelerator_controller.h
@@ -169,6 +169,8 @@ class ASH_EXPORT AcceleratorController : public ui::AcceleratorTarget {
std::set<int> nonrepeatable_actions_;
// Actions allowed in app mode.
std::set<int> actions_allowed_in_app_mode_;
+ // Actions disallowed if there are no windows.
+ std::set<int> actions_needing_window_;
DISALLOW_COPY_AND_ASSIGN(AcceleratorController);
};
diff --git a/ash/accelerators/accelerator_controller_unittest.cc b/ash/accelerators/accelerator_controller_unittest.cc
index cece328..4a98b0e 100644
--- a/ash/accelerators/accelerator_controller_unittest.cc
+++ b/ash/accelerators/accelerator_controller_unittest.cc
@@ -1330,4 +1330,35 @@ TEST_F(AcceleratorControllerTest, DisallowedAtModalWindow) {
}
#endif
+TEST_F(AcceleratorControllerTest, DisallowedWithNoWindow) {
+ const ui::Accelerator dummy;
+ AccessibilityDelegate* delegate =
+ ash::Shell::GetInstance()->accessibility_delegate();
+
+ for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
+ delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE);
+ EXPECT_TRUE(
+ GetController()->PerformAction(kActionsNeedingWindow[i], dummy));
+ EXPECT_EQ(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_WINDOW_NEEDED);
+ }
+
+ // Make sure we don't alert if we do have a window.
+ scoped_ptr<aura::Window> window(
+ CreateTestWindowInShellWithBounds(gfx::Rect(5, 5, 20, 20)));
+ wm::ActivateWindow(window.get());
+ for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
+ delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE);
+ GetController()->PerformAction(kActionsNeedingWindow[i], dummy);
+ EXPECT_EQ(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_NONE);
+ }
+
+ // Don't alert if we have a minimized window either.
+ GetController()->PerformAction(WINDOW_MINIMIZE, dummy);
+ for (size_t i = 0; i < kActionsNeedingWindowLength; ++i) {
+ delegate->TriggerAccessibilityAlert(A11Y_ALERT_NONE);
+ GetController()->PerformAction(kActionsNeedingWindow[i], dummy);
+ EXPECT_EQ(delegate->GetLastAccessibilityAlert(), A11Y_ALERT_NONE);
+ }
+}
+
} // namespace ash
diff --git a/ash/accelerators/accelerator_table.cc b/ash/accelerators/accelerator_table.cc
index b82c4d8..4ffc1ab 100644
--- a/ash/accelerators/accelerator_table.cc
+++ b/ash/accelerators/accelerator_table.cc
@@ -413,4 +413,21 @@ const AcceleratorAction kActionsAllowedInAppMode[] = {
const size_t kActionsAllowedInAppModeLength =
arraysize(kActionsAllowedInAppMode);
+const AcceleratorAction kActionsNeedingWindow[] = {
+ ACCESSIBLE_FOCUS_NEXT,
+ ACCESSIBLE_FOCUS_PREVIOUS,
+ CYCLE_BACKWARD_MRU,
+ CYCLE_FORWARD_MRU,
+ CYCLE_LINEAR,
+ WINDOW_SNAP_LEFT,
+ WINDOW_SNAP_RIGHT,
+ WINDOW_MINIMIZE,
+ TOGGLE_FULLSCREEN,
+ TOGGLE_MAXIMIZED,
+ WINDOW_POSITION_CENTER,
+ ROTATE_WINDOW,
+};
+
+const size_t kActionsNeedingWindowLength = arraysize(kActionsNeedingWindow);
+
} // namespace ash
diff --git a/ash/accelerators/accelerator_table.h b/ash/accelerators/accelerator_table.h
index 38b156c..21bbf6a 100644
--- a/ash/accelerators/accelerator_table.h
+++ b/ash/accelerators/accelerator_table.h
@@ -192,6 +192,10 @@ ASH_EXPORT extern const size_t kNonrepeatableActionsLength;
ASH_EXPORT extern const AcceleratorAction kActionsAllowedInAppMode[];
ASH_EXPORT extern const size_t kActionsAllowedInAppModeLength;
+// Actions that require at least 1 window.
+ASH_EXPORT extern const AcceleratorAction kActionsNeedingWindow[];
+ASH_EXPORT extern const size_t kActionsNeedingWindowLength;
+
} // namespace ash
#endif // ASH_ACCELERATORS_ACCELERATOR_TABLE_H_
diff --git a/ash/accessibility_delegate.h b/ash/accessibility_delegate.h
index 1f0f349..7bfd5b4 100644
--- a/ash/accessibility_delegate.h
+++ b/ash/accessibility_delegate.h
@@ -15,6 +15,11 @@ enum AccessibilityNotificationVisibility {
A11Y_NOTIFICATION_SHOW,
};
+enum AccessibilityAlert {
+ A11Y_ALERT_NONE,
+ A11Y_ALERT_WINDOW_NEEDED
+};
+
// A deletate class to control accessibility features.
class ASH_EXPORT AccessibilityDelegate {
public:
@@ -70,6 +75,12 @@ class ASH_EXPORT AccessibilityDelegate {
// Gets a saved value of the zoom scale of full screen magnifier. If a value
// is not saved, return a negative value.
virtual double GetSavedScreenMagnifierScale() = 0;
+
+ // Triggers an accessibility alert to give the user feedback.
+ virtual void TriggerAccessibilityAlert(AccessibilityAlert alert) = 0;
+
+ // Gets the last accessibility alert that was triggered.
+ virtual AccessibilityAlert GetLastAccessibilityAlert() = 0;
};
} // namespace ash
diff --git a/ash/default_accessibility_delegate.cc b/ash/default_accessibility_delegate.cc
index bfc6b50..5bce4a5 100644
--- a/ash/default_accessibility_delegate.cc
+++ b/ash/default_accessibility_delegate.cc
@@ -15,7 +15,8 @@ DefaultAccessibilityDelegate::DefaultAccessibilityDelegate()
screen_magnifier_enabled_(false),
screen_magnifier_type_(kDefaultMagnifierType),
large_cursor_enabled_(false),
- autoclick_enabled_(false) {
+ autoclick_enabled_(false),
+ accessibility_alert_(A11Y_ALERT_NONE) {
}
DefaultAccessibilityDelegate::~DefaultAccessibilityDelegate() {}
@@ -83,5 +84,14 @@ double DefaultAccessibilityDelegate::GetSavedScreenMagnifierScale() {
return std::numeric_limits<double>::min();
}
+void DefaultAccessibilityDelegate::TriggerAccessibilityAlert(
+ AccessibilityAlert alert) {
+ accessibility_alert_ = alert;
+}
+
+AccessibilityAlert DefaultAccessibilityDelegate::GetLastAccessibilityAlert() {
+ return accessibility_alert_;
+}
+
} // namespace internal
} // namespace ash
diff --git a/ash/default_accessibility_delegate.h b/ash/default_accessibility_delegate.h
index 58a48ab..11e3c6a 100644
--- a/ash/default_accessibility_delegate.h
+++ b/ash/default_accessibility_delegate.h
@@ -35,6 +35,8 @@ class ASH_EXPORT DefaultAccessibilityDelegate : public AccessibilityDelegate {
AccessibilityNotificationVisibility notify) OVERRIDE;
virtual void SaveScreenMagnifierScale(double scale) OVERRIDE;
virtual double GetSavedScreenMagnifierScale() OVERRIDE;
+ virtual void TriggerAccessibilityAlert(AccessibilityAlert alert) OVERRIDE;
+ virtual AccessibilityAlert GetLastAccessibilityAlert() OVERRIDE;
private:
bool spoken_feedback_enabled_;
@@ -43,7 +45,7 @@ class ASH_EXPORT DefaultAccessibilityDelegate : public AccessibilityDelegate {
MagnifierType screen_magnifier_type_;
bool large_cursor_enabled_;
bool autoclick_enabled_;
-
+ AccessibilityAlert accessibility_alert_;
DISALLOW_COPY_AND_ASSIGN(DefaultAccessibilityDelegate);
};
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 91964c5..176a503 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -15834,6 +15834,11 @@ Do you accept?
<message name="IDS_PROFILE_IN_USE_LINUX_RELAUNCH" desc="Text of button in dialog to delete the profile lock file.">
Unlock Profile and Relaunch
</message>
+
+ <!-- Accessibility alerts -->
+ <message name="IDS_A11Y_ALERT_WINDOW_NEEDED" desc="Alert sent to the accessibility api when the user attempts a keyboard command that requires a window to work.">
+ Command unavailable. Press control-N to open a new window.
+ </message>
</messages>
<structures fallback_to_english="true">
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
index ed86767..ad659e7 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_chromeos.cc
@@ -10,6 +10,7 @@
#include "ash/wm/window_util.h"
#include "base/command_line.h"
#include "base/prefs/pref_service.h"
+#include "chrome/browser/accessibility/accessibility_events.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
@@ -33,7 +34,9 @@
#include "chromeos/ime/input_method_manager.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/user_metrics.h"
+#include "grit/generated_resources.h"
#include "ui/aura/window.h"
+#include "ui/base/l10n/l10n_util.h"
namespace {
@@ -142,6 +145,28 @@ class AccessibilityDelegateImpl : public ash::AccessibilityDelegate {
return std::numeric_limits<double>::min();
}
+ virtual void TriggerAccessibilityAlert(
+ ash::AccessibilityAlert alert) OVERRIDE {
+ Profile* profile = ProfileManager::GetDefaultProfile();
+ if (profile) {
+ switch (alert) {
+ case ash::A11Y_ALERT_WINDOW_NEEDED: {
+ AccessibilityAlertInfo event(
+ profile, l10n_util::GetStringUTF8(IDS_A11Y_ALERT_WINDOW_NEEDED));
+ SendControlAccessibilityNotification(
+ ui::AccessibilityTypes::EVENT_ALERT, &event);
+ break;
+ }
+ case ash::A11Y_ALERT_NONE:
+ break;
+ }
+ }
+ }
+
+ virtual ash::AccessibilityAlert GetLastAccessibilityAlert() OVERRIDE {
+ return ash::A11Y_ALERT_NONE;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(AccessibilityDelegateImpl);
};
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate_views.cc b/chrome/browser/ui/ash/chrome_shell_delegate_views.cc
index 440ed0a..3e12d75 100644
--- a/chrome/browser/ui/ash/chrome_shell_delegate_views.cc
+++ b/chrome/browser/ui/ash/chrome_shell_delegate_views.cc
@@ -10,6 +10,7 @@
#include "ash/system/tray/default_system_tray_delegate.h"
#include "ash/wm/window_util.h"
#include "base/command_line.h"
+#include "chrome/browser/accessibility/accessibility_events.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/prefs/session_startup_pref.h"
#include "chrome/browser/profiles/profile_manager.h"
@@ -122,6 +123,14 @@ class EmptyAccessibilityDelegate : public ash::AccessibilityDelegate {
virtual void SilenceSpokenFeedback() const OVERRIDE {
}
+ virtual void TriggerAccessibilityAlert(
+ ash::AccessibilityAlert alert) OVERRIDE {
+ }
+
+ virtual ash::AccessibilityAlert GetLastAccessibilityAlert() OVERRIDE {
+ return ash::A11Y_ALERT_NONE;
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(EmptyAccessibilityDelegate);
};