• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/chromeos/status/input_method_menu_button.h"
6 
7 #include <string>
8 
9 #include "base/utf_string_conversions.h"
10 #include "chrome/browser/chromeos/cros/cros_library.h"
11 #include "chrome/browser/chromeos/input_method/input_method_util.h"
12 #include "chrome/browser/chromeos/status/status_area_host.h"
13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_list.h"
17 #include "chrome/browser/ui/browser_window.h"
18 #include "views/window/window.h"
19 
20 namespace {
21 
22 // Returns PrefService object associated with |host|. Returns NULL if we are NOT
23 // within a browser.
GetPrefService(chromeos::StatusAreaHost * host)24 PrefService* GetPrefService(chromeos::StatusAreaHost* host) {
25   if (host->GetProfile()) {
26     return host->GetProfile()->GetPrefs();
27   }
28   return NULL;
29 }
30 
31 // A class which implements interfaces of chromeos::InputMethodMenu. This class
32 // is just for avoiding multiple inheritance.
33 class MenuImpl : public chromeos::InputMethodMenu {
34  public:
MenuImpl(chromeos::InputMethodMenuButton * button,PrefService * pref_service,chromeos::StatusAreaHost::ScreenMode screen_mode)35   MenuImpl(chromeos::InputMethodMenuButton* button,
36            PrefService* pref_service,
37            chromeos::StatusAreaHost::ScreenMode screen_mode)
38       : InputMethodMenu(pref_service, screen_mode, false), button_(button) {}
39 
40  private:
41   // InputMethodMenu implementation.
UpdateUI(const std::string & input_method_id,const std::wstring & name,const std::wstring & tooltip,size_t num_active_input_methods)42   virtual void UpdateUI(const std::string& input_method_id,
43                         const std::wstring& name,
44                         const std::wstring& tooltip,
45                         size_t num_active_input_methods) {
46     button_->UpdateUI(input_method_id, name, tooltip, num_active_input_methods);
47   }
ShouldSupportConfigUI()48   virtual bool ShouldSupportConfigUI() {
49     return button_->ShouldSupportConfigUI();
50   }
OpenConfigUI()51   virtual void OpenConfigUI() {
52     button_->OpenConfigUI();
53   }
54   // The UI (views button) to which this class delegates all requests.
55   chromeos::InputMethodMenuButton* button_;
56 
57   DISALLOW_COPY_AND_ASSIGN(MenuImpl);
58 };
59 
60 }  // namespace
61 
62 namespace chromeos {
63 
64 ////////////////////////////////////////////////////////////////////////////////
65 // InputMethodMenuButton
66 
InputMethodMenuButton(StatusAreaHost * host)67 InputMethodMenuButton::InputMethodMenuButton(StatusAreaHost* host)
68     : StatusAreaButton(host, this),
69       menu_(new MenuImpl(this, GetPrefService(host), host->GetScreenMode())) {
70   UpdateUIFromCurrentInputMethod();
71 }
72 
73 ////////////////////////////////////////////////////////////////////////////////
74 // views::View implementation:
75 
GetPreferredSize()76 gfx::Size InputMethodMenuButton::GetPreferredSize() {
77   // If not enabled, then hide this button.
78   if (!IsEnabled()) {
79     return gfx::Size(0, 0);
80   }
81   return StatusAreaButton::GetPreferredSize();
82 }
83 
OnLocaleChanged()84 void InputMethodMenuButton::OnLocaleChanged() {
85   input_method::OnLocaleChanged();
86   UpdateUIFromCurrentInputMethod();
87   Layout();
88   SchedulePaint();
89 }
90 
91 ////////////////////////////////////////////////////////////////////////////////
92 // views::ViewMenuDelegate implementation:
93 
RunMenu(views::View * unused_source,const gfx::Point & pt)94 void InputMethodMenuButton::RunMenu(views::View* unused_source,
95                                     const gfx::Point& pt) {
96   menu_->RunMenu(unused_source, pt);
97 }
98 
WindowIsActive()99 bool InputMethodMenuButton::WindowIsActive() {
100   Browser* active_browser = BrowserList::GetLastActive();
101   if (!active_browser) {
102     // Can't get an active browser. Just return true, which is safer.
103     return true;
104   }
105   BrowserWindow* active_window = active_browser->window();
106   const views::Window* current_window = GetWindow();
107   if (!active_window || !current_window) {
108     // Can't get an active or current window. Just return true as well.
109     return true;
110   }
111   return active_window->GetNativeHandle() == current_window->GetNativeWindow();
112 }
113 
UpdateUI(const std::string & input_method_id,const std::wstring & name,const std::wstring & tooltip,size_t num_active_input_methods)114 void InputMethodMenuButton::UpdateUI(const std::string& input_method_id,
115                                      const std::wstring& name,
116                                      const std::wstring& tooltip,
117                                      size_t num_active_input_methods) {
118   // Hide the button only if there is only one input method, and the input
119   // method is a XKB keyboard layout. We don't hide the button for other
120   // types of input methods as these might have intra input method modes,
121   // like Hiragana and Katakana modes in Japanese input methods.
122   if (num_active_input_methods == 1 &&
123       input_method::IsKeyboardLayout(input_method_id) &&
124       host_->GetScreenMode() == StatusAreaHost::kBrowserMode) {
125     // As the disabled color is set to invisible, disabling makes the
126     // button disappear.
127     SetEnabled(false);
128     SetTooltipText(L"");  // remove tooltip
129   } else {
130     SetEnabled(true);
131     SetTooltipText(tooltip);
132   }
133   SetText(name);
134 
135   if (WindowIsActive()) {
136     // We don't call these functions if the |current_window| is not active since
137     // the calls are relatively expensive (crosbug.com/9206). Please note that
138     // PrepareMenu() is necessary for fixing crosbug.com/7522 when the window
139     // is active.
140     menu_->PrepareMenu();
141     SchedulePaint();
142   }
143 
144   // TODO(yusukes): For a window which isn't on top, probably it's better to
145   // update the texts when the window gets activated because SetTooltipText()
146   // and SetText() are also expensive.
147 }
148 
OpenConfigUI()149 void InputMethodMenuButton::OpenConfigUI() {
150   host_->OpenButtonOptions(this);  // ask browser to open the WebUI page.
151 }
152 
ShouldSupportConfigUI()153 bool InputMethodMenuButton::ShouldSupportConfigUI() {
154   return host_->ShouldOpenButtonOptions(this);
155 }
156 
UpdateUIFromCurrentInputMethod()157 void InputMethodMenuButton::UpdateUIFromCurrentInputMethod() {
158   chromeos::InputMethodLibrary* input_method_library =
159       chromeos::CrosLibrary::Get()->GetInputMethodLibrary();
160   const InputMethodDescriptor& input_method =
161       input_method_library->current_input_method();
162   const std::wstring name = InputMethodMenu::GetTextForIndicator(input_method);
163   const std::wstring tooltip = InputMethodMenu::GetTextForMenu(input_method);
164   const size_t num_active_input_methods =
165       input_method_library->GetNumActiveInputMethods();
166   UpdateUI(input_method.id, name, tooltip, num_active_input_methods);
167 }
168 
169 }  // namespace chromeos
170