• 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