Remove unused parameter.
[chromium-blink-merge.git] / ui / keyboard / keyboard_util.cc
bloba1cffb2b0bdf7d7de7176fdd4f0434a9bb04ce72
1 // Copyright (c) 2013 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.
5 #include "ui/keyboard/keyboard_util.h"
7 #include <string>
9 #include "base/command_line.h"
10 #include "base/lazy_instance.h"
11 #include "base/logging.h"
12 #include "base/metrics/histogram.h"
13 #include "base/strings/string16.h"
14 #include "grit/keyboard_resources.h"
15 #include "grit/keyboard_resources_map.h"
16 #include "ui/aura/client/aura_constants.h"
17 #include "ui/aura/window_tree_host.h"
18 #include "ui/base/ime/input_method.h"
19 #include "ui/base/ime/text_input_client.h"
20 #include "ui/events/event_processor.h"
21 #include "ui/events/keycodes/dom4/keycode_converter.h"
22 #include "ui/keyboard/keyboard_controller.h"
23 #include "ui/keyboard/keyboard_controller_proxy.h"
24 #include "ui/keyboard/keyboard_switches.h"
25 #include "url/gurl.h"
27 namespace {
29 const char kKeyDown[] ="keydown";
30 const char kKeyUp[] = "keyup";
32 void SendProcessKeyEvent(ui::EventType type,
33 aura::WindowTreeHost* host) {
34 ui::KeyEvent event(type, ui::VKEY_PROCESSKEY, ui::EF_NONE);
35 event.SetTranslated(true);
36 ui::EventDispatchDetails details =
37 host->event_processor()->OnEventFromSource(&event);
38 CHECK(!details.dispatcher_destroyed);
41 base::LazyInstance<base::Time> g_keyboard_load_time_start =
42 LAZY_INSTANCE_INITIALIZER;
44 bool g_accessibility_keyboard_enabled = false;
46 base::LazyInstance<GURL> g_override_content_url = LAZY_INSTANCE_INITIALIZER;
48 bool g_touch_keyboard_enabled = false;
50 keyboard::KeyboardOverscrolOverride g_keyboard_overscroll_override =
51 keyboard::KEYBOARD_OVERSCROLL_OVERRIDE_NONE;
53 keyboard::KeyboardShowOverride g_keyboard_show_override =
54 keyboard::KEYBOARD_SHOW_OVERRIDE_NONE;
56 } // namespace
58 namespace keyboard {
60 gfx::Rect DefaultKeyboardBoundsFromWindowBounds(
61 const gfx::Rect& window_bounds) {
62 // Initialize default keyboard height to 0. The keyboard window height should
63 // only be set by window.resizeTo in virtual keyboard web contents. Otherwise,
64 // the default height may conflict with the new height and causing some
65 // strange animation issues.
66 return KeyboardBoundsFromWindowBounds(window_bounds, 0);
69 gfx::Rect KeyboardBoundsFromWindowBounds(const gfx::Rect& window_bounds,
70 int keyboard_height) {
71 return gfx::Rect(
72 window_bounds.x(),
73 window_bounds.bottom() - keyboard_height,
74 window_bounds.width(),
75 keyboard_height);
78 void SetAccessibilityKeyboardEnabled(bool enabled) {
79 g_accessibility_keyboard_enabled = enabled;
82 bool GetAccessibilityKeyboardEnabled() {
83 return g_accessibility_keyboard_enabled;
86 void SetTouchKeyboardEnabled(bool enabled) {
87 g_touch_keyboard_enabled = enabled;
90 bool GetTouchKeyboardEnabled() {
91 return g_touch_keyboard_enabled;
94 std::string GetKeyboardLayout() {
95 // TODO(bshe): layout string is currently hard coded. We should use more
96 // standard keyboard layouts.
97 return GetAccessibilityKeyboardEnabled() ? "system-qwerty" : "qwerty";
100 bool IsKeyboardEnabled() {
101 // Accessibility setting prioritized over policy setting.
102 if (g_accessibility_keyboard_enabled)
103 return true;
104 // Policy strictly disables showing a virtual keyboard.
105 if (g_keyboard_show_override == keyboard::KEYBOARD_SHOW_OVERRIDE_DISABLED)
106 return false;
107 // Check if any of the flags are enabled.
108 return base::CommandLine::ForCurrentProcess()->HasSwitch(
109 switches::kEnableVirtualKeyboard) ||
110 g_touch_keyboard_enabled ||
111 (g_keyboard_show_override == keyboard::KEYBOARD_SHOW_OVERRIDE_ENABLED);
114 bool IsKeyboardOverscrollEnabled() {
115 if (!IsKeyboardEnabled())
116 return false;
118 // Users of the accessibility on-screen keyboard are likely to be using mouse
119 // input, which may interfere with overscrolling.
120 if (g_accessibility_keyboard_enabled)
121 return false;
123 // If overscroll enabled override is set, use it instead. Currently
124 // login / out-of-box disable keyboard overscroll. http://crbug.com/363635
125 if (g_keyboard_overscroll_override != KEYBOARD_OVERSCROLL_OVERRIDE_NONE) {
126 return g_keyboard_overscroll_override ==
127 KEYBOARD_OVERSCROLL_OVERRIDE_ENABLED;
130 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
131 switches::kDisableVirtualKeyboardOverscroll)) {
132 return false;
134 return true;
137 void SetKeyboardOverscrollOverride(KeyboardOverscrolOverride override) {
138 g_keyboard_overscroll_override = override;
141 void SetKeyboardShowOverride(KeyboardShowOverride override) {
142 g_keyboard_show_override = override;
145 bool IsInputViewEnabled() {
146 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
147 switches::kEnableInputView))
148 return true;
149 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
150 switches::kDisableInputView))
151 return false;
152 // Default value if no command line flags specified.
153 return true;
156 bool IsExperimentalInputViewEnabled() {
157 return base::CommandLine::ForCurrentProcess()->HasSwitch(
158 switches::kEnableExperimentalInputViewFeatures);
161 bool IsGestureTypingEnabled() {
162 return base::CommandLine::ForCurrentProcess()->HasSwitch(
163 switches::kEnableGestureTyping);
166 bool IsGestureSelectionEnabled() {
167 return base::CommandLine::ForCurrentProcess()->HasSwitch(
168 switches::kEnableGestureSelection);
171 bool IsGestureDeletionEnabled() {
172 return base::CommandLine::ForCurrentProcess()->HasSwitch(
173 switches::kEnableGestureDeletion);
176 bool InsertText(const base::string16& text) {
177 keyboard::KeyboardController* controller = KeyboardController::GetInstance();
178 if (!controller)
179 return false;
181 ui::InputMethod* input_method = controller->proxy()->GetInputMethod();
182 if (!input_method)
183 return false;
185 ui::TextInputClient* tic = input_method->GetTextInputClient();
186 if (!tic || tic->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
187 return false;
189 tic->InsertText(text);
191 return true;
194 // TODO(varunjain): It would be cleaner to have something in the
195 // ui::TextInputClient interface, say MoveCaretInDirection(). The code in
196 // here would get the ui::InputMethod from the root_window, and the
197 // ui::TextInputClient from that (see above in InsertText()).
198 bool MoveCursor(int swipe_direction,
199 int modifier_flags,
200 aura::WindowTreeHost* host) {
201 if (!host)
202 return false;
203 ui::KeyboardCode codex = ui::VKEY_UNKNOWN;
204 ui::KeyboardCode codey = ui::VKEY_UNKNOWN;
205 if (swipe_direction & kCursorMoveRight)
206 codex = ui::VKEY_RIGHT;
207 else if (swipe_direction & kCursorMoveLeft)
208 codex = ui::VKEY_LEFT;
210 if (swipe_direction & kCursorMoveUp)
211 codey = ui::VKEY_UP;
212 else if (swipe_direction & kCursorMoveDown)
213 codey = ui::VKEY_DOWN;
215 // First deal with the x movement.
216 if (codex != ui::VKEY_UNKNOWN) {
217 ui::KeyEvent press_event(ui::ET_KEY_PRESSED, codex, modifier_flags);
218 ui::EventDispatchDetails details =
219 host->event_processor()->OnEventFromSource(&press_event);
220 CHECK(!details.dispatcher_destroyed);
221 ui::KeyEvent release_event(ui::ET_KEY_RELEASED, codex, modifier_flags);
222 details = host->event_processor()->OnEventFromSource(&release_event);
223 CHECK(!details.dispatcher_destroyed);
226 // Then deal with the y movement.
227 if (codey != ui::VKEY_UNKNOWN) {
228 ui::KeyEvent press_event(ui::ET_KEY_PRESSED, codey, modifier_flags);
229 ui::EventDispatchDetails details =
230 host->event_processor()->OnEventFromSource(&press_event);
231 CHECK(!details.dispatcher_destroyed);
232 ui::KeyEvent release_event(ui::ET_KEY_RELEASED, codey, modifier_flags);
233 details = host->event_processor()->OnEventFromSource(&release_event);
234 CHECK(!details.dispatcher_destroyed);
236 return true;
239 bool SendKeyEvent(const std::string type,
240 int key_value,
241 int key_code,
242 std::string key_name,
243 int modifiers,
244 aura::WindowTreeHost* host) {
245 ui::EventType event_type = ui::ET_UNKNOWN;
246 if (type == kKeyDown)
247 event_type = ui::ET_KEY_PRESSED;
248 else if (type == kKeyUp)
249 event_type = ui::ET_KEY_RELEASED;
250 if (event_type == ui::ET_UNKNOWN)
251 return false;
253 ui::KeyboardCode code = static_cast<ui::KeyboardCode>(key_code);
255 if (code == ui::VKEY_UNKNOWN) {
256 // Handling of special printable characters (e.g. accented characters) for
257 // which there is no key code.
258 if (event_type == ui::ET_KEY_RELEASED) {
259 ui::InputMethod* input_method = host->window()->GetProperty(
260 aura::client::kRootWindowInputMethodKey);
261 if (!input_method)
262 return false;
264 ui::TextInputClient* tic = input_method->GetTextInputClient();
266 SendProcessKeyEvent(ui::ET_KEY_PRESSED, host);
267 tic->InsertChar(static_cast<uint16>(key_value), ui::EF_NONE);
268 SendProcessKeyEvent(ui::ET_KEY_RELEASED, host);
270 } else {
271 if (event_type == ui::ET_KEY_RELEASED) {
272 // The number of key press events seen since the last backspace.
273 static int keys_seen = 0;
274 if (code == ui::VKEY_BACK) {
275 // Log the rough lengths of characters typed between backspaces. This
276 // metric will be used to determine the error rate for the keyboard.
277 UMA_HISTOGRAM_CUSTOM_COUNTS(
278 "VirtualKeyboard.KeystrokesBetweenBackspaces",
279 keys_seen, 1, 1000, 50);
280 keys_seen = 0;
281 } else {
282 ++keys_seen;
286 ui::KeyEvent event(
287 event_type,
288 code,
289 ui::KeycodeConverter::CodeStringToDomCode(key_name.c_str()),
290 modifiers);
291 ui::EventDispatchDetails details =
292 host->event_processor()->OnEventFromSource(&event);
293 CHECK(!details.dispatcher_destroyed);
295 return true;
298 void MarkKeyboardLoadStarted() {
299 if (!g_keyboard_load_time_start.Get().ToInternalValue())
300 g_keyboard_load_time_start.Get() = base::Time::Now();
303 void MarkKeyboardLoadFinished() {
304 // Possible to get a load finished without a start if navigating directly to
305 // chrome://keyboard.
306 if (!g_keyboard_load_time_start.Get().ToInternalValue())
307 return;
309 // It should not be possible to finish loading the keyboard without starting
310 // to load it first.
311 DCHECK(g_keyboard_load_time_start.Get().ToInternalValue());
313 static bool logged = false;
314 if (!logged) {
315 // Log the delta only once.
316 UMA_HISTOGRAM_TIMES(
317 "VirtualKeyboard.FirstLoadTime",
318 base::Time::Now() - g_keyboard_load_time_start.Get());
319 logged = true;
323 const GritResourceMap* GetKeyboardExtensionResources(size_t* size) {
324 // This looks a lot like the contents of a resource map; however it is
325 // necessary to have a custom path for the extension path, so the resource
326 // map cannot be used directly.
327 static const GritResourceMap kKeyboardResources[] = {
328 {"keyboard/locales/en.js", IDR_KEYBOARD_LOCALES_EN},
329 {"keyboard/config/m-emoji.js", IDR_KEYBOARD_CONFIG_EMOJI},
330 {"keyboard/config/m-hwt.js", IDR_KEYBOARD_CONFIG_HWT},
331 {"keyboard/config/us.js", IDR_KEYBOARD_CONFIG_US},
332 {"keyboard/emoji.css", IDR_KEYBOARD_CSS_EMOJI},
333 {"keyboard/images/backspace.png", IDR_KEYBOARD_IMAGES_BACKSPACE},
334 {"keyboard/images/car.png", IDR_KEYBOARD_IMAGES_CAR},
335 {"keyboard/images/check.png", IDR_KEYBOARD_IMAGES_CHECK},
336 {"keyboard/images/compact.png", IDR_KEYBOARD_IMAGES_COMPACT},
337 {"keyboard/images/down.png", IDR_KEYBOARD_IMAGES_DOWN},
338 {"keyboard/images/emoji.png", IDR_KEYBOARD_IMAGES_EMOJI},
339 {"keyboard/images/emoji_cat_items.png", IDR_KEYBOARD_IMAGES_CAT},
340 {"keyboard/images/emoticon.png", IDR_KEYBOARD_IMAGES_EMOTICON},
341 {"keyboard/images/enter.png", IDR_KEYBOARD_IMAGES_RETURN},
342 {"keyboard/images/error.png", IDR_KEYBOARD_IMAGES_ERROR},
343 {"keyboard/images/favorit.png", IDR_KEYBOARD_IMAGES_FAVORITE},
344 {"keyboard/images/flower.png", IDR_KEYBOARD_IMAGES_FLOWER},
345 {"keyboard/images/globe.png", IDR_KEYBOARD_IMAGES_GLOBE},
346 {"keyboard/images/hide.png", IDR_KEYBOARD_IMAGES_HIDE_KEYBOARD},
347 {"keyboard/images/keyboard.svg", IDR_KEYBOARD_IMAGES_KEYBOARD},
348 {"keyboard/images/left.png", IDR_KEYBOARD_IMAGES_LEFT},
349 {"keyboard/images/penci.png", IDR_KEYBOARD_IMAGES_PENCIL},
350 {"keyboard/images/recent.png", IDR_KEYBOARD_IMAGES_RECENT},
351 {"keyboard/images/regular_size.png", IDR_KEYBOARD_IMAGES_FULLSIZE},
352 {"keyboard/images/menu.png", IDR_KEYBOARD_IMAGES_MENU},
353 {"keyboard/images/pencil.png", IDR_KEYBOARD_IMAGES_PENCIL},
354 {"keyboard/images/right.png", IDR_KEYBOARD_IMAGES_RIGHT},
355 {"keyboard/images/search.png", IDR_KEYBOARD_IMAGES_SEARCH},
356 {"keyboard/images/setting.png", IDR_KEYBOARD_IMAGES_SETTINGS},
357 {"keyboard/images/shift.png", IDR_KEYBOARD_IMAGES_SHIFT},
358 {"keyboard/images/space.png", IDR_KEYBOARD_IMAGES_SPACE},
359 {"keyboard/images/tab.png", IDR_KEYBOARD_IMAGES_TAB},
360 {"keyboard/images/triangle.png", IDR_KEYBOARD_IMAGES_TRIANGLE},
361 {"keyboard/images/up.png", IDR_KEYBOARD_IMAGES_UP},
362 {"keyboard/index.html", IDR_KEYBOARD_INDEX},
363 {"keyboard/inputview_adapter.js", IDR_KEYBOARD_INPUTVIEW_ADAPTER},
364 {"keyboard/inputview.css", IDR_KEYBOARD_INPUTVIEW_CSS},
365 {"keyboard/inputview.js", IDR_KEYBOARD_INPUTVIEW_JS},
366 {"keyboard/inputview_layouts/101kbd.js", IDR_KEYBOARD_LAYOUTS_101},
367 {"keyboard/inputview_layouts/compactkbd-qwerty.js",
368 IDR_KEYBOARD_LAYOUTS_COMPACT_QWERTY},
369 {"keyboard/inputview_layouts/compactkbd-numberpad.js",
370 IDR_KEYBOARD_LAYOUTS_COMPACT_NUMBERPAD},
371 {"keyboard/inputview_layouts/emoji.js", IDR_KEYBOARD_LAYOUTS_EMOJI},
372 {"keyboard/inputview_layouts/handwriting.js", IDR_KEYBOARD_LAYOUTS_HWT},
373 {"keyboard/inputview_layouts/m-101kbd.js",
374 IDR_KEYBOARD_LAYOUTS_MATERIAL_101},
375 {"keyboard/inputview_layouts/m-compactkbd-qwerty.js",
376 IDR_KEYBOARD_LAYOUTS_MATERIAL_COMPACT_QWERTY},
377 {"keyboard/inputview_layouts/m-compactkbd-numberpad.js",
378 IDR_KEYBOARD_LAYOUTS_MATERIAL_COMPACT_NUMBERPAD},
379 {"keyboard/inputview_layouts/m-emoji.js",
380 IDR_KEYBOARD_LAYOUTS_MATERIAL_EMOJI},
381 {"keyboard/inputview_layouts/m-handwriting.js",
382 IDR_KEYBOARD_LAYOUTS_MATERIAL_HWT},
383 {"keyboard/manifest.json", IDR_KEYBOARD_MANIFEST},
384 {"keyboard/sounds/keypress-delete.wav",
385 IDR_KEYBOARD_SOUNDS_KEYPRESS_DELETE},
386 {"keyboard/sounds/keypress-return.wav",
387 IDR_KEYBOARD_SOUNDS_KEYPRESS_RETURN},
388 {"keyboard/sounds/keypress-spacebar.wav",
389 IDR_KEYBOARD_SOUNDS_KEYPRESS_SPACEBAR},
390 {"keyboard/sounds/keypress-standard.wav",
391 IDR_KEYBOARD_SOUNDS_KEYPRESS_STANDARD},
393 static const size_t kKeyboardResourcesSize = arraysize(kKeyboardResources);
394 *size = kKeyboardResourcesSize;
395 return kKeyboardResources;
398 void SetOverrideContentUrl(const GURL& url) {
399 g_override_content_url.Get() = url;
402 const GURL& GetOverrideContentUrl() {
403 return g_override_content_url.Get();
406 void LogKeyboardControlEvent(KeyboardControlEvent event) {
407 UMA_HISTOGRAM_ENUMERATION(
408 "VirtualKeyboard.KeyboardControlEvent",
409 event,
410 keyboard::KEYBOARD_CONTROL_MAX);
413 } // namespace keyboard