[go: nahoru, domu]

blob: 87b9df9f1b89c09ccb4c7e17ecd08507dd711701 [file] [log] [blame]
azureweic0b0a4f2016-07-15 08:56:121// Copyright 2016 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
James Cooka35a1e22017-04-08 02:33:085#include "ash/system/ime_menu/ime_menu_tray.h"
azureweic0b0a4f2016-07-15 08:56:126
Mike Wassermand13e95a2019-06-28 23:29:487#include "ash/accessibility/accessibility_controller_impl.h"
Darren Shen7b132782019-12-10 04:36:068#include "ash/ime/ime_controller_impl.h"
Darren Shen7daf3e12019-07-02 07:25:499#include "ash/keyboard/keyboard_controller_impl.h"
Darren Shencb2508442019-07-03 21:48:2310#include "ash/keyboard/ui/keyboard_ui_controller.h"
James Cook8d912522018-06-19 02:18:4711#include "ash/keyboard/virtual_keyboard_controller.h"
Steven Bennetts93d3e5b12018-05-05 01:14:5012#include "ash/public/cpp/ash_constants.h"
James Cooka354b3b2019-05-22 23:15:3813#include "ash/public/cpp/system_tray_client.h"
Yuichiro Hanada81b13422018-07-10 05:49:4114#include "ash/resources/vector_icons/vector_icons.h"
skyb6643832017-01-11 22:08:4515#include "ash/root_window_controller.h"
Xiyuan Xiae7b19542019-05-06 23:05:1816#include "ash/session/session_controller_impl.h"
James Cook840177e2017-05-25 02:20:0117#include "ash/shelf/shelf.h"
sky07a24d42017-03-09 23:57:3018#include "ash/shell.h"
jamescooke45f8112017-03-02 16:45:4219#include "ash/strings/grit/ash_strings.h"
minch8675df52019-08-09 17:46:4620#include "ash/style/ash_color_provider.h"
James Cooka35a1e22017-04-08 02:33:0821#include "ash/system/ime_menu/ime_list_view.h"
Tetsui Ohkubo36794462018-06-29 07:26:0222#include "ash/system/model/system_tray_model.h"
Tetsui Ohkubocd222612018-05-28 06:47:5423#include "ash/system/tray/detailed_view_delegate.h"
James Cookb0bf8e82017-04-09 17:01:4424#include "ash/system/tray/system_menu_button.h"
James Cookb0bf8e82017-04-09 17:01:4425#include "ash/system/tray/system_tray_notifier.h"
Ahmed Mehfooz15cebdd2021-03-03 01:07:0726#include "ash/system/tray/tray_background_view.h"
Ahmed Mehfooz3a2573c2020-07-22 23:06:3727#include "ash/system/tray/tray_constants.h"
mohsene6704a02017-04-20 06:30:2028#include "ash/system/tray/tray_container.h"
James Cookb0bf8e82017-04-09 17:01:4429#include "ash/system/tray/tray_popup_utils.h"
30#include "ash/system/tray/tray_utils.h"
Andre Lebacf0ac12020-08-25 19:24:4431#include "ash/system/unified/top_shortcut_button.h"
azurewei19203f9502017-01-11 03:45:4332#include "base/metrics/histogram_macros.h"
James Cook465370c72017-06-28 22:55:0833#include "base/metrics/user_metrics.h"
azureweic0b0a4f2016-07-15 08:56:1234#include "base/strings/utf_string_conversions.h"
jamescook85312ee2017-04-18 22:47:2035#include "components/session_manager/session_manager_types.h"
Yuichiro Hanada81b13422018-07-10 05:49:4136#include "ui/base/ime/chromeos/extension_ime_util.h"
Darren Shen377ad2d52020-05-29 00:25:0537#include "ui/base/ime/chromeos/ime_bridge.h"
azurewei1c4c4e82017-01-10 04:47:1838#include "ui/base/ime/text_input_client.h"
azureweic0b0a4f2016-07-15 08:56:1239#include "ui/base/l10n/l10n_util.h"
azurewei6bc89eb2016-08-26 22:56:5640#include "ui/base/resource/resource_bundle.h"
Allen Bauer99a93792017-06-05 20:59:0741#include "ui/gfx/geometry/insets.h"
azurewei6a186282016-09-20 15:46:3042#include "ui/gfx/paint_vector_icon.h"
azurewei92ccc5c2016-09-21 16:14:2543#include "ui/gfx/range/range.h"
Yuichiro Hanada81b13422018-07-10 05:49:4144#include "ui/views/controls/image_view.h"
azureweic0b0a4f2016-07-15 08:56:1245#include "ui/views/controls/label.h"
estade252bd5362017-02-07 23:40:0146#include "ui/views/controls/scroll_view.h"
azurewei92ccc5c2016-09-21 16:14:2547#include "ui/views/controls/separator.h"
azurewei4ecb8442016-07-28 06:06:0948#include "ui/views/layout/box_layout.h"
Shengsong Tanf2153772020-12-28 08:45:0749#include "ui/views/layout/box_layout_view.h"
Shengsong Tan64ce6342020-12-23 03:44:3350#include "ui/views/metadata/metadata_impl_macros.h"
azureweic0b0a4f2016-07-15 08:56:1251
52namespace ash {
53
54namespace {
James Cookced4693e2017-07-12 02:04:2855
56// Used for testing.
57const int kEmojiButtonId = 1;
58
Andre Lebacf0ac12020-08-25 19:24:4459// Insets for the title view (dp).
60constexpr gfx::Insets kTitleViewPadding(0, 0, 0, 16);
61
azurewei92ccc5c2016-09-21 16:14:2562// Returns the height range of ImeListView.
63gfx::Range GetImeListViewRange() {
64 const int max_items = 5;
azurewei9786d462016-12-22 23:34:2765 const int min_items = 1;
estadeda123cac2017-03-01 05:02:5566 const int tray_item_height = kTrayPopupItemMinHeight;
azurewei92ccc5c2016-09-21 16:14:2567 return gfx::Range(tray_item_height * min_items, tray_item_height * max_items);
azurewei5ee46212016-08-24 00:49:3668}
69
azurewei23b7cdb02016-11-08 04:16:5770// Returns true if the current screen is login or lock screen.
71bool IsInLoginOrLockScreen() {
jamescook85312ee2017-04-18 22:47:2072 using session_manager::SessionState;
73 SessionState state = Shell::Get()->session_controller()->GetSessionState();
74 return state == SessionState::LOGIN_PRIMARY ||
75 state == SessionState::LOCKED ||
76 state == SessionState::LOGIN_SECONDARY;
azurewei23b7cdb02016-11-08 04:16:5777}
78
azurewei1c4c4e82017-01-10 04:47:1879// Returns true if the current input context type is password.
80bool IsInPasswordInputContext() {
Scott Violet7618db6a2019-06-20 01:22:0781 return ui::IMEBridge::Get()->GetCurrentInputContext().type ==
82 ui::TEXT_INPUT_TYPE_PASSWORD;
azurewei1c4c4e82017-01-10 04:47:1883}
84
azureweic0b0a4f2016-07-15 08:56:1285class ImeMenuLabel : public views::Label {
86 public:
Shengsong Tan64ce6342020-12-23 03:44:3387 METADATA_HEADER(ImeMenuLabel);
88
estadeb0aaaea2017-04-17 22:55:2589 ImeMenuLabel() {
90 // Sometimes the label will be more than 2 characters, e.g. INTL and EXTD.
91 // This border makes sure we only leave room for ~2 and the others are
92 // truncated.
93 SetBorder(views::CreateEmptyBorder(gfx::Insets(0, 6)));
94 }
Shengsong Tan64ce6342020-12-23 03:44:3395 ImeMenuLabel(const ImeMenuLabel&) = delete;
96 ImeMenuLabel& operator=(const ImeMenuLabel&) = delete;
Chris Watkinsc24daf62017-11-28 03:43:0997 ~ImeMenuLabel() override = default;
azureweic0b0a4f2016-07-15 08:56:1298
99 // views:Label:
estadef285a782017-05-22 21:52:24100 gfx::Size CalculatePreferredSize() const override {
estadeda123cac2017-03-01 05:02:55101 return gfx::Size(kTrayItemSize, kTrayItemSize);
azureweic0b0a4f2016-07-15 08:56:12102 }
estadeda123cac2017-03-01 05:02:55103 int GetHeightForWidth(int width) const override { return kTrayItemSize; }
azureweic0b0a4f2016-07-15 08:56:12104};
105
Shengsong Tan64ce6342020-12-23 03:44:33106BEGIN_METADATA(ImeMenuLabel, views::Label)
107END_METADATA
108
Yuichiro Hanada81b13422018-07-10 05:49:41109class ImeMenuImageView : public views::ImageView {
110 public:
Shengsong Tan64ce6342020-12-23 03:44:33111 METADATA_HEADER(ImeMenuImageView);
112
Yuichiro Hanada81b13422018-07-10 05:49:41113 ImeMenuImageView() { SetBorder(views::CreateEmptyBorder(gfx::Insets(0, 6))); }
Shengsong Tan64ce6342020-12-23 03:44:33114 ImeMenuImageView(const ImeMenuImageView&) = delete;
115 ImeMenuImageView& operator=(const ImeMenuImageView&) = delete;
Yuichiro Hanada81b13422018-07-10 05:49:41116 ~ImeMenuImageView() override = default;
Yuichiro Hanada81b13422018-07-10 05:49:41117};
118
Shengsong Tan64ce6342020-12-23 03:44:33119BEGIN_METADATA(ImeMenuImageView, views::ImageView)
120END_METADATA
121
estadea553b86b2017-03-29 19:04:55122// The view that contains IME menu title.
Shengsong Tanf2153772020-12-28 08:45:07123class ImeTitleView : public views::BoxLayoutView {
azurewei92ccc5c2016-09-21 16:14:25124 public:
Shengsong Tan64ce6342020-12-23 03:44:33125 METADATA_HEADER(ImeTitleView);
minchae1caf02020-11-06 18:29:03126 ImeTitleView() {
127 auto* color_provider = AshColorProvider::Get();
estade55bb1892016-11-09 22:39:21128 SetBorder(views::CreatePaddedBorder(
minch8675df52019-08-09 17:46:46129 views::CreateSolidSidedBorder(
130 0, 0, kMenuSeparatorWidth, 0,
minchae1caf02020-11-06 18:29:03131 color_provider->GetContentLayerColor(
minch5847c6f2020-09-08 01:13:17132 AshColorProvider::ContentLayerType::kSeparatorColor)),
Manu Cornet88510ca2019-01-30 03:31:42133 gfx::Insets(kMenuSeparatorVerticalPadding - kMenuSeparatorWidth, 0)));
Shengsong Tanf2153772020-12-28 08:45:07134 SetOrientation(views::BoxLayout::Orientation::kHorizontal);
135 SetInsideBorderInsets(kTitleViewPadding);
136 SetMinimumCrossAxisSize(kTrayPopupItemMinHeight);
137
minchae1caf02020-11-06 18:29:03138 auto* title_label = AddChildView(std::make_unique<views::Label>(
139 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_IME)));
azureweid0cea0b2017-02-07 02:15:48140 title_label->SetBorder(
141 views::CreateEmptyBorder(0, kMenuEdgeEffectivePadding, 1, 0));
estade99ef2a32017-02-03 03:57:40142 title_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
minchae1caf02020-11-06 18:29:03143 title_label->SetEnabledColor(color_provider->GetContentLayerColor(
144 AshColorProvider::ContentLayerType::kTextColorPrimary));
145 TrayPopupUtils::SetLabelFontList(title_label,
Ahmed Mehfoozfcf27422020-11-21 05:18:51146 TrayPopupUtils::FontStyle::kPodMenuHeader);
Shengsong Tanf2153772020-12-28 08:45:07147 SetFlexForView(title_label, 1);
azurewei23b7cdb02016-11-08 04:16:57148
Andre Lebacf0ac12020-08-25 19:24:44149 settings_button_ = AddChildView(std::make_unique<TopShortcutButton>(
Peter Kasting1056ad8f2020-11-04 17:26:24150 base::BindRepeating([]() {
151 base::RecordAction(
152 base::UserMetricsAction("StatusArea_IME_Detailed"));
153 Shell::Get()->system_tray_model()->client()->ShowIMESettings();
154 }),
155 kSystemMenuSettingsIcon, IDS_ASH_STATUS_TRAY_IME_SETTINGS));
Andre Lebacf0ac12020-08-25 19:24:44156 settings_button_->SetEnabled(TrayPopupUtils::CanOpenWebUISettings());
azurewei23b7cdb02016-11-08 04:16:57157 }
Shengsong Tan64ce6342020-12-23 03:44:33158 ImeTitleView(const ImeTitleView&) = delete;
159 ImeTitleView& operator=(const ImeTitleView&) = delete;
azurewei23b7cdb02016-11-08 04:16:57160
Chris Watkinsc24daf62017-11-28 03:43:09161 ~ImeTitleView() override = default;
azurewei92ccc5c2016-09-21 16:14:25162
azurewei92ccc5c2016-09-21 16:14:25163 private:
Andre Lebacf0ac12020-08-25 19:24:44164 TopShortcutButton* settings_button_ = nullptr;
azurewei92ccc5c2016-09-21 16:14:25165};
166
Shengsong Tanf2153772020-12-28 08:45:07167BEGIN_METADATA(ImeTitleView, views::BoxLayoutView)
Shengsong Tan64ce6342020-12-23 03:44:33168END_METADATA
169
azureweiacbd0c32016-08-30 05:45:38170// The view that contains buttons shown on the bottom of IME menu.
Peter Kasting1056ad8f2020-11-04 17:26:24171class ImeButtonsView : public views::View {
azurewei4ecb8442016-07-28 06:06:09172 public:
Shengsong Tan64ce6342020-12-23 03:44:33173 METADATA_HEADER(ImeButtonsView);
azurewei079691f2017-06-30 15:04:18174 ImeButtonsView(ImeMenuTray* ime_menu_tray,
175 bool show_emoji,
176 bool show_handwriting,
James Cookced4693e2017-07-12 02:04:28177 bool show_voice)
178 : ime_menu_tray_(ime_menu_tray) {
azurewei649030a22016-09-20 13:11:43179 DCHECK(ime_menu_tray_);
180
azurewei079691f2017-06-30 15:04:18181 Init(show_emoji, show_handwriting, show_voice);
azurewei4ecb8442016-07-28 06:06:09182 }
Shengsong Tan64ce6342020-12-23 03:44:33183 ImeButtonsView(const ImeButtonsView&) = delete;
184 ImeButtonsView& operator=(const ImeButtonsView&) = delete;
azurewei4ecb8442016-07-28 06:06:09185
Chris Watkinsc24daf62017-11-28 03:43:09186 ~ImeButtonsView() override = default;
azurewei4ecb8442016-07-28 06:06:09187
Peter Kasting1056ad8f2020-11-04 17:26:24188 void KeysetButtonPressed(chromeos::input_method::ImeKeyset keyset) {
Darren Shena4bf7492018-03-16 04:25:52189 // TODO(dcheng): When https://crbug.com/742517 is fixed, Mojo will generate
190 // a constant for the number of values in the enum. For now, we just define
191 // it here and keep it in sync with the enum.
192 const int kImeKeysetUmaBoundary = 4;
193 UMA_HISTOGRAM_ENUMERATION("InputMethod.ImeMenu.EmojiHandwritingVoiceButton",
194 keyset, kImeKeysetUmaBoundary);
Peter Kasting1056ad8f2020-11-04 17:26:24195 // The |keyset| will be used for drawing input view keyset in IME
196 // extensions. ImeMenuTray::ShowKeyboardWithKeyset() will deal with
197 // the |keyset| string to generate the right input view url.
azurewei649030a22016-09-20 13:11:43198 ime_menu_tray_->ShowKeyboardWithKeyset(keyset);
azurewei4ecb8442016-07-28 06:06:09199 }
200
201 private:
azurewei079691f2017-06-30 15:04:18202 void Init(bool show_emoji, bool show_handwriting, bool show_voice) {
Hwanseung Lee5b9e43d2019-06-25 01:55:32203 auto box_layout = std::make_unique<views::BoxLayout>(
204 views::BoxLayout::Orientation::kHorizontal);
estadea553b86b2017-03-29 19:04:55205 box_layout->set_minimum_cross_axis_size(kTrayPopupItemMinHeight);
Brett Wilson501d6642017-12-14 17:58:18206 SetLayoutManager(std::move(box_layout));
estadea553b86b2017-03-29 19:04:55207 SetBorder(views::CreatePaddedBorder(
minch8675df52019-08-09 17:46:46208 views::CreateSolidSidedBorder(
209 kMenuSeparatorWidth, 0, 0, 0,
minch6a718bb2019-08-20 20:45:28210 AshColorProvider::Get()->GetContentLayerColor(
minch5847c6f2020-09-08 01:13:17211 AshColorProvider::ContentLayerType::kSeparatorColor)),
Manu Cornet88510ca2019-01-30 03:31:42212 gfx::Insets(kMenuSeparatorVerticalPadding - kMenuSeparatorWidth,
estadea553b86b2017-03-29 19:04:55213 kMenuExtraMarginFromLeftEdge)));
azureweiacbd0c32016-08-30 05:45:38214
azurewei079691f2017-06-30 15:04:18215 if (show_emoji) {
Peter Kasting1056ad8f2020-11-04 17:26:24216 emoji_button_ = new SystemMenuButton(
217 base::BindRepeating(&ImeButtonsView::KeysetButtonPressed,
218 base::Unretained(this),
219 chromeos::input_method::ImeKeyset::kEmoji),
220 kImeMenuEmoticonIcon, IDS_ASH_STATUS_TRAY_IME_EMOJI);
Allen Bauer942cd542019-05-08 13:06:13221 emoji_button_->SetID(kEmojiButtonId);
azurewei079691f2017-06-30 15:04:18222 AddChildView(emoji_button_);
223 }
azureweiacbd0c32016-08-30 05:45:38224
azurewei079691f2017-06-30 15:04:18225 if (show_handwriting) {
Peter Kasting1056ad8f2020-11-04 17:26:24226 handwriting_button_ = new SystemMenuButton(
227 base::BindRepeating(&ImeButtonsView::KeysetButtonPressed,
228 base::Unretained(this),
229 chromeos::input_method::ImeKeyset::kHandwriting),
230 kImeMenuWriteIcon, IDS_ASH_STATUS_TRAY_IME_HANDWRITING);
azurewei079691f2017-06-30 15:04:18231 AddChildView(handwriting_button_);
232 }
azureweiacbd0c32016-08-30 05:45:38233
azurewei079691f2017-06-30 15:04:18234 if (show_voice) {
Peter Kasting1056ad8f2020-11-04 17:26:24235 voice_button_ = new SystemMenuButton(
236 base::BindRepeating(&ImeButtonsView::KeysetButtonPressed,
237 base::Unretained(this),
238 chromeos::input_method::ImeKeyset::kVoice),
239 kImeMenuMicrophoneIcon, IDS_ASH_STATUS_TRAY_IME_VOICE);
azurewei079691f2017-06-30 15:04:18240 AddChildView(voice_button_);
241 }
azureweiacbd0c32016-08-30 05:45:38242 }
243
azurewei649030a22016-09-20 13:11:43244 ImeMenuTray* ime_menu_tray_;
azureweia3cd5302016-11-04 01:58:00245 SystemMenuButton* emoji_button_;
246 SystemMenuButton* handwriting_button_;
247 SystemMenuButton* voice_button_;
azurewei4ecb8442016-07-28 06:06:09248};
249
Shengsong Tan64ce6342020-12-23 03:44:33250BEGIN_METADATA(ImeButtonsView, views::View)
251END_METADATA
252
tdanderson9e3fb282017-04-05 21:43:33253// A list of available IMEs shown in the opt-in IME menu, which has a different
254// height depending on the number of IMEs in the list.
Tetsui Ohkubobd07ddd2019-01-17 03:35:58255class ImeMenuListView : public ImeListView {
azurewei29b403d2016-12-08 03:40:00256 public:
Shengsong Tan64ce6342020-12-23 03:44:33257 METADATA_HEADER(ImeMenuListView);
azurewei29b403d2016-12-08 03:40:00258
Shengsong Tan64ce6342020-12-23 03:44:33259 ImeMenuListView() : ImeMenuListView(std::make_unique<Delegate>()) {}
260 ImeMenuListView(const ImeMenuListView&) = delete;
261 ImeMenuListView& operator=(const ImeMenuListView&) = delete;
262
263 ~ImeMenuListView() override = default;
Andrew Leec99ea552019-05-21 20:42:16264
Tetsui Ohkubobd07ddd2019-01-17 03:35:58265 private:
266 class Delegate : public DetailedViewDelegate {
267 public:
268 Delegate() : DetailedViewDelegate(nullptr /* tray_controller */) {}
269
270 // DetailedViewDelegate:
271 void TransitionToMainView(bool restore_focus) override {}
272 void CloseBubble() override {}
Tetsui Ohkubobd07ddd2019-01-17 03:35:58273
Jiaming Cheng4e741682021-02-18 22:57:55274 gfx::Insets GetInsetsForDetailedView() const override {
275 return gfx::Insets();
276 }
277
Tetsui Ohkubobd07ddd2019-01-17 03:35:58278 private:
279 DISALLOW_COPY_AND_ASSIGN(Delegate);
280 };
281
Ahmed Mehfooz3a2573c2020-07-22 23:06:37282 explicit ImeMenuListView(std::unique_ptr<Delegate> delegate)
minchae7206192020-11-03 20:51:41283 : ImeListView(delegate.get()) {
Tetsui Ohkubobd07ddd2019-01-17 03:35:58284 set_should_focus_ime_after_selection_with_keyboard(true);
285 delegate_ = std::move(delegate);
Tetsui Ohkubob879459d2018-06-11 02:41:16286 }
Tetsui Ohkubocd222612018-05-28 06:47:54287
Tetsui Ohkubobd07ddd2019-01-17 03:35:58288 // ImeListView:
azurewei29b403d2016-12-08 03:40:00289 void Layout() override {
290 gfx::Range height_range = GetImeListViewRange();
estade252bd5362017-02-07 23:40:01291 scroller()->ClipHeightTo(height_range.start(), height_range.end());
azurewei29b403d2016-12-08 03:40:00292 ImeListView::Layout();
293 }
294
Tetsui Ohkubobd07ddd2019-01-17 03:35:58295 std::unique_ptr<Delegate> delegate_;
azurewei29b403d2016-12-08 03:40:00296};
297
Shengsong Tan64ce6342020-12-23 03:44:33298BEGIN_METADATA(ImeMenuListView, ImeListView)
299END_METADATA
300
azureweic0b0a4f2016-07-15 08:56:12301} // namespace
302
James Cook840177e2017-05-25 02:20:01303ImeMenuTray::ImeMenuTray(Shelf* shelf)
304 : TrayBackgroundView(shelf),
James Cookbb026732017-06-09 23:01:55305 ime_controller_(Shell::Get()->ime_controller()),
Yuichiro Hanada81b13422018-07-10 05:49:41306 label_(nullptr),
307 image_view_(nullptr),
azureweie2664492016-12-29 00:30:42308 keyboard_suppressed_(false),
azureweie8761592017-05-17 03:16:46309 show_bubble_after_keyboard_hidden_(false),
Blake O'Haref61c66e2017-10-05 01:55:49310 is_emoji_enabled_(false),
311 is_handwriting_enabled_(false),
Jeremy Roman47d432e2019-08-20 14:24:00312 is_voice_enabled_(false) {
James Cookbb026732017-06-09 23:01:55313 DCHECK(ime_controller_);
Yuichiro Hanada81b13422018-07-10 05:49:41314 CreateLabel();
sky5b45ed82017-03-27 02:54:23315 SystemTrayNotifier* tray_notifier = Shell::Get()->system_tray_notifier();
azurewei1fb9e772016-11-23 06:29:11316 tray_notifier->AddIMEObserver(this);
317 tray_notifier->AddVirtualKeyboardObserver(this);
Tetsui Ohkubo852abe62018-10-03 02:52:27318
319 // Show the tray even if virtual keyboard is shown. (Other tray buttons will
320 // be hidden).
321 set_show_with_virtual_keyboard(true);
azureweic0b0a4f2016-07-15 08:56:12322}
323
324ImeMenuTray::~ImeMenuTray() {
azureweic6200ab2016-08-26 21:42:30325 if (bubble_)
yawano66c305b2017-06-27 00:37:14326 bubble_->bubble_view()->ResetDelegate();
sky5b45ed82017-03-27 02:54:23327 SystemTrayNotifier* tray_notifier = Shell::Get()->system_tray_notifier();
azurewei1fb9e772016-11-23 06:29:11328 tray_notifier->RemoveIMEObserver(this);
329 tray_notifier->RemoveVirtualKeyboardObserver(this);
Darren Shencb2508442019-07-03 21:48:23330 auto* keyboard_controller = keyboard::KeyboardUIController::Get();
Steven Bennetts137a18e2018-10-10 19:13:45331 if (keyboard_controller->HasObserver(this))
azurewei886f6482017-01-07 08:38:44332 keyboard_controller->RemoveObserver(this);
azureweic0b0a4f2016-07-15 08:56:12333}
334
Ahmed Mehfooz15cebdd2021-03-03 01:07:07335void ImeMenuTray::ShowImeMenuBubbleInternal() {
James Cook76e92052018-09-21 23:10:30336 TrayBubbleView::InitParams init_params;
jamescookc3301602017-05-30 21:49:28337 init_params.delegate = this;
338 init_params.parent_window = GetBubbleWindowContainer();
339 init_params.anchor_view = GetBubbleAnchor();
Manu Cornet588b54a2019-04-11 07:36:15340 init_params.shelf_alignment = shelf()->alignment();
Anastasia Helfinstein94cd64a2020-04-09 18:31:42341 init_params.preferred_width = kTrayMenuWidth;
azureweie853e622016-08-27 10:52:09342 init_params.close_on_deactivate = true;
Ahmed Mehfooz3a2573c2020-07-22 23:06:37343 init_params.has_shadow = false;
344 init_params.translucent = true;
345 init_params.corner_radius = kTrayItemCornerRadius;
Ahmed Mehfooz15cebdd2021-03-03 01:07:07346 init_params.reroute_event_handler = true;
azureweie853e622016-08-27 10:52:09347
Ahmed Mehfooz3a2573c2020-07-22 23:06:37348 auto setup_layered_view = [](views::View* view) {
349 view->SetPaintToLayer();
350 view->layer()->SetFillsBoundsOpaquely(false);
351 };
352
James Cook76e92052018-09-21 23:10:30353 TrayBubbleView* bubble_view = new TrayBubbleView(init_params);
estade3acb088db2016-11-16 18:31:30354 bubble_view->set_anchor_view_insets(GetBubbleAnchorInsets());
Ahmed Mehfooz3a2573c2020-07-22 23:06:37355 bubble_view->set_margins(GetSecondaryBubbleInsets());
azureweie853e622016-08-27 10:52:09356
estadea553b86b2017-03-29 19:04:55357 // Add a title item with a separator on the top of the IME menu.
Andre Lebacf0ac12020-08-25 19:24:44358 setup_layered_view(
359 bubble_view->AddChildView(std::make_unique<ImeTitleView>()));
azurewei92ccc5c2016-09-21 16:14:25360
azureweie853e622016-08-27 10:52:09361 // Adds IME list to the bubble.
Ahmed Mehfooz3a2573c2020-07-22 23:06:37362 ime_list_view_ =
363 bubble_view->AddChildView(std::make_unique<ImeMenuListView>());
azureweid0cea0b2017-02-07 02:15:48364 ime_list_view_->Init(ShouldShowKeyboardToggle(),
365 ImeListView::SHOW_SINGLE_IME);
Ahmed Mehfooz3a2573c2020-07-22 23:06:37366 setup_layered_view(ime_list_view_);
azureweie853e622016-08-27 10:52:09367
Andre Lebacf0ac12020-08-25 19:24:44368 if (ShouldShowBottomButtons()) {
Ahmed Mehfooz3a2573c2020-07-22 23:06:37369 setup_layered_view(
370 bubble_view->AddChildView(std::make_unique<ImeButtonsView>(
371 this, is_emoji_enabled_, is_handwriting_enabled_,
372 is_voice_enabled_)));
azurewei079691f2017-06-30 15:04:18373 }
azureweie853e622016-08-27 10:52:09374
Tetsui Ohkubo4c8f43422017-10-18 04:41:16375 bubble_ = std::make_unique<TrayBubbleWrapper>(this, bubble_view,
376 false /* is_persistent */);
mohsen4614a8c2016-11-14 19:08:20377 SetIsActive(true);
azureweie853e622016-08-27 10:52:09378}
379
Yuichiro Hanada2b66e9c2018-03-27 03:08:02380void ImeMenuTray::ShowKeyboardWithKeyset(
Darren Shen7b132782019-12-10 04:36:06381 chromeos::input_method::ImeKeyset keyset) {
minchd86339372017-07-18 20:07:50382 CloseBubble();
azurewei649030a22016-09-20 13:11:43383
Steven Bennettsedb5fa392018-10-18 17:47:52384 Shell::Get()
Darren Shen7daf3e12019-07-02 07:25:49385 ->keyboard_controller()
Steven Bennettsedb5fa392018-10-18 17:47:52386 ->virtual_keyboard_controller()
387 ->ForceShowKeyboardWithKeyset(keyset);
azurewei649030a22016-09-20 13:11:43388}
389
azurewei079691f2017-06-30 15:04:18390bool ImeMenuTray::ShouldShowBottomButtons() {
azurewei1c4c4e82017-01-10 04:47:18391 // Emoji, handwriting and voice input is not supported for these cases:
Elly Fong-Jonesc00b17c2019-02-20 14:32:22392 // 1) third party IME extensions.
393 // 2) login/lock screen.
394 // 3) password input client.
Blake O'Haref61c66e2017-10-05 01:55:49395
azurewei079691f2017-06-30 15:04:18396 bool should_show_buttom_buttoms =
Blake O'Haref61c66e2017-10-05 01:55:49397 ime_controller_->is_extra_input_options_enabled() &&
azurewei079691f2017-06-30 15:04:18398 !ime_controller_->current_ime().third_party && !IsInLoginOrLockScreen() &&
399 !IsInPasswordInputContext();
400
401 if (!should_show_buttom_buttoms) {
Blake O'Haref61c66e2017-10-05 01:55:49402 is_emoji_enabled_ = is_handwriting_enabled_ = is_voice_enabled_ = false;
azurewei079691f2017-06-30 15:04:18403 return false;
404 }
405
Blake O'Haref61c66e2017-10-05 01:55:49406 is_emoji_enabled_ = ime_controller_->is_emoji_enabled();
407 is_handwriting_enabled_ = ime_controller_->is_handwriting_enabled();
408 is_voice_enabled_ = ime_controller_->is_voice_enabled();
409
410 return is_emoji_enabled_ || is_handwriting_enabled_ || is_voice_enabled_;
azurewei23b7cdb02016-11-08 04:16:57411}
412
azurewei1fb9e772016-11-23 06:29:11413bool ImeMenuTray::ShouldShowKeyboardToggle() const {
Anatoliy Potapchuke3687582020-09-08 22:50:32414 return keyboard_suppressed_ && !Shell::Get()
415 ->accessibility_controller()
416 ->virtual_keyboard()
417 .enabled();
azurewei1fb9e772016-11-23 06:29:11418}
419
Ahmed Mehfooz9f4dc132020-11-12 03:10:49420void ImeMenuTray::OnThemeChanged() {
421 TrayBackgroundView::OnThemeChanged();
422 UpdateTrayLabel();
423}
424
Jan Wilken Dörrie85285b02021-03-11 23:38:47425std::u16string ImeMenuTray::GetAccessibleNameForTray() {
azureweic0b0a4f2016-07-15 08:56:12426 return l10n_util::GetStringUTF16(IDS_ASH_IME_MENU_ACCESSIBLE_NAME);
427}
428
Toni Barzice4627b852020-06-04 02:22:49429void ImeMenuTray::HandleLocaleChange() {
430 if (image_view_) {
Allen Bauerd9daac112020-09-15 21:54:04431 image_view_->SetTooltipText(
Toni Barzice4627b852020-06-04 02:22:49432 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_IME));
433 }
434
435 if (label_)
436 label_->SetTooltipText(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_IME));
437}
438
James Cook76e92052018-09-21 23:10:30439void ImeMenuTray::HideBubbleWithView(const TrayBubbleView* bubble_view) {
azurewei4ecb8442016-07-28 06:06:09440 if (bubble_->bubble_view() == bubble_view)
minchd86339372017-07-18 20:07:50441 CloseBubble();
azureweic0b0a4f2016-07-15 08:56:12442}
443
azurewei4ecb8442016-07-28 06:06:09444void ImeMenuTray::ClickedOutsideBubble() {
minchd86339372017-07-18 20:07:50445 CloseBubble();
azurewei4ecb8442016-07-28 06:06:09446}
azureweic0b0a4f2016-07-15 08:56:12447
448bool ImeMenuTray::PerformAction(const ui::Event& event) {
Ahmed Mehfooz15cebdd2021-03-03 01:07:07449 if (event.IsMouseEvent() || event.IsGestureEvent()) {
450 UserMetricsRecorder::RecordUserClickOnTray(
451 LoginMetricsRecorder::TrayClickTarget::kImeTray);
452 }
453 return TrayBackgroundView::PerformAction(event);
azureweic0b0a4f2016-07-15 08:56:12454}
455
minchd86339372017-07-18 20:07:50456void ImeMenuTray::CloseBubble() {
457 bubble_.reset();
458 ime_list_view_ = nullptr;
459 SetIsActive(false);
460 shelf()->UpdateAutoHideState();
461}
462
Ahmed Mehfooz15cebdd2021-03-03 01:07:07463void ImeMenuTray::ShowBubble() {
Darren Shencb2508442019-07-03 21:48:23464 auto* keyboard_controller = keyboard::KeyboardUIController::Get();
Steven Bennetts137a18e2018-10-10 19:13:45465 if (keyboard_controller->IsKeyboardVisible()) {
minchd86339372017-07-18 20:07:50466 show_bubble_after_keyboard_hidden_ = true;
467 keyboard_controller->AddObserver(this);
Blake O'Haref768600e02018-06-13 10:01:01468 keyboard_controller->HideKeyboardExplicitlyBySystem();
minchd86339372017-07-18 20:07:50469 } else {
MinChenda041272017-07-27 17:20:10470 base::RecordAction(base::UserMetricsAction("Tray_ImeMenu_Opened"));
Ahmed Mehfooz15cebdd2021-03-03 01:07:07471 ShowImeMenuBubbleInternal();
minchd86339372017-07-18 20:07:50472 }
473}
474
James Cook76e92052018-09-21 23:10:30475TrayBubbleView* ImeMenuTray::GetBubbleView() {
Ahmed Mehfooz15cebdd2021-03-03 01:07:07476 return bubble_ ? bubble_->GetBubbleView() : nullptr;
477}
478
479views::Widget* ImeMenuTray::GetBubbleWidget() const {
480 return bubble_ ? bubble_->GetBubbleWidget() : nullptr;
minchd86339372017-07-18 20:07:50481}
482
azureweic0b0a4f2016-07-15 08:56:12483void ImeMenuTray::OnIMERefresh() {
484 UpdateTrayLabel();
azureweic6200ab2016-08-26 21:42:30485 if (bubble_ && ime_list_view_) {
James Cook23f56b72017-06-21 00:38:28486 ime_list_view_->Update(ime_controller_->current_ime().id,
487 ime_controller_->available_imes(),
James Cookf0c78fc2017-06-15 14:42:55488 ime_controller_->current_ime_menu_items(), false,
azureweic6200ab2016-08-26 21:42:30489 ImeListView::SHOW_SINGLE_IME);
490 }
azureweic0b0a4f2016-07-15 08:56:12491}
492
493void ImeMenuTray::OnIMEMenuActivationChanged(bool is_activated) {
Tim Song21921b982019-11-08 00:57:14494 SetVisiblePreferred(is_activated);
azureweic0b0a4f2016-07-15 08:56:12495 if (is_activated)
496 UpdateTrayLabel();
497 else
minchd86339372017-07-18 20:07:50498 CloseBubble();
azurewei4ecb8442016-07-28 06:06:09499}
500
Jan Wilken Dörrie85285b02021-03-11 23:38:47501std::u16string ImeMenuTray::GetAccessibleNameForBubble() {
azurewei4ecb8442016-07-28 06:06:09502 return l10n_util::GetStringUTF16(IDS_ASH_IME_MENU_ACCESSIBLE_NAME);
503}
504
yawano66c305b2017-06-27 00:37:14505bool ImeMenuTray::ShouldEnableExtraKeyboardAccessibility() {
Anatoliy Potapchuke3687582020-09-08 22:50:32506 return Shell::Get()->accessibility_controller()->spoken_feedback().enabled();
yawano66c305b2017-06-27 00:37:14507}
508
James Cook76e92052018-09-21 23:10:30509void ImeMenuTray::HideBubble(const TrayBubbleView* bubble_view) {
azurewei4ecb8442016-07-28 06:06:09510 HideBubbleWithView(bubble_view);
azureweic0b0a4f2016-07-15 08:56:12511}
512
Darren Shenbb5851b2018-07-19 07:04:06513void ImeMenuTray::OnKeyboardHidden(bool is_temporary_hide) {
azureweie2664492016-12-29 00:30:42514 if (show_bubble_after_keyboard_hidden_) {
515 show_bubble_after_keyboard_hidden_ = false;
Darren Shencb2508442019-07-03 21:48:23516 auto* keyboard_controller = keyboard::KeyboardUIController::Get();
Darren Shen96c912532018-05-22 01:20:38517 keyboard_controller->RemoveObserver(this);
azureweie2664492016-12-29 00:30:42518
Ahmed Mehfooz15cebdd2021-03-03 01:07:07519 ShowImeMenuBubbleInternal();
azureweie2664492016-12-29 00:30:42520 return;
521 }
Darren Shena4bf7492018-03-16 04:25:52522}
523
azurewei1fb9e772016-11-23 06:29:11524void ImeMenuTray::OnKeyboardSuppressionChanged(bool suppressed) {
525 if (suppressed != keyboard_suppressed_ && bubble_)
minchd86339372017-07-18 20:07:50526 CloseBubble();
azurewei1fb9e772016-11-23 06:29:11527 keyboard_suppressed_ = suppressed;
528}
529
azureweic0b0a4f2016-07-15 08:56:12530void ImeMenuTray::UpdateTrayLabel() {
Darren Shen7b132782019-12-10 04:36:06531 const ImeInfo& current_ime = ime_controller_->current_ime();
azureweic0b0a4f2016-07-15 08:56:12532
Yuichiro Hanada81b13422018-07-10 05:49:41533 // For ARC IMEs, we use the globe icon instead of the short name of the active
534 // IME.
535 if (chromeos::extension_ime_util::IsArcIME(current_ime.id)) {
536 CreateImageView();
minchbee2e312019-08-15 21:52:40537 image_view_->SetImage(gfx::CreateVectorIcon(
Xiaoqian Daif1252082020-06-16 23:13:36538 kShelfGlobeIcon,
539 AshColorProvider::Get()->GetContentLayerColor(
minch5847c6f2020-09-08 01:13:17540 AshColorProvider::ContentLayerType::kIconColorPrimary)));
Yuichiro Hanada81b13422018-07-10 05:49:41541 return;
542 }
543
azureweic0b0a4f2016-07-15 08:56:12544 // Updates the tray label based on the current input method.
Yuichiro Hanada81b13422018-07-10 05:49:41545 CreateLabel();
Ahmed Mehfooz9f4dc132020-11-12 03:10:49546
547 label_->SetEnabledColor(AshColorProvider::Get()->GetContentLayerColor(
548 AshColorProvider::ContentLayerType::kIconColorPrimary));
549
James Cookf0c78fc2017-06-15 14:42:55550 if (current_ime.third_party)
551 label_->SetText(current_ime.short_name + base::UTF8ToUTF16("*"));
azureweic0b0a4f2016-07-15 08:56:12552 else
James Cookf0c78fc2017-06-15 14:42:55553 label_->SetText(current_ime.short_name);
azureweic0b0a4f2016-07-15 08:56:12554}
555
Yuichiro Hanada81b13422018-07-10 05:49:41556void ImeMenuTray::CreateLabel() {
557 // Do nothing if label_ is already created.
558 if (label_)
559 return;
560 // Remove image_view_ at first if it's created.
561 if (image_view_) {
562 tray_container()->RemoveChildView(image_view_);
563 image_view_ = nullptr;
564 }
565 label_ = new ImeMenuLabel();
566 SetupLabelForTray(label_);
567 label_->SetElideBehavior(gfx::TRUNCATE);
568 label_->SetTooltipText(l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_IME));
569 tray_container()->AddChildView(label_);
570}
571
572void ImeMenuTray::CreateImageView() {
573 // Do nothing if image_view_ is already created.
574 if (image_view_)
575 return;
576 // Remove label_ at first if it's created.
577 if (label_) {
578 tray_container()->RemoveChildView(label_);
579 label_ = nullptr;
580 }
581 image_view_ = new ImeMenuImageView();
Allen Bauerd9daac112020-09-15 21:54:04582 image_view_->SetTooltipText(
Yuichiro Hanada81b13422018-07-10 05:49:41583 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_IME));
584 tray_container()->AddChildView(image_view_);
585}
586
Shengsong Tan64ce6342020-12-23 03:44:33587BEGIN_METADATA(ImeMenuTray, TrayBackgroundView)
588END_METADATA
589
azureweic0b0a4f2016-07-15 08:56:12590} // namespace ash