Skip to content

Commit

Permalink
Show a notification when a braille display is connected.
Browse files Browse the repository at this point in the history
BUG=293011
R=dmazzoni@chromium.org,oshima@chromium.org

Review URL: https://codereview.chromium.org/213233003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@260079 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
plundblad@chromium.org committed Mar 28, 2014
1 parent 52502be commit a81b2c3
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 99 deletions.
9 changes: 6 additions & 3 deletions ash/accessibility_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ enum AccessibilityAlert {
A11Y_ALERT_WINDOW_NEEDED
};

// A deletate class to control accessibility features.
// A delegate class to control and query accessibility features.
class ASH_EXPORT AccessibilityDelegate {
public:
virtual ~AccessibilityDelegate() {}
Expand All @@ -45,7 +45,7 @@ class ASH_EXPORT AccessibilityDelegate {
// Invoked to change the type of the screen magnifier.
virtual void SetMagnifierType(MagnifierType type) = 0;

// Returns true if the screen magnifier is enabled or not.
// Returns true if the screen magnifier is enabled.
virtual bool IsMagnifierEnabled() const = 0;

// Returns the current screen magnifier mode.
Expand All @@ -54,7 +54,7 @@ class ASH_EXPORT AccessibilityDelegate {
// Invoked to enable Large Cursor.
virtual void SetLargeCursorEnabled(bool enabled) = 0;

// Returns ture if Large Cursor is enabled or not.
// Returns ture if Large Cursor is enabled.
virtual bool IsLargeCursorEnabled() const = 0;

// Invoked to enable autoclick.
Expand All @@ -72,6 +72,9 @@ class ASH_EXPORT AccessibilityDelegate {
// Returns true when the accessibility menu should be shown.
virtual bool ShouldShowAccessibilityMenu() const = 0;

// Returns true if a braille display is connected to the system.
virtual bool IsBrailleDisplayConnected() const = 0;

// Cancel all current and queued speech immediately.
virtual void SilenceSpokenFeedback() const = 0;

Expand Down
3 changes: 3 additions & 0 deletions ash/ash_strings.grd
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,9 @@ This file contains the strings for ash.
<message name="IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME" desc="The accessible name of the status tray.">
Status tray
</message>
<message name="IDS_ASH_STATUS_TRAY_BRAILLE_DISPLAY_CONNECTED_BUBBLE" desc="The message shown on a bubble when a braille display is connected">
Braille display connected.
</message>
<message name="IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED_BUBBLE" desc="The message shown on a bubble when spoken feedback is enabled">
ChromeVox (spoken feedback) is enabled.
Press Ctrl+Alt+Z to disable.
Expand Down
4 changes: 4 additions & 0 deletions ash/default_accessibility_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ bool DefaultAccessibilityDelegate::ShouldShowAccessibilityMenu() const {
virtual_keyboard_enabled_;
}

bool DefaultAccessibilityDelegate::IsBrailleDisplayConnected() const {
return false;
}

void DefaultAccessibilityDelegate::SilenceSpokenFeedback() const {
}

Expand Down
1 change: 1 addition & 0 deletions ash/default_accessibility_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class ASH_EXPORT DefaultAccessibilityDelegate : public AccessibilityDelegate {
virtual void SetVirtualKeyboardEnabled(bool enabled) OVERRIDE;
virtual bool IsVirtualKeyboardEnabled() const OVERRIDE;
virtual bool ShouldShowAccessibilityMenu() const OVERRIDE;
virtual bool IsBrailleDisplayConnected() const OVERRIDE;
virtual void SilenceSpokenFeedback() const OVERRIDE;
virtual void ToggleSpokenFeedback(
AccessibilityNotificationVisibility notify) OVERRIDE;
Expand Down
86 changes: 55 additions & 31 deletions ash/system/tray_accessibility.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#include "ash/system/tray/tray_constants.h"
#include "ash/system/tray/tray_details_view.h"
#include "ash/system/tray/tray_item_more.h"
#include "ash/system/tray/tray_notification_view.h"
#include "ash/system/tray/tray_popup_label_button.h"
#include "base/strings/utf_string_conversions.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "ui/base/l10n/l10n_util.h"
Expand All @@ -32,13 +32,14 @@ namespace internal {
namespace {

enum AccessibilityState {
A11Y_NONE = 0,
A11Y_SPOKEN_FEEDBACK = 1 << 0,
A11Y_HIGH_CONTRAST = 1 << 1,
A11Y_NONE = 0,
A11Y_SPOKEN_FEEDBACK = 1 << 0,
A11Y_HIGH_CONTRAST = 1 << 1,
A11Y_SCREEN_MAGNIFIER = 1 << 2,
A11Y_LARGE_CURSOR = 1 << 3,
A11Y_AUTOCLICK = 1 << 4,
A11Y_LARGE_CURSOR = 1 << 3,
A11Y_AUTOCLICK = 1 << 4,
A11Y_VIRTUAL_KEYBOARD = 1 << 5,
A11Y_BRAILLE_DISPLAY_CONNECTED = 1 << 6,
};

uint32 GetAccessibilityState() {
Expand All @@ -57,6 +58,8 @@ uint32 GetAccessibilityState() {
state |= A11Y_AUTOCLICK;
if (delegate->IsVirtualKeyboardEnabled())
state |= A11Y_VIRTUAL_KEYBOARD;
if (delegate->IsBrailleDisplayConnected())
state |= A11Y_BRAILLE_DISPLAY_CONNECTED;
return state;
}

Expand Down Expand Up @@ -88,25 +91,35 @@ class DefaultAccessibilityView : public TrayItemMore {
DISALLOW_COPY_AND_ASSIGN(DefaultAccessibilityView);
};

class AccessibilityPopupView : public TrayNotificationView {
public:
AccessibilityPopupView(SystemTrayItem* owner)
: TrayNotificationView(owner, IDR_AURA_UBER_TRAY_ACCESSIBILITY_DARK) {
InitView(GetLabel());
}
////////////////////////////////////////////////////////////////////////////////
// ash::internal::tray::AccessibilityPopupView

private:
views::Label* GetLabel() {
views::Label* label = new views::Label(
l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED_BUBBLE));
label->SetMultiLine(true);
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
return label;
}
AccessibilityPopupView::AccessibilityPopupView(SystemTrayItem* owner,
uint32 enabled_state_bits)
: TrayNotificationView(owner, IDR_AURA_UBER_TRAY_ACCESSIBILITY_DARK),
label_(CreateLabel(enabled_state_bits)) {
InitView(label_);
}

DISALLOW_COPY_AND_ASSIGN(AccessibilityPopupView);
};
views::Label* AccessibilityPopupView::CreateLabel(uint32 enabled_state_bits) {
DCHECK((enabled_state_bits &
(A11Y_SPOKEN_FEEDBACK | A11Y_BRAILLE_DISPLAY_CONNECTED)) != 0);
base::string16 text;
if (enabled_state_bits & A11Y_BRAILLE_DISPLAY_CONNECTED) {
text.append(l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_BRAILLE_DISPLAY_CONNECTED_BUBBLE));
}
if (enabled_state_bits & A11Y_SPOKEN_FEEDBACK) {
if (!text.empty())
text.append(base::ASCIIToUTF16(" "));
text.append(l10n_util::GetStringUTF16(
IDS_ASH_STATUS_TRAY_SPOKEN_FEEDBACK_ENABLED_BUBBLE));
}
views::Label* label = new views::Label(text);
label->SetMultiLine(true);
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
return label;
}

////////////////////////////////////////////////////////////////////////////////
// ash::internal::tray::AccessibilityDetailedView
Expand Down Expand Up @@ -302,7 +315,7 @@ TrayAccessibility::TrayAccessibility(SystemTray* system_tray)
default_(NULL),
detailed_popup_(NULL),
detailed_menu_(NULL),
request_popup_view_(false),
request_popup_view_state_(A11Y_NONE),
tray_icon_visible_(false),
login_(GetCurrentLoginStatus()),
previous_accessibility_state_(GetAccessibilityState()),
Expand Down Expand Up @@ -359,9 +372,10 @@ views::View* TrayAccessibility::CreateDetailedView(user::LoginStatus status) {
CHECK(detailed_popup_ == NULL);
CHECK(detailed_menu_ == NULL);

if (request_popup_view_) {
detailed_popup_ = new tray::AccessibilityPopupView(this);
request_popup_view_ = false;
if (request_popup_view_state_) {
detailed_popup_ =
new tray::AccessibilityPopupView(this, request_popup_view_state_);
request_popup_view_state_ = A11Y_NONE;
return detailed_popup_;
} else {
Shell::GetInstance()->metrics()->RecordUserMetricsAction(
Expand Down Expand Up @@ -394,11 +408,21 @@ void TrayAccessibility::OnAccessibilityModeChanged(
SetTrayIconVisible(GetInitialVisibility());

uint32 accessibility_state = GetAccessibilityState();
if ((notify == ash::A11Y_NOTIFICATION_SHOW) &&
!(previous_accessibility_state_ & A11Y_SPOKEN_FEEDBACK) &&
(accessibility_state & A11Y_SPOKEN_FEEDBACK)) {
// We'll get an extra notification if a braille display is connected when
// spoken feedback wasn't already enabled. This is because the braille
// connection state is already updated when spoken feedback is enabled so
// that the notifications can be consolidated into one. Therefore, we
// return early if there's no change in the state that we keep track of.
if (accessibility_state == previous_accessibility_state_)
return;
// Contains bits for spoken feedback and braille display connected currently
// being enabled.
uint32 being_enabled =
(accessibility_state & ~previous_accessibility_state_) &
(A11Y_SPOKEN_FEEDBACK | A11Y_BRAILLE_DISPLAY_CONNECTED);
if ((notify == ash::A11Y_NOTIFICATION_SHOW) && being_enabled != A11Y_NONE) {
// Shows popup if |notify| is true and the spoken feedback is being enabled.
request_popup_view_ = true;
request_popup_view_state_ = being_enabled;
PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false);
} else {
if (detailed_popup_)
Expand Down
21 changes: 19 additions & 2 deletions ash/system/tray_accessibility.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "ash/shell_observer.h"
#include "ash/system/tray/tray_details_view.h"
#include "ash/system/tray/tray_image_item.h"
#include "ash/system/tray/tray_notification_view.h"
#include "ash/system/tray/view_click_listener.h"
#include "base/gtest_prod_util.h"
#include "ui/gfx/font.h"
Expand All @@ -21,6 +22,7 @@ class TrayAccessibilityTest;
namespace views {
class Button;
class ImageView;
class Label;
class View;
}

Expand All @@ -43,7 +45,19 @@ class HoverHighlightView;

namespace tray {

class AccessibilityPopupView;
class AccessibilityPopupView : public TrayNotificationView {
public:
AccessibilityPopupView(SystemTrayItem* owner, uint32 enabled_state_bits);

const views::Label* label_for_test() const { return label_; }

private:
views::Label* CreateLabel(uint32 enabled_state_bits);

views::Label* label_;

DISALLOW_COPY_AND_ASSIGN(AccessibilityPopupView);
};

class AccessibilityDetailedView : public TrayDetailsView,
public ViewClickListener,
Expand Down Expand Up @@ -119,7 +133,10 @@ class TrayAccessibility : public TrayImageItem,
tray::AccessibilityPopupView* detailed_popup_;
tray::AccessibilityDetailedView* detailed_menu_;

bool request_popup_view_;
// Bitmap of fvalues from AccessibilityState. Can contain any or
// both of A11Y_SPOKEN_FEEDBACK A11Y_BRAILLE_DISPLAY_CONNECTED.
uint32 request_popup_view_state_;

bool tray_icon_visible_;
user::LoginStatus login_;

Expand Down
35 changes: 26 additions & 9 deletions chrome/browser/chromeos/accessibility/accessibility_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,9 @@ AccessibilityManager::AccessibilityManager()
spoken_feedback_notification_(ash::A11Y_NOTIFICATION_NONE),
weak_ptr_factory_(this),
should_speak_chrome_vox_announcements_on_user_screen_(true),
system_sounds_enabled_(false) {
system_sounds_enabled_(false),
braille_display_connected_(false),
scoped_braille_observer_(this) {
notification_registrar_.Add(this,
chrome::NOTIFICATION_LOGIN_OR_LOCK_WEBUI_VISIBLE,
content::NotificationService::AllSources());
Expand All @@ -322,8 +324,6 @@ AccessibilityManager::AccessibilityManager()
chrome::NOTIFICATION_SCREEN_LOCK_STATE_CHANGED,
content::NotificationService::AllSources());

GetBrailleController()->AddObserver(this);

ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
media::SoundsManager* manager = media::SoundsManager::Get();
manager->Initialize(SOUND_SHUTDOWN,
Expand Down Expand Up @@ -739,11 +739,19 @@ void AccessibilityManager::UpdateVirtualKeyboardFromPref() {
#endif
}

bool AccessibilityManager::IsBrailleDisplayConnected() const {
return braille_display_connected_;
}

void AccessibilityManager::CheckBrailleState() {
BrailleController* braille_controller = GetBrailleController();
if (!scoped_braille_observer_.IsObserving(braille_controller))
scoped_braille_observer_.Add(braille_controller);
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::IO, FROM_HERE, base::Bind(
&BrailleController::GetDisplayState,
base::Unretained(GetBrailleController())),
BrowserThread::IO,
FROM_HERE,
base::Bind(&BrailleController::GetDisplayState,
base::Unretained(braille_controller)),
base::Bind(&AccessibilityManager::ReceiveBrailleDisplayState,
weak_ptr_factory_.GetWeakPtr()));
}
Expand Down Expand Up @@ -811,10 +819,12 @@ void AccessibilityManager::SetProfile(Profile* profile) {
autoclick_delay_pref_handler_.HandleProfileChanged(profile_, profile);
virtual_keyboard_pref_handler_.HandleProfileChanged(profile_, profile);

if (!profile_ && profile)
bool had_profile = (profile_ != NULL);
profile_ = profile;

if (!had_profile && profile)
CheckBrailleState();

profile_ = profile;
UpdateLargeCursorFromPref();
UpdateStickyKeysFromPref();
UpdateSpokenFeedbackFromPref();
Expand Down Expand Up @@ -962,8 +972,15 @@ void AccessibilityManager::Observe(

void AccessibilityManager::OnDisplayStateChanged(
const DisplayState& display_state) {
if (display_state.available)
braille_display_connected_ = display_state.available;
if (braille_display_connected_)
EnableSpokenFeedback(true, ash::A11Y_NOTIFICATION_SHOW);

AccessibilityStatusEventDetails details(
ACCESSIBILITY_BRAILLE_DISPLAY_CONNECTION_STATE_CHANGED,
braille_display_connected_,
ash::A11Y_NOTIFICATION_SHOW);
NotifyAccessibilityStatusChanged(details);
}

void AccessibilityManager::PostLoadChromeVox(Profile* profile) {
Expand Down
19 changes: 15 additions & 4 deletions chrome/browser/chromeos/accessibility/accessibility_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "base/callback_list.h"
#include "base/memory/weak_ptr.h"
#include "base/prefs/pref_change_registrar.h"
#include "base/scoped_observer.h"
#include "base/time/time.h"
#include "chrome/browser/chromeos/accessibility/accessibility_util.h"
#include "chrome/browser/extensions/api/braille_display_private/braille_controller.h"
Expand All @@ -33,7 +34,8 @@ enum AccessibilityNotificationType {
ACCESSIBILITY_TOGGLE_LARGE_CURSOR,
ACCESSIBILITY_TOGGLE_SCREEN_MAGNIFIER,
ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK,
ACCESSIBILITY_TOGGLE_VIRTUAL_KEYBOARD
ACCESSIBILITY_TOGGLE_VIRTUAL_KEYBOARD,
ACCESSIBILITY_BRAILLE_DISPLAY_CONNECTION_STATE_CHANGED
};

struct AccessibilityStatusEventDetails {
Expand Down Expand Up @@ -66,9 +68,10 @@ typedef AccessibilityStatusCallbackList::Subscription
// AccessibilityManager changes the statuses of accessibility features
// watching profile notifications and pref-changes.
// TODO(yoshiki): merge MagnificationManager with AccessibilityManager.
class AccessibilityManager : public content::NotificationObserver,
extensions::api::braille_display_private::BrailleObserver,
public ash::SessionStateObserver {
class AccessibilityManager
: public content::NotificationObserver,
public extensions::api::braille_display_private::BrailleObserver,
public ash::SessionStateObserver {
public:
// Creates an instance of AccessibilityManager, this should be called once,
// because only one instance should exist at the same time.
Expand Down Expand Up @@ -149,6 +152,10 @@ class AccessibilityManager : public content::NotificationObserver,
// Returns true if the virtual keyboard is enabled, otherwise false.
bool IsVirtualKeyboardEnabled();

// Returns true if a braille display is connected to the system, otherwise
// false.
bool IsBrailleDisplayConnected() const;

// SessionStateObserver overrides:
virtual void ActiveUserChanged(const std::string& user_id) OVERRIDE;

Expand Down Expand Up @@ -256,6 +263,10 @@ class AccessibilityManager : public content::NotificationObserver,

AccessibilityStatusCallbackList callback_list_;

bool braille_display_connected_;
ScopedObserver<extensions::api::braille_display_private::BrailleController,
AccessibilityManager> scoped_braille_observer_;

DISALLOW_COPY_AND_ASSIGN(AccessibilityManager);
};

Expand Down
Loading

0 comments on commit a81b2c3

Please sign in to comment.