Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Unified Diff: chrome/browser/chromeos/status/caps_lock_menu_button.cc

Issue 8330016: Implement the final UI for the CAPS LOCK indicator (part 3 of 3) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/chromeos/status/caps_lock_menu_button.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/chromeos/status/caps_lock_menu_button.cc
diff --git a/chrome/browser/chromeos/status/caps_lock_menu_button.cc b/chrome/browser/chromeos/status/caps_lock_menu_button.cc
index 2b0bc760c0f02f37e8851e84f2601f06e026a871..565079cca09b9de74a2195e5860844b6641c4bfb 100644
--- a/chrome/browser/chromeos/status/caps_lock_menu_button.cc
+++ b/chrome/browser/chromeos/status/caps_lock_menu_button.cc
@@ -8,8 +8,10 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/input_method/xkeyboard.h"
+#include "chrome/browser/chromeos/system/runtime_environment.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/views/bubble/bubble.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/pref_names.h"
#include "grit/generated_resources.h"
@@ -36,6 +38,9 @@ const int kPadLeftX = 10, kPadRightX = 10, kPadY = 5;
// Padding between image and text.
const int kTextPadX = 10;
+const size_t kMaxBubbleCount = 3;
+const size_t kCloseBubbleTimerInSec = 5;
+
// Returns PrefService object associated with |host|.
PrefService* GetPrefService(chromeos::StatusAreaHost* host) {
if (host->GetProfile())
@@ -58,7 +63,7 @@ class CapsLockMenuButton::StatusView : public View {
virtual ~StatusView() {
}
- gfx::Size GetPreferredSize() {
+ virtual gfx::Size GetPreferredSize() OVERRIDE {
// TODO(yusukes): For better string localization, we should use either
// IDS_STATUSBAR_CAPS_LOCK_ENABLED_PRESS_SHIFT_KEYS or
// IDS_STATUSBAR_CAPS_LOCK_ENABLED_PRESS_SEARCH here instead of just
@@ -122,10 +127,12 @@ class CapsLockMenuButton::StatusView : public View {
}
void OnMouseReleased(const views::MouseEvent& event) {
- if (event.IsLeftMouseButton()) {
- DCHECK(menu_button_->menu_runner_.get());
- menu_button_->menu_runner_->Cancel();
- }
+ if (!event.IsLeftMouseButton())
+ return;
+ if (menu_button_->IsMenuShown())
+ menu_button_->HideMenu();
+ if (menu_button_->IsBubbleShown())
+ menu_button_->HideBubble();
}
private:
@@ -141,7 +148,10 @@ class CapsLockMenuButton::StatusView : public View {
CapsLockMenuButton::CapsLockMenuButton(StatusAreaHost* host)
: StatusAreaButton(host, this),
prefs_(GetPrefService(host)),
- status_(NULL) {
+ status_(NULL),
+ bubble_(NULL),
+ should_show_bubble_(true),
+ bubble_count_(0) {
if (prefs_)
remap_search_key_to_.Init(
prefs::kLanguageXkbRemapSearchKeyTo, prefs_, this);
@@ -180,6 +190,9 @@ bool CapsLockMenuButton::IsCommandEnabled(int id) const {
void CapsLockMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
static const int kDummyCommandId = 1000;
+ if (IsBubbleShown())
+ HideBubble();
+
views::MenuItemView* menu = new views::MenuItemView(this);
// MenuRunner takes ownership of |menu|.
menu_runner_.reset(new views::MenuRunner(menu));
@@ -210,7 +223,25 @@ void CapsLockMenuButton::RunMenu(views::View* source, const gfx::Point& pt) {
// SystemKeyEventListener::CapsLockObserver implementation
void CapsLockMenuButton::OnCapsLockChange(bool enabled) {
+ if (!enabled && !HasCapsLock() && bubble_count_ > 0) {
+ // Both shift keys are pressed. We can assume that the user now recognizes
+ // how to turn off Caps Lock.
+ should_show_bubble_ = false;
+ }
+
+ // Update the indicator.
UpdateUIFromCurrentCapsLock(enabled);
+
+ // Update the drop-down menu and bubble. Since the constructor also calls
+ // UpdateUIFromCurrentCapsLock, we shouldn't do this in the function.
+ if (enabled && IsMenuShown())
+ status_->Update(); // Update the drop-down menu if it's already shown.
+ else if (!enabled && IsMenuShown())
+ HideMenu();
+ if (enabled)
+ MaybeShowBubble();
+ else if (!enabled && IsBubbleShown())
+ HideBubble();
}
////////////////////////////////////////////////////////////////////////////////
@@ -225,14 +256,14 @@ void CapsLockMenuButton::Observe(int type,
void CapsLockMenuButton::UpdateAccessibleName() {
int id = IDS_STATUSBAR_CAPS_LOCK_ENABLED_PRESS_SHIFT_KEYS;
- if (prefs_ && (remap_search_key_to_.GetValue() == input_method::kCapsLockKey))
+ if (HasCapsLock())
id = IDS_STATUSBAR_CAPS_LOCK_ENABLED_PRESS_SEARCH;
SetAccessibleName(l10n_util::GetStringUTF16(id));
}
string16 CapsLockMenuButton::GetText() const {
int id = IDS_STATUSBAR_PRESS_SHIFT_KEYS;
- if (prefs_ && (remap_search_key_to_.GetValue() == input_method::kCapsLockKey))
+ if (HasCapsLock())
id = IDS_STATUSBAR_PRESS_SEARCH;
return l10n_util::GetStringUTF16(id);
}
@@ -240,10 +271,72 @@ string16 CapsLockMenuButton::GetText() const {
void CapsLockMenuButton::UpdateUIFromCurrentCapsLock(bool enabled) {
SetVisible(enabled);
SchedulePaint();
- if (enabled && status_)
- status_->Update();
- if (!enabled && menu_runner_.get())
- menu_runner_->Cancel();
+}
+
+bool CapsLockMenuButton::IsMenuShown() const {
+ return menu_runner_.get() && status_;
+}
+
+void CapsLockMenuButton::HideMenu() {
+ if (!IsMenuShown())
+ return;
+ menu_runner_->Cancel();
+}
+
+bool CapsLockMenuButton::IsBubbleShown() const {
+ return bubble_;
+}
+
+void CapsLockMenuButton::MaybeShowBubble() {
+ if (IsBubbleShown() ||
+ // We've already shown the bubble |kMaxBubbleCount| times.
+ !should_show_bubble_ ||
+ // Don't show the bubble when Caps Lock key is available.
+ HasCapsLock())
+ return;
+
+ ++bubble_count_;
+ if (bubble_count_ > kMaxBubbleCount) {
+ should_show_bubble_ = false;
+ } else {
+ CreateAndShowBubble();
+ bubble_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromSeconds(kCloseBubbleTimerInSec),
+ this,
+ &CapsLockMenuButton::HideBubble);
+ }
+}
+
+void CapsLockMenuButton::CreateAndShowBubble() {
+ if (IsBubbleShown()) {
+ NOTREACHED();
+ return;
+ }
+
+ gfx::Rect button_bounds = GetScreenBounds();
+ button_bounds.set_y(button_bounds.y() + 1); // See login/message_bubble.cc.
+
+ bubble_ = Bubble::ShowFocusless(GetWidget(),
+ button_bounds,
+ views::BubbleBorder::TOP_RIGHT,
+ new CapsLockMenuButton::StatusView(this),
+ NULL /* no delegate */,
+ true /* show_while_screen_is_locked */);
+}
+
+void CapsLockMenuButton::HideBubble() {
+ if (!IsBubbleShown())
+ return;
+ bubble_timer_.Stop(); // no-op if it's not running.
+ bubble_->Close();
+ bubble_ = NULL;
+}
+
+bool CapsLockMenuButton::HasCapsLock() const {
+ return (prefs_ &&
+ (remap_search_key_to_.GetValue() == input_method::kCapsLockKey)) ||
+ // A keyboard for Linux usually has Caps Lock.
+ !system::runtime_environment::IsRunningOnChromeOS();
}
} // namespace chromeos
« no previous file with comments | « chrome/browser/chromeos/status/caps_lock_menu_button.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698